mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-01-24 07:16:55 -06:00
fix: resolve merge conflict
This commit is contained in:
commit
6bb79597e8
18
db/patch-add-radius-monitor.sql
Normal file
18
db/patch-add-radius-monitor.sql
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE monitor
|
||||||
|
ADD radius_username VARCHAR(255);
|
||||||
|
|
||||||
|
ALTER TABLE monitor
|
||||||
|
ADD radius_password VARCHAR(255);
|
||||||
|
|
||||||
|
ALTER TABLE monitor
|
||||||
|
ADD radius_calling_station_id VARCHAR(50);
|
||||||
|
|
||||||
|
ALTER TABLE monitor
|
||||||
|
ADD radius_called_station_id VARCHAR(50);
|
||||||
|
|
||||||
|
ALTER TABLE monitor
|
||||||
|
ADD radius_secret VARCHAR(255);
|
||||||
|
|
||||||
|
COMMIT
|
10
db/patch-monitor-add-resend-interval.sql
Normal file
10
db/patch-monitor-add-resend-interval.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
ALTER TABLE monitor
|
||||||
|
ADD resend_interval INTEGER default 0 not null;
|
||||||
|
|
||||||
|
ALTER TABLE heartbeat
|
||||||
|
ADD down_count INTEGER default 0 not null;
|
||||||
|
|
||||||
|
COMMIT;
|
@ -4,5 +4,5 @@ WORKDIR /app
|
|||||||
|
|
||||||
# Install apprise, iputils for non-root ping, setpriv
|
# Install apprise, iputils for non-root ping, setpriv
|
||||||
RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \
|
RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \
|
||||||
pip3 --no-cache-dir install apprise==0.9.9 && \
|
pip3 --no-cache-dir install apprise==1.0.0 && \
|
||||||
rm -rf /root/.cache
|
rm -rf /root/.cache
|
||||||
|
@ -11,7 +11,7 @@ WORKDIR /app
|
|||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
apt --yes --no-install-recommends install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \
|
apt --yes --no-install-recommends install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \
|
||||||
sqlite3 iputils-ping util-linux dumb-init && \
|
sqlite3 iputils-ping util-linux dumb-init && \
|
||||||
pip3 --no-cache-dir install apprise==0.9.9 && \
|
pip3 --no-cache-dir install apprise==1.0.0 && \
|
||||||
rm -rf /var/lib/apt/lists/* && \
|
rm -rf /var/lib/apt/lists/* && \
|
||||||
apt --yes autoremove
|
apt --yes autoremove
|
||||||
|
|
||||||
|
118
package-lock.json
generated
118
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.17.1",
|
"version": "1.18.0-beta.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.17.1",
|
"version": "1.18.0-beta.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||||
@ -44,6 +44,7 @@
|
|||||||
"mqtt": "^4.2.8",
|
"mqtt": "^4.2.8",
|
||||||
"mssql": "^8.1.0",
|
"mssql": "^8.1.0",
|
||||||
"node-cloudflared-tunnel": "~1.0.9",
|
"node-cloudflared-tunnel": "~1.0.9",
|
||||||
|
"node-radius-client": "^1.0.0",
|
||||||
"nodemailer": "~6.6.5",
|
"nodemailer": "~6.6.5",
|
||||||
"notp": "~2.0.3",
|
"notp": "~2.0.3",
|
||||||
"password-hash": "~1.2.2",
|
"password-hash": "~1.2.2",
|
||||||
@ -8326,6 +8327,12 @@
|
|||||||
"readable-stream": "^3.6.0"
|
"readable-stream": "^3.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hoek": {
|
||||||
|
"version": "6.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
|
||||||
|
"integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==",
|
||||||
|
"deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues."
|
||||||
|
},
|
||||||
"node_modules/homedir-polyfill": {
|
"node_modules/homedir-polyfill": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
||||||
@ -9026,6 +9033,17 @@
|
|||||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/isemail": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==",
|
||||||
|
"dependencies": {
|
||||||
|
"punycode": "2.x.x"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@ -12272,6 +12290,32 @@
|
|||||||
"integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
|
"integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/node-radius-client": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-radius-client/-/node-radius-client-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-FkR9cMV5hNoX+kKDUTzuagvEixlLiaEJQ1/ywOdhahsihKrGDhVZmnCvmrCStA589MT3yuC/J2eKc6z68IGdBw==",
|
||||||
|
"dependencies": {
|
||||||
|
"joi": "^14.3.1",
|
||||||
|
"node-radius-utils": "^1.2.0",
|
||||||
|
"radius": "^1.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-radius-client/node_modules/joi": {
|
||||||
|
"version": "14.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz",
|
||||||
|
"integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==",
|
||||||
|
"deprecated": "This module has moved and is now available at @hapi/joi. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
|
||||||
|
"dependencies": {
|
||||||
|
"hoek": "6.x.x",
|
||||||
|
"isemail": "3.x.x",
|
||||||
|
"topo": "3.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-radius-utils": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-radius-utils/-/node-radius-utils-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-i3Sf6khnenl0aXumo0whAlfPWTaBqHxEnVBBxpu3dZ7q69NkPPv71rvPjlDZ5wkeKCTNNUTECljerS5kcYQxRw=="
|
||||||
|
},
|
||||||
"node_modules/node-releases": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
|
||||||
@ -13579,6 +13623,14 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/radius": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/radius/-/radius-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-UWuzdF6xf3NpsXFZZmUEkxtEalDXj8hdmMXgbGzn7vOk6zXNsiIY2I6SJ1euHt7PTQuMoz2qDEJB+AfJDJgQYw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/range-parser": {
|
"node_modules/range-parser": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
@ -15410,6 +15462,15 @@
|
|||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/topo": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==",
|
||||||
|
"deprecated": "This module has moved and is now available at @hapi/topo. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
|
||||||
|
"dependencies": {
|
||||||
|
"hoek": "6.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/toposort": {
|
"node_modules/toposort": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||||
@ -22878,6 +22939,11 @@
|
|||||||
"readable-stream": "^3.6.0"
|
"readable-stream": "^3.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hoek": {
|
||||||
|
"version": "6.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
|
||||||
|
"integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ=="
|
||||||
|
},
|
||||||
"homedir-polyfill": {
|
"homedir-polyfill": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
||||||
@ -23360,6 +23426,14 @@
|
|||||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
|
"isemail": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==",
|
||||||
|
"requires": {
|
||||||
|
"punycode": "2.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"isexe": {
|
"isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@ -25865,6 +25939,33 @@
|
|||||||
"integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
|
"integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node-radius-client": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-radius-client/-/node-radius-client-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-FkR9cMV5hNoX+kKDUTzuagvEixlLiaEJQ1/ywOdhahsihKrGDhVZmnCvmrCStA589MT3yuC/J2eKc6z68IGdBw==",
|
||||||
|
"requires": {
|
||||||
|
"joi": "^14.3.1",
|
||||||
|
"node-radius-utils": "^1.2.0",
|
||||||
|
"radius": "^1.1.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"joi": {
|
||||||
|
"version": "14.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz",
|
||||||
|
"integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==",
|
||||||
|
"requires": {
|
||||||
|
"hoek": "6.x.x",
|
||||||
|
"isemail": "3.x.x",
|
||||||
|
"topo": "3.x.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node-radius-utils": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-radius-utils/-/node-radius-utils-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-i3Sf6khnenl0aXumo0whAlfPWTaBqHxEnVBBxpu3dZ7q69NkPPv71rvPjlDZ5wkeKCTNNUTECljerS5kcYQxRw=="
|
||||||
|
},
|
||||||
"node-releases": {
|
"node-releases": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
|
||||||
@ -26806,6 +26907,11 @@
|
|||||||
"integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
|
"integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"radius": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/radius/-/radius-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-UWuzdF6xf3NpsXFZZmUEkxtEalDXj8hdmMXgbGzn7vOk6zXNsiIY2I6SJ1euHt7PTQuMoz2qDEJB+AfJDJgQYw=="
|
||||||
|
},
|
||||||
"range-parser": {
|
"range-parser": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
@ -28240,6 +28346,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
|
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
|
||||||
},
|
},
|
||||||
|
"topo": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==",
|
||||||
|
"requires": {
|
||||||
|
"hoek": "6.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"toposort": {
|
"toposort": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.17.1",
|
"version": "1.18.0-beta.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -96,6 +96,7 @@
|
|||||||
"mqtt": "^4.2.8",
|
"mqtt": "^4.2.8",
|
||||||
"mssql": "^8.1.0",
|
"mssql": "^8.1.0",
|
||||||
"node-cloudflared-tunnel": "~1.0.9",
|
"node-cloudflared-tunnel": "~1.0.9",
|
||||||
|
"node-radius-client": "^1.0.0",
|
||||||
"nodemailer": "~6.6.5",
|
"nodemailer": "~6.6.5",
|
||||||
"notp": "~2.0.3",
|
"notp": "~2.0.3",
|
||||||
"password-hash": "~1.2.2",
|
"password-hash": "~1.2.2",
|
||||||
|
@ -63,6 +63,8 @@ class Database {
|
|||||||
"patch-add-sqlserver-monitor.sql": true,
|
"patch-add-sqlserver-monitor.sql": true,
|
||||||
"patch-add-other-auth.sql": { parents: [ "patch-monitor-basic-auth.sql" ] },
|
"patch-add-other-auth.sql": { parents: [ "patch-monitor-basic-auth.sql" ] },
|
||||||
"patch-grpc-monitor.sql": true,
|
"patch-grpc-monitor.sql": true,
|
||||||
|
"patch-add-radius-monitor.sql": true,
|
||||||
|
"patch-monitor-add-resend-interval.sql": true,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,6 +151,9 @@ class Database {
|
|||||||
await R.exec("PRAGMA cache_size = -12000");
|
await R.exec("PRAGMA cache_size = -12000");
|
||||||
await R.exec("PRAGMA auto_vacuum = FULL");
|
await R.exec("PRAGMA auto_vacuum = FULL");
|
||||||
|
|
||||||
|
// Avoid error "SQLITE_BUSY: database is locked" by allowing SQLITE to wait up to 5 seconds to do a write
|
||||||
|
await R.exec("PRAGMA busy_timeout = 5000");
|
||||||
|
|
||||||
// This ensures that an operating system crash or power failure will not corrupt the database.
|
// This ensures that an operating system crash or power failure will not corrupt the database.
|
||||||
// FULL synchronous is very safe, but it is also slower.
|
// FULL synchronous is very safe, but it is also slower.
|
||||||
// Read more: https://sqlite.org/pragma.html#pragma_synchronous
|
// Read more: https://sqlite.org/pragma.html#pragma_synchronous
|
||||||
|
@ -7,7 +7,7 @@ dayjs.extend(timezone);
|
|||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const { Prometheus } = require("../prometheus");
|
const { Prometheus } = require("../prometheus");
|
||||||
const { log, UP, DOWN, PENDING, flipStatus, TimeLogger } = require("../../src/util");
|
const { log, UP, DOWN, PENDING, flipStatus, TimeLogger } = require("../../src/util");
|
||||||
const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mqttAsync, setSetting, httpNtlm, grpcQuery } = require("../util-server");
|
const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery } = require("../util-server");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
const { Notification } = require("../notification");
|
const { Notification } = require("../notification");
|
||||||
@ -79,6 +79,7 @@ class Monitor extends BeanModel {
|
|||||||
type: this.type,
|
type: this.type,
|
||||||
interval: this.interval,
|
interval: this.interval,
|
||||||
retryInterval: this.retryInterval,
|
retryInterval: this.retryInterval,
|
||||||
|
resendInterval: this.resendInterval,
|
||||||
keyword: this.keyword,
|
keyword: this.keyword,
|
||||||
expiryNotification: this.isEnabledExpiryNotification(),
|
expiryNotification: this.isEnabledExpiryNotification(),
|
||||||
ignoreTls: this.getIgnoreTls(),
|
ignoreTls: this.getIgnoreTls(),
|
||||||
@ -108,6 +109,11 @@ class Monitor extends BeanModel {
|
|||||||
grpcMethod: this.grpcMethod,
|
grpcMethod: this.grpcMethod,
|
||||||
grpcServiceName: this.grpcServiceName,
|
grpcServiceName: this.grpcServiceName,
|
||||||
grpcEnableTls: this.getGrpcEnableTls(),
|
grpcEnableTls: this.getGrpcEnableTls(),
|
||||||
|
radiusUsername: this.radiusUsername,
|
||||||
|
radiusPassword: this.radiusPassword,
|
||||||
|
radiusCalledStationId: this.radiusCalledStationId,
|
||||||
|
radiusCallingStationId: this.radiusCallingStationId,
|
||||||
|
radiusSecret: this.radiusSecret,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (includeSensitiveData) {
|
if (includeSensitiveData) {
|
||||||
@ -224,6 +230,7 @@ class Monitor extends BeanModel {
|
|||||||
bean.monitor_id = this.id;
|
bean.monitor_id = this.id;
|
||||||
bean.time = R.isoDateTimeMillis(dayjs.utc());
|
bean.time = R.isoDateTimeMillis(dayjs.utc());
|
||||||
bean.status = DOWN;
|
bean.status = DOWN;
|
||||||
|
bean.downCount = previousBeat?.downCount || 0;
|
||||||
|
|
||||||
if (this.isUpsideDown()) {
|
if (this.isUpsideDown()) {
|
||||||
bean.status = flipStatus(bean.status);
|
bean.status = flipStatus(bean.status);
|
||||||
@ -570,6 +577,30 @@ class Monitor extends BeanModel {
|
|||||||
bean.msg = "";
|
bean.msg = "";
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
bean.ping = dayjs().valueOf() - startTime;
|
bean.ping = dayjs().valueOf() - startTime;
|
||||||
|
} else if (this.type === "radius") {
|
||||||
|
let startTime = dayjs().valueOf();
|
||||||
|
try {
|
||||||
|
const resp = await radius(
|
||||||
|
this.hostname,
|
||||||
|
this.radiusUsername,
|
||||||
|
this.radiusPassword,
|
||||||
|
this.radiusCalledStationId,
|
||||||
|
this.radiusCallingStationId,
|
||||||
|
this.radiusSecret
|
||||||
|
);
|
||||||
|
if (resp.code) {
|
||||||
|
bean.msg = resp.code;
|
||||||
|
}
|
||||||
|
bean.status = UP;
|
||||||
|
} catch (error) {
|
||||||
|
bean.status = DOWN;
|
||||||
|
if (error.response?.code) {
|
||||||
|
bean.msg = error.response.code;
|
||||||
|
} else {
|
||||||
|
bean.msg = error.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bean.ping = dayjs().valueOf() - startTime;
|
||||||
} else {
|
} else {
|
||||||
bean.msg = "Unknown Monitor Type";
|
bean.msg = "Unknown Monitor Type";
|
||||||
bean.status = PENDING;
|
bean.status = PENDING;
|
||||||
@ -611,12 +642,27 @@ class Monitor extends BeanModel {
|
|||||||
log.debug("monitor", `[${this.name}] sendNotification`);
|
log.debug("monitor", `[${this.name}] sendNotification`);
|
||||||
await Monitor.sendNotification(isFirstBeat, this, bean);
|
await Monitor.sendNotification(isFirstBeat, this, bean);
|
||||||
|
|
||||||
|
// Reset down count
|
||||||
|
bean.downCount = 0;
|
||||||
|
|
||||||
// Clear Status Page Cache
|
// Clear Status Page Cache
|
||||||
log.debug("monitor", `[${this.name}] apicache clear`);
|
log.debug("monitor", `[${this.name}] apicache clear`);
|
||||||
apicache.clear();
|
apicache.clear();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
bean.important = false;
|
bean.important = false;
|
||||||
|
|
||||||
|
if (bean.status === DOWN && this.resendInterval > 0) {
|
||||||
|
++bean.downCount;
|
||||||
|
if (bean.downCount >= this.resendInterval) {
|
||||||
|
// Send notification again, because we are still DOWN
|
||||||
|
log.debug("monitor", `[${this.name}] sendNotification again: Down Count: ${bean.downCount} | Resend Interval: ${this.resendInterval}`);
|
||||||
|
await Monitor.sendNotification(isFirstBeat, this, bean);
|
||||||
|
|
||||||
|
// Reset down count
|
||||||
|
bean.downCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bean.status === UP) {
|
if (bean.status === UP) {
|
||||||
@ -627,7 +673,7 @@ class Monitor extends BeanModel {
|
|||||||
}
|
}
|
||||||
log.warn("monitor", `Monitor #${this.id} '${this.name}': Pending: ${bean.msg} | Max retries: ${this.maxretries} | Retry: ${retries} | Retry Interval: ${beatInterval} seconds | Type: ${this.type}`);
|
log.warn("monitor", `Monitor #${this.id} '${this.name}': Pending: ${bean.msg} | Max retries: ${this.maxretries} | Retry: ${retries} | Retry Interval: ${beatInterval} seconds | Type: ${this.type}`);
|
||||||
} else {
|
} else {
|
||||||
log.warn("monitor", `Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type}`);
|
log.warn("monitor", `Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type} | Down Count: ${bean.downCount} | Resend Interval: ${this.resendInterval}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("monitor", `[${this.name}] Send to socket`);
|
log.debug("monitor", `[${this.name}] Send to socket`);
|
||||||
|
@ -12,9 +12,7 @@ const { default: axios } = require("axios");
|
|||||||
|
|
||||||
// bark is an APN bridge that sends notifications to Apple devices.
|
// bark is an APN bridge that sends notifications to Apple devices.
|
||||||
|
|
||||||
const barkNotificationGroup = "UptimeKuma";
|
|
||||||
const barkNotificationAvatar = "https://github.com/louislam/uptime-kuma/raw/master/public/icon.png";
|
const barkNotificationAvatar = "https://github.com/louislam/uptime-kuma/raw/master/public/icon.png";
|
||||||
const barkNotificationSound = "telegraph";
|
|
||||||
const successMessage = "Successes!";
|
const successMessage = "Successes!";
|
||||||
|
|
||||||
class Bark extends NotificationProvider {
|
class Bark extends NotificationProvider {
|
||||||
@ -50,13 +48,23 @@ class Bark extends NotificationProvider {
|
|||||||
* @param {string} postUrl URL to append parameters to
|
* @param {string} postUrl URL to append parameters to
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
appendAdditionalParameters(postUrl) {
|
appendAdditionalParameters(notification, postUrl) {
|
||||||
// grouping all our notifications
|
|
||||||
postUrl += "?group=" + barkNotificationGroup;
|
|
||||||
// set icon to uptime kuma icon, 11kb should be fine
|
// set icon to uptime kuma icon, 11kb should be fine
|
||||||
postUrl += "&icon=" + barkNotificationAvatar;
|
postUrl += "&icon=" + barkNotificationAvatar;
|
||||||
|
// grouping all our notifications
|
||||||
|
if (notification.barkGroup != null) {
|
||||||
|
postUrl += "&group=" + notification.barkGroup;
|
||||||
|
} else {
|
||||||
|
// default name
|
||||||
|
postUrl += "&group=" + "UptimeKuma";
|
||||||
|
}
|
||||||
// picked a sound, this should follow system's mute status when arrival
|
// picked a sound, this should follow system's mute status when arrival
|
||||||
postUrl += "&sound=" + barkNotificationSound;
|
if (notification.barkSound != null) {
|
||||||
|
postUrl += "&sound=" + notification.barkSound;
|
||||||
|
} else {
|
||||||
|
// default sound
|
||||||
|
postUrl += "&sound=" + "telegraph";
|
||||||
|
}
|
||||||
return postUrl;
|
return postUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
38
server/notification-providers/home-assistant.js
Normal file
38
server/notification-providers/home-assistant.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
const NotificationProvider = require("./notification-provider");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
const defaultNotificationService = "notify";
|
||||||
|
|
||||||
|
class HomeAssistant extends NotificationProvider {
|
||||||
|
name = "HomeAssistant";
|
||||||
|
|
||||||
|
async send(notification, message, monitor = null, heartbeat = null) {
|
||||||
|
const notificationService = notification?.notificationService || defaultNotificationService;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post(
|
||||||
|
`${notification.homeAssistantUrl}/api/services/notify/${notificationService}`,
|
||||||
|
{
|
||||||
|
title: "Uptime Kuma",
|
||||||
|
message,
|
||||||
|
...(notificationService !== "persistent_notification" && { data: {
|
||||||
|
name: monitor?.name,
|
||||||
|
status: heartbeat?.status,
|
||||||
|
} }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${notification.longLivedAccessToken}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return "Sent Successfully.";
|
||||||
|
} catch (error) {
|
||||||
|
this.throwGeneralAxiosError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = HomeAssistant;
|
@ -12,6 +12,7 @@ const Feishu = require("./notification-providers/feishu");
|
|||||||
const GoogleChat = require("./notification-providers/google-chat");
|
const GoogleChat = require("./notification-providers/google-chat");
|
||||||
const Gorush = require("./notification-providers/gorush");
|
const Gorush = require("./notification-providers/gorush");
|
||||||
const Gotify = require("./notification-providers/gotify");
|
const Gotify = require("./notification-providers/gotify");
|
||||||
|
const HomeAssistant = require("./notification-providers/home-assistant");
|
||||||
const Line = require("./notification-providers/line");
|
const Line = require("./notification-providers/line");
|
||||||
const LineNotify = require("./notification-providers/linenotify");
|
const LineNotify = require("./notification-providers/linenotify");
|
||||||
const LunaSea = require("./notification-providers/lunasea");
|
const LunaSea = require("./notification-providers/lunasea");
|
||||||
@ -61,6 +62,7 @@ class Notification {
|
|||||||
new GoogleChat(),
|
new GoogleChat(),
|
||||||
new Gorush(),
|
new Gorush(),
|
||||||
new Gotify(),
|
new Gotify(),
|
||||||
|
new HomeAssistant(),
|
||||||
new Line(),
|
new Line(),
|
||||||
new LineNotify(),
|
new LineNotify(),
|
||||||
new LunaSea(),
|
new LunaSea(),
|
||||||
|
@ -669,6 +669,7 @@ let needSetup = false;
|
|||||||
bean.basic_auth_pass = monitor.basic_auth_pass;
|
bean.basic_auth_pass = monitor.basic_auth_pass;
|
||||||
bean.interval = monitor.interval;
|
bean.interval = monitor.interval;
|
||||||
bean.retryInterval = monitor.retryInterval;
|
bean.retryInterval = monitor.retryInterval;
|
||||||
|
bean.resendInterval = monitor.resendInterval;
|
||||||
bean.hostname = monitor.hostname;
|
bean.hostname = monitor.hostname;
|
||||||
bean.maxretries = monitor.maxretries;
|
bean.maxretries = monitor.maxretries;
|
||||||
bean.port = parseInt(monitor.port);
|
bean.port = parseInt(monitor.port);
|
||||||
@ -699,6 +700,11 @@ let needSetup = false;
|
|||||||
bean.grpcBody = monitor.grpcBody;
|
bean.grpcBody = monitor.grpcBody;
|
||||||
bean.grpcMetadata = monitor.grpcMetadata;
|
bean.grpcMetadata = monitor.grpcMetadata;
|
||||||
bean.grpcEnableTls = monitor.grpcEnableTls;
|
bean.grpcEnableTls = monitor.grpcEnableTls;
|
||||||
|
bean.radiusUsername = monitor.radiusUsername;
|
||||||
|
bean.radiusPassword = monitor.radiusPassword;
|
||||||
|
bean.radiusCalledStationId = monitor.radiusCalledStationId;
|
||||||
|
bean.radiusCallingStationId = monitor.radiusCallingStationId;
|
||||||
|
bean.radiusSecret = monitor.radiusSecret;
|
||||||
|
|
||||||
await R.store(bean);
|
await R.store(bean);
|
||||||
|
|
||||||
@ -1279,6 +1285,7 @@ let needSetup = false;
|
|||||||
authDomain: monitorListData[i].authDomain,
|
authDomain: monitorListData[i].authDomain,
|
||||||
interval: monitorListData[i].interval,
|
interval: monitorListData[i].interval,
|
||||||
retryInterval: retryInterval,
|
retryInterval: retryInterval,
|
||||||
|
resendInterval: monitorListData[i].resendInterval || 0,
|
||||||
hostname: monitorListData[i].hostname,
|
hostname: monitorListData[i].hostname,
|
||||||
maxretries: monitorListData[i].maxretries,
|
maxretries: monitorListData[i].maxretries,
|
||||||
port: monitorListData[i].port,
|
port: monitorListData[i].port,
|
||||||
|
@ -17,6 +17,12 @@ const { NtlmClient } = require("axios-ntlm");
|
|||||||
const { Settings } = require("./settings");
|
const { Settings } = require("./settings");
|
||||||
const grpc = require("@grpc/grpc-js");
|
const grpc = require("@grpc/grpc-js");
|
||||||
const protojs = require("protobufjs");
|
const protojs = require("protobufjs");
|
||||||
|
const radiusClient = require("node-radius-client");
|
||||||
|
const {
|
||||||
|
dictionaries: {
|
||||||
|
rfc2865: { file, attributes },
|
||||||
|
},
|
||||||
|
} = require("node-radius-utils");
|
||||||
|
|
||||||
// From ping-lite
|
// From ping-lite
|
||||||
exports.WIN = /^win/.test(process.platform);
|
exports.WIN = /^win/.test(process.platform);
|
||||||
@ -287,6 +293,30 @@ exports.postgresQuery = function (connectionString, query) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.radius = function (
|
||||||
|
hostname,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
calledStationId,
|
||||||
|
callingStationId,
|
||||||
|
secret,
|
||||||
|
) {
|
||||||
|
const client = new radiusClient({
|
||||||
|
host: hostname,
|
||||||
|
dictionaries: [ file ],
|
||||||
|
});
|
||||||
|
|
||||||
|
return client.accessRequest({
|
||||||
|
secret: secret,
|
||||||
|
attributes: [
|
||||||
|
[ attributes.USER_NAME, username ],
|
||||||
|
[ attributes.USER_PASSWORD, password ],
|
||||||
|
[ attributes.CALLING_STATION_ID, callingStationId ],
|
||||||
|
[ attributes.CALLED_STATION_ID, calledStationId ],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve value of setting based on key
|
* Retrieve value of setting based on key
|
||||||
* @param {string} key Key of setting to retrieve
|
* @param {string} key Key of setting to retrieve
|
||||||
|
@ -2,9 +2,6 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="Bark Endpoint" class="form-label">{{ $t("Bark Endpoint") }}<span style="color: red;"><sup>*</sup></span></label>
|
<label for="Bark Endpoint" class="form-label">{{ $t("Bark Endpoint") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||||
<input id="Bark Endpoint" v-model="$parent.notification.barkEndpoint" type="text" class="form-control" required>
|
<input id="Bark Endpoint" v-model="$parent.notification.barkEndpoint" 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">
|
<i18n-t tag="div" keypath="wayToGetTeamsURL" class="form-text">
|
||||||
<a
|
<a
|
||||||
href="https://github.com/Finb/Bark"
|
href="https://github.com/Finb/Bark"
|
||||||
@ -12,4 +9,45 @@
|
|||||||
>{{ $t("here") }}</a>
|
>{{ $t("here") }}</a>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="Bark Group" class="form-label">{{ $t("Bark Group") }}</label>
|
||||||
|
<input id="Bark Group" v-model="$parent.notification.barkGroup" type="text" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="Bark Sound" class="form-label">{{ $t("Bark Sound") }}</label>
|
||||||
|
<select id="Bark Sound" v-model="$parent.notification.barkSound" class="form-select" required>
|
||||||
|
<option value="alarm">alarm</option>
|
||||||
|
<option value="anticipate">anticipate</option>
|
||||||
|
<option value="bell">bell</option>
|
||||||
|
<option value="birdsong">birdsong</option>
|
||||||
|
<option value="bloom">bloom</option>
|
||||||
|
<option value="calypso">calypso</option>
|
||||||
|
<option value="chime">chime</option>
|
||||||
|
<option value="choo">choo</option>
|
||||||
|
<option value="descent">descent</option>
|
||||||
|
<option value="electronic">electronic</option>
|
||||||
|
<option value="fanfare">fanfare</option>
|
||||||
|
<option value="glass">glass</option>
|
||||||
|
<option value="gotosleep">gotosleep</option>
|
||||||
|
<option value="healthnotification">healthnotification</option>
|
||||||
|
<option value="horn">horn</option>
|
||||||
|
<option value="ladder">ladder</option>
|
||||||
|
<option value="mailsent">mailsent</option>
|
||||||
|
<option value="minuet">minuet</option>
|
||||||
|
<option value="multiwayinvitation">multiwayinvitation</option>
|
||||||
|
<option value="newmail">newmail</option>
|
||||||
|
<option value="newsflash">newsflash</option>
|
||||||
|
<option value="noir">noir</option>
|
||||||
|
<option value="paymentsuccess">paymentsuccess</option>
|
||||||
|
<option value="shake">shake</option>
|
||||||
|
<option value="sherwoodforest">sherwoodforest</option>
|
||||||
|
<option value="silence">silence</option>
|
||||||
|
<option value="spell">spell</option>
|
||||||
|
<option value="suspense">suspense</option>
|
||||||
|
<option value="telegraph">telegraph</option>
|
||||||
|
<option value="tiptoes">tiptoes</option>
|
||||||
|
<option value="typewriters">typewriters</option>
|
||||||
|
<option value="update">update</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
40
src/components/notifications/HomeAssistant.vue
Normal file
40
src/components/notifications/HomeAssistant.vue
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="homeAssistantUrl" class="form-label">{{ $t("Home Assistant URL") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||||
|
<input id="homeAssistantUrl" v-model="$parent.notification.homeAssistantUrl" type="url" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="longLivedAccessToken" class="form-label">{{ $t("Long-Lived Access Token") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||||
|
<input id="longLivedAccessToken" v-model="$parent.notification.longLivedAccessToken" type="text" class="form-control" required>
|
||||||
|
|
||||||
|
<div class="form-text">
|
||||||
|
<p>{{ $t("Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ") }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="notificationService" class="form-label">{{ $t("Notification Service") }}</label>
|
||||||
|
<input id="notificationService" v-model="$parent.notification.notificationService" type="text" :placeholder="$t('default: notify all devices')" class="form-control">
|
||||||
|
|
||||||
|
<div class="form-text">
|
||||||
|
<p>{{ $t("A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.") }}</p>
|
||||||
|
<p>{{ $t("Automations can optionally be triggered in Home Assistant:") }}</p>
|
||||||
|
<p>
|
||||||
|
{{ $t("Trigger type:") }} <code>Event</code><br />
|
||||||
|
{{ $t("Event type:") }} <code>call_service</code><br />
|
||||||
|
{{ $t("Event data:") }}
|
||||||
|
</p>
|
||||||
|
<pre>domain: notify
|
||||||
|
service: mobile_app_my_phone # change to your device name
|
||||||
|
service_data:
|
||||||
|
title: Uptime Kuma
|
||||||
|
data:
|
||||||
|
status: 0 # 0=down 1=up
|
||||||
|
# name: Optional Uptime Kuma Monitor Name to filter by</pre>
|
||||||
|
<p>
|
||||||
|
{{ $t("Then choose an action, for example switch the scene to where an RGB light is red.") }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -10,6 +10,7 @@ import Feishu from "./Feishu.vue";
|
|||||||
import GoogleChat from "./GoogleChat.vue";
|
import GoogleChat from "./GoogleChat.vue";
|
||||||
import Gorush from "./Gorush.vue";
|
import Gorush from "./Gorush.vue";
|
||||||
import Gotify from "./Gotify.vue";
|
import Gotify from "./Gotify.vue";
|
||||||
|
import HomeAssistant from "./HomeAssistant.vue";
|
||||||
import Line from "./Line.vue";
|
import Line from "./Line.vue";
|
||||||
import LineNotify from "./LineNotify.vue";
|
import LineNotify from "./LineNotify.vue";
|
||||||
import LunaSea from "./LunaSea.vue";
|
import LunaSea from "./LunaSea.vue";
|
||||||
@ -54,6 +55,7 @@ const NotificationFormList = {
|
|||||||
"GoogleChat": GoogleChat,
|
"GoogleChat": GoogleChat,
|
||||||
"gorush": Gorush,
|
"gorush": Gorush,
|
||||||
"gotify": Gotify,
|
"gotify": Gotify,
|
||||||
|
"HomeAssistant": HomeAssistant,
|
||||||
"line": Line,
|
"line": Line,
|
||||||
"LineNotify": LineNotify,
|
"LineNotify": LineNotify,
|
||||||
"lunasea": LunaSea,
|
"lunasea": LunaSea,
|
||||||
|
@ -165,7 +165,10 @@ export default {
|
|||||||
Pink: "Pink",
|
Pink: "Pink",
|
||||||
"Search...": "Suchen...",
|
"Search...": "Suchen...",
|
||||||
"Heartbeat Retry Interval": "Überprüfungsintervall",
|
"Heartbeat Retry Interval": "Überprüfungsintervall",
|
||||||
|
"Resend Notification if Down X times consequently": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander",
|
||||||
retryCheckEverySecond: "Alle {0} Sekunden neu versuchen",
|
retryCheckEverySecond: "Alle {0} Sekunden neu versuchen",
|
||||||
|
resendEveryXTimes: "Erneut versenden alle {0} mal",
|
||||||
|
resendDisabled: "Erneut versenden deaktiviert",
|
||||||
"Import Backup": "Backup importieren",
|
"Import Backup": "Backup importieren",
|
||||||
"Export Backup": "Backup exportieren",
|
"Export Backup": "Backup exportieren",
|
||||||
"Avg. Ping": "Durchschn. Ping",
|
"Avg. Ping": "Durchschn. Ping",
|
||||||
|
@ -2,6 +2,8 @@ export default {
|
|||||||
languageName: "English",
|
languageName: "English",
|
||||||
checkEverySecond: "Check every {0} seconds",
|
checkEverySecond: "Check every {0} seconds",
|
||||||
retryCheckEverySecond: "Retry every {0} seconds",
|
retryCheckEverySecond: "Retry every {0} seconds",
|
||||||
|
resendEveryXTimes: "Resend every {0} times",
|
||||||
|
resendDisabled: "Resend disabled",
|
||||||
retriesDescription: "Maximum retries before the service is marked as down and a notification is sent",
|
retriesDescription: "Maximum retries before the service is marked as down and a notification is sent",
|
||||||
ignoreTLSError: "Ignore TLS/SSL error for HTTPS websites",
|
ignoreTLSError: "Ignore TLS/SSL error for HTTPS websites",
|
||||||
upsideDownModeDescription: "Flip the status upside down. If the service is reachable, it is DOWN.",
|
upsideDownModeDescription: "Flip the status upside down. If the service is reachable, it is DOWN.",
|
||||||
@ -74,6 +76,7 @@ export default {
|
|||||||
"Heartbeat Interval": "Heartbeat Interval",
|
"Heartbeat Interval": "Heartbeat Interval",
|
||||||
Retries: "Retries",
|
Retries: "Retries",
|
||||||
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
|
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
|
||||||
|
"Resend Notification if Down X times consequently": "Resend Notification if Down X times consequently",
|
||||||
Advanced: "Advanced",
|
Advanced: "Advanced",
|
||||||
"Upside Down Mode": "Upside Down Mode",
|
"Upside Down Mode": "Upside Down Mode",
|
||||||
"Max. Redirects": "Max. Redirects",
|
"Max. Redirects": "Max. Redirects",
|
||||||
@ -410,6 +413,8 @@ export default {
|
|||||||
SignName: "SignName",
|
SignName: "SignName",
|
||||||
"Sms template must contain parameters: ": "Sms template must contain parameters: ",
|
"Sms template must contain parameters: ": "Sms template must contain parameters: ",
|
||||||
"Bark Endpoint": "Bark Endpoint",
|
"Bark Endpoint": "Bark Endpoint",
|
||||||
|
"Bark Group": "Bark Group",
|
||||||
|
"Bark Sound": "Bark Sound",
|
||||||
WebHookUrl: "WebHookUrl",
|
WebHookUrl: "WebHookUrl",
|
||||||
SecretKey: "SecretKey",
|
SecretKey: "SecretKey",
|
||||||
"For safety, must use secret key": "For safety, must use secret key",
|
"For safety, must use secret key": "For safety, must use secret key",
|
||||||
@ -469,6 +474,7 @@ export default {
|
|||||||
"Domain Name Expiry Notification": "Domain Name Expiry Notification",
|
"Domain Name Expiry Notification": "Domain Name Expiry Notification",
|
||||||
Proxy: "Proxy",
|
Proxy: "Proxy",
|
||||||
"Date Created": "Date Created",
|
"Date Created": "Date Created",
|
||||||
|
HomeAssistant: "Home Assistant",
|
||||||
onebotHttpAddress: "OneBot HTTP Address",
|
onebotHttpAddress: "OneBot HTTP Address",
|
||||||
onebotMessageType: "OneBot Message Type",
|
onebotMessageType: "OneBot Message Type",
|
||||||
onebotGroupMessage: "Group",
|
onebotGroupMessage: "Group",
|
||||||
@ -481,6 +487,12 @@ export default {
|
|||||||
"Domain Names": "Domain Names",
|
"Domain Names": "Domain Names",
|
||||||
signedInDisp: "Signed in as {0}",
|
signedInDisp: "Signed in as {0}",
|
||||||
signedInDispDisabled: "Auth Disabled.",
|
signedInDispDisabled: "Auth Disabled.",
|
||||||
|
RadiusSecret: "Radius Secret",
|
||||||
|
RadiusSecretDescription: "Shared Secret between client and server",
|
||||||
|
RadiusCalledStationId: "Called Station Id",
|
||||||
|
RadiusCalledStationIdDescription: "Identifier of the called device",
|
||||||
|
RadiusCallingStationId: "Calling Station Id",
|
||||||
|
RadiusCallingStationIdDescription: "Identifier of the calling device",
|
||||||
"Certificate Expiry Notification": "Certificate Expiry Notification",
|
"Certificate Expiry Notification": "Certificate Expiry Notification",
|
||||||
"API Username": "API Username",
|
"API Username": "API Username",
|
||||||
"API Key": "API Key",
|
"API Key": "API Key",
|
||||||
|
@ -404,6 +404,8 @@ export default {
|
|||||||
TemplateCode: "TemplateCode",
|
TemplateCode: "TemplateCode",
|
||||||
SignName: "SignName",
|
SignName: "SignName",
|
||||||
"Bark Endpoint": "Bark 接入点",
|
"Bark Endpoint": "Bark 接入点",
|
||||||
|
"Bark Group": "Bark 群组",
|
||||||
|
"Bark Sound": "Bark 铃声",
|
||||||
"Device Token": "Apple Device Token",
|
"Device Token": "Apple Device Token",
|
||||||
Platform: "平台",
|
Platform: "平台",
|
||||||
iOS: "iOS",
|
iOS: "iOS",
|
||||||
|
@ -408,6 +408,8 @@ export default {
|
|||||||
SignName: "SignName",
|
SignName: "SignName",
|
||||||
"Sms template must contain parameters: ": "Sms 範本必須包含參數:",
|
"Sms template must contain parameters: ": "Sms 範本必須包含參數:",
|
||||||
"Bark Endpoint": "Bark 端點",
|
"Bark Endpoint": "Bark 端點",
|
||||||
|
"Bark Group": "Bark 群組",
|
||||||
|
"Bark Sound": "Bark 鈴聲",
|
||||||
WebHookUrl: "WebHookUrl",
|
WebHookUrl: "WebHookUrl",
|
||||||
SecretKey: "SecretKey",
|
SecretKey: "SecretKey",
|
||||||
"For safety, must use secret key": "為了安全起見,必須使用秘密金鑰",
|
"For safety, must use secret key": "為了安全起見,必須使用秘密金鑰",
|
||||||
|
@ -54,6 +54,9 @@
|
|||||||
<option value="postgres">
|
<option value="postgres">
|
||||||
PostgreSQL
|
PostgreSQL
|
||||||
</option>
|
</option>
|
||||||
|
<option value="radius">
|
||||||
|
Radius
|
||||||
|
</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -96,8 +99,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Hostname -->
|
<!-- Hostname -->
|
||||||
<!-- TCP Port / Ping / DNS / Steam / MQTT only -->
|
<!-- TCP Port / Ping / DNS / Steam / MQTT / Radius only -->
|
||||||
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam' || monitor.type === 'mqtt'" class="my-3">
|
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam' || monitor.type === 'mqtt' || monitor.type === 'radius'" class="my-3">
|
||||||
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
|
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
|
||||||
<input id="hostname" v-model="monitor.hostname" type="text" class="form-control" :pattern="`${ipRegexPattern}|${hostnameRegexPattern}`" required>
|
<input id="hostname" v-model="monitor.hostname" type="text" class="form-control" :pattern="`${ipRegexPattern}|${hostnameRegexPattern}`" required>
|
||||||
</div>
|
</div>
|
||||||
@ -211,6 +214,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-if="monitor.type === 'radius'">
|
||||||
|
<div class="my-3">
|
||||||
|
<label for="radius_username" class="form-label">Radius {{ $t("Username") }}</label>
|
||||||
|
<input id="radius_username" v-model="monitor.radiusUsername" type="text" class="form-control" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="my-3">
|
||||||
|
<label for="radius_password" class="form-label">Radius {{ $t("Password") }}</label>
|
||||||
|
<input id="radius_password" v-model="monitor.radiusPassword" type="password" class="form-control" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="my-3">
|
||||||
|
<label for="radius_secret" class="form-label">{{ $t("RadiusSecret") }}</label>
|
||||||
|
<input id="radius_secret" v-model="monitor.radiusSecret" type="password" class="form-control" required />
|
||||||
|
<div class="form-text"> {{ $t( "RadiusSecretDescription") }} </div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="my-3">
|
||||||
|
<label for="radius_called_station_id" class="form-label">{{ $t("RadiusCalledStationId") }}</label>
|
||||||
|
<input id="radius_called_station_id" v-model="monitor.radiusCalledStationId" type="text" class="form-control" required />
|
||||||
|
<div class="form-text"> {{ $t( "RadiusCalledStationIdDescription") }} </div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="my-3">
|
||||||
|
<label for="radius_calling_station_id" class="form-label">{{ $t("RadiusCallingStationId") }}</label>
|
||||||
|
<input id="radius_calling_station_id" v-model="monitor.radiusCallingStationId" type="text" class="form-control" required />
|
||||||
|
<div class="form-text"> {{ $t( "RadiusCallingStationIdDescription") }} </div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- SQL Server and PostgreSQL -->
|
<!-- SQL Server and PostgreSQL -->
|
||||||
<template v-if="monitor.type === 'sqlserver' || monitor.type === 'postgres'">
|
<template v-if="monitor.type === 'sqlserver' || monitor.type === 'postgres'">
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
@ -251,6 +284,15 @@
|
|||||||
<input id="retry-interval" v-model="monitor.retryInterval" type="number" class="form-control" required min="20" step="1">
|
<input id="retry-interval" v-model="monitor.retryInterval" type="number" class="form-control" required min="20" step="1">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="my-3">
|
||||||
|
<label for="resend-interval" class="form-label">
|
||||||
|
{{ $t("Resend Notification if Down X times consequently") }}
|
||||||
|
<span v-if="monitor.resendInterval > 0">({{ $t("resendEveryXTimes", [ monitor.resendInterval ]) }})</span>
|
||||||
|
<span v-else>({{ $t("resendDisabled") }})</span>
|
||||||
|
</label>
|
||||||
|
<input id="resend-interval" v-model="monitor.resendInterval" type="number" class="form-control" required min="0" step="1">
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2 v-if="monitor.type !== 'push'" class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
<h2 v-if="monitor.type !== 'push'" class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
||||||
|
|
||||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
|
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
|
||||||
@ -719,6 +761,7 @@ message HealthCheckResponse {
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
interval: 60,
|
interval: 60,
|
||||||
retryInterval: this.interval,
|
retryInterval: this.interval,
|
||||||
|
resendInterval: 0,
|
||||||
maxretries: 0,
|
maxretries: 0,
|
||||||
notificationIDList: {},
|
notificationIDList: {},
|
||||||
ignoreTls: false,
|
ignoreTls: false,
|
||||||
|
Loading…
Reference in New Issue
Block a user