mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-10-31 19:39:20 +08:00 
			
		
		
		
	Merge branch 'master' of https://github.com/louislam/uptime-kuma
This commit is contained in:
		| @@ -4,7 +4,6 @@ | ||||
|         "indentation": 4, | ||||
|         "no-descending-specificity": null, | ||||
|         "selector-list-comma-newline-after": null, | ||||
|         "declaration-empty-line-before": null, | ||||
|         "no-duplicate-selectors": null | ||||
|         "declaration-empty-line-before": null | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -279,6 +279,116 @@ class Notification { | ||||
|                 throwGeneralAxiosError(error) | ||||
|             } | ||||
|  | ||||
|         } else if (notification.type === "mattermost") { | ||||
|             try { | ||||
|                 const mattermostUserName = notification.mattermostusername || "Uptime Kuma"; | ||||
|                 // If heartbeatJSON is null, assume we're testing. | ||||
|                 if (heartbeatJSON == null) { | ||||
|                     let mattermostTestData = { | ||||
|                         username: mattermostUserName, | ||||
|                         text: msg, | ||||
|                     } | ||||
|                     await axios.post(notification.mattermostWebhookUrl, mattermostTestData) | ||||
|                     return okMsg; | ||||
|                 } | ||||
|                  | ||||
|                 const mattermostChannel = notification.mattermostchannel; | ||||
|                 const mattermostIconEmoji = notification.mattermosticonemo; | ||||
|                 const mattermostIconUrl = notification.mattermosticonurl; | ||||
|  | ||||
|                 if (heartbeatJSON["status"] == 0) { | ||||
|                     let mattermostdowndata = { | ||||
|                         username: mattermostUserName, | ||||
|                         text: "Uptime Kuma Alert", | ||||
|                         channel: mattermostChannel, | ||||
|                         icon_emoji: mattermostIconEmoji, | ||||
|                         icon_url: mattermostIconUrl, | ||||
|                         attachments: [ | ||||
|                             { | ||||
|                                 fallback: | ||||
|                                     "Your " + | ||||
|                                     monitorJSON["name"] + | ||||
|                                     " service went down.", | ||||
|                                 color: "#FF0000", | ||||
|                                 title: | ||||
|                                     "❌ " + | ||||
|                                     monitorJSON["name"] + | ||||
|                                     " service went down. ❌", | ||||
|                                 title_link: monitorJSON["url"], | ||||
|                                 fields: [ | ||||
|                                     { | ||||
|                                         short: true, | ||||
|                                         title: "Service Name", | ||||
|                                         value: monitorJSON["name"], | ||||
|                                     }, | ||||
|                                     { | ||||
|                                         short: true, | ||||
|                                         title: "Time (UTC)", | ||||
|                                         value: heartbeatJSON["time"], | ||||
|                                     }, | ||||
|                                     { | ||||
|                                         short: false, | ||||
|                                         title: "Error", | ||||
|                                         value: heartbeatJSON["msg"], | ||||
|                                     }, | ||||
|                                 ], | ||||
|                             }, | ||||
|                         ], | ||||
|                     }; | ||||
|                     await axios.post( | ||||
|                         notification.mattermostWebhookUrl, | ||||
|                         mattermostdowndata | ||||
|                     ); | ||||
|                     return okMsg; | ||||
|                 } else if (heartbeatJSON["status"] == 1) { | ||||
|                     let mattermostupdata = { | ||||
|                         username: mattermostUserName, | ||||
|                         text: "Uptime Kuma Alert", | ||||
|                         channel: mattermostChannel, | ||||
|                         icon_emoji: mattermostIconEmoji, | ||||
|                         icon_url: mattermostIconUrl, | ||||
|                         attachments: [ | ||||
|                             { | ||||
|                                 fallback: | ||||
|                                     "Your " + | ||||
|                                     monitorJSON["name"] + | ||||
|                                     " service went up!", | ||||
|                                 color: "#32CD32", | ||||
|                                 title: | ||||
|                                     "✅ " + | ||||
|                                     monitorJSON["name"] + | ||||
|                                     " service went up! ✅", | ||||
|                                 title_link: monitorJSON["url"], | ||||
|                                 fields: [ | ||||
|                                     { | ||||
|                                         short: true, | ||||
|                                         title: "Service Name", | ||||
|                                         value: monitorJSON["name"], | ||||
|                                     }, | ||||
|                                     { | ||||
|                                         short: true, | ||||
|                                         title: "Time (UTC)", | ||||
|                                         value: heartbeatJSON["time"], | ||||
|                                     }, | ||||
|                                     { | ||||
|                                         short: false, | ||||
|                                         title: "Ping", | ||||
|                                         value: heartbeatJSON["ping"] + "ms", | ||||
|                                     }, | ||||
|                                 ], | ||||
|                             }, | ||||
|                         ], | ||||
|                     }; | ||||
|                     await axios.post( | ||||
|                         notification.mattermostWebhookUrl, | ||||
|                         mattermostupdata | ||||
|                     ); | ||||
|                     return okMsg; | ||||
|                 } | ||||
|             } catch (error) { | ||||
|                 throwGeneralAxiosError(error); | ||||
|             } | ||||
|  | ||||
|         } else if (notification.type === "pushover") { | ||||
|             let pushoverlink = "https://api.pushover.net/1/messages.json" | ||||
|             try { | ||||
|   | ||||
| @@ -163,10 +163,6 @@ export default { | ||||
|  | ||||
|         &.empty { | ||||
|             background-color: aliceblue; | ||||
|  | ||||
|             .dark & { | ||||
|                 background-color: #d0d3d5; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         &.down { | ||||
|   | ||||
| @@ -27,6 +27,7 @@ | ||||
|                                 <option value="apprise">Apprise (Support 50+ Notification services)</option> | ||||
|                                 <option value="pushbullet">Pushbullet</option> | ||||
|                                 <option value="line">Line Messenger</option> | ||||
|                                 <option value="mattermost">Mattermost</option> | ||||
|                             </select> | ||||
|                         </div> | ||||
|  | ||||
| @@ -238,6 +239,39 @@ | ||||
|                             </div> | ||||
|                         </template> | ||||
|  | ||||
|                         <template v-if="notification.type === 'mattermost'"> | ||||
|                             <div class="mb-3"> | ||||
|                                 <label for="mattermost-webhook-url" class="form-label">Webhook URL<span style="color:red;"><sup>*</sup></span></label> | ||||
|                                 <input id="mattermost-webhook-url" v-model="notification.mattermostWebhookUrl" type="text" class="form-control" required> | ||||
|                                 <label for="mattermost-username" class="form-label">Username</label> | ||||
|                                 <input id="mattermost-username" v-model="notification.mattermostusername" type="text" class="form-control"> | ||||
|                                 <label for="mattermost-iconurl" class="form-label">Icon URL</label> | ||||
|                                 <input id="mattermost-iconurl" v-model="notification.mattermosticonurl" type="text" class="form-control"> | ||||
|                                 <label for="mattermost-iconemo" class="form-label">Icon Emoji</label> | ||||
|                                 <input id="mattermost-iconemo" v-model="notification.mattermosticonemo" type="text" class="form-control"> | ||||
|                                 <label for="mattermost-channel" class="form-label">Channel Name</label> | ||||
|                                 <input id="mattermost-channel-name" v-model="notification.mattermostchannel" type="text" class="form-control"> | ||||
|                                 <div class="form-text"> | ||||
|                                     <span style="color:red;"><sup>*</sup></span>Required | ||||
|                                     <p style="margin-top: 8px;"> | ||||
|                                         More info about webhooks on: <a href="https://docs.mattermost.com/developer/webhooks-incoming.html" target="_blank">https://docs.mattermost.com/developer/webhooks-incoming.html</a> | ||||
|                                     </p> | ||||
|                                     <p style="margin-top: 8px;"> | ||||
|                                         You can override the default channel that webhook posts to by entering the channel name into "Channel Name" field. This needs to be enabled in Mattermost webhook settings. Ex: #other-channel | ||||
|                                     </p> | ||||
|                                     <p style="margin-top: 8px;"> | ||||
|                                         If you leave the Uptime Kuma URL field blank, it will default to the Project Github page. | ||||
|                                     </p> | ||||
|                                     <p style="margin-top: 8px;"> | ||||
|                                         You can provide a link to a picture in "Icon URL" to override the default profile picture. Will not be used if Icon Emoji is set. | ||||
|                                     </p> | ||||
|                                     <p style="margin-top: 8px;"> | ||||
|                                         Emoji cheat sheet: <a href="https://www.webfx.com/tools/emoji-cheat-sheet/" target="_blank">https://www.webfx.com/tools/emoji-cheat-sheet/</a> Note: emoji takes preference over Icon URL. | ||||
|                                     </p> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </template> | ||||
|  | ||||
|                         <template v-if="notification.type === 'pushy'"> | ||||
|                             <div class="mb-3"> | ||||
|                                 <label for="pushy-app-token" class="form-label">API_KEY</label> | ||||
|   | ||||
| @@ -24,6 +24,7 @@ export default { | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             // Configurable filtering on top of the returned data | ||||
|             chartPeriodHrs: 6, | ||||
|         }; | ||||
|     }, | ||||
| @@ -55,11 +56,10 @@ export default { | ||||
|  | ||||
|                 elements: { | ||||
|                     point: { | ||||
|                         // Hide points on chart unless mouse-over | ||||
|                         radius: 0, | ||||
|                         hitRadius: 100, | ||||
|                     }, | ||||
|                     bar: { | ||||
|                         barThickness: "flex", | ||||
|                     } | ||||
|                 }, | ||||
|                 scales: { | ||||
|                     x: { | ||||
| @@ -77,9 +77,9 @@ export default { | ||||
|                             maxRotation: 0, | ||||
|                             autoSkipPadding: 30, | ||||
|                         }, | ||||
|                         bounds: "ticks", | ||||
|                         grid: { | ||||
|                             color: this.$root.theme === "light" ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.1)", | ||||
|                             offset: false, | ||||
|                         }, | ||||
|                     }, | ||||
|                     y: { | ||||
| @@ -109,8 +109,11 @@ export default { | ||||
|                         mode: "nearest", | ||||
|                         intersect: false, | ||||
|                         padding: 10, | ||||
|                         backgroundColor: this.$root.theme === "light" ? "rgba(212,232,222,1.0)" : "rgba(32,42,38,1.0)", | ||||
|                         bodyColor: this.$root.theme === "light" ? "rgba(12,12,18,1.0)" : "rgba(220,220,220,1.0)", | ||||
|                         titleColor: this.$root.theme === "light" ? "rgba(12,12,18,1.0)" : "rgba(220,220,220,1.0)", | ||||
|                         filter: function (tooltipItem) { | ||||
|                             return tooltipItem.datasetIndex === 0; | ||||
|                             return tooltipItem.datasetIndex === 0;  // Hide tooltip on Bar Chart | ||||
|                         }, | ||||
|                         callbacks: { | ||||
|                             label: (context) => { | ||||
| @@ -125,32 +128,29 @@ export default { | ||||
|             } | ||||
|         }, | ||||
|         chartData() { | ||||
|             let ping_data = []; | ||||
|             let down_data = []; | ||||
|             let pingData = [];  // Ping Data for Line Chart, y-axis contains ping time | ||||
|             let downData = [];  // Down Data for Bar Chart, y-axis is 1 if target is down, 0 if target is up | ||||
|             if (this.monitorId in this.$root.heartbeatList) { | ||||
|                 ping_data = this.$root.heartbeatList[this.monitorId] | ||||
|                 this.$root.heartbeatList[this.monitorId] | ||||
|                     .filter( | ||||
|                         (beat) => dayjs.utc(beat.time).tz(this.$root.timezone).isAfter(dayjs().subtract(this.chartPeriodHrs, "hours"))) | ||||
|                     .map((beat) => { | ||||
|                         return { | ||||
|                             x: dayjs.utc(beat.time).tz(this.$root.timezone).format("YYYY-MM-DD HH:mm:ss"), | ||||
|                         const x = this.$root.datetime(beat.time); | ||||
|                         pingData.push({ | ||||
|                             x, | ||||
|                             y: beat.ping, | ||||
|                         }; | ||||
|                     }); | ||||
|                 down_data = this.$root.heartbeatList[this.monitorId] | ||||
|                     .filter( | ||||
|                         (beat) => dayjs.utc(beat.time).tz(this.$root.timezone).isAfter(dayjs().subtract(this.chartPeriodHrs, "hours"))) | ||||
|                     .map((beat) => { | ||||
|                         return { | ||||
|                             x: dayjs.utc(beat.time).tz(this.$root.timezone).format("YYYY-MM-DD HH:mm:ss"), | ||||
|                         }); | ||||
|                         downData.push({ | ||||
|                             x, | ||||
|                             y: beat.status === 0 ? 1 : 0, | ||||
|                         }; | ||||
|                         }) | ||||
|                     }); | ||||
|             } | ||||
|             return { | ||||
|                 datasets: [ | ||||
|                     { | ||||
|                         data: ping_data, | ||||
|                         // Line Chart | ||||
|                         data: pingData, | ||||
|                         fill: "origin", | ||||
|                         tension: 0.2, | ||||
|                         borderColor: "#5CDD8B", | ||||
| @@ -158,11 +158,15 @@ export default { | ||||
|                         yAxisID: "y", | ||||
|                     }, | ||||
|                     { | ||||
|                         // Bar Chart | ||||
|                         type: "bar", | ||||
|                         data: down_data, | ||||
|                         data: downData, | ||||
|                         borderColor: "#00000000", | ||||
|                         backgroundColor: "#DC354568", | ||||
|                         yAxisID: "y1", | ||||
|                         barThickness: "flex", | ||||
|                         barPercentage: 1, | ||||
|                         categoryPercentage: 1, | ||||
|                     }, | ||||
|                 ], | ||||
|             }; | ||||
|   | ||||
| @@ -191,6 +191,7 @@ main { | ||||
| } | ||||
|  | ||||
| footer { | ||||
|     color: #aaa; | ||||
|     font-size: 13px; | ||||
|     margin-top: 10px; | ||||
|     padding-bottom: 30px; | ||||
| @@ -198,10 +199,6 @@ footer { | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| footer { | ||||
|     color: #aaa; | ||||
| } | ||||
|  | ||||
| .dark { | ||||
|     header { | ||||
|         background-color: #161b22; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user