43 changed files with 1595 additions and 349 deletions
			
			
		| @ -0,0 +1,5 @@ | |||||
|  | module.exports = { | ||||
|  |     "rootDir": "..", | ||||
|  |     "testRegex": "./test/backend.spec.js", | ||||
|  | }; | ||||
|  | 
 | ||||
| @ -1,5 +1,5 @@ | |||||
| module.exports = { | module.exports = { | ||||
|     "rootDir": ".", |     "rootDir": "..", | ||||
|     "testRegex": "./test/frontend.spec.js", |     "testRegex": "./test/frontend.spec.js", | ||||
| }; | }; | ||||
| 
 | 
 | ||||
| @ -0,0 +1,6 @@ | |||||
|  | module.exports = { | ||||
|  |   apps: [{ | ||||
|  |     name: "uptime-kuma", | ||||
|  |     script: "./server/server.js", | ||||
|  |   }] | ||||
|  | } | ||||
| @ -0,0 +1,108 @@ | |||||
|  | const NotificationProvider = require("./notification-provider"); | ||||
|  | const { DOWN, UP } = require("../../src/util"); | ||||
|  | const { default: axios } = require("axios"); | ||||
|  | const Crypto = require("crypto"); | ||||
|  | const qs = require("qs"); | ||||
|  | 
 | ||||
|  | class AliyunSMS extends NotificationProvider { | ||||
|  |     name = "AliyunSMS"; | ||||
|  | 
 | ||||
|  |     async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { | ||||
|  |         let okMsg = "Sent Successfully."; | ||||
|  | 
 | ||||
|  |         try { | ||||
|  |             if (heartbeatJSON != null) { | ||||
|  |                 let msgBody = JSON.stringify({ | ||||
|  |                     name: monitorJSON["name"], | ||||
|  |                     time: heartbeatJSON["time"], | ||||
|  |                     status: this.statusToString(heartbeatJSON["status"]), | ||||
|  |                     msg: heartbeatJSON["msg"], | ||||
|  |                 }); | ||||
|  |                 if (this.sendSms(notification, msgBody)) { | ||||
|  |                     return okMsg; | ||||
|  |                 } | ||||
|  |             } else { | ||||
|  |                 let msgBody = JSON.stringify({ | ||||
|  |                     name: "", | ||||
|  |                     time: "", | ||||
|  |                     status: "", | ||||
|  |                     msg: msg, | ||||
|  |                 }); | ||||
|  |                 if (this.sendSms(notification, msgBody)) { | ||||
|  |                     return okMsg; | ||||
|  |                 } | ||||
|  |             } | ||||
|  |         } catch (error) { | ||||
|  |             this.throwGeneralAxiosError(error); | ||||
|  |         } | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     async sendSms(notification, msgbody) { | ||||
|  |         let params = { | ||||
|  |             PhoneNumbers: notification.phonenumber, | ||||
|  |             TemplateCode: notification.templateCode, | ||||
|  |             SignName: notification.signName, | ||||
|  |             TemplateParam: msgbody, | ||||
|  |             AccessKeyId: notification.accessKeyId, | ||||
|  |             Format: "JSON", | ||||
|  |             SignatureMethod: "HMAC-SHA1", | ||||
|  |             SignatureVersion: "1.0", | ||||
|  |             SignatureNonce: Math.random().toString(), | ||||
|  |             Timestamp: new Date().toISOString(), | ||||
|  |             Action: "SendSms", | ||||
|  |             Version: "2017-05-25", | ||||
|  |         }; | ||||
|  | 
 | ||||
|  |         params.Signature = this.sign(params, notification.secretAccessKey); | ||||
|  |         let config = { | ||||
|  |             method: "POST", | ||||
|  |             url: "http://dysmsapi.aliyuncs.com/", | ||||
|  |             headers: { | ||||
|  |                 "Content-Type": "application/x-www-form-urlencoded", | ||||
|  |             }, | ||||
|  |             data: qs.stringify(params), | ||||
|  |         }; | ||||
|  | 
 | ||||
|  |         let result = await axios(config); | ||||
|  |         if (result.data.Message == "OK") { | ||||
|  |             return true; | ||||
|  |         } | ||||
|  |         return false; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     /** Aliyun request sign */ | ||||
|  |     sign(param, AccessKeySecret) { | ||||
|  |         let param2 = {}; | ||||
|  |         let data = []; | ||||
|  | 
 | ||||
|  |         let oa = Object.keys(param).sort(); | ||||
|  | 
 | ||||
|  |         for (let i = 0; i < oa.length; i++) { | ||||
|  |             let key = oa[i]; | ||||
|  |             param2[key] = param[key]; | ||||
|  |         } | ||||
|  | 
 | ||||
|  |         for (let key in param2) { | ||||
|  |             data.push(`${encodeURIComponent(key)}=${encodeURIComponent(param2[key])}`); | ||||
|  |         } | ||||
|  | 
 | ||||
|  |         let StringToSign = `POST&${encodeURIComponent("/")}&${encodeURIComponent(data.join("&"))}`; | ||||
|  |         return Crypto | ||||
|  |             .createHmac("sha1", `${AccessKeySecret}&`) | ||||
|  |             .update(Buffer.from(StringToSign)) | ||||
|  |             .digest("base64"); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     statusToString(status) { | ||||
|  |         switch (status) { | ||||
|  |             case DOWN: | ||||
|  |                 return "DOWN"; | ||||
|  |             case UP: | ||||
|  |                 return "UP"; | ||||
|  |             default: | ||||
|  |                 return status; | ||||
|  |         } | ||||
|  |     } | ||||
|  | } | ||||
|  | 
 | ||||
|  | module.exports = AliyunSMS; | ||||
| @ -0,0 +1,79 @@ | |||||
|  | const NotificationProvider = require("./notification-provider"); | ||||
|  | const { DOWN, UP } = require("../../src/util"); | ||||
|  | const { default: axios } = require("axios"); | ||||
|  | const Crypto = require("crypto"); | ||||
|  | 
 | ||||
|  | class DingDing extends NotificationProvider { | ||||
|  |     name = "DingDing"; | ||||
|  | 
 | ||||
|  |     async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { | ||||
|  |         let okMsg = "Sent Successfully."; | ||||
|  | 
 | ||||
|  |         try { | ||||
|  |             if (heartbeatJSON != null) { | ||||
|  |                 let params = { | ||||
|  |                     msgtype: "markdown", | ||||
|  |                     markdown: { | ||||
|  |                         title: monitorJSON["name"], | ||||
|  |                         text: `## [${this.statusToString(heartbeatJSON["status"])}] \n > ${heartbeatJSON["msg"]}  \n > Time(UTC):${heartbeatJSON["time"]}`, | ||||
|  |                     } | ||||
|  |                 }; | ||||
|  |                 if (this.sendToDingDing(notification, params)) { | ||||
|  |                     return okMsg; | ||||
|  |                 } | ||||
|  |             } else { | ||||
|  |                 let params = { | ||||
|  |                     msgtype: "text", | ||||
|  |                     text: { | ||||
|  |                         content: msg | ||||
|  |                     } | ||||
|  |                 }; | ||||
|  |                 if (this.sendToDingDing(notification, params)) { | ||||
|  |                     return okMsg; | ||||
|  |                 } | ||||
|  |             } | ||||
|  |         } catch (error) { | ||||
|  |             this.throwGeneralAxiosError(error); | ||||
|  |         } | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     async sendToDingDing(notification, params) { | ||||
|  |         let timestamp = Date.now(); | ||||
|  | 
 | ||||
|  |         let config = { | ||||
|  |             method: "POST", | ||||
|  |             headers: { | ||||
|  |                 "Content-Type": "application/json", | ||||
|  |             }, | ||||
|  |             url: `${notification.webHookUrl}×tamp=${timestamp}&sign=${encodeURIComponent(this.sign(timestamp, notification.secretKey))}`, | ||||
|  |             data: JSON.stringify(params), | ||||
|  |         }; | ||||
|  | 
 | ||||
|  |         let result = await axios(config); | ||||
|  |         if (result.data.errmsg == "ok") { | ||||
|  |             return true; | ||||
|  |         } | ||||
|  |         return false; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     /** DingDing sign */ | ||||
|  |     sign(timestamp, secretKey) { | ||||
|  |         return Crypto | ||||
|  |             .createHmac("sha256", Buffer.from(secretKey, "utf8")) | ||||
|  |             .update(Buffer.from(`${timestamp}\n${secretKey}`, "utf8")) | ||||
|  |             .digest("base64"); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     statusToString(status) { | ||||
|  |         switch (status) { | ||||
|  |             case DOWN: | ||||
|  |                 return "DOWN"; | ||||
|  |             case UP: | ||||
|  |                 return "UP"; | ||||
|  |             default: | ||||
|  |                 return status; | ||||
|  |         } | ||||
|  |     } | ||||
|  | } | ||||
|  | 
 | ||||
|  | module.exports = DingDing; | ||||
| @ -0,0 +1,83 @@ | |||||
|  | const NotificationProvider = require("./notification-provider"); | ||||
|  | const axios = require("axios"); | ||||
|  | const { DOWN, UP } = require("../../src/util"); | ||||
|  | 
 | ||||
|  | class Feishu extends NotificationProvider { | ||||
|  |     name = "Feishu"; | ||||
|  | 
 | ||||
|  |     async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { | ||||
|  |         let okMsg = "Sent Successfully."; | ||||
|  |         let feishuWebHookUrl = notification.feishuWebHookUrl; | ||||
|  | 
 | ||||
|  |         try { | ||||
|  |             if (heartbeatJSON == null) { | ||||
|  |                 let testdata = { | ||||
|  |                     msg_type: "text", | ||||
|  |                     content: { | ||||
|  |                         text: msg, | ||||
|  |                     }, | ||||
|  |                 }; | ||||
|  |                 await axios.post(feishuWebHookUrl, testdata); | ||||
|  |                 return okMsg; | ||||
|  |             } | ||||
|  | 
 | ||||
|  |             if (heartbeatJSON["status"] == DOWN) { | ||||
|  |                 let downdata = { | ||||
|  |                     msg_type: "post", | ||||
|  |                     content: { | ||||
|  |                         post: { | ||||
|  |                             zh_cn: { | ||||
|  |                                 title: "UptimeKuma Alert: " + monitorJSON["name"], | ||||
|  |                                 content: [ | ||||
|  |                                     [ | ||||
|  |                                         { | ||||
|  |                                             tag: "text", | ||||
|  |                                             text: | ||||
|  |                                                 "[Down] " + | ||||
|  |                                                 heartbeatJSON["msg"] + | ||||
|  |                                                 "\nTime (UTC): " + | ||||
|  |                                                 heartbeatJSON["time"], | ||||
|  |                                         }, | ||||
|  |                                     ], | ||||
|  |                                 ], | ||||
|  |                             }, | ||||
|  |                         }, | ||||
|  |                     }, | ||||
|  |                 }; | ||||
|  |                 await axios.post(feishuWebHookUrl, downdata); | ||||
|  |                 return okMsg; | ||||
|  |             } | ||||
|  | 
 | ||||
|  |             if (heartbeatJSON["status"] == UP) { | ||||
|  |                 let updata = { | ||||
|  |                     msg_type: "post", | ||||
|  |                     content: { | ||||
|  |                         post: { | ||||
|  |                             zh_cn: { | ||||
|  |                                 title: "UptimeKuma Alert: " + monitorJSON["name"], | ||||
|  |                                 content: [ | ||||
|  |                                     [ | ||||
|  |                                         { | ||||
|  |                                             tag: "text", | ||||
|  |                                             text: | ||||
|  |                                                 "[Up] " + | ||||
|  |                                                 heartbeatJSON["msg"] + | ||||
|  |                                                 "\nTime (UTC): " + | ||||
|  |                                                 heartbeatJSON["time"], | ||||
|  |                                         }, | ||||
|  |                                     ], | ||||
|  |                                 ], | ||||
|  |                             }, | ||||
|  |                         }, | ||||
|  |                     }, | ||||
|  |                 }; | ||||
|  |                 await axios.post(feishuWebHookUrl, updata); | ||||
|  |                 return okMsg; | ||||
|  |             } | ||||
|  |         } catch (error) { | ||||
|  |             this.throwGeneralAxiosError(error); | ||||
|  |         } | ||||
|  |     } | ||||
|  | } | ||||
|  | 
 | ||||
|  | module.exports = Feishu; | ||||
| @ -0,0 +1,25 @@ | |||||
|  | <template> | ||||
|  |     <div class="mb-3"> | ||||
|  |         <label for="accessKeyId" class="form-label">{{ $t("AccessKeyId") }}<span style="color: red;"><sup>*</sup></span></label> | ||||
|  |         <input id="accessKeyId" v-model="$parent.notification.accessKeyId" type="text" class="form-control" required> | ||||
|  | 
 | ||||
|  |         <label for="secretAccessKey" class="form-label">{{ $t("SecretAccessKey") }}<span style="color: red;"><sup>*</sup></span></label> | ||||
|  |         <input id="secretAccessKey" v-model="$parent.notification.secretAccessKey" type="text" class="form-control" required> | ||||
|  | 
 | ||||
|  |         <label for="phonenumber" class="form-label">{{ $t("Phonenumber") }}<span style="color: red;"><sup>*</sup></span></label> | ||||
|  |         <input id="phonenumber" v-model="$parent.notification.phonenumber" type="text" class="form-control" required> | ||||
|  | 
 | ||||
|  |         <label for="templateCode" class="form-label">{{ $t("TemplateCode") }}<span style="color: red;"><sup>*</sup></span></label> | ||||
|  |         <input id="templateCode" v-model="$parent.notification.templateCode" type="text" class="form-control" required> | ||||
|  | 
 | ||||
|  |         <label for="signName" class="form-label">{{ $t("SignName") }}<span style="color: red;"><sup>*</sup></span></label> | ||||
|  |         <input id="signName" v-model="$parent.notification.signName" type="text" class="form-control" required> | ||||
|  | 
 | ||||
|  |         <div class="form-text"> | ||||
|  |             <p>Sms template must contain parameters: <br> <code>${name} ${time} ${status} ${msg}</code></p> | ||||
|  |             <i18n-t tag="p" keypath="Read more:"> | ||||
|  |                 <a href="https://help.aliyun.com/document_detail/101414.html" target="_blank">https://help.aliyun.com/document_detail/101414.html</a> | ||||
|  |             </i18n-t> | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  | </template> | ||||
| @ -0,0 +1,16 @@ | |||||
|  | <template> | ||||
|  |     <div class="mb-3"> | ||||
|  |         <label for="WebHookUrl" class="form-label">{{ $t("WebHookUrl") }}<span style="color: red;"><sup>*</sup></span></label> | ||||
|  |         <input id="WebHookUrl" v-model="$parent.notification.webHookUrl" type="text" class="form-control" required> | ||||
|  | 
 | ||||
|  |         <label for="secretKey" class="form-label">{{ $t("SecretKey") }}<span style="color: red;"><sup>*</sup></span></label> | ||||
|  |         <input id="secretKey" v-model="$parent.notification.secretKey" type="text" class="form-control" required> | ||||
|  | 
 | ||||
|  |         <div class="form-text"> | ||||
|  |             <p>For safety, must use secret key</p> | ||||
|  |             <i18n-t tag="p" keypath="Read more:"> | ||||
|  |                 <a href="https://developers.dingtalk.com/document/robots/custom-robot-access" target="_blank">https://developers.dingtalk.com/document/robots/custom-robot-access</a> | ||||
|  |             </i18n-t> | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  | </template> | ||||
| @ -0,0 +1,15 @@ | |||||
|  | <template> | ||||
|  |     <div class="mb-3"> | ||||
|  |         <label for="Feishu-WebHookUrl" class="form-label">{{ $t("Feishu WebHookUrl") }}<span style="color: red;"><sup>*</sup></span></label> | ||||
|  |         <input id="Feishu-WebHookUrl" v-model="$parent.notification.feishuWebHookUrl" type="text" class="form-control" required> | ||||
|  |         <div class="form-text"> | ||||
|  |             <p><span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}</p> | ||||
|  |         </div> | ||||
|  |         <i18n-t tag="div" keypath="wayToGetTeamsURL" class="form-text"> | ||||
|  |             <a | ||||
|  |                 href="https://www.feishu.cn/hc/zh-CN/articles/360024984973" | ||||
|  |                 target="_blank" | ||||
|  |             >{{ $t("here") }}</a> | ||||
|  |         </i18n-t> | ||||
|  |     </div> | ||||
|  | </template> | ||||
| @ -0,0 +1,285 @@ | |||||
|  | export default { | ||||
|  |     languageName: "Indonesia", | ||||
|  |     checkEverySecond: "Cek Setiap {0} detik.", | ||||
|  |     retryCheckEverySecond: "Coba lagi setiap {0} detik.", | ||||
|  |     retriesDescription: "Percobaan ulang maksimum sebelum layanan dinyatakan tidak aktif dan notifikasi dikirim", | ||||
|  |     ignoreTLSError: "Abaikan kesalahan TLS/SSL untuk situs web HTTPS", | ||||
|  |     upsideDownModeDescription: "Balikkan statusnya. Jika layanan dapat dijangkau, TIDAK AKTIF.", | ||||
|  |     maxRedirectDescription: "Jumlah maksimum pengalihan untuk diikuti. Setel ke 0 untuk menonaktifkan pengalihan.", | ||||
|  |     acceptedStatusCodesDescription: "Pilih kode status yang dianggap sebagai respons yang berhasil.", | ||||
|  |     passwordNotMatchMsg: "Sandi kedua tidak cocok.", | ||||
|  |     notificationDescription: "Harap atur notifikasi ke monitor agar berfungsi.", | ||||
|  |     keywordDescription: "Cari kata kunci dalam code html atau JSON huruf besar-kecil berpengaruh", | ||||
|  |     pauseDashboardHome: "Jeda", | ||||
|  |     deleteMonitorMsg: "Apakah anda mau menghapus monitor ini?", | ||||
|  |     deleteNotificationMsg: "Apakah anda mau menghapus notifikasi ini untuk semua monitor?", | ||||
|  |     resoverserverDescription: "Cloudflare adalah server default, Anda dapat mengubah server resolver kapan saja.", | ||||
|  |     rrtypeDescription: "Pilih RR-Type yang mau anda monitor", | ||||
|  |     pauseMonitorMsg: "Apakah anda yakin mau menjeda?", | ||||
|  |     enableDefaultNotificationDescription: "Untuk setiap monitor baru, notifikasi ini akan diaktifkan secara default. Anda masih dapat menonaktifkan notifikasi secara terpisah untuk setiap monitor.", | ||||
|  |     clearEventsMsg: "Apakah anda yakin mau menghapus semua event di monitor ini?", | ||||
|  |     clearHeartbeatsMsg: "Apakah anda yakin mau menghapus semua heartbeats di monitor ini?", | ||||
|  |     confirmClearStatisticsMsg: "Apakah anda yakin mau menghapus semua statistik?", | ||||
|  |     importHandleDescription: "Pilih 'Lewati yang ada' jika Anda ingin melewati setiap monitor atau notifikasi dengan nama yang sama. 'Timpa' akan menghapus setiap monitor dan notifikasi yang ada.", | ||||
|  |     confirmImportMsg: "Apakah Anda yakin untuk mengimpor cadangan? Pastikan Anda telah memilih opsi impor yang tepat.", | ||||
|  |     twoFAVerifyLabel: "Silakan ketik token Anda untuk memverifikasi bahwa 2FA berfungsi", | ||||
|  |     tokenValidSettingsMsg: "Tokennya valid! Anda sekarang dapat menyimpan pengaturan 2FA.", | ||||
|  |     confirmEnableTwoFAMsg: "Apakah Anda yakin ingin mengaktifkan 2FA?", | ||||
|  |     confirmDisableTwoFAMsg: "Apakah Anda yakin ingin menonaktifkan 2FA?", | ||||
|  |     Settings: "Pengaturan", | ||||
|  |     Dashboard: "Dashboard", | ||||
|  |     "New Update": "Update Baru", | ||||
|  |     Language: "Bahasa", | ||||
|  |     Appearance: "Tampilan", | ||||
|  |     Theme: "Tema", | ||||
|  |     General: "General", | ||||
|  |     Version: "Versi", | ||||
|  |     "Check Update On GitHub": "Cek Update di GitHub", | ||||
|  |     List: "List", | ||||
|  |     Add: "Tambah", | ||||
|  |     "Add New Monitor": "Tambah Monitor Baru", | ||||
|  |     "Quick Stats": "Statistik Cepat", | ||||
|  |     Up: "Aktif", | ||||
|  |     Down: "Tidak Aktif", | ||||
|  |     Pending: "Tertunda", | ||||
|  |     Unknown: "Tidak diketahui", | ||||
|  |     Pause: "Jeda", | ||||
|  |     Name: "Nama", | ||||
|  |     Status: "Status", | ||||
|  |     DateTime: "Tanggal Waktu", | ||||
|  |     Message: "Pesan", | ||||
|  |     "No important events": "Tidak ada Event penting", | ||||
|  |     Resume: "Melanjutkan", | ||||
|  |     Edit: "Rubah", | ||||
|  |     Delete: "Hapus", | ||||
|  |     Current: "Saat ini", | ||||
|  |     Uptime: "Waktu aktif", | ||||
|  |     "Cert Exp.": "Cert Exp.", | ||||
|  |     days: "hari-hari", | ||||
|  |     day: "hari", | ||||
|  |     "-day": "-hari", | ||||
|  |     hour: "Jam", | ||||
|  |     "-hour": "-Jam", | ||||
|  |     Response: "Respon", | ||||
|  |     Ping: "Ping", | ||||
|  |     "Monitor Type": "Tipe Monitor", | ||||
|  |     Keyword: "Keyword", | ||||
|  |     "Friendly Name": "Friendly Name", | ||||
|  |     URL: "URL", | ||||
|  |     Hostname: "Hostname", | ||||
|  |     Port: "Port", | ||||
|  |     "Heartbeat Interval": "Interval Heartbeat ", | ||||
|  |     Retries: "Retries", | ||||
|  |     "Heartbeat Retry Interval": "Interval Heartbeat Mencoba kembali ", | ||||
|  |     Advanced: "Advanced", | ||||
|  |     "Upside Down Mode": "Mode Terbalik", | ||||
|  |     "Max. Redirects": "Maksimal Redirect/Pengalihan", | ||||
|  |     "Accepted Status Codes": "Kode Status yang Diterima", | ||||
|  |     Save: "Simpan", | ||||
|  |     Notifications: "Notifikasi", | ||||
|  |     "Not available, please setup.": "Tidak tersedia, silakan atur.", | ||||
|  |     "Setup Notification": "Setel Notifikasi", | ||||
|  |     Light: "Terang", | ||||
|  |     Dark: "Gelap", | ||||
|  |     Auto: "Automatis", | ||||
|  |     "Theme - Heartbeat Bar": "Theme - Heartbeat Bar", | ||||
|  |     Normal: "Normal", | ||||
|  |     Bottom: "Bawah", | ||||
|  |     None: "Tidak ada", | ||||
|  |     Timezone: "Zona Waktu", | ||||
|  |     "Search Engine Visibility": "Visibilitas Mesin Pencari", | ||||
|  |     "Allow indexing": "Mengizinkan untuk diindex", | ||||
|  |     "Discourage search engines from indexing site": "Mencegah mesin pencari untuk mengindex site", | ||||
|  |     "Change Password": "Ganti Sandi", | ||||
|  |     "Current Password": "Sandi Lama", | ||||
|  |     "New Password": "Sandi Baru", | ||||
|  |     "Repeat New Password": "Ulangi Sandi Baru", | ||||
|  |     "Update Password": "Perbarui Kata Sandi", | ||||
|  |     "Disable Auth": "Nonaktifkan auth", | ||||
|  |     "Enable Auth": "Aktifkan Auth", | ||||
|  |     Logout: "Keluar", | ||||
|  |     Leave: "Pergi", | ||||
|  |     "I understand, please disable": "Saya mengerti, silahkan dinonaktifkan", | ||||
|  |     Confirm: "Konfirmasi", | ||||
|  |     Yes: "Ya", | ||||
|  |     No: "Tidak", | ||||
|  |     Username: "Nama Pengguna", | ||||
|  |     Password: "Sandi", | ||||
|  |     "Remember me": "Ingat saya", | ||||
|  |     Login: "Masuk", | ||||
|  |     "No Monitors, please": "Tidak ada monitor, silahkan", | ||||
|  |     "add one": "tambah baru", | ||||
|  |     "Notification Type": "Tipe Notifikasi", | ||||
|  |     Email: "Email", | ||||
|  |     Test: "Test", | ||||
|  |     "Certificate Info": "Info Sertifikasi ", | ||||
|  |     "Resolver Server": "Resolver Server", | ||||
|  |     "Resource Record Type": "Resource Record Type", | ||||
|  |     "Last Result": "Hasil Terakhir", | ||||
|  |     "Create your admin account": "Buat admin akun anda", | ||||
|  |     "Repeat Password": "Ulangi Sandi", | ||||
|  |     "Import Backup": "Impor Backup", | ||||
|  |     "Export Backup": "Expor Backup", | ||||
|  |     Export: "Expor", | ||||
|  |     Import: "Impor", | ||||
|  |     respTime: "Tanggapan. Waktu (milidetik)", | ||||
|  |     notAvailableShort: "N/A", | ||||
|  |     "Default enabled": "Default diaktifkan", | ||||
|  |     "Apply on all existing monitors": "Terapkan pada semua monitor yang ada", | ||||
|  |     Create: "Buat", | ||||
|  |     "Clear Data": "Bersihkan Data", | ||||
|  |     Events: "Event", | ||||
|  |     Heartbeats: "Heartbeats", | ||||
|  |     "Auto Get": "Auto Get", | ||||
|  |     backupDescription: "Anda dapat mencadangkan semua monitor dan semua notifikasi ke dalam file JSON.", | ||||
|  |     backupDescription2: "Catatan: Data sejarah dan event tidak disertakan.", | ||||
|  |     backupDescription3: "Data sensitif seperti notifikasi token disertakan dalam file ekspor, harap simpan dengan hati-hati.", | ||||
|  |     alertNoFile: "Silakan pilih file untuk diimpor.", | ||||
|  |     alertWrongFileType: "Silakan pilih file JSON .", | ||||
|  |     "Clear all statistics": "Hapus semua statistik", | ||||
|  |     "Skip existing": "Lewati yang ada", | ||||
|  |     Overwrite: "Timpa", | ||||
|  |     Options: "Opsi", | ||||
|  |     "Keep both": "Simpan keduanya", | ||||
|  |     "Verify Token": "Verifikasi Token", | ||||
|  |     "Setup 2FA": "Pengaturan 2FA", | ||||
|  |     "Enable 2FA": "Aktifkan 2FA", | ||||
|  |     "Disable 2FA": "Nonaktifkan 2FA", | ||||
|  |     "2FA Settings": "Settings 2FA", | ||||
|  |     "Two Factor Authentication": "Otentikasi Dua Faktor", | ||||
|  |     Active: "Aktif", | ||||
|  |     Inactive: "Tidak Aktif", | ||||
|  |     Token: "Token", | ||||
|  |     "Show URI": "Lihat URI", | ||||
|  |     Tags: "Tag", | ||||
|  |     "Add New below or Select...": "Tambahkan Baru di bawah atau Pilih...", | ||||
|  |     "Tag with this name already exist.": "Tag dengan nama ini sudah ada.", | ||||
|  |     "Tag with this value already exist.": "Tag dengan nilai ini sudah ada.", | ||||
|  |     color: "warna", | ||||
|  |     "value (optional)": "nilai (harus diisi)", | ||||
|  |     Gray: "Abu Abu", | ||||
|  |     Red: "Merah", | ||||
|  |     Orange: "Oranye", | ||||
|  |     Green: "Hijau", | ||||
|  |     Blue: "Biru", | ||||
|  |     Indigo: "Indigo", | ||||
|  |     Purple: "Ungu", | ||||
|  |     Pink: "Merah Muda", | ||||
|  |     "Search...": "Cari...", | ||||
|  |     "Avg. Ping": "Rata-rata. Ping", | ||||
|  |     "Avg. Response": "Rata-rata. Respon", | ||||
|  |     "Entry Page": "Halaman Masuk", | ||||
|  |     statusPageNothing: "Tidak ada di sini, silakan tambahkan grup atau monitor.", | ||||
|  |     "No Services": "Tidak ada Layanan", | ||||
|  |     "All Systems Operational": "Semua Sistem Berfungsi", | ||||
|  |     "Partially Degraded Service": "Layanan Terdegradasi Sebagian", | ||||
|  |     "Degraded Service": "Layanan Terdegradasi", | ||||
|  |     "Add Group": "Tambah Grup", | ||||
|  |     "Add a monitor": "Tambah monitor", | ||||
|  |     "Edit Status Page": "Edit Halaman Status", | ||||
|  |     "Go to Dashboard": "Lihat Dashboard", | ||||
|  |     "Status Page": "Halaman Status", | ||||
|  |     // Start notification form
 | ||||
|  |     defaultNotificationName: "{notification} saya Peringatan ({number})", | ||||
|  |     here: "di sini", | ||||
|  |     "Required": "Dibutuhkan", | ||||
|  |     "telegram": "Telegram", | ||||
|  |     "Bot Token": "Bot Token", | ||||
|  |     "You can get a token from": "Anda bisa mendapatkan token dari", | ||||
|  |     "Chat ID": "Chat ID", | ||||
|  |     supportTelegramChatID: "Mendukung Obrolan Langsung / Grup / Channel Chat ID", | ||||
|  |     wayToGetTelegramChatID: "Anda bisa mendapatkan chat id Anda dengan mengirim pesan ke bot dan pergi ke url ini untuk melihat chat_id:", | ||||
|  |     "YOUR BOT TOKEN HERE": "BOT TOKEN ANDA DI SINI", | ||||
|  |     chatIDNotFound: "Chat ID tidak ditemukan, tolong kirim pesan ke bot ini dulu", | ||||
|  |     "webhook": "Webhook", | ||||
|  |     "Post URL": "Post URL", | ||||
|  |     "Content Type": "Tipe konten", | ||||
|  |     webhookJsonDesc: "{0}   bagus untuk server http modern seperti express.js", | ||||
|  |     webhookFormDataDesc: "{multipart} bagus untuk PHP, Anda hanya perlu mengurai json dengan {decodeFunction}", | ||||
|  |     "smtp": "Email (SMTP)", | ||||
|  |     secureOptionNone: "None / STARTTLS (25, 587)", | ||||
|  |     secureOptionTLS: "TLS (465)", | ||||
|  |     "Ignore TLS Error": "Ignore TLS Error", | ||||
|  |     "From Email": "From Email", | ||||
|  |     "To Email": "To Email", | ||||
|  |     smtpCC: "CC", | ||||
|  |     smtpBCC: "BCC", | ||||
|  |     "discord": "Discord", | ||||
|  |     "Discord Webhook URL": "Discord Webhook URL", | ||||
|  |     wayToGetDiscordURL: "Anda bisa mendapatkan ini dengan pergi ke Server Settings -> Integrations -> Create Webhook", | ||||
|  |     "Bot Display Name": "Nama Bot", | ||||
|  |     "Prefix Custom Message": "Prefix Pesan", | ||||
|  |     "Hello @everyone is...": "Hallo {'@'}everyone is...", | ||||
|  |     "teams": "Microsoft Teams", | ||||
|  |     "Webhook URL": "Webhook URL", | ||||
|  |     wayToGetTeamsURL: "Anda dapat mempelajari cara membuat url webhook {0}.", | ||||
|  |     "signal": "Sinyal", | ||||
|  |     "Number": "Nomer", | ||||
|  |     "Recipients": "Penerima", | ||||
|  |     needSignalAPI: "Anda harus memiliki klien sinyal dengan REST API.", | ||||
|  |     wayToCheckSignalURL: "Anda dapat memeriksa url ini untuk melihat cara menyiapkannya:", | ||||
|  |     signalImportant: "PENTING: Anda tidak dapat mencampur grup dan nomor di penerima!", | ||||
|  |     "gotify": "Gotify", | ||||
|  |     "Application Token": "Token Aplikasi", | ||||
|  |     "Server URL": "Server URL", | ||||
|  |     "Priority": "Prioritas", | ||||
|  |     "slack": "Slack", | ||||
|  |     "Icon Emoji": "Icon Emoji", | ||||
|  |     "Channel Name": "Nama Channel", | ||||
|  |     "Uptime Kuma URL": "Uptime Kuma URL", | ||||
|  |     aboutWebhooks: "Info lain tentang webhook: {0}", | ||||
|  |     aboutChannelName: "Masukan nama channel di {0} Kolom Nama Channel jika Anda ingin melewati channel webhook. Contoh: #other-channel", | ||||
|  |     aboutKumaURL: "Jika Anda membiarkan bidang URL Uptime Kuma kosong, itu akan menjadi default ke halaman Project Github.", | ||||
|  |     emojiCheatSheet: "Emoji cheat sheet: {0}", | ||||
|  |     "rocket.chat": "Rocket.chat", | ||||
|  |     pushover: "Pushover", | ||||
|  |     pushy: "Pushy", | ||||
|  |     octopush: "Octopush", | ||||
|  |     promosms: "PromoSMS", | ||||
|  |     lunasea: "LunaSea", | ||||
|  |     apprise: "Apprise (Mendukung 50+ layanan notifikasi)", | ||||
|  |     pushbullet: "Pushbullet", | ||||
|  |     line: "Line Messenger", | ||||
|  |     mattermost: "Mattermost", | ||||
|  |     "User Key": "Kunci pengguna", | ||||
|  |     "Device": "Perangkat", | ||||
|  |     "Message Title": "Judul Pesan", | ||||
|  |     "Notification Sound": "Suara Nofifikasi", | ||||
|  |     "More info on:": "Info lebih lanjut tentang: {0}", | ||||
|  |     pushoverDesc1: "Prioritas darurat (2) memiliki batas waktu default 30 detik antara percobaan ulang dan akan kadaluwarsa setelah 1 jam.", | ||||
|  |     pushoverDesc2: "Jika Anda ingin mengirim pemberitahuan ke perangkat yang berbeda, isi kolom Perangkat.", | ||||
|  |     "SMS Type": "Tipe SMS", | ||||
|  |     octopushTypePremium: "Premium (Cepat - direkomendasikan untuk mengingatkan)", | ||||
|  |     octopushTypeLowCost: "Low Cost (Lambat, terkadang diblokir oleh operator)", | ||||
|  |     "Check octopush prices": "Cek harga octopush {0}.", | ||||
|  |     octopushPhoneNumber: "Nomer Telpon/HP (format internasional, contoh : +33612345678) ", | ||||
|  |     octopushSMSSender: "Nama Pengirim SMS : 3-11 karakter alfanumerik dan spasi (a-zA-Z0-9)", | ||||
|  |     "LunaSea Device ID": "LunaSea Device ID", | ||||
|  |     "Apprise URL": "Apprise URL", | ||||
|  |     "Example:": "Contoh: {0}", | ||||
|  |     "Read more:": "Baca lebih lajut: {0}", | ||||
|  |     "Status:": "Status: {0}", | ||||
|  |     "Read more": "Baca lebih lajut", | ||||
|  |     appriseInstalled: "Apprise diinstall.", | ||||
|  |     appriseNotInstalled: "Apprise tidak diinstall. {0}", | ||||
|  |     "Access Token": "Access Token", | ||||
|  |     "Channel access token": "Channel access token", | ||||
|  |     "Line Developers Console": "Line Developers Console", | ||||
|  |     lineDevConsoleTo: "Line Developers Console - {0}", | ||||
|  |     "Basic Settings": "Pengaturan dasar", | ||||
|  |     "User ID": "User ID", | ||||
|  |     "Messaging API": "Messaging API", | ||||
|  |     wayToGetLineChannelToken: "Pertama akses {0}, buat penyedia dan saluran (Messaging API), lalu Anda bisa mendapatkan token akses saluran dan id pengguna dari item menu yang disebutkan di atas.", | ||||
|  |     "Icon URL": "Icon URL", | ||||
|  |     aboutIconURL: "Anda dapat memberikan tautan ke gambar di \"Icon URL\" untuk mengganti gambar profil default. Tidak akan digunakan jika Ikon Emoji diset.", | ||||
|  |     aboutMattermostChannelName: "Anda dapat mengganti channel default tujuan posting webhook dengan memasukkan nama channel ke dalam Kolom \"Channel Name\". Ini perlu diaktifkan di pengaturan webhook Mattermost. contoh: #other-channel", | ||||
|  |     "matrix": "Matrix", | ||||
|  |     promosmsTypeEco: "SMS ECO - murah tapi lambat dan sering kelebihan beban. Terbatas hanya untuk penerima Polandia.", | ||||
|  |     promosmsTypeFlash: "SMS FLASH - Pesan akan otomatis muncul di perangkat penerima. Terbatas hanya untuk penerima Polandia.", | ||||
|  |     promosmsTypeFull: "SMS FULL - SMS tingkat premium, Anda dapat menggunakan Nama Pengirim Anda (Anda harus mendaftarkan nama terlebih dahulu). Dapat diandalkan untuk peringatan.", | ||||
|  |     promosmsTypeSpeed: "SMS SPEED - Prioritas tertinggi dalam sistem. Sangat cepat dan dapat diandalkan tetapi mahal (sekitar dua kali lipat dari harga SMS FULL).", | ||||
|  |     promosmsPhoneNumber: "Nomor telepon (untuk penerima Polandia Anda dapat melewati kode area)", | ||||
|  |     promosmsSMSSender: "Nama Pengirim SMS : Nama pra-registrasi atau salah satu default: InfoSMS, Info SMS, MaxSMS, INFO, SMS", | ||||
|  |     "Feishu WebHookUrl": "Feishu WebHookUrl", | ||||
|  |     // End notification form
 | ||||
|  | }; | ||||
| @ -0,0 +1,284 @@ | |||||
|  | export default { | ||||
|  |     languageName: "Norsk", | ||||
|  |     checkEverySecond: "Sjekk hvert {0} sekund.", | ||||
|  |     retryCheckEverySecond: "Prøv igjen hvert {0} sekund.", | ||||
|  |     retriesDescription: "Maksimalt antall forsøk før tjenesten er merket som nede og et varsel sendes", | ||||
|  |     ignoreTLSError: "Ignorer TLS/SSL-feil for HTTPS-nettsteder", | ||||
|  |     upsideDownModeDescription: "Snu statusen opp ned. Hvis tjenesten er tilgjengelig, er den NED.", | ||||
|  |     maxRedirectDescription: "Maksimalt antall viderekoblinger å følge. Sett til 0 for å deaktivere viderekoblinger.", | ||||
|  |     acceptedStatusCodesDescription: "Velg statuskoder som anses som et vellykket svar.", | ||||
|  |     passwordNotMatchMsg: "Passordene stemmer ikke overens.", | ||||
|  |     notificationDescription: "Tilordne et varsel for å overvåkningen for å få det til å fungere.", | ||||
|  |     keywordDescription: "Søk etter nøkkelord i vanlig HTML eller JSON, og det er versalfølsom", | ||||
|  |     pauseDashboardHome: "Pause", | ||||
|  |     deleteMonitorMsg: "Er du sikker på at du vil slette denne overvåkningen?", | ||||
|  |     deleteNotificationMsg: "Er du sikker på at du vil slette dette varselet for alle overvåkningene?", | ||||
|  |     resoverserverDescription: "Cloudflare er standardserveren, kan du når som helst endre DNS-serveren.", | ||||
|  |     rrtypeDescription: "Velg RR-typen du vil overvåke", | ||||
|  |     pauseMonitorMsg: "Er du sikker på at du vil sette en pause?", | ||||
|  |     enableDefaultNotificationDescription: "For hver ny overvåkning vil denne varslingen være aktivert som standard. Du kan fortsatt deaktivere varselet separat for hver overvåkning.", | ||||
|  |     clearEventsMsg: "Er du sikker på at du vil slette alle hendelser for denne overvåkningen?", | ||||
|  |     clearHeartbeatsMsg: "Er du sikker på at du vil slette alle hjerteslag for denne overvåkningen?", | ||||
|  |     confirmClearStatisticsMsg: "Er du sikker på at du vil slette ALL statistikk?", | ||||
|  |     importHandleDescription: "Velg 'Hopp over eksisterende' hvis du vil hoppe over hver overvåkning eller varsel med samme navn. 'Overskriv' sletter alle eksisterende overvåkninger og varsler.", | ||||
|  |     confirmImportMsg: "Er du sikker på å importere sikkerhetskopien? Sørg for at du har valgt riktig importalternativ.", | ||||
|  |     twoFAVerifyLabel: "Skriv inn tokenet ditt for å bekrefte at 2FA fungerer", | ||||
|  |     tokenValidSettingsMsg: "Token er gyldig! Du kan nå lagre 2FA-innstillingene.", | ||||
|  |     confirmEnableTwoFAMsg: "Er du sikker på at du vil aktivere 2FA?", | ||||
|  |     confirmDisableTwoFAMsg: "Er du sikker på at du vil deaktivere 2FA?", | ||||
|  |     Settings: "Innstillinger", | ||||
|  |     Dashboard: "Dashboard", | ||||
|  |     "New Update": "Ny Oppdatering", | ||||
|  |     Language: "Språk", | ||||
|  |     Appearance: "Utseende", | ||||
|  |     Theme: "Tema", | ||||
|  |     General: "Generelt", | ||||
|  |     Version: "Versjon", | ||||
|  |     "Check Update On GitHub": "Sjekk oppdatering på GitHub", | ||||
|  |     List: "Liste", | ||||
|  |     Add: "Legg til", | ||||
|  |     "Add New Monitor": "Legg til ny overvåkning", | ||||
|  |     "Quick Stats": "Statistikk", | ||||
|  |     Up: "Oppe", | ||||
|  |     Down: "Nede", | ||||
|  |     Pending: "Avventer", | ||||
|  |     Unknown: "Ukjent", | ||||
|  |     Pause: "Pause", | ||||
|  |     Name: "Navn", | ||||
|  |     Status: "Status", | ||||
|  |     DateTime: "Dato tid", | ||||
|  |     Message: "Melding", | ||||
|  |     "No important events": "Ingen viktige hendelser", | ||||
|  |     Resume: "Fortsett", | ||||
|  |     Edit: "Endre", | ||||
|  |     Delete: "Slett", | ||||
|  |     Current: "Nåværende", | ||||
|  |     Uptime: "Oppetid", | ||||
|  |     "Cert Exp.": "Sertifikat utløper", | ||||
|  |     days: "dager", | ||||
|  |     day: "dag", | ||||
|  |     "-day": "-dag", | ||||
|  |     hour: "time", | ||||
|  |     "-hour": "-time", | ||||
|  |     Response: "Respons", | ||||
|  |     Ping: "Ping", | ||||
|  |     "Monitor Type": "Overvåkningstype", | ||||
|  |     Keyword: "Stikkord", | ||||
|  |     "Friendly Name": "Vennlig navn", | ||||
|  |     URL: "URL", | ||||
|  |     Hostname: "Vertsnavn", | ||||
|  |     Port: "Port", | ||||
|  |     "Heartbeat Interval": "Hjerteslagsintervall", | ||||
|  |     Retries: "Forsøk", | ||||
|  |     "Heartbeat Retry Interval": "Hjerteslagsforsøkintervall", | ||||
|  |     Advanced: "Avansert", | ||||
|  |     "Upside Down Mode": "Opp-ned-modus", | ||||
|  |     "Max. Redirects": "Maks. viderekoblinger", | ||||
|  |     "Accepted Status Codes": "Godkjente statuskoder", | ||||
|  |     Save: "Lagre", | ||||
|  |     Notifications: "Varsler", | ||||
|  |     "Not available, please setup.": "Ikke tilgjengelig, sett opp.", | ||||
|  |     "Setup Notification": "Sett opp varsel", | ||||
|  |     Light: "Lys", | ||||
|  |     Dark: "Mørk", | ||||
|  |     Auto: "Auto", | ||||
|  |     "Theme - Heartbeat Bar": "Theme - Heartbeat Bar", | ||||
|  |     Normal: "Normal", | ||||
|  |     Bottom: "Bunn", | ||||
|  |     None: "Ingen", | ||||
|  |     Timezone: "Tidssone", | ||||
|  |     "Search Engine Visibility": "Søkemotor synlighet", | ||||
|  |     "Allow indexing": "Tillat indeksering", | ||||
|  |     "Discourage search engines from indexing site": "Avskrekk søkemotorer fra å indeksere nettstedet", | ||||
|  |     "Change Password": "Endre passord", | ||||
|  |     "Current Password": "Nåværende passord", | ||||
|  |     "New Password": "Nytt passord", | ||||
|  |     "Repeat New Password": "Gjenta nytt passord", | ||||
|  |     "Update Password": "Oppdater passord", | ||||
|  |     "Disable Auth": "Deaktiver autentisering", | ||||
|  |     "Enable Auth": "Aktiver autentisering", | ||||
|  |     Logout: "Logg ut", | ||||
|  |     Leave: "Forlat", | ||||
|  |     "I understand, please disable": "Jeg forstår, deaktiver", | ||||
|  |     Confirm: "Bekreft", | ||||
|  |     Yes: "Ja", | ||||
|  |     No: "Nei", | ||||
|  |     Username: "Brukernavn", | ||||
|  |     Password: "Passord", | ||||
|  |     "Remember me": "Husk meg", | ||||
|  |     Login: "Logg inn", | ||||
|  |     "No Monitors, please": "Ingen overvåkning, vær så snill", | ||||
|  |     "add one": "legg til en", | ||||
|  |     "Notification Type": "Meldingstype", | ||||
|  |     Email: "E-post", | ||||
|  |     Test: "Test", | ||||
|  |     "Certificate Info": "Sertifikatinformasjon", | ||||
|  |     "Resolver Server": "DNS-server", | ||||
|  |     "Resource Record Type": "DNS-posttype", | ||||
|  |     "Last Result": "Siste resultat", | ||||
|  |     "Create your admin account": "Opprett en administratorkonto", | ||||
|  |     "Repeat Password": "Gjenta passord", | ||||
|  |     "Import Backup": "Importer sikkerhetskopi", | ||||
|  |     "Export Backup": "Eksporter sikkerhetskopi", | ||||
|  |     Export: "Eksporter", | ||||
|  |     Import: "Importer", | ||||
|  |     respTime: "Svartid (ms)", | ||||
|  |     notAvailableShort: "N/A", | ||||
|  |     "Default enabled": "Standard aktivert", | ||||
|  |     "Apply on all existing monitors": "Påfør på alle eksisterende overvåkninger", | ||||
|  |     Create: "Opprett", | ||||
|  |     "Clear Data": "Slett data", | ||||
|  |     Events: "Hendelser", | ||||
|  |     Heartbeats: "Hjerteslag", | ||||
|  |     "Auto Get": "Auto Get", | ||||
|  |     backupDescription: "Du kan sikkerhetskopiere alle overvåkninger og alle varsler til en JSON-fil.", | ||||
|  |     backupDescription2: "PS: Historikk og hendelsesdata er ikke inkludert.", | ||||
|  |     backupDescription3: "Følsomme data som varslingstokener er inkludert i eksportfilen. Vennligst oppbevar dem nøye.", | ||||
|  |     alertNoFile: "Velg en fil som skal importeres.", | ||||
|  |     alertWrongFileType: "Velg en JSON-fil.", | ||||
|  |     "Clear all statistics": "Fjern all statistikk", | ||||
|  |     "Skip existing": "Hopp over eksisterende", | ||||
|  |     Overwrite: "Overskriv", | ||||
|  |     Options: "Alternativer", | ||||
|  |     "Keep both": "Behold begge", | ||||
|  |     "Verify Token": "Bekreft token", | ||||
|  |     "Setup 2FA": "Konfigurer 2FA", | ||||
|  |     "Enable 2FA": "Aktiver 2FA", | ||||
|  |     "Disable 2FA": "Deaktiver 2FA", | ||||
|  |     "2FA Settings": "2FA Innstillinger", | ||||
|  |     "Two Factor Authentication": "To-faktor autentisering", | ||||
|  |     Active: "Aktiv", | ||||
|  |     Inactive: "Inaktiv", | ||||
|  |     Token: "Token", | ||||
|  |     "Show URI": "Vis URI", | ||||
|  |     Tags: "Etiketter", | ||||
|  |     "Add New below or Select...": "Legg til nytt nedenfor eller Velg ...", | ||||
|  |     "Tag with this name already exist.": "Etikett med dette navnet eksisterer allerede.", | ||||
|  |     "Tag with this value already exist.": "Etikett med denne verdien finnes allerede.", | ||||
|  |     color: "farge", | ||||
|  |     "value (optional)": "verdi (valgfritt)", | ||||
|  |     Gray: "Grå", | ||||
|  |     Red: "Rød", | ||||
|  |     Orange: "Oransje", | ||||
|  |     Green: "Grønn", | ||||
|  |     Blue: "Blå", | ||||
|  |     Indigo: "Indigo", | ||||
|  |     Purple: "Lilla", | ||||
|  |     Pink: "Rosa", | ||||
|  |     "Search...": "Søk...", | ||||
|  |     "Avg. Ping": "Gj.sn. Ping", | ||||
|  |     "Avg. Response": "Gj.sn. Respons", | ||||
|  |     "Entry Page": "Oppføringsside", | ||||
|  |     statusPageNothing: "Ingenting her, vennligst legg til en gruppe eller en overvåkning.", | ||||
|  |     "No Services": "Ingen tjenester", | ||||
|  |     "All Systems Operational": "Alle systemer i drift", | ||||
|  |     "Partially Degraded Service": "Delvis degradert drift", | ||||
|  |     "Degraded Service": "Degradert drift", | ||||
|  |     "Add Group": "Legg til gruppe", | ||||
|  |     "Add a monitor": "Legg til en overvåkning", | ||||
|  |     "Edit Status Page": "Rediger statusside", | ||||
|  |     "Go to Dashboard": "Gå til Dashboard", | ||||
|  |     "Status Page": "Statusside", | ||||
|  |     // Start notification form
 | ||||
|  |     defaultNotificationName: "Min {notification} varsling ({number})", | ||||
|  |     here: "here", | ||||
|  |     "Required": "Obligatorisk", | ||||
|  |     "telegram": "Telegram", | ||||
|  |     "Bot Token": "Bot Token", | ||||
|  |     "You can get a token from": "Du kan få et token fra", | ||||
|  |     "Chat ID": "Chat ID", | ||||
|  |     supportTelegramChatID: "Support Direct Chat / Group / Channel's Chat ID", | ||||
|  |     wayToGetTelegramChatID: "Du kan få chat-ID-en din ved å sende meldingen til boten og gå til denne nettadressen for å se chat_id:", | ||||
|  |     "YOUR BOT TOKEN HERE": "DITT BOT TOKEN HER", | ||||
|  |     chatIDNotFound: "Chat-ID ble ikke funnet. Send en melding til denne boten først", | ||||
|  |     "webhook": "Webhook", | ||||
|  |     "Post URL": "Post URL", | ||||
|  |     "Content Type": "Content Type", | ||||
|  |     webhookJsonDesc: "{0} er bra for alle moderne HTTP-servere som express.js", | ||||
|  |     webhookFormDataDesc: "{multipart} er bra for PHP, du trenger bare å analysere JSON etter {decodeFunction}", | ||||
|  |     "smtp": "E-post (SMTP)", | ||||
|  |     secureOptionNone: "None / STARTTLS (25, 587)", | ||||
|  |     secureOptionTLS: "TLS (465)", | ||||
|  |     "Ignore TLS Error": "Ignorer TLS feilmelding", | ||||
|  |     "From Email": "Fra E-post", | ||||
|  |     "To Email": "Til E-post", | ||||
|  |     smtpCC: "CC", | ||||
|  |     smtpBCC: "BCC", | ||||
|  |     "discord": "Discord", | ||||
|  |     "Discord Webhook URL": "Discord Webhook URL", | ||||
|  |     wayToGetDiscordURL: "Du kan få dette ved å gå til Serverinnstillinger -> Integrasjoner -> Webhooks -> Ny webhook", | ||||
|  |     "Bot Display Name": "Bot Visningsnavn", | ||||
|  |     "Prefix Custom Message": "Prefiks tilpasset melding", | ||||
|  |     "Hello @everyone is...": "Hei {'@'}everyone det er...", | ||||
|  |     "teams": "Microsoft Teams", | ||||
|  |     "Webhook URL": "Webhook URL", | ||||
|  |     wayToGetTeamsURL: "Du kan lære hvordan du oppretter en webhook-URL {0}.", | ||||
|  |     "signal": "Signal", | ||||
|  |     "Number": "Nummer", | ||||
|  |     "Recipients": "Mottakere", | ||||
|  |     needSignalAPI: "Du må ha en Signal-klient med REST API.", | ||||
|  |     wayToCheckSignalURL: "Du kan sjekke denne nettadressen for å se hvordan du konfigurerer en:", | ||||
|  |     signalImportant: "VIKTIG: Du kan ikke blande grupper og nummere i mottakere!", | ||||
|  |     "gotify": "Gotify", | ||||
|  |     "Application Token": "Application Token", | ||||
|  |     "Server URL": "Server URL", | ||||
|  |     "Priority": "Prioritet", | ||||
|  |     "slack": "Slack", | ||||
|  |     "Icon Emoji": "Icon Emoji", | ||||
|  |     "Channel Name": "Kanal navn", | ||||
|  |     "Uptime Kuma URL": "Uptime Kuma URL", | ||||
|  |     aboutWebhooks: "Mer informasjon om webhooks på: {0}", | ||||
|  |     aboutChannelName: "Skriv inn kanalnavnet på {0} Kanalnavn-feltet hvis du vil omgå webhook-kanalen. Eks: #other-channel", | ||||
|  |     aboutKumaURL: "Hvis du lar Uptime Kuma URL feltet være blank, den blir som standard til Github-siden for dette prosjektet.", | ||||
|  |     emojiCheatSheet: "Emoji cheat sheet: {0}", | ||||
|  |     "rocket.chat": "Rocket.chat", | ||||
|  |     pushover: "Pushover", | ||||
|  |     pushy: "Pushy", | ||||
|  |     octopush: "Octopush", | ||||
|  |     promosms: "PromoSMS", | ||||
|  |     lunasea: "LunaSea", | ||||
|  |     apprise: "Apprise (Support 50+ Notification services)", | ||||
|  |     pushbullet: "Pushbullet", | ||||
|  |     line: "Line Messenger", | ||||
|  |     mattermost: "Mattermost", | ||||
|  |     "User Key": "User Key", | ||||
|  |     "Device": "Device", | ||||
|  |     "Message Title": "Message Title", | ||||
|  |     "Notification Sound": "Notification Sound", | ||||
|  |     "More info on:": "More info on: {0}", | ||||
|  |     pushoverDesc1: "Emergency priority (2) has default 30 second timeout between retries and will expire after 1 hour.", | ||||
|  |     pushoverDesc2: "If you want to send notifications to different devices, fill out Device field.", | ||||
|  |     "SMS Type": "SMS Type", | ||||
|  |     octopushTypePremium: "Premium (Fast - recommended for alerting)", | ||||
|  |     octopushTypeLowCost: "Low Cost (Slow, sometimes blocked by operator)", | ||||
|  |     "Check octopush prices": "Check octopush prices {0}.", | ||||
|  |     octopushPhoneNumber: "Phone number (intl format, eg : +33612345678) ", | ||||
|  |     octopushSMSSender: "SMS Sender Name : 3-11 alphanumeric characters and space (a-zA-Z0-9)", | ||||
|  |     "LunaSea Device ID": "LunaSea Device ID", | ||||
|  |     "Apprise URL": "Apprise URL", | ||||
|  |     "Example:": "Example: {0}", | ||||
|  |     "Read more:": "Read more: {0}", | ||||
|  |     "Status:": "Status: {0}", | ||||
|  |     "Read more": "Read more", | ||||
|  |     appriseInstalled: "Apprise is installed.", | ||||
|  |     appriseNotInstalled: "Apprise is not installed. {0}", | ||||
|  |     "Access Token": "Access Token", | ||||
|  |     "Channel access token": "Channel access token", | ||||
|  |     "Line Developers Console": "Line Developers Console", | ||||
|  |     lineDevConsoleTo: "Line Developers Console - {0}", | ||||
|  |     "Basic Settings": "Basic Settings", | ||||
|  |     "User ID": "User ID", | ||||
|  |     "Messaging API": "Messaging API", | ||||
|  |     wayToGetLineChannelToken: "First access the {0}, create a provider and channel (Messaging API), then you can get the channel access token and user id from the above mentioned menu items.", | ||||
|  |     "Icon URL": "Icon URL", | ||||
|  |     aboutIconURL: "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.", | ||||
|  |     aboutMattermostChannelName: "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", | ||||
|  |     "matrix": "Matrix", | ||||
|  |     promosmsTypeEco: "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.", | ||||
|  |     promosmsTypeFlash: "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.", | ||||
|  |     promosmsTypeFull: "SMS FULL - Premium tier of SMS, You can use Your Sender Name (You need to register name first). Reliable for alerts.", | ||||
|  |     promosmsTypeSpeed: "SMS SPEED - Highest priority in system. Very quick and reliable but costly (about twice of SMS FULL price).", | ||||
|  |     promosmsPhoneNumber: "Phone number (for Polish recipient You can skip area codes)", | ||||
|  |     promosmsSMSSender: "SMS Sender Name : Pre-registred name or one of defaults: InfoSMS, SMS Info, MaxSMS, INFO, SMS", | ||||
|  |     // End notification form
 | ||||
|  | }; | ||||
| @ -0,0 +1,37 @@ | |||||
|  | const { genSecret } = require("../src/util"); | ||||
|  | 
 | ||||
|  | beforeAll(() => { | ||||
|  | 
 | ||||
|  | }); | ||||
|  | 
 | ||||
|  | describe("Test genSecret", () => { | ||||
|  | 
 | ||||
|  |     it("should be correct length", () => { | ||||
|  |         let secret = genSecret(-1); | ||||
|  |         expect(secret).toEqual(""); | ||||
|  | 
 | ||||
|  |         secret = genSecret(0); | ||||
|  |         expect(secret).toEqual(""); | ||||
|  | 
 | ||||
|  |         secret = genSecret(1); | ||||
|  |         expect(secret.length).toEqual(1); | ||||
|  | 
 | ||||
|  |         secret = genSecret(2); | ||||
|  |         expect(secret.length).toEqual(2); | ||||
|  | 
 | ||||
|  |         secret = genSecret(64); | ||||
|  |         expect(secret.length).toEqual(64); | ||||
|  | 
 | ||||
|  |         secret = genSecret(9000); | ||||
|  |         expect(secret.length).toEqual(9000); | ||||
|  | 
 | ||||
|  |         secret = genSecret(90000); | ||||
|  |         expect(secret.length).toEqual(90000); | ||||
|  |     }); | ||||
|  | 
 | ||||
|  |     it("should contain first and last possible chars", () => { | ||||
|  |         let secret = genSecret(90000); | ||||
|  |         expect(secret).toContain("A"); | ||||
|  |         expect(secret).toContain("9"); | ||||
|  |     }); | ||||
|  | }); | ||||
					Loading…
					
					
				
		Reference in new issue