diff --git a/db/knex_migrations/2024-04-26-0000-snmp-monitor.js b/db/knex_migrations/2024-04-26-0000-snmp-monitor.js new file mode 100644 index 00000000..24752f2d --- /dev/null +++ b/db/knex_migrations/2024-04-26-0000-snmp-monitor.js @@ -0,0 +1,16 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("monitor", function (table) { + table.string("snmp_oid").defaultTo(null); + table.enum("snmp_version", [ "1", "2c", "3" ]).defaultTo("2c"); + table.string("json_path_operator").defaultTo(null); + }); +}; + +exports.down = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.dropColumn("snmp_oid"); + table.dropColumn("snmp_version"); + table.dropColumn("json_path_operator"); + }); +}; diff --git a/package-lock.json b/package-lock.json index 918c3dd0..c805df6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,7 @@ "mssql": "~11.0.0", "mysql2": "~3.9.6", "nanoid": "~3.3.4", + "net-snmp": "^3.11.2", "node-cloudflared-tunnel": "~1.0.9", "node-radius-client": "~1.0.0", "nodemailer": "~6.9.13", @@ -5525,6 +5526,11 @@ "safer-buffer": "~2.1.0" } }, + "node_modules/asn1-ber": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/asn1-ber/-/asn1-ber-1.2.2.tgz", + "integrity": "sha512-CbNem/7hxrjSiOAOOTX4iZxu+0m3jiLqlsERQwwPM1IDR/22M8IPpA1VVndCLw5KtjRYyRODbvAEIfuTogNDng==" + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -11285,6 +11291,31 @@ "node": ">= 0.6" } }, + "node_modules/net-snmp": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/net-snmp/-/net-snmp-3.11.2.tgz", + "integrity": "sha512-QKy2JQHIBsSK344dUxYRZv7tU0ANk8f8fzKD/Mmq/cCxm/cPbtiT7009QEgxdViW/gGjqGIOiLHxkCc+JhZltg==", + "dependencies": { + "asn1-ber": "^1.2.1", + "smart-buffer": "^4.1.0" + } + }, + "node_modules/node-abi": { + "version": "3.62.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.62.0.tgz", + "integrity": "sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + }, "node_modules/node-cloudflared-tunnel": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/node-cloudflared-tunnel/-/node-cloudflared-tunnel-1.0.10.tgz", diff --git a/package.json b/package.json index 31a89a7c..b750f331 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "mssql": "~11.0.0", "mysql2": "~3.9.6", "nanoid": "~3.3.4", + "net-snmp": "^3.11.2", "node-cloudflared-tunnel": "~1.0.9", "node-radius-client": "~1.0.0", "nodemailer": "~6.9.13", diff --git a/server/model/monitor.js b/server/model/monitor.js index 1b11c614..a5c290c3 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -2,7 +2,7 @@ const dayjs = require("dayjs"); const axios = require("axios"); const { Prometheus } = require("../prometheus"); const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, - SQL_DATETIME_FORMAT + SQL_DATETIME_FORMAT, evaluateJsonQuery } = require("../../src/util"); const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery, redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal @@ -17,7 +17,6 @@ const apicache = require("../modules/apicache"); const { UptimeKumaServer } = require("../uptime-kuma-server"); const { DockerHost } = require("../docker"); const Gamedig = require("gamedig"); -const jsonata = require("jsonata"); const jwt = require("jsonwebtoken"); const crypto = require("crypto"); const { UptimeCalculator } = require("../uptime-calculator"); @@ -161,6 +160,9 @@ class Monitor extends BeanModel { kafkaProducerMessage: this.kafkaProducerMessage, screenshot, remote_browser: this.remote_browser, + snmpOid: this.snmpOid, + jsonPathOperator: this.jsonPathOperator, + snmpVersion: this.snmpVersion, }; if (includeSensitiveData) { @@ -598,25 +600,15 @@ class Monitor extends BeanModel { } else if (this.type === "json-query") { let data = res.data; - // convert data to object - if (typeof data === "string" && res.headers["content-type"] !== "application/json") { - try { - data = JSON.parse(data); - } catch (_) { - // Failed to parse as JSON, just process it as a string - } - } + const { status, response } = await evaluateJsonQuery(data, this.jsonPath, this.jsonPathOperator, this.expectedValue); - let expression = jsonata(this.jsonPath); - - let result = await expression.evaluate(data); - - if (result.toString() === this.expectedValue) { - bean.msg += ", expected value is found"; + if (status) { bean.status = UP; + bean.msg = `JSON query passes (comparing ${response} ${this.jsonPathOperator} ${this.expectedValue})`; } else { - throw new Error(bean.msg + ", but value is not equal to expected value, value was: [" + result + "]"); + throw new Error(`JSON query does not pass (comparing ${response} ${this.jsonPathOperator} ${this.expectedValue})`); } + } } else if (this.type === "port") { diff --git a/server/monitor-types/snmp.js b/server/monitor-types/snmp.js new file mode 100644 index 00000000..a1760fa3 --- /dev/null +++ b/server/monitor-types/snmp.js @@ -0,0 +1,63 @@ +const { MonitorType } = require("./monitor-type"); +const { UP, log, evaluateJsonQuery } = require("../../src/util"); +const snmp = require("net-snmp"); + +class SNMPMonitorType extends MonitorType { + name = "snmp"; + + /** + * @inheritdoc + */ + async check(monitor, heartbeat, _server) { + let session; + try { + const sessionOptions = { + port: monitor.port || "161", + retries: monitor.maxretries, + timeout: monitor.timeout * 1000, + version: snmp.Version[monitor.snmpVersion], + }; + session = snmp.createSession(monitor.hostname, monitor.radiusPassword, sessionOptions); + + // Handle errors during session creation + session.on("error", (error) => { + throw new Error(`Error creating SNMP session: ${error.message}`); + }); + + const varbinds = await new Promise((resolve, reject) => { + session.get([ monitor.snmpOid ], (error, varbinds) => { + error ? reject(error) : resolve(varbinds); + }); + }); + log.debug("monitor", `SNMP: Received varbinds (Type: ${snmp.ObjectType[varbinds[0].type]} Value: ${varbinds[0].value})`); + + if (varbinds.length === 0) { + throw new Error(`No varbinds returned from SNMP session (OID: ${monitor.snmpOid})`); + } + + if (varbinds[0].type === snmp.ObjectType.NoSuchInstance) { + throw new Error(`The SNMP query returned that no instance exists for OID ${monitor.snmpOid}`); + } + + // We restrict querying to one OID per monitor, therefore `varbinds[0]` will always contain the value we're interested in. + const value = varbinds[0].value; + + const { status, response } = await evaluateJsonQuery(value, monitor.jsonPath, monitor.jsonPathOperator, monitor.expectedValue); + + if (status) { + heartbeat.status = UP; + heartbeat.msg = `JSON query passes (comparing ${response} ${monitor.jsonPathOperator} ${monitor.expectedValue})`; + } else { + throw new Error(`JSON query does not pass (comparing ${response} ${monitor.jsonPathOperator} ${monitor.expectedValue})`); + } + } finally { + if (session) { + session.close(); + } + } + } +} + +module.exports = { + SNMPMonitorType, +}; diff --git a/server/server.js b/server/server.js index 38158c54..d0af4038 100644 --- a/server/server.js +++ b/server/server.js @@ -831,6 +831,10 @@ let needSetup = false; monitor.kafkaProducerAllowAutoTopicCreation; bean.gamedigGivenPortOnly = monitor.gamedigGivenPortOnly; bean.remote_browser = monitor.remote_browser; + bean.snmpVersion = monitor.snmpVersion; + bean.snmpOid = monitor.snmpOid; + bean.jsonPathOperator = monitor.jsonPathOperator; + bean.timeout = monitor.timeout; bean.validate(); diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index 6ab5f6c2..573d791a 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -113,6 +113,7 @@ class UptimeKumaServer { UptimeKumaServer.monitorTypeList["tailscale-ping"] = new TailscalePing(); UptimeKumaServer.monitorTypeList["dns"] = new DnsMonitorType(); UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType(); + UptimeKumaServer.monitorTypeList["snmp"] = new SNMPMonitorType(); UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType(); // Allow all CORS origins (polling) in development @@ -517,4 +518,5 @@ const { RealBrowserMonitorType } = require("./monitor-types/real-browser-monitor const { TailscalePing } = require("./monitor-types/tailscale-ping"); const { DnsMonitorType } = require("./monitor-types/dns"); const { MqttMonitorType } = require("./monitor-types/mqtt"); +const { SNMPMonitorType } = require("./monitor-types/snmp"); const { MongodbMonitorType } = require("./monitor-types/mongodb"); diff --git a/src/lang/bg-BG.json b/src/lang/bg-BG.json index 0eed93e3..25d24c24 100644 --- a/src/lang/bg-BG.json +++ b/src/lang/bg-BG.json @@ -802,7 +802,6 @@ "twilioApiKey": "API ключ (по избор)", "Expected Value": "Очаквана стойност", "Json Query": "Заявка тип JSON", - "jsonQueryDescription": "Прави JSON заявка срещу отговора и проверява за очаквана стойност (Върнатата стойност ще бъде преобразувана в низ за сравнение). Разгледайте {0} за документация относно езика на заявката. Имате възможност да тествате {1}.", "Badge Duration (in hours)": "Времетраене на баджа (в часове)", "Badge Preview": "Преглед на баджа", "Notify Channel": "Канал за известяване", diff --git a/src/lang/cs-CZ.json b/src/lang/cs-CZ.json index 6e8a8ba0..4936cdea 100644 --- a/src/lang/cs-CZ.json +++ b/src/lang/cs-CZ.json @@ -823,7 +823,6 @@ "Enable Kafka Producer Auto Topic Creation": "Povolit Kafka zprostředkovateli automatické vytváření vláken", "Kafka Producer Message": "Zpráva Kafka zprostředkovatele", "tailscalePingWarning": "Abyste mohli používat Tailscale Ping monitor, je nutné Uptime Kuma nainstalovat mimo Docker, a dále na váš server nainstalovat Tailscale klienta.", - "jsonQueryDescription": "Proveďte JSON dotaz vůči odpovědi a zkontrolujte očekávaný výstup (za účelem porovnání bude návratová hodnota převedena na řetězec). Dokumentaci k dotazovacímu jazyku naleznete na {0}, a využít můžete též {1}.", "Select": "Vybrat", "selectedMonitorCount": "Vybráno: {0}", "Check/Uncheck": "Vybrat/Zrušit výběr", diff --git a/src/lang/de-CH.json b/src/lang/de-CH.json index f334e3ff..ac1b5116 100644 --- a/src/lang/de-CH.json +++ b/src/lang/de-CH.json @@ -812,7 +812,6 @@ "Json Query": "Json-Abfrage", "filterActive": "Aktiv", "filterActivePaused": "Pausiert", - "jsonQueryDescription": "Führe eine JSON-Abfrage gegen die Antwort durch und prüfe den erwarteten Wert (der Rückgabewert wird zum Vergleich in eine Zeichenkette umgewandelt). Auf {0} findest du die Dokumentation zur Abfragesprache. {1} kannst du Abfragen üben.", "Badge Duration (in hours)": "Abzeichen Dauer (in Stunden)", "Badge Preview": "Abzeichen Vorschau", "tailscalePingWarning": "Um den Tailscale Ping Monitor nutzen zu können, musst du Uptime Kuma ohne Docker installieren und den Tailscale Client auf dem Server installieren.", diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 551a3925..303055d8 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -817,7 +817,6 @@ "filterActivePaused": "Pausiert", "Expected Value": "Erwarteter Wert", "Json Query": "Json-Abfrage", - "jsonQueryDescription": "Führe eine JSON-Abfrage gegen die Antwort durch und prüfe den erwarteten Wert (der Rückgabewert wird zum Vergleich in eine Zeichenkette umgewandelt). Auf {0} findest du die Dokumentation zur Abfragesprache. {1} kannst du Abfragen üben.", "tailscalePingWarning": "Um den Tailscale Ping Monitor nutzen zu können, musst du Uptime Kuma ohne Docker installieren und den Tailscale Client auf dem Server installieren.", "Server URL should not contain the nfty topic": "Die Server-URL sollte das nfty-Thema nicht enthalten", "pushDeerServerDescription": "Leer lassen um den offiziellen Server zu verwenden", diff --git a/src/lang/en.json b/src/lang/en.json index 649b3d51..7cb663b6 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -59,7 +59,7 @@ "Keyword": "Keyword", "Invert Keyword": "Invert Keyword", "Expected Value": "Expected Value", - "Json Query": "Json Query", + "Json Query Expression": "Json Query Expression", "Friendly Name": "Friendly Name", "URL": "URL", "Hostname": "Hostname", @@ -588,7 +588,7 @@ "notificationDescription": "Notifications must be assigned to a monitor to function.", "keywordDescription": "Search keyword in plain HTML or JSON response. The search is case-sensitive.", "invertKeywordDescription": "Look for the keyword to be absent rather than present.", - "jsonQueryDescription": "Do a json Query against the response and check for expected value (Return value will get converted into string for comparison). Check out {0} for the documentation about the query language. A playground can be found {1}.", + "jsonQueryDescription": "Parse and extract specific data from the server's JSON response using JSON query or use \"$\" for the raw response, if not expecting JSON. The result is then compared to the expected value, as strings. See {0} for documentation and use {1} to experiment with queries.", "backupDescription": "You can backup all monitors and notifications into a JSON file.", "backupDescription2": "Note: history and event data is not included.", "backupDescription3": "Sensitive data such as notification tokens are included in the export file; please store export securely.", @@ -943,6 +943,13 @@ "cellsyntSplitLongMessages": "Split long messages into up to 6 parts. 153 x 6 = 918 characters.", "max 15 digits": "max 15 digits", "max 11 alphanumeric characters": "max 11 alphanumeric characters", + "Community String": "Community String", + "snmpCommunityStringHelptext": "This string functions as a password to authenticate and control access to SNMP-enabled devices. Match it with your SNMP device's configuration.", + "OID (Object Identifier)": "OID (Object Identifier)", + "snmpOIDHelptext": "Enter the OID for the sensor or status you want to monitor. Use network management tools like MIB browsers or SNMP software if you're unsure about the OID.", + "Condition": "Condition", + "SNMP Version": "SNMP Version", + "Please enter a valid OID.": "Please enter a valid OID.", "wayToGetThreemaGateway": "You can register for Threema Gateway {0}.", "threemaRecipient": "Recipient", "threemaRecipientType": "Recipient Type", diff --git a/src/lang/es-ES.json b/src/lang/es-ES.json index 8dfe04c3..3151ef95 100644 --- a/src/lang/es-ES.json +++ b/src/lang/es-ES.json @@ -771,7 +771,6 @@ "Json Query": "Consulta Json", "invertKeywordDescription": "Comprobar si la palabra clave está ausente en vez de presente.", "enableNSCD": "Habilitar NSCD (Demonio de Caché de Servicio de Nombres) para almacenar en caché todas las solicitudes DNS", - "jsonQueryDescription": "Realiza una consulta JSON contra la respuesta y verifica el valor esperado (el valor de retorno se convertirá a una cadena para la comparación). Consulta {0} para obtener documentación sobre el lenguaje de consulta. Puede encontrar un espacio de prueba {1}.", "Request Timeout": "Tiempo de espera máximo de petición", "timeoutAfter": "Expirar después de {0} segundos", "chromeExecutableDescription": "Para usuarios de Docker, si Chromium no está instalado, puede que tarde unos minutos en ser instalado y mostrar el resultado de la prueba. Usa 1GB de espacio.", diff --git a/src/lang/fa.json b/src/lang/fa.json index 83110e8f..9a32c0be 100644 --- a/src/lang/fa.json +++ b/src/lang/fa.json @@ -759,7 +759,6 @@ "filterActive": "فعال", "webhookCustomBodyDesc": "یک بدنه HTTP سفارشی برای ریکوئست تعریف کنید. متغیر های قابل استفاده: {msg}, {heartbeat}, {monitor}.", "tailscalePingWarning": "برای استفاده از Tailscale Ping monitor، شما باید آپتایم کوما را بدون استفاده از داکر و همچنین Tailscale client را نیز بر روی سرور خود نصب داشته باشید.", - "jsonQueryDescription": "یک کوئری json در برابر پاسخ انجام دهید و مقدار مورد انتظار را (مقدار برگشتی برای مقایسه به رشته تبدیل می شود). برای مستندات درباره زبان کوئری، {0} مشاهده کنید. همچنین محیط تست را میتوانید در {1} پیدا کنید.", "Enter the list of brokers": "لیست بروکر هارا وارد کنید", "Enable Kafka Producer Auto Topic Creation": "فعال سازی ایجاپ موضوع اتوماتیک تهیه کننده", "Secret AccessKey": "کلید محرمانه AccessKey", diff --git a/src/lang/fi.json b/src/lang/fi.json index 61fa86bb..628bfa1b 100644 --- a/src/lang/fi.json +++ b/src/lang/fi.json @@ -792,7 +792,6 @@ "emailTemplateLimitedToUpDownNotification": "saatavilla vain YLÖS/ALAS sydämensykkeille, muulloin null", "Your User ID": "Käyttäjätunnuksesi", "invertKeywordDescription": "Etsi puuttuvaa avainsanaa.", - "jsonQueryDescription": "Suorita JSON-kysely vastaukselle ja tarkista odotettu arvo (Paluuarvo muutetaan merkkijonoksi vertailua varten). Katso kyselykielen ohjeita osoitteesta {0}. Leikkikenttä löytyy osoitteesta {1}.", "Bark API Version": "Bark API-versio", "Notify Channel": "Ilmoitus kanavalle", "aboutNotifyChannel": "Ilmoitus kanavalle antaa työpöytä- tai mobiili-ilmoituksen kaikille kanavan jäsenille; riippumatta ovatko he paikalla vai poissa.", diff --git a/src/lang/fr-FR.json b/src/lang/fr-FR.json index ac7b0922..5838a3cd 100644 --- a/src/lang/fr-FR.json +++ b/src/lang/fr-FR.json @@ -797,7 +797,6 @@ "twilioApiKey": "Clé API (facultatif)", "Expected Value": "Valeur attendue", "Json Query": "Requête Json", - "jsonQueryDescription": "Faites une requête json contre la réponse et vérifiez la valeur attendue (la valeur de retour sera convertie en chaîne pour comparaison). Consultez {0} pour la documentation sur le langage de requête. Une aire de jeux peut être trouvée {1}.", "Badge Duration (in hours)": "Durée du badge (en heures)", "Badge Preview": "Aperçu du badge", "aboutNotifyChannel": "Notifier le canal déclenchera une notification de bureau ou mobile pour tous les membres du canal, que leur disponibilité soit active ou absente.", diff --git a/src/lang/ga.json b/src/lang/ga.json index a367f908..f5287b38 100644 --- a/src/lang/ga.json +++ b/src/lang/ga.json @@ -682,7 +682,6 @@ "confirmDisableTwoFAMsg": "An bhfuil tú cinnte gur mhaith leat 2FA a dhíchumasú?", "affectedStatusPages": "Taispeáin an teachtaireacht cothabhála seo ar leathanaigh stádais roghnaithe", "keywordDescription": "Cuardaigh eochairfhocal i ngnáthfhreagra HTML nó JSON. Tá an cuardach cás-íogair.", - "jsonQueryDescription": "Déan Iarratas json in aghaidh an fhreagra agus seiceáil an luach a bhfuiltear ag súil leis (Déanfar an luach fillte a thiontú ina theaghrán le haghaidh comparáide). Seiceáil {0} le haghaidh na gcáipéisí faoin teanga iarratais. Is féidir clós súgartha a aimsiú {1}.", "backupDescription": "Is féidir leat gach monatóir agus fógra a chúltaca isteach i gcomhad JSON.", "backupDescription2": "Nóta: níl sonraí staire agus imeachta san áireamh.", "octopushAPIKey": "\"Eochair API\" ó dhintiúir API HTTP sa phainéal rialaithe", diff --git a/src/lang/hr-HR.json b/src/lang/hr-HR.json index 5bf12867..a0246bd1 100644 --- a/src/lang/hr-HR.json +++ b/src/lang/hr-HR.json @@ -799,7 +799,6 @@ "affectedStatusPages": "Prikazuje poruku o održavanju na odabranim statusnim stranicama", "atLeastOneMonitor": "Odaberite barem jedan zahvaćeni Monitor", "invertKeywordDescription": "Postavi da ključna riječ mora biti odsutna umjesto prisutna.", - "jsonQueryDescription": "Izvršite JSON upit nad primljenim odgovorom i provjerite očekivanu povrtanu vrijednost. Ona će se za usporedbu pretvoriti u niz znakova (string). Pogledajte stranicu {0} za dokumentaciju o jeziku upita. Testno okruženje možete pronaći {1}.", "Strategy": "Strategija", "Free Mobile User Identifier": "Besplatni mobilni korisnički identifikator", "Free Mobile API Key": "Besplatni mobilni ključ za API", diff --git a/src/lang/hu.json b/src/lang/hu.json index 89c42ebc..4945dd2e 100644 --- a/src/lang/hu.json +++ b/src/lang/hu.json @@ -797,7 +797,6 @@ "emailTemplateHeartbeatJSON": "a szívverést leíró objektum", "emailTemplateMsg": "az értesítés üzenete", "emailTemplateLimitedToUpDownNotification": "csak FEL/LE szívverés esetén érhető el, egyébként null érték", - "jsonQueryDescription": "Végezzen JSON-lekérdezést a válasz alapján, és ellenőrizze a várt értéket (a visszatérési értéket a rendszer karakterlánccá alakítja az összehasonlításhoz). Nézze meg a {0} webhelyet a lekérdezés paramétereivel kapcsolatos dokumentációért. A test környezet itt található: {1}.", "pushoverMessageTtl": "TTL üzenet (másodperc)", "Platform": "Platform", "aboutNotifyChannel": "A Csatorna értesítése opció, értesítést fog küldeni a csatorna összes tagjának, függetlenül a tagok elérhetőségétől.", diff --git a/src/lang/id-ID.json b/src/lang/id-ID.json index ebd4f862..edaeffa9 100644 --- a/src/lang/id-ID.json +++ b/src/lang/id-ID.json @@ -838,7 +838,6 @@ "emailTemplateHeartbeatJSON": "objek yang menggambarkan heartbeat", "emailTemplateMsg": "pesan pemberitahuan", "emailCustomBody": "Kustomisasi Body", - "jsonQueryDescription": "Lakukan Query json terhadap respons dan periksa nilai yang diharapkan (Nilai yang dikembalikan akan diubah menjadi string untuk perbandingan). Lihat {0} untuk dokumentasi tentang bahasa kueri. Taman bermain dapat ditemukan {1}.", "Notify Channel": "Beritahu Saluran", "Server URL should not contain the nfty topic": "URL server tidak boleh berisi topik nfty", "PushDeer Server": "Server PushDeer", diff --git a/src/lang/it-IT.json b/src/lang/it-IT.json index 05341f1f..5f0ce882 100644 --- a/src/lang/it-IT.json +++ b/src/lang/it-IT.json @@ -620,7 +620,6 @@ "enableNSCD": "Abilita NSCD (Name Service Cache Daemon) per abilitare la cache su tutte le richieste DNS", "recurringIntervalMessage": "Esegui una volta al giorno | Esegui una volta ogni {0} giorni", "affectedMonitorsDescription": "Seleziona i monitoraggi che sono influenzati da questa manutenzione", - "jsonQueryDescription": "Fai una query JSON verso la risposta e controlla se è presente il valore richiesto. (Il valore di ritorno verrà convertito in stringa ai fini della comparazione). Puoi controllare la documentazione su jsonata.org per conoscere come scrivere una query. Un area dimostrativa può essere trovata qui.", "For safety, must use secret key": "Per sicurezza, devi usare una chiave segreta", "Proxy server has authentication": "Il server Proxy ha una autenticazione", "smseaglePriority": "Priorità messaggio (0-9, default = 0)", diff --git a/src/lang/nl-NL.json b/src/lang/nl-NL.json index b30af0d2..65cfa079 100644 --- a/src/lang/nl-NL.json +++ b/src/lang/nl-NL.json @@ -804,7 +804,6 @@ "Reconnecting...": "Opnieuw verbinden...", "Expected Value": "Verwachte waarde", "Json Query": "Json zoekopdracht", - "jsonQueryDescription": "Voer een JSON-query uit op de respons en controleer de verwachte waarde (De retourwaarde wordt omgezet naar een string voor vergelijking). Bekijk {0} voor de documentatie over de querytaal. Een speelplaats is beschikbaar {1}.", "pushViewCode": "Hoe gebruik je Push monitor?(View Code)", "setupDatabaseChooseDatabase": "Welke database wil je gebruiken?", "setupDatabaseEmbeddedMariaDB": "Je hoeft niks in te stellen. Dit docker image heeft een ingebouwde en geconfigureerde MariaDB instantie. Uptime Kuma verbindt met deze database via een unix socket.", diff --git a/src/lang/pl.json b/src/lang/pl.json index 9f941e32..fd9c6e82 100644 --- a/src/lang/pl.json +++ b/src/lang/pl.json @@ -793,7 +793,6 @@ "styleElapsedTime": "Czas, który upłynął pod paskiem bicia serca", "tailscalePingWarning": "Aby korzystać z monitora Tailscale Ping, należy zainstalować Uptime Kuma bez Dockera, a także zainstalować klienta Tailscale na serwerze.", "invertKeywordDescription": "Słowo kluczowe powinno być raczej nieobecne niż obecne.", - "jsonQueryDescription": "Wykonaj zapytanie json względem odpowiedzi i sprawdź oczekiwaną wartość (wartość zwracana zostanie przekonwertowana na ciąg znaków do porównania). Sprawdź {0}, aby uzyskać dokumentację dotyczącą języka zapytań. Plac zabaw można znaleźć {1}.", "Server URL should not contain the nfty topic": "Adres URL serwera nie powinien zawierać tematu nfty", "Badge Duration (in hours)": "Czas trwania odznaki (w godzinach)", "Enter the list of brokers": "Wprowadź listę brokerów", diff --git a/src/lang/pt-BR.json b/src/lang/pt-BR.json index f138a07c..c105d374 100644 --- a/src/lang/pt-BR.json +++ b/src/lang/pt-BR.json @@ -605,7 +605,6 @@ "wayToGetLineChannelToken": "Primeiro acesse o {0}, crie um provedor e um canal (API de Mensagens), então você pode obter o token de acesso do canal e o ID do usuário nos itens de menu mencionados acima.", "aboutMattermostChannelName": "Você pode substituir o canal padrão para o qual o Webhook envia postagens, inserindo o nome do canal no campo \"Nome do Canal\". Isso precisa ser habilitado nas configurações do Webhook do Mattermost. Por exemplo: #outro-canal", "invertKeywordDescription": "Procure pela palavra-chave estar ausente em vez de presente.", - "jsonQueryDescription": "Faça uma consulta JSON na resposta e verifique o valor esperado (o valor de retorno será convertido em uma string para comparação). Confira {0} para a documentação sobre a linguagem de consulta. Você pode encontrar um playground {1}.", "octopushTypePremium": "Premium (Rápido - recomendado para alertas)", "octopushTypeLowCost": "Baixo Custo (Lento - às vezes bloqueado pelo operador)", "octopushSMSSender": "Nome do Remetente de SMS: 3-11 caracteres alfanuméricos e espaço (a-zA-Z0-9)", diff --git a/src/lang/ro.json b/src/lang/ro.json index 5329c2f1..8a826cfa 100644 --- a/src/lang/ro.json +++ b/src/lang/ro.json @@ -689,7 +689,6 @@ "emailTemplateLimitedToUpDownNotification": "disponibil numai pentru heartbeat-uri UP/DOWN, altfel nul", "emailTemplateStatus": "Stare", "invertKeywordDescription": "Căutați după cuvântul cheie să fie absent și nu prezent.", - "jsonQueryDescription": "Efectuați o interogare json după răspuns și verificați valoarea așteptată (valoarea returnată va fi convertită în șir pentru comparație). Consultați {0} pentru documentația despre limbajul de interogare. Un playground poate fi găsit {1}.", "goAlertInfo": "GoAlert este o aplicație open source pentru programarea apelurilor, escalări automate și notificări (cum ar fi SMS-uri sau apeluri vocale). Angajați automat persoana potrivită, în modul potrivit și la momentul potrivit! {0}", "goAlertIntegrationKeyInfo": "Obțineți cheia generică de integrare API pentru serviciu în formatul \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" de obicei valoarea parametrului token al URL-ului copiat.", "SecretAccessKey": "Secret AccessKey", diff --git a/src/lang/ru-RU.json b/src/lang/ru-RU.json index 62358b44..735920b3 100644 --- a/src/lang/ru-RU.json +++ b/src/lang/ru-RU.json @@ -812,7 +812,6 @@ "AccessKey Id": "AccessKey Id", "Secret AccessKey": "Секретный ключ доступа", "Session Token": "Токен сессии", - "jsonQueryDescription": "Выполните json-запрос к ответу и проверьте наличие ожидаемого значения (возвращаемое значение будет преобразовано в строку для сравнения). Посмотрите {0} для получения документации по языку запросов. A Потренироваться вы можете {1}.", "Notify Channel": "Канал оповещений", "aboutNotifyChannel": "Уведомление о канале вызовет настольное или мобильное уведомление для всех участников канала, независимо от того, установлена ли их доступность как активная или отсутствующая.", "Enter the list of brokers": "Введите список брокеров", diff --git a/src/lang/sv-SE.json b/src/lang/sv-SE.json index 270017eb..e68d3265 100644 --- a/src/lang/sv-SE.json +++ b/src/lang/sv-SE.json @@ -795,7 +795,6 @@ "pushoverDesc1": "Nödprioritet (2) har 30 sekunders timeout mellan försök och löper ut efter 1 timme som standard.", "octopushTypePremium": "Premium (Snabb - rekommenderas för varningar)", "octopushTypeLowCost": "Låg kostnad (långsam - blockeras ibland av operatören)", - "jsonQueryDescription": "Gör en json-förfrågan mot svaret och kontrollera det förväntade värdet (returvärde konverteras till en sträng för jämförelse). Se {0} för dokumentation angående frågespråket. En lekplats kan hittas här {1}.", "Check octopush prices": "Kontrollera octopush priser {0}.", "octopushSMSSender": "SMS avsändarnamn: 3-11 alfanumeriska tecken och mellanslag (a-zA-Z0-9)", "LunaSea Device ID": "LunaSea enhetsid", diff --git a/src/lang/tr-TR.json b/src/lang/tr-TR.json index a56c60c6..ed6e4eb8 100644 --- a/src/lang/tr-TR.json +++ b/src/lang/tr-TR.json @@ -794,7 +794,6 @@ "webhookBodyPresetOption": "Ön ayar - {0}", "webhookBodyCustomOption": "Özel Gövde", "Request Body": "İstek Gövdesi", - "jsonQueryDescription": "Yanıta karşı bir json sorgusu yapın ve beklenen değeri kontrol edin (Dönüş değeri, karşılaştırma için dizgeye dönüştürülür). Sorgu diliyle ilgili belgeler için {0}'a bakın. Bir oyun alanı {1} bulunabilir.", "twilioApiKey": "Api Anahtarı (isteğe bağlı)", "Expected Value": "Beklenen Değer", "Json Query": "Json Sorgusu", diff --git a/src/lang/uk-UA.json b/src/lang/uk-UA.json index 6f9c833d..3aca5a90 100644 --- a/src/lang/uk-UA.json +++ b/src/lang/uk-UA.json @@ -802,7 +802,6 @@ "Request Body": "Тіло запиту", "Badge Preview": "Попередній перегляд бейджа", "Badge Duration (in hours)": "Тривалість бейджа (у годинах)", - "jsonQueryDescription": "Виконувати json-запит до відповіді та перевірити очікуване значення (значення, що повертається, буде перетворено в рядок для порівняння). Зверніться до {0} щоб ознайомитися з документацією про мову запитів. Навчальний майданчик можна знайти {1}.", "twilioApiKey": "Api ключ (необов'язково)", "Expected Value": "Очікуване значення", "Json Query": "Json-запит", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index 5094b390..6c10a037 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -802,7 +802,6 @@ "webhookCustomBodyDesc": "为 webhook 设定一个自定义 HTTP 请求体。可在模板内使用 {msg}、{heartbeat}和{monitor} 变量。", "webhookBodyPresetOption": "预设 - {0}", "Request Body": "请求体", - "jsonQueryDescription": "对响应结果执行一次 JSON 查询,其返回值将会被转换为字符串,再与期望值进行比较。可访问 {0} 阅读 JSON 查询语言的文档,或在{1}测试查询语句。", "Json Query": "JSON 查询", "twilioApiKey": "API Key(可选)", "Expected Value": "预期值", diff --git a/src/lang/zh-TW.json b/src/lang/zh-TW.json index fa8a5aeb..a528a89d 100644 --- a/src/lang/zh-TW.json +++ b/src/lang/zh-TW.json @@ -772,7 +772,6 @@ "Check/Uncheck": "選中/取消選中", "tailscalePingWarning": "如需使用 Tailscale Ping 客戶端,您需要以非 docker 方式安裝 Uptime Kuma,並同時安裝 Tailscale 客戶端。", "invertKeywordDescription": "出現關鍵詞將令檢測結果設為失敗,而非成功。", - "jsonQueryDescription": "對回應結果執行一次 JSON 查詢,其返回值將會被轉換為字串,再與期望值進行比較。可造訪{0}閱讀JSON 查詢語言的文件,或在{1}測試查詢語句。", "wayToGetKookGuildID": "在 Kook 設定中打開“開發者模式”,然後右鍵點選頻道可取得其 ID", "Notify Channel": "通知該頻道", "aboutNotifyChannel": "勾選“通知該頻道”,會令該頻道內所有成員都收到一條桌面端或移動端通知,無論其狀態是在線或離開。", diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 3577d633..fd2f3c72 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -24,6 +24,9 @@ + @@ -168,21 +171,6 @@ - -
- - - - - jsonata.org - {{ $t('here') }} - -
- - - -
-
@@ -246,19 +234,79 @@ - -
+ +
- -
+ +
+ +
+ + + + +
{{ $t('snmpCommunityStringHelptext') }}
+
+ +
+ + +
{{ $t('snmpOIDHelptext') }}
+
+ +
+ + +
+ + + +
+
+ + + jsonata.org + {{ $t('playground') }} + + +
+ +
+
+ + +
+
+ + + +
+
+
+