mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-02-25 13:05:55 +00:00
Merge remote-tracking branch 'upstream/master' into add-xml-support-to-http-monitors
# Conflicts: # src/languages/en.js
This commit is contained in:
commit
1901d93f51
24 changed files with 1806 additions and 1191 deletions
|
@ -1,6 +1,6 @@
|
||||||
# Project Info
|
# Project Info
|
||||||
|
|
||||||
First of all, thank you everyone who made pull requests for Uptime Kuma, I never thought GitHub Community can be that nice! And also because of this, I also never thought other people actually read my code and edit my code. It is not structured and commented so well, lol. Sorry about that.
|
First of all, I want to thank everyone who made pull requests for Uptime Kuma. I never thought the GitHub Community would be so nice! Because of this, I also never thought that other people would actually read and edit my code. It is not very well structured or commented, sorry about that.
|
||||||
|
|
||||||
The project was created with vite.js (vue3). Then I created a subdirectory called "server" for server part. Both frontend and backend share the same package.json.
|
The project was created with vite.js (vue3). Then I created a subdirectory called "server" for server part. Both frontend and backend share the same package.json.
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ The frontend code build into "dist" directory. The server (express.js) exposes t
|
||||||
|
|
||||||
## Can I create a pull request for Uptime Kuma?
|
## Can I create a pull request for Uptime Kuma?
|
||||||
|
|
||||||
Yes or no, it depends on what you will try to do. Since I don't want to waste your time, be sure to **create an empty draft pull request or open an issue, so we can discuss first**. Especially for a large pull request or you don't know it will be merged or not.
|
Yes or no, it depends on what you will try to do. Since I don't want to waste your time, be sure to **create an empty draft pull request or open an issue, so we can have a discussion first**. Especially for a large pull request or you don't know it will be merged or not.
|
||||||
|
|
||||||
Here are some references:
|
Here are some references:
|
||||||
|
|
||||||
|
@ -48,8 +48,13 @@ Here are some references:
|
||||||
- UI/UX is not close to Uptime Kuma
|
- UI/UX is not close to Uptime Kuma
|
||||||
- Existing logic is completely modified or deleted for no reason
|
- Existing logic is completely modified or deleted for no reason
|
||||||
- A function that is completely out of scope
|
- A function that is completely out of scope
|
||||||
|
- Convert existing code into other programming languages
|
||||||
- Unnecessary large code changes (Hard to review, causes code conflicts to other pull requests)
|
- Unnecessary large code changes (Hard to review, causes code conflicts to other pull requests)
|
||||||
|
|
||||||
|
The above cases cannot cover all situations.
|
||||||
|
|
||||||
|
I (@louislam) have the final say. If your pull request does not meet my expectations, I will reject it, no matter how much time you spend on it. Therefore, it is essential to have a discussion beforehand.
|
||||||
|
|
||||||
I will mark your pull request in the [milestones](https://github.com/louislam/uptime-kuma/milestones), if I am plan to review and merge it.
|
I will mark your pull request in the [milestones](https://github.com/louislam/uptime-kuma/milestones), if I am plan to review and merge it.
|
||||||
|
|
||||||
Also, please don't rush or ask for ETA, because I have to understand the pull request, make sure it is no breaking changes and stick to my vision of this project, especially for large pull requests.
|
Also, please don't rush or ask for ETA, because I have to understand the pull request, make sure it is no breaking changes and stick to my vision of this project, especially for large pull requests.
|
||||||
|
@ -72,9 +77,9 @@ Before deep into coding, discussion first is preferred. Creating an empty pull r
|
||||||
|
|
||||||
## Project Styles
|
## Project Styles
|
||||||
|
|
||||||
I personally do not like something need to learn so much and need to config so much before you can finally start the app.
|
I personally do not like it when something requires so much learning and configuration before you can finally start the app.
|
||||||
|
|
||||||
- Easy to install for non-Docker users, no native build dependency is needed (at least for x86_64), no extra config, no extra effort to get it run
|
- Easy to install for non-Docker users, no native build dependency is needed (at least for x86_64), no extra config, no extra effort required to get it running
|
||||||
- Single container for Docker users, no very complex docker-compose file. Just map the volume and expose the port, then good to go
|
- Single container for Docker users, no very complex docker-compose file. Just map the volume and expose the port, then good to go
|
||||||
- Settings should be configurable in the frontend. Environment variable is not encouraged, unless it is related to startup such as `DATA_DIR`.
|
- Settings should be configurable in the frontend. Environment variable is not encouraged, unless it is related to startup such as `DATA_DIR`.
|
||||||
- Easy to use
|
- Easy to use
|
||||||
|
@ -172,15 +177,11 @@ The data and socket logic are in `src/mixins/socket.js`.
|
||||||
|
|
||||||
## Unit Test
|
## Unit Test
|
||||||
|
|
||||||
It is an end-to-end testing. It is using Jest and Puppeteer.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
npm test
|
npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, the Chromium window will be shown up during the test. Specifying `HEADLESS_TEST=1` for terminal environments.
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
Both frontend and backend share the same package.json. However, the frontend dependencies are eventually not used in the production environment, because it is usually also baked into dist files. So:
|
Both frontend and backend share the same package.json. However, the frontend dependencies are eventually not used in the production environment, because it is usually also baked into dist files. So:
|
||||||
|
|
26
README.md
26
README.md
|
@ -22,17 +22,17 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Use the
|
||||||
|
|
||||||
## ⭐ Features
|
## ⭐ Features
|
||||||
|
|
||||||
* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / Ping / DNS Record / Push / Steam Game Server / Docker Containers.
|
* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / Ping / DNS Record / Push / Steam Game Server / Docker Containers
|
||||||
* Fancy, Reactive, Fast UI/UX.
|
* Fancy, Reactive, Fast UI/UX
|
||||||
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications).
|
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications)
|
||||||
* 20 second intervals.
|
* 20 second intervals
|
||||||
* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/languages)
|
* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/languages)
|
||||||
* Multiple Status Pages
|
* Multiple status pages
|
||||||
* Map Status Page to Domain
|
* Map status pages to specific domains
|
||||||
* Ping Chart
|
* Ping chart
|
||||||
* Certificate Info
|
* Certificate info
|
||||||
* Proxy Support
|
* Proxy support
|
||||||
* 2FA available
|
* 2FA support
|
||||||
|
|
||||||
## 🔧 How to Install
|
## 🔧 How to Install
|
||||||
|
|
||||||
|
@ -44,14 +44,14 @@ docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name upti
|
||||||
|
|
||||||
⚠️ Please use a **local volume** only. Other types such as NFS are not supported.
|
⚠️ Please use a **local volume** only. Other types such as NFS are not supported.
|
||||||
|
|
||||||
Browse to http://localhost:3001 after starting.
|
Uptime Kuma is now running on http://localhost:3001
|
||||||
|
|
||||||
### 💪🏻 Non-Docker
|
### 💪🏻 Non-Docker
|
||||||
|
|
||||||
Required Tools:
|
Required Tools:
|
||||||
- [Node.js](https://nodejs.org/en/download/) >= 14
|
- [Node.js](https://nodejs.org/en/download/) >= 14
|
||||||
- [Git](https://git-scm.com/downloads)
|
- [Git](https://git-scm.com/downloads)
|
||||||
- [pm2](https://pm2.keymetrics.io/) - For run in background
|
- [pm2](https://pm2.keymetrics.io/) - For running Uptime Kuma in the background
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Update your npm to the latest version
|
# Update your npm to the latest version
|
||||||
|
@ -73,7 +73,7 @@ pm2 start server/server.js --name uptime-kuma
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
Browse to http://localhost:3001 after starting.
|
Uptime Kuma is now running on http://localhost:3001
|
||||||
|
|
||||||
More useful PM2 Commands
|
More useful PM2 Commands
|
||||||
|
|
||||||
|
|
|
@ -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==1.2.0 && \
|
pip3 --no-cache-dir install apprise==1.2.1 && \
|
||||||
rm -rf /root/.cache
|
rm -rf /root/.cache
|
||||||
|
|
16
docker/builder-go.dockerfile
Normal file
16
docker/builder-go.dockerfile
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
############################################
|
||||||
|
# Build in Golang
|
||||||
|
# Run npm run build-healthcheck-armv7 in the host first, another it will be super slow where it is building the armv7 healthcheck
|
||||||
|
############################################
|
||||||
|
FROM golang:1.19.4-buster
|
||||||
|
WORKDIR /app
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
COPY ./extra/ ./extra/
|
||||||
|
|
||||||
|
# Compile healthcheck.go
|
||||||
|
RUN apt update
|
||||||
|
RUN apt --yes --no-install-recommends install curl
|
||||||
|
RUN curl -sL https://deb.nodesource.com/setup_18.x | bash
|
||||||
|
RUN apt --yes --no-install-recommends install nodejs
|
||||||
|
RUN node -v
|
||||||
|
RUN node ./extra/build-healthcheck.js $TARGETPLATFORM
|
|
@ -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==1.2.0 && \
|
pip3 --no-cache-dir install apprise==1.2.1 && \
|
||||||
rm -rf /var/lib/apt/lists/* && \
|
rm -rf /var/lib/apt/lists/* && \
|
||||||
apt --yes autoremove
|
apt --yes autoremove
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,9 @@
|
||||||
############################################
|
############################################
|
||||||
# Build in Golang
|
# Build in Golang
|
||||||
# Run npm run build-healthcheck-armv7 in the host first, another it will be super slow where it is building the armv7 healthcheck
|
# Run npm run build-healthcheck-armv7 in the host first, another it will be super slow where it is building the armv7 healthcheck
|
||||||
|
# Check file: builder-go.dockerfile
|
||||||
############################################
|
############################################
|
||||||
FROM golang:1.19.4-buster AS build_healthcheck
|
FROM louislam/uptime-kuma:builder-go AS build_healthcheck
|
||||||
WORKDIR /app
|
|
||||||
ARG TARGETPLATFORM
|
|
||||||
COPY ./extra/ ./extra/
|
|
||||||
|
|
||||||
# Compile healthcheck.go
|
|
||||||
RUN apt update
|
|
||||||
RUN apt --yes --no-install-recommends install curl
|
|
||||||
RUN curl -sL https://deb.nodesource.com/setup_18.x | bash
|
|
||||||
RUN apt --yes --no-install-recommends install nodejs
|
|
||||||
RUN node -v
|
|
||||||
RUN node ./extra/build-healthcheck.js $TARGETPLATFORM
|
|
||||||
|
|
||||||
############################################
|
############################################
|
||||||
# Build in Node.js
|
# Build in Node.js
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/*
|
||||||
|
* If changed, have to run `npm run build-docker-builder-go`.
|
||||||
|
* This script should be run after a period of time (180s), because the server may need some time to prepare.
|
||||||
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
2266
package-lock.json
generated
2266
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.19.2",
|
"version": "1.19.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -31,6 +31,7 @@
|
||||||
"build-docker": "npm run build && npm run build-docker-debian && npm run build-docker-alpine",
|
"build-docker": "npm run build && npm run build-docker-debian && npm run build-docker-alpine",
|
||||||
"build-docker-alpine-base": "docker buildx build -f docker/alpine-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-alpine . --push",
|
"build-docker-alpine-base": "docker buildx build -f docker/alpine-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-alpine . --push",
|
||||||
"build-docker-debian-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-debian . --push",
|
"build-docker-debian-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-debian . --push",
|
||||||
|
"build-docker-builder-go": "docker buildx build -f docker/builder-go.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:builder-go . --push",
|
||||||
"build-docker-alpine": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:$VERSION-alpine --target release . --push",
|
"build-docker-alpine": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:$VERSION-alpine --target release . --push",
|
||||||
"build-docker-debian": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:$VERSION-debian --target release . --push",
|
"build-docker-debian": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:$VERSION-debian --target release . --push",
|
||||||
"build-docker-nightly": "npm run build && docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
|
"build-docker-nightly": "npm run build && docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
|
||||||
|
@ -38,7 +39,7 @@
|
||||||
"build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
|
"build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
|
||||||
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test --target pr-test . --push",
|
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test --target pr-test . --push",
|
||||||
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||||
"setup": "git checkout 1.19.2 && npm ci --production && npm run download-dist",
|
"setup": "git checkout 1.19.3 && npm ci --production && npm run download-dist",
|
||||||
"download-dist": "node extra/download-dist.js",
|
"download-dist": "node extra/download-dist.js",
|
||||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||||
"reset-password": "node extra/reset-password.js",
|
"reset-password": "node extra/reset-password.js",
|
||||||
|
@ -90,7 +91,7 @@
|
||||||
"https-proxy-agent": "~5.0.1",
|
"https-proxy-agent": "~5.0.1",
|
||||||
"iconv-lite": "~0.6.3",
|
"iconv-lite": "~0.6.3",
|
||||||
"jsesc": "~3.0.2",
|
"jsesc": "~3.0.2",
|
||||||
"jsonwebtoken": "~8.5.1",
|
"jsonwebtoken": "~9.0.0",
|
||||||
"jwt-decode": "~3.1.2",
|
"jwt-decode": "~3.1.2",
|
||||||
"limiter": "~2.1.0",
|
"limiter": "~2.1.0",
|
||||||
"mqtt": "~4.3.7",
|
"mqtt": "~4.3.7",
|
||||||
|
@ -103,6 +104,7 @@
|
||||||
"password-hash": "~1.2.2",
|
"password-hash": "~1.2.2",
|
||||||
"pg": "~8.8.0",
|
"pg": "~8.8.0",
|
||||||
"pg-connection-string": "~2.5.0",
|
"pg-connection-string": "~2.5.0",
|
||||||
|
"ping": "~0.4.2",
|
||||||
"prom-client": "~13.2.0",
|
"prom-client": "~13.2.0",
|
||||||
"prometheus-api-metrics": "~3.2.1",
|
"prometheus-api-metrics": "~3.2.1",
|
||||||
"protobufjs": "~7.1.1",
|
"protobufjs": "~7.1.1",
|
||||||
|
|
|
@ -25,15 +25,20 @@ const DEFAULT_KEEP_PERIOD = 180;
|
||||||
parsedPeriod = DEFAULT_KEEP_PERIOD;
|
parsedPeriod = DEFAULT_KEEP_PERIOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(`Clearing Data older than ${parsedPeriod} days...`);
|
if (parsedPeriod < 1) {
|
||||||
|
log(`Data deletion has been disabled as period is less than 1. Period is ${parsedPeriod} days.`);
|
||||||
|
} else {
|
||||||
|
|
||||||
try {
|
log(`Clearing Data older than ${parsedPeriod} days...`);
|
||||||
await R.exec(
|
|
||||||
"DELETE FROM heartbeat WHERE time < DATETIME('now', '-' || ? || ' days') ",
|
try {
|
||||||
[ parsedPeriod ]
|
await R.exec(
|
||||||
);
|
"DELETE FROM heartbeat WHERE time < DATETIME('now', '-' || ? || ' days') ",
|
||||||
} catch (e) {
|
[ parsedPeriod ]
|
||||||
log(`Failed to clear old data: ${e.message}`);
|
);
|
||||||
|
} catch (e) {
|
||||||
|
log(`Failed to clear old data: ${e.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit();
|
exit();
|
||||||
|
|
|
@ -527,7 +527,9 @@ class Monitor extends BeanModel {
|
||||||
let res = await axios.request(options);
|
let res = await axios.request(options);
|
||||||
if (res.data.State.Running) {
|
if (res.data.State.Running) {
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
bean.msg = "";
|
bean.msg = res.data.State.Status;
|
||||||
|
} else {
|
||||||
|
throw Error("Container State is " + res.data.State.Status);
|
||||||
}
|
}
|
||||||
} else if (this.type === "mqtt") {
|
} else if (this.type === "mqtt") {
|
||||||
bean.msg = await mqttAsync(this.hostname, this.mqttTopic, this.mqttSuccessMessage, {
|
bean.msg = await mqttAsync(this.hostname, this.mqttTopic, this.mqttSuccessMessage, {
|
||||||
|
|
|
@ -281,7 +281,7 @@ class StatusPage extends BeanModel {
|
||||||
|
|
||||||
let activeCondition = Maintenance.getActiveMaintenanceSQLCondition();
|
let activeCondition = Maintenance.getActiveMaintenanceSQLCondition();
|
||||||
let maintenanceBeanList = R.convertToBeans("maintenance", await R.getAll(`
|
let maintenanceBeanList = R.convertToBeans("maintenance", await R.getAll(`
|
||||||
SELECT maintenance.*
|
SELECT DISTINCT maintenance.*
|
||||||
FROM maintenance
|
FROM maintenance
|
||||||
JOIN maintenance_status_page
|
JOIN maintenance_status_page
|
||||||
ON maintenance_status_page.maintenance_id = maintenance.id
|
ON maintenance_status_page.maintenance_id = maintenance.id
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Pushover extends NotificationProvider {
|
||||||
let pushoverlink = "https://api.pushover.net/1/messages.json";
|
let pushoverlink = "https://api.pushover.net/1/messages.json";
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
"message": "<b>Uptime Kuma Alert</b>\n\n<b>Message</b>:" + msg,
|
"message": "<b>Message</b>:" + msg,
|
||||||
"user": notification.pushoveruserkey,
|
"user": notification.pushoveruserkey,
|
||||||
"token": notification.pushoverapptoken,
|
"token": notification.pushoverapptoken,
|
||||||
"sound": notification.pushoversounds,
|
"sound": notification.pushoversounds,
|
||||||
|
|
|
@ -1,199 +0,0 @@
|
||||||
// https://github.com/ben-bradley/ping-lite/blob/master/ping-lite.js
|
|
||||||
// Fixed on Windows
|
|
||||||
const net = require("net");
|
|
||||||
const spawn = require("child_process").spawn;
|
|
||||||
const events = require("events");
|
|
||||||
const fs = require("fs");
|
|
||||||
const util = require("./util-server");
|
|
||||||
|
|
||||||
module.exports = Ping;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for ping class
|
|
||||||
* @param {string} host Host to ping
|
|
||||||
* @param {object} [options] Options for the ping command
|
|
||||||
* @param {array|string} [options.args] - Arguments to pass to the ping command
|
|
||||||
*/
|
|
||||||
function Ping(host, options) {
|
|
||||||
if (!host) {
|
|
||||||
throw new Error("You must specify a host to ping!");
|
|
||||||
}
|
|
||||||
|
|
||||||
this._host = host;
|
|
||||||
this._options = options = (options || {});
|
|
||||||
|
|
||||||
events.EventEmitter.call(this);
|
|
||||||
|
|
||||||
const timeout = 10;
|
|
||||||
|
|
||||||
if (util.WIN) {
|
|
||||||
this._bin = "c:/windows/system32/ping.exe";
|
|
||||||
this._args = (options.args) ? options.args : [ "-n", "1", "-w", timeout * 1000, host ];
|
|
||||||
this._regmatch = /[><=]([0-9.]+?)ms/;
|
|
||||||
|
|
||||||
} else if (util.LIN) {
|
|
||||||
this._bin = "/bin/ping";
|
|
||||||
|
|
||||||
const defaultArgs = [ "-n", "-w", timeout, "-c", "1", host ];
|
|
||||||
|
|
||||||
if (net.isIPv6(host) || options.ipv6) {
|
|
||||||
defaultArgs.unshift("-6");
|
|
||||||
}
|
|
||||||
|
|
||||||
this._args = (options.args) ? options.args : defaultArgs;
|
|
||||||
this._regmatch = /=([0-9.]+?) ms/;
|
|
||||||
|
|
||||||
} else if (util.MAC) {
|
|
||||||
|
|
||||||
if (net.isIPv6(host) || options.ipv6) {
|
|
||||||
this._bin = "/sbin/ping6";
|
|
||||||
} else {
|
|
||||||
this._bin = "/sbin/ping";
|
|
||||||
}
|
|
||||||
|
|
||||||
this._args = (options.args) ? options.args : [ "-n", "-t", timeout, "-c", "1", host ];
|
|
||||||
this._regmatch = /=([0-9.]+?) ms/;
|
|
||||||
|
|
||||||
} else if (util.BSD) {
|
|
||||||
this._bin = "/sbin/ping";
|
|
||||||
|
|
||||||
const defaultArgs = [ "-n", "-t", timeout, "-c", "1", host ];
|
|
||||||
|
|
||||||
if (net.isIPv6(host) || options.ipv6) {
|
|
||||||
defaultArgs.unshift("-6");
|
|
||||||
}
|
|
||||||
|
|
||||||
this._args = (options.args) ? options.args : defaultArgs;
|
|
||||||
this._regmatch = /=([0-9.]+?) ms/;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new Error("Could not detect your ping binary.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs.existsSync(this._bin)) {
|
|
||||||
throw new Error("Could not detect " + this._bin + " on your system");
|
|
||||||
}
|
|
||||||
|
|
||||||
this._i = 0;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ping.prototype.__proto__ = events.EventEmitter.prototype;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for send
|
|
||||||
* @callback pingCB
|
|
||||||
* @param {any} err Any error encountered
|
|
||||||
* @param {number} ms Ping time in ms
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a ping
|
|
||||||
* @param {pingCB} callback Callback to call with results
|
|
||||||
*/
|
|
||||||
Ping.prototype.send = function (callback) {
|
|
||||||
let self = this;
|
|
||||||
callback = callback || function (err, ms) {
|
|
||||||
if (err) {
|
|
||||||
return self.emit("error", err);
|
|
||||||
}
|
|
||||||
return self.emit("result", ms);
|
|
||||||
};
|
|
||||||
|
|
||||||
let _ended;
|
|
||||||
let _exited;
|
|
||||||
let _errored;
|
|
||||||
|
|
||||||
this._ping = spawn(this._bin, this._args, { windowsHide: true }); // spawn the binary
|
|
||||||
|
|
||||||
this._ping.on("error", function (err) { // handle binary errors
|
|
||||||
_errored = true;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
this._ping.stdout.on("data", function (data) { // log stdout
|
|
||||||
if (util.WIN) {
|
|
||||||
data = convertOutput(data);
|
|
||||||
}
|
|
||||||
this._stdout = (this._stdout || "") + data;
|
|
||||||
});
|
|
||||||
|
|
||||||
this._ping.stdout.on("end", function () {
|
|
||||||
_ended = true;
|
|
||||||
if (_exited && !_errored) {
|
|
||||||
onEnd.call(self._ping);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this._ping.stderr.on("data", function (data) { // log stderr
|
|
||||||
if (util.WIN) {
|
|
||||||
data = convertOutput(data);
|
|
||||||
}
|
|
||||||
this._stderr = (this._stderr || "") + data;
|
|
||||||
});
|
|
||||||
|
|
||||||
this._ping.on("exit", function (code) { // handle complete
|
|
||||||
_exited = true;
|
|
||||||
if (_ended && !_errored) {
|
|
||||||
onEnd.call(self._ping);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Function} callback
|
|
||||||
*
|
|
||||||
* Generated by Trelent
|
|
||||||
*/
|
|
||||||
function onEnd() {
|
|
||||||
let stdout = this.stdout._stdout;
|
|
||||||
let stderr = this.stderr._stderr;
|
|
||||||
let ms;
|
|
||||||
|
|
||||||
if (stderr) {
|
|
||||||
return callback(new Error(stderr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stdout) {
|
|
||||||
return callback(new Error("No stdout detected"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ms = stdout.match(self._regmatch); // parse out the ##ms response
|
|
||||||
ms = (ms && ms[1]) ? Number(ms[1]) : ms;
|
|
||||||
|
|
||||||
callback(null, ms, stdout);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ping every interval
|
|
||||||
* @param {pingCB} callback Callback to call with results
|
|
||||||
*/
|
|
||||||
Ping.prototype.start = function (callback) {
|
|
||||||
let self = this;
|
|
||||||
this._i = setInterval(function () {
|
|
||||||
self.send(callback);
|
|
||||||
}, (self._options.interval || 5000));
|
|
||||||
self.send(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Stop sending pings */
|
|
||||||
Ping.prototype.stop = function () {
|
|
||||||
clearInterval(this._i);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to convert to UTF-8 for Windows, as the ping's output on Windows is not UTF-8 and could be in other languages
|
|
||||||
* Thank @pemassi
|
|
||||||
* https://github.com/louislam/uptime-kuma/issues/570#issuecomment-941984094
|
|
||||||
* @param {any} data
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function convertOutput(data) {
|
|
||||||
if (util.WIN) {
|
|
||||||
if (data) {
|
|
||||||
return util.convertToUTF8(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
const tcpp = require("tcp-ping");
|
const tcpp = require("tcp-ping");
|
||||||
const Ping = require("./ping-lite");
|
const ping = require("ping");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const { log, genSecret } = require("../src/util");
|
const { log, genSecret } = require("../src/util");
|
||||||
const passwordHash = require("./password-hash");
|
const passwordHash = require("./password-hash");
|
||||||
|
@ -26,12 +26,7 @@ const {
|
||||||
} = require("node-radius-utils");
|
} = require("node-radius-utils");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
|
|
||||||
// From ping-lite
|
const isWindows = process.platform === /^win/.test(process.platform);
|
||||||
exports.WIN = /^win/.test(process.platform);
|
|
||||||
exports.LIN = /^linux/.test(process.platform);
|
|
||||||
exports.MAC = /^darwin/.test(process.platform);
|
|
||||||
exports.FBSD = /^freebsd/.test(process.platform);
|
|
||||||
exports.BSD = /bsd$/.test(process.platform);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init or reset JWT secret
|
* Init or reset JWT secret
|
||||||
|
@ -105,18 +100,23 @@ exports.ping = async (hostname) => {
|
||||||
*/
|
*/
|
||||||
exports.pingAsync = function (hostname, ipv6 = false) {
|
exports.pingAsync = function (hostname, ipv6 = false) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const ping = new Ping(hostname, {
|
ping.promise.probe(hostname, {
|
||||||
ipv6
|
v6: ipv6,
|
||||||
});
|
min_reply: 1,
|
||||||
|
timeout: 10,
|
||||||
ping.send(function (err, ms, stdout) {
|
}).then((res) => {
|
||||||
if (err) {
|
// If ping failed, it will set field to unknown
|
||||||
reject(err);
|
if (res.alive) {
|
||||||
} else if (ms === null) {
|
resolve(res.time);
|
||||||
reject(new Error(stdout));
|
|
||||||
} else {
|
} else {
|
||||||
resolve(Math.round(ms));
|
if (isWindows) {
|
||||||
|
reject(new Error(exports.convertToUTF8(res.output)));
|
||||||
|
} else {
|
||||||
|
reject(new Error(res.output));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -204,7 +204,7 @@ export default {
|
||||||
nameInvalid = false;
|
nameInvalid = false;
|
||||||
valueInvalid = false;
|
valueInvalid = false;
|
||||||
invalid = false;
|
invalid = false;
|
||||||
} else if (this.existingTags.filter(tag => tag.name === this.newDraftTag.name).length > 0) {
|
} else if (this.existingTags.filter(tag => tag.name === this.newDraftTag.name).length > 0 && this.newDraftTag.select == null) {
|
||||||
// Try to create new tag with existing name
|
// Try to create new tag with existing name
|
||||||
nameInvalid = true;
|
nameInvalid = true;
|
||||||
invalid = true;
|
invalid = true;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
settings.keepDataPeriodDays,
|
settings.keepDataPeriodDays,
|
||||||
])
|
])
|
||||||
}}
|
}}
|
||||||
|
{{ $t("infiniteRetention") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="keepDataPeriodDays"
|
id="keepDataPeriodDays"
|
||||||
|
@ -14,9 +15,12 @@
|
||||||
type="number"
|
type="number"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
required
|
required
|
||||||
min="1"
|
min="0"
|
||||||
step="1"
|
step="1"
|
||||||
/>
|
/>
|
||||||
|
<div v-if="settings.keepDataPeriodDays < 0" class="form-text">
|
||||||
|
{{ $t("dataRetentionTimeError") }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-4">
|
<div class="my-4">
|
||||||
<button class="btn btn-primary" type="button" @click="saveSettings()">
|
<button class="btn btn-primary" type="button" @click="saveSettings()">
|
||||||
|
|
|
@ -669,4 +669,10 @@ export default {
|
||||||
"General Monitor Type": "Общ тип монитор",
|
"General Monitor Type": "Общ тип монитор",
|
||||||
"Passive Monitor Type": "Пасивет тип монитор",
|
"Passive Monitor Type": "Пасивет тип монитор",
|
||||||
"Specific Monitor Type": "Специфичен тип монитор",
|
"Specific Monitor Type": "Специфичен тип монитор",
|
||||||
|
ZohoCliq: "ZohoCliq",
|
||||||
|
wayToGetZohoCliqURL: "Можете да научите как се създава URL адрес за уеб кука {0}.",
|
||||||
|
Kook: "Kook",
|
||||||
|
wayToGetKookBotToken: "Създайте приложение и вземете вашия бот токен на {0}",
|
||||||
|
wayToGetKookGuildID: "Превключете в 'Developer Mode' в 'Kook' настройките, след което десен клик върху 'guild' за да вземете неговото 'ID'",
|
||||||
|
"Guild ID": "Guild ID",
|
||||||
};
|
};
|
||||||
|
|
|
@ -675,5 +675,7 @@ export default {
|
||||||
"General Monitor Type": "General Monitor Type",
|
"General Monitor Type": "General Monitor Type",
|
||||||
"Passive Monitor Type": "Passive Monitor Type",
|
"Passive Monitor Type": "Passive Monitor Type",
|
||||||
"Specific Monitor Type": "Specific Monitor Type",
|
"Specific Monitor Type": "Specific Monitor Type",
|
||||||
|
dataRetentionTimeError: "Retention period must be 0 or greater",
|
||||||
|
infiniteRetention: "Set to 0 for infinite retention.",
|
||||||
"Body Encoding": "Body Encoding",
|
"Body Encoding": "Body Encoding",
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,7 +99,7 @@ export default {
|
||||||
pushOptionalParams: "Paramètres facultatifs : {0}",
|
pushOptionalParams: "Paramètres facultatifs : {0}",
|
||||||
Save: "Sauvegarder",
|
Save: "Sauvegarder",
|
||||||
Notifications: "Notifications",
|
Notifications: "Notifications",
|
||||||
"Not available, please setup.": "Pas de système de notification disponible, merci de le configurer.",
|
"Not available, please setup.": "Non disponible, merci de le configurer.",
|
||||||
"Setup Notification": "Créer une notification",
|
"Setup Notification": "Créer une notification",
|
||||||
Light: "Clair",
|
Light: "Clair",
|
||||||
Dark: "Sombre",
|
Dark: "Sombre",
|
||||||
|
@ -209,6 +209,7 @@ export default {
|
||||||
here: "ici",
|
here: "ici",
|
||||||
Required: "Requis",
|
Required: "Requis",
|
||||||
telegram: "Telegram",
|
telegram: "Telegram",
|
||||||
|
"ZohoCliq": "ZohoCliq",
|
||||||
"Bot Token": "Jeton du robot",
|
"Bot Token": "Jeton du robot",
|
||||||
wayToGetTelegramToken: "Vous pouvez obtenir un token depuis {0}.",
|
wayToGetTelegramToken: "Vous pouvez obtenir un token depuis {0}.",
|
||||||
"Chat ID": "Chat ID",
|
"Chat ID": "Chat ID",
|
||||||
|
@ -240,7 +241,8 @@ export default {
|
||||||
"Hello @everyone is...": "Bonjour {'@'}everyone il...",
|
"Hello @everyone is...": "Bonjour {'@'}everyone il...",
|
||||||
teams: "Microsoft Teams",
|
teams: "Microsoft Teams",
|
||||||
"Webhook URL": "URL vers le webhook",
|
"Webhook URL": "URL vers le webhook",
|
||||||
wayToGetTeamsURL: "Vous pouvez apprendre comment créer un Webhook {0}.",
|
wayToGetTeamsURL: "Vous pouvez apprendre comment créer une URL Webhook {0}.",
|
||||||
|
wayToGetZohoCliqURL: "Vous pouvez apprendre comment créer une URL Webhook {0}.",
|
||||||
signal: "Signal",
|
signal: "Signal",
|
||||||
Number: "Numéro",
|
Number: "Numéro",
|
||||||
Recipients: "Destinataires",
|
Recipients: "Destinataires",
|
||||||
|
@ -270,6 +272,10 @@ export default {
|
||||||
apprise: "Apprise (prend en charge plus de 50 services de notification)",
|
apprise: "Apprise (prend en charge plus de 50 services de notification)",
|
||||||
GoogleChat: "Google Chat (Google Workspace uniquement)",
|
GoogleChat: "Google Chat (Google Workspace uniquement)",
|
||||||
pushbullet: "Pushbullet",
|
pushbullet: "Pushbullet",
|
||||||
|
Kook: "Kook",
|
||||||
|
wayToGetKookBotToken: "Créez une application et récupérer le jeton de robot à l'addresse {0}",
|
||||||
|
wayToGetKookGuildID: "Passez en « mode développeur » dans les paramètres de Kook, et cliquez droit sur le Guild pour obtenir son identifiant",
|
||||||
|
"Guild ID": "Identifiant de Guild",
|
||||||
line: "Line Messenger",
|
line: "Line Messenger",
|
||||||
mattermost: "Mattermost",
|
mattermost: "Mattermost",
|
||||||
"User Key": "Clé d'utilisateur",
|
"User Key": "Clé d'utilisateur",
|
||||||
|
|
|
@ -582,4 +582,97 @@ export default {
|
||||||
goAlert: "GoAlert",
|
goAlert: "GoAlert",
|
||||||
backupOutdatedWarning: "Kullanımdan Kaldırıldı: Birçok özellik eklendiğinden ve bu yedekleme özelliği biraz bakımsız olduğundan, tam bir yedekleme oluşturamaz veya geri yükleyemez.",
|
backupOutdatedWarning: "Kullanımdan Kaldırıldı: Birçok özellik eklendiğinden ve bu yedekleme özelliği biraz bakımsız olduğundan, tam bir yedekleme oluşturamaz veya geri yükleyemez.",
|
||||||
backupRecommend: "Lütfen bunun yerine birimi veya veri klasörünü (./data/) doğrudan yedekleyin.",
|
backupRecommend: "Lütfen bunun yerine birimi veya veri klasörünü (./data/) doğrudan yedekleyin.",
|
||||||
|
enableGRPCTls: "TLS bağlantısıyla gRPC isteği göndermeye izin ver",
|
||||||
|
grpcMethodDescription: "Yöntem adı, sayHello, check, vb. gibi cammelCase biçimine dönüştürülür.",
|
||||||
|
Maintenance: "Bakım",
|
||||||
|
statusMaintenance: "Bakım",
|
||||||
|
"Schedule maintenance": "Bakım Planla",
|
||||||
|
"Affected Monitors": "Etkilenen Monitörler",
|
||||||
|
"Pick Affected Monitors...": "Etkilenen Monitörleri Seçin...",
|
||||||
|
"Start of maintenance": "Bakım başlangıcı",
|
||||||
|
"All Status Pages": "Tüm Durum Sayfaları",
|
||||||
|
"Select status pages...": "Durum sayfalarını seçin...",
|
||||||
|
recurringIntervalMessage: "Her gün bir kez çalıştırın | {0} günde bir çalıştırın",
|
||||||
|
affectedMonitorsDescription: "Geçerli bakımdan etkilenen monitörleri seçin",
|
||||||
|
affectedStatusPages: "Bu bakım mesajını seçili durum sayfalarında göster",
|
||||||
|
atLeastOneMonitor: "Etkilenen en az bir monitör seçin",
|
||||||
|
deleteMaintenanceMsg: "Bu bakımı silmek istediğinizden emin misiniz?",
|
||||||
|
ZohoCliq: "ZohoCliq",
|
||||||
|
webhookAdditionalHeadersTitle: "Ek Başlıklar",
|
||||||
|
webhookAdditionalHeadersDesc: "Webhook ile gönderilen ek başlıkları ayarlar.",
|
||||||
|
wayToGetZohoCliqURL: "Bir webhook URL'sinin nasıl oluşturulacağını öğrenebilirsiniz {0}.",
|
||||||
|
Kook: "Kook",
|
||||||
|
wayToGetKookBotToken: "Uygulama oluşturun ve {0} adresinde bot tokenı alın",
|
||||||
|
wayToGetKookGuildID: "Kook ayarında \"Geliştirici Modu\"nu açın ve kimliğini almak için guild'e sağ tıklayın",
|
||||||
|
"Guild ID": "Guild ID",
|
||||||
|
smseagle: "SMSEagle",
|
||||||
|
smseagleTo: "Telefon numara(ları)",
|
||||||
|
smseagleGroup: "Telefon defteri grubu ad(lar)ı",
|
||||||
|
smseagleContact: "Telefon rehberi kişi ad(lar)ı",
|
||||||
|
smseagleRecipientType: "Alıcı Türü",
|
||||||
|
smseagleRecipient: "Alıcı(lar) (birden çok olanlar virgülle ayrılmalıdır)",
|
||||||
|
smseagleToken: "API Erişim Tokenı",
|
||||||
|
smseagleUrl: "SMSEagle cihaz URL\"niz",
|
||||||
|
smseagleEncoding: "Unicode olarak gönder",
|
||||||
|
smseaglePriority: "Mesaj önceliği (0-9, varsayılan = 0)",
|
||||||
|
Optional: "İsteğe bağlı",
|
||||||
|
squadcast: "Squadcast",
|
||||||
|
SendKey: "SendKey",
|
||||||
|
"SMSManager API Docs": "SMSManager API Dökümanları ",
|
||||||
|
"Gateway Type": "Ağ Geçidi Türü",
|
||||||
|
SMSManager: "SMSManager",
|
||||||
|
"You can divide numbers with": "Sayıları aşağıdakilerle bölebilirsiniz",
|
||||||
|
or: "veya",
|
||||||
|
recurringInterval: "Sıklık",
|
||||||
|
Recurring: "Yineleme",
|
||||||
|
strategyManual: "Manuel olarak Aktif/Pasif",
|
||||||
|
warningTimezone: "Sunucunun kullandığı saat dilimi",
|
||||||
|
weekdayShortMon: "Pzt",
|
||||||
|
weekdayShortTue: "Sal",
|
||||||
|
weekdayShortWed: "Çar",
|
||||||
|
weekdayShortThu: "Per",
|
||||||
|
weekdayShortFri: "Cum",
|
||||||
|
weekdayShortSat: "Cmt",
|
||||||
|
weekdayShortSun: "Paz",
|
||||||
|
dayOfWeek: "Haftanın Günleri",
|
||||||
|
dayOfMonth: "Ayın Günleri",
|
||||||
|
lastDay: "Son Gün",
|
||||||
|
lastDay1: "Ayın Son Günü",
|
||||||
|
lastDay2: "Ayın 2. Son Günü",
|
||||||
|
lastDay3: "Ayın 3. Son Günü",
|
||||||
|
lastDay4: "Ayın 4. Son Günü",
|
||||||
|
"No Maintenance": "Bakım Yok",
|
||||||
|
pauseMaintenanceMsg: "Duraklatmak istediğinizden emin misiniz?",
|
||||||
|
"maintenanceStatus-under-maintenance": "Bakımda",
|
||||||
|
"maintenanceStatus-inactive": "Etkin Değil",
|
||||||
|
"maintenanceStatus-scheduled": "Planlanmış",
|
||||||
|
"maintenanceStatus-ended": "Bitti",
|
||||||
|
"maintenanceStatus-unknown": "Bilinmiyor",
|
||||||
|
"Display Timezone": "Saat dilimini göster",
|
||||||
|
"Server Timezone": "Sunucu Saat Dilimi",
|
||||||
|
statusPageMaintenanceEndDate: "Bitiş Zamanı",
|
||||||
|
IconUrl: "Icon URL",
|
||||||
|
"Enable DNS Cache": "DNS Önbelleğini Etkinleştir",
|
||||||
|
Enable: "Etkin",
|
||||||
|
Disable: "Devre Dışı",
|
||||||
|
dnsCacheDescription: "Bazı IPv6 ortamlarında çalışmıyor olabilir, herhangi bir sorunla karşılaşırsanız devre dışı bırakın.",
|
||||||
|
"Single Maintenance Window": "Tek Seferlik Bakım",
|
||||||
|
"Maintenance Time Window of a Day": "Bür Günlük Bakım",
|
||||||
|
"Effective Date Range": "Bakim Tarih Aralığı",
|
||||||
|
"Schedule Maintenance": "Bakım Planla",
|
||||||
|
"Date and Time": "Tarih ve Saat",
|
||||||
|
"DateTime Range": "Tarih ve Saat Aralığı",
|
||||||
|
Strategy: "Strateji",
|
||||||
|
"Free Mobile User Identifier": "Ücretsiz Mobil Kullanıcı ID",
|
||||||
|
"Free Mobile API Key": "Ücretsiz Mobil API Anahtarı",
|
||||||
|
"Enable TLS": "TLS'yi Etkinleştir",
|
||||||
|
"Proto Service Name": "Proto Service İsmi",
|
||||||
|
"Proto Method": "Proto Method",
|
||||||
|
"Proto Content": "Proto İçeriği",
|
||||||
|
Economy: "Ekonomik",
|
||||||
|
Lowcost: "Düşük maliyetli",
|
||||||
|
high: "Yüksek",
|
||||||
|
"General Monitor Type": "Genel Monitör Tipi",
|
||||||
|
"Passive Monitor Type": "Pasif Monitör Tipi",
|
||||||
|
"Specific Monitor Type": "Özel Monitör Tipi",
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,17 +2,35 @@ export default {
|
||||||
languageName: "简体中文",
|
languageName: "简体中文",
|
||||||
checkEverySecond: "检测频率 {0} 秒",
|
checkEverySecond: "检测频率 {0} 秒",
|
||||||
retryCheckEverySecond: "重试间隔 {0} 秒",
|
retryCheckEverySecond: "重试间隔 {0} 秒",
|
||||||
|
resendEveryXTimes: "每 {0} 次失败则重复发送一次",
|
||||||
|
resendDisabled: "为 0 时禁用重复发送",
|
||||||
retriesDescription: "服务被标记为故障并发送通知之前的最大重试次数",
|
retriesDescription: "服务被标记为故障并发送通知之前的最大重试次数",
|
||||||
ignoreTLSError: "忽略 HTTPS 站点的 TLS/SSL 错误",
|
ignoreTLSError: "忽略 HTTPS 站点的 TLS/SSL 错误",
|
||||||
upsideDownModeDescription: "反转状态监控,如果服务可访问,则认为是故障。",
|
upsideDownModeDescription: "反转状态监控,如果服务可访问,则认为是故障。",
|
||||||
maxRedirectDescription: "允许的最大重定向次数。设置为 0 禁用重定向。",
|
maxRedirectDescription: "允许的最大重定向次数。设置为 0 禁用重定向。",
|
||||||
|
enableGRPCTls: "允许通过 TLS 连接发送 gRPC 请求",
|
||||||
|
grpcMethodDescription: "方法名会转换为小驼峰格式,例如 sayHello、check 等等",
|
||||||
acceptedStatusCodesDescription: "选择被视为成功响应的状态码。",
|
acceptedStatusCodesDescription: "选择被视为成功响应的状态码。",
|
||||||
|
Maintenance: "维护",
|
||||||
|
statusMaintenance: "维护",
|
||||||
|
"Schedule maintenance": "计划维护",
|
||||||
|
"Affected Monitors": "受影响的监控项",
|
||||||
|
"Pick Affected Monitors...": "选择受影响的监控项…",
|
||||||
|
"Start of maintenance": "维护开始",
|
||||||
|
"All Status Pages": "所有状态页面",
|
||||||
|
"Select status pages...": "选择状态页面…",
|
||||||
|
recurringIntervalMessage: "每天一次 | 每 {0} 天一次",
|
||||||
|
affectedMonitorsDescription: "选择受当前维护影响的监控项",
|
||||||
|
affectedStatusPages: "在所选状态页面上显示此维护消息",
|
||||||
|
atLeastOneMonitor: "至少选择一个受影响的监控项",
|
||||||
passwordNotMatchMsg: "两次输入的密码不一致。",
|
passwordNotMatchMsg: "两次输入的密码不一致。",
|
||||||
notificationDescription: "通知必须被分配给监控项才能正常工作。",
|
notificationDescription: "通知必须被分配给监控项才能正常工作。",
|
||||||
keywordDescription: "在纯 HTML 或 JSON 响应中搜索关键字,区分大小写。",
|
keywordDescription: "在纯 HTML 或 JSON 响应中搜索关键字,区分大小写。",
|
||||||
pauseDashboardHome: "暂停",
|
pauseDashboardHome: "暂停",
|
||||||
deleteMonitorMsg: "确定要删除此监控项吗?",
|
deleteMonitorMsg: "确定要删除此监控项吗?",
|
||||||
|
deleteMaintenanceMsg: "确定要删除此维护吗?",
|
||||||
deleteNotificationMsg: "确定要为所有监控项删除此通知吗?",
|
deleteNotificationMsg: "确定要为所有监控项删除此通知吗?",
|
||||||
|
dnsPortDescription: "DNS 服务器端口,默认为 53,您可以在任何时候更改此端口.",
|
||||||
resolverserverDescription: "默认服务器是 Cloudflare。您随时可以修改解析服务器。",
|
resolverserverDescription: "默认服务器是 Cloudflare。您随时可以修改解析服务器。",
|
||||||
rrtypeDescription: "选择要监控的资源记录类型",
|
rrtypeDescription: "选择要监控的资源记录类型",
|
||||||
pauseMonitorMsg: "确定要暂停吗?",
|
pauseMonitorMsg: "确定要暂停吗?",
|
||||||
|
@ -34,7 +52,6 @@ export default {
|
||||||
Theme: "主题",
|
Theme: "主题",
|
||||||
General: "常规",
|
General: "常规",
|
||||||
"Primary Base URL": "站点主 URL",
|
"Primary Base URL": "站点主 URL",
|
||||||
About: "关于",
|
|
||||||
Version: "版本",
|
Version: "版本",
|
||||||
"Check Update On GitHub": "检查 GitHub 上的更新",
|
"Check Update On GitHub": "检查 GitHub 上的更新",
|
||||||
List: "列表",
|
List: "列表",
|
||||||
|
@ -72,6 +89,7 @@ export default {
|
||||||
"Heartbeat Interval": "心跳间隔",
|
"Heartbeat Interval": "心跳间隔",
|
||||||
Retries: "重试次数",
|
Retries: "重试次数",
|
||||||
"Heartbeat Retry Interval": "心跳重试间隔",
|
"Heartbeat Retry Interval": "心跳重试间隔",
|
||||||
|
"Resend Notification if Down X times consequently": "连续失败时重复发送通知的间隔次数",
|
||||||
Advanced: "高级",
|
Advanced: "高级",
|
||||||
"Upside Down Mode": "反转监控",
|
"Upside Down Mode": "反转监控",
|
||||||
"Max. Redirects": "最大重定向次数",
|
"Max. Redirects": "最大重定向次数",
|
||||||
|
@ -125,7 +143,6 @@ export default {
|
||||||
"Last Result": "上次结果",
|
"Last Result": "上次结果",
|
||||||
"Create your admin account": "创建管理员账户",
|
"Create your admin account": "创建管理员账户",
|
||||||
"Repeat Password": "重复密码",
|
"Repeat Password": "重复密码",
|
||||||
Backup: "备份",
|
|
||||||
"Import Backup": "导入备份",
|
"Import Backup": "导入备份",
|
||||||
"Export Backup": "导出备份",
|
"Export Backup": "导出备份",
|
||||||
Export: "导出",
|
Export: "导出",
|
||||||
|
@ -160,7 +177,7 @@ export default {
|
||||||
Token: "令牌",
|
Token: "令牌",
|
||||||
"Show URI": "显示 URI",
|
"Show URI": "显示 URI",
|
||||||
Tags: "标签",
|
Tags: "标签",
|
||||||
"Add New below or Select...": "在下面添加或选择...",
|
"Add New below or Select...": "在下面添加或选择…",
|
||||||
"Tag with this name already exist.": "相同名称的标签已存在。",
|
"Tag with this name already exist.": "相同名称的标签已存在。",
|
||||||
"Tag with this value already exist.": "相同内容的标签已存在。",
|
"Tag with this value already exist.": "相同内容的标签已存在。",
|
||||||
color: "颜色",
|
color: "颜色",
|
||||||
|
@ -173,7 +190,7 @@ export default {
|
||||||
Indigo: "靛蓝",
|
Indigo: "靛蓝",
|
||||||
Purple: "紫色",
|
Purple: "紫色",
|
||||||
Pink: "粉色",
|
Pink: "粉色",
|
||||||
"Search...": "搜索...",
|
"Search...": "搜索…",
|
||||||
"Avg. Ping": "平均 Ping",
|
"Avg. Ping": "平均 Ping",
|
||||||
"Avg. Response": "平均响应",
|
"Avg. Response": "平均响应",
|
||||||
"Entry Page": "入口页面",
|
"Entry Page": "入口页面",
|
||||||
|
@ -192,6 +209,7 @@ export default {
|
||||||
here: "这里",
|
here: "这里",
|
||||||
Required: "必填",
|
Required: "必填",
|
||||||
telegram: "Telegram",
|
telegram: "Telegram",
|
||||||
|
"ZohoCliq": "ZohoCliq",
|
||||||
"Bot Token": "Bot Token",
|
"Bot Token": "Bot Token",
|
||||||
wayToGetTelegramToken: "您可以从 {0} 获取 Token。",
|
wayToGetTelegramToken: "您可以从 {0} 获取 Token。",
|
||||||
"Chat ID": "Chat ID",
|
"Chat ID": "Chat ID",
|
||||||
|
@ -204,6 +222,8 @@ export default {
|
||||||
"Content Type": "Content Type",
|
"Content Type": "Content Type",
|
||||||
webhookJsonDesc: "{0} 适合现代的 HTTP 服务器,例如 Express.js",
|
webhookJsonDesc: "{0} 适合现代的 HTTP 服务器,例如 Express.js",
|
||||||
webhookFormDataDesc: "{multipart} 适合 PHP,其中 JSON 需要使用 {decodeFunction} 解码",
|
webhookFormDataDesc: "{multipart} 适合 PHP,其中 JSON 需要使用 {decodeFunction} 解码",
|
||||||
|
webhookAdditionalHeadersTitle: "额外 Header",
|
||||||
|
webhookAdditionalHeadersDesc: "设置通过此 Webhook 发送的额外 Header。",
|
||||||
smtp: "电子邮件(SMTP)",
|
smtp: "电子邮件(SMTP)",
|
||||||
secureOptionNone: "无 / STARTTLS(常用端口 25、587)",
|
secureOptionNone: "无 / STARTTLS(常用端口 25、587)",
|
||||||
secureOptionTLS: "TLS(常用端口 465)",
|
secureOptionTLS: "TLS(常用端口 465)",
|
||||||
|
@ -221,7 +241,8 @@ export default {
|
||||||
"Hello @everyone is...": "{'@'}everyone,……",
|
"Hello @everyone is...": "{'@'}everyone,……",
|
||||||
teams: "Microsoft Teams",
|
teams: "Microsoft Teams",
|
||||||
"Webhook URL": "Webhook URL",
|
"Webhook URL": "Webhook URL",
|
||||||
wayToGetTeamsURL: "您可以在 {0} 了解如何获取 Webhook URL。",
|
wayToGetTeamsURL: "您可以在{0}了解如何获取 Webhook URL。",
|
||||||
|
wayToGetZohoCliqURL: "您可以在{0}了解如何创建 Webhook URL。",
|
||||||
signal: "Signal",
|
signal: "Signal",
|
||||||
Number: "号码",
|
Number: "号码",
|
||||||
Recipients: "收件人",
|
Recipients: "收件人",
|
||||||
|
@ -243,6 +264,7 @@ export default {
|
||||||
"rocket.chat": "Rocket.Chat",
|
"rocket.chat": "Rocket.Chat",
|
||||||
pushover: "Pushover",
|
pushover: "Pushover",
|
||||||
pushy: "Pushy",
|
pushy: "Pushy",
|
||||||
|
PushByTechulus: "Push by Techulus",
|
||||||
octopush: "Octopush",
|
octopush: "Octopush",
|
||||||
promosms: "PromoSMS",
|
promosms: "PromoSMS",
|
||||||
clicksendsms: "ClickSend SMS",
|
clicksendsms: "ClickSend SMS",
|
||||||
|
@ -250,9 +272,10 @@ export default {
|
||||||
apprise: "Apprise (支持 50+ 种通知服务)",
|
apprise: "Apprise (支持 50+ 种通知服务)",
|
||||||
GoogleChat: "Google Chat(仅 Google Workspace)",
|
GoogleChat: "Google Chat(仅 Google Workspace)",
|
||||||
pushbullet: "Pushbullet",
|
pushbullet: "Pushbullet",
|
||||||
|
AliyunSMS: "阿里云短信服务",
|
||||||
Kook: "Kook",
|
Kook: "Kook",
|
||||||
wayToGetKookBotToken: "在 {0} 创建应用并获取机器人 Token",
|
wayToGetKookBotToken: "在 {0} 创建应用并获取机器人 Token",
|
||||||
wayToGetKookGuildID: "在Kook设置中打开 ‘开发者模式’,然后右键频道可获取其 ID",
|
wayToGetKookGuildID: "在 Kook 设置中打开“开发者模式”,然后右键点击频道可获取其 ID",
|
||||||
"Guild ID": "频道 ID",
|
"Guild ID": "频道 ID",
|
||||||
line: "Line Messenger",
|
line: "Line Messenger",
|
||||||
mattermost: "Mattermost",
|
mattermost: "Mattermost",
|
||||||
|
@ -298,6 +321,7 @@ export default {
|
||||||
promosmsTypeSpeed: "SMS SPEED - 最高优先级。非常快速可靠,但更贵(大约两倍 SMS FULL 的价格)。",
|
promosmsTypeSpeed: "SMS SPEED - 最高优先级。非常快速可靠,但更贵(大约两倍 SMS FULL 的价格)。",
|
||||||
promosmsPhoneNumber: "电话号码(波兰地区收信人可以不填区号)",
|
promosmsPhoneNumber: "电话号码(波兰地区收信人可以不填区号)",
|
||||||
promosmsSMSSender: "短信发信人名称:已注册的名称或以下默认值之一:InfoSMS、SMS Info、MaxSMS、INFO、SMS",
|
promosmsSMSSender: "短信发信人名称:已注册的名称或以下默认值之一:InfoSMS、SMS Info、MaxSMS、INFO、SMS",
|
||||||
|
Feishu: "飞书",
|
||||||
"Feishu WebHookUrl": "飞书 WebHook URL",
|
"Feishu WebHookUrl": "飞书 WebHook URL",
|
||||||
matrixHomeserverURL: "服务器 URL(包含 http(s):// 和可选的端口号)",
|
matrixHomeserverURL: "服务器 URL(包含 http(s):// 和可选的端口号)",
|
||||||
"Internal Room Id": "内部房间 ID",
|
"Internal Room Id": "内部房间 ID",
|
||||||
|
@ -316,14 +340,18 @@ export default {
|
||||||
"One record": "一条记录",
|
"One record": "一条记录",
|
||||||
steamApiKeyDescription: "要监控 Steam 游戏服务器,您需要 Steam Web-API 密钥。您可以在这里注册您的 API 密钥: ",
|
steamApiKeyDescription: "要监控 Steam 游戏服务器,您需要 Steam Web-API 密钥。您可以在这里注册您的 API 密钥: ",
|
||||||
"Current User": "当前用户",
|
"Current User": "当前用户",
|
||||||
|
topic: "Topic",
|
||||||
|
topicExplanation: "要监控的 MQTT Topic",
|
||||||
|
successMessage: "成功消息",
|
||||||
|
successMessageExplanation: "视为成功的 MQTT 消息",
|
||||||
recent: "最近",
|
recent: "最近",
|
||||||
Done: "完成",
|
Done: "完成",
|
||||||
Info: "信息",
|
Info: "信息",
|
||||||
Security: "安全性",
|
Security: "安全性",
|
||||||
"Steam API Key": "Steam API 密钥",
|
"Steam API Key": "Steam API 密钥",
|
||||||
"Shrink Database": "压缩数据库",
|
"Shrink Database": "压缩数据库",
|
||||||
"Pick a RR-Type...": "选择资源记录类型...",
|
"Pick a RR-Type...": "选择资源记录类型…",
|
||||||
"Pick Accepted Status Codes...": "选择有效的状态码...",
|
"Pick Accepted Status Codes...": "选择有效的状态码…",
|
||||||
Default: "默认",
|
Default: "默认",
|
||||||
"HTTP Options": "HTTP 选项",
|
"HTTP Options": "HTTP 选项",
|
||||||
"Create Incident": "创建事件",
|
"Create Incident": "创建事件",
|
||||||
|
@ -333,6 +361,8 @@ export default {
|
||||||
info: "信息",
|
info: "信息",
|
||||||
warning: "警告",
|
warning: "警告",
|
||||||
danger: "危险",
|
danger: "危险",
|
||||||
|
error: "错误",
|
||||||
|
critical: "关键",
|
||||||
primary: "主要",
|
primary: "主要",
|
||||||
light: "明亮",
|
light: "明亮",
|
||||||
dark: "黑暗",
|
dark: "黑暗",
|
||||||
|
@ -360,7 +390,20 @@ export default {
|
||||||
serwersmsAPIPassword: "API 密码",
|
serwersmsAPIPassword: "API 密码",
|
||||||
serwersmsPhoneNumber: "电话号码",
|
serwersmsPhoneNumber: "电话号码",
|
||||||
serwersmsSenderName: "SMS 发信人名称(需要在客户中心注册)",
|
serwersmsSenderName: "SMS 发信人名称(需要在客户中心注册)",
|
||||||
|
smseagle: "SMSEagle",
|
||||||
|
smseagleTo: "电话号码",
|
||||||
|
smseagleGroup: "通讯录群组名",
|
||||||
|
smseagleContact: "通讯录联系人",
|
||||||
|
smseagleRecipientType: "收信人类型",
|
||||||
|
smseagleRecipient: "收信人(多个需用半角逗号分隔)",
|
||||||
|
smseagleToken: "API Access token",
|
||||||
|
smseagleUrl: "您的 SMSEagle 设备 URL",
|
||||||
|
smseagleEncoding: "以 Unicode 发送",
|
||||||
|
smseaglePriority: "消息优先级(0-9,默认为 0)",
|
||||||
stackfield: "Stackfield",
|
stackfield: "Stackfield",
|
||||||
|
Customize: "自定义",
|
||||||
|
"Custom Footer": "自定义底部",
|
||||||
|
"Custom CSS": "自定义 CSS",
|
||||||
smtpDkimSettings: "DKIM 设置",
|
smtpDkimSettings: "DKIM 设置",
|
||||||
smtpDkimDesc: "请访问 Nodemailer DKIM {0} 了解配置方法。",
|
smtpDkimDesc: "请访问 Nodemailer DKIM {0} 了解配置方法。",
|
||||||
documentation: "文档",
|
documentation: "文档",
|
||||||
|
@ -370,16 +413,13 @@ export default {
|
||||||
smtpDkimHashAlgo: "哈希算法(可选)",
|
smtpDkimHashAlgo: "哈希算法(可选)",
|
||||||
smtpDkimheaderFieldNames: "包含在哈希计算对象内的 Header 列表(可选)",
|
smtpDkimheaderFieldNames: "包含在哈希计算对象内的 Header 列表(可选)",
|
||||||
smtpDkimskipFields: "不包含在哈希计算对象内的 Header 列表(可选)",
|
smtpDkimskipFields: "不包含在哈希计算对象内的 Header 列表(可选)",
|
||||||
Feishu: "飞书",
|
wayToGetPagerDutyKey: "您可以在 Service -> Service Directory -> (选择一个 Service) -> Integrations -> Add integration 页面中搜索“Events API V2”以获取此 Integration Key,更多信息请看{0}",
|
||||||
AliyunSMS: "阿里云短信服务",
|
"Integration Key": "Integration Key",
|
||||||
"Sms template must contain parameters: ": "短信模板必须包含以下变量:",
|
"Integration URL": "Integration URL",
|
||||||
DingDing: "钉钉自定义机器人",
|
"Auto resolve or acknowledged": "自动标记为已解决或已读",
|
||||||
WebHookUrl: "钉钉自定义机器人 Webhook 地址",
|
"do nothing": "不做任何操作",
|
||||||
SecretKey: "钉钉自定义机器人加签密钥",
|
"auto acknowledged": "自动标记为已读",
|
||||||
"For safety, must use secret key": "出于安全考虑,必须使用加签密钥",
|
"auto resolve": "自动标记为已解决",
|
||||||
WeCom: "企业微信群机器人",
|
|
||||||
"WeCom Bot Key": "企业微信群机器人 Key",
|
|
||||||
PushByTechulus: "Push by Techulus",
|
|
||||||
gorush: "Gorush",
|
gorush: "Gorush",
|
||||||
alerta: "Alerta",
|
alerta: "Alerta",
|
||||||
alertaApiEndpoint: "API 接入点",
|
alertaApiEndpoint: "API 接入点",
|
||||||
|
@ -396,9 +436,6 @@ export default {
|
||||||
proxyDescription: "代理必须配置到至少一个监控项后才会工作。",
|
proxyDescription: "代理必须配置到至少一个监控项后才会工作。",
|
||||||
enableProxyDescription: "此代理必须启用才能对监控项的网络请求起作用。您可以通过修改激活状态,临时在所有监控项中禁用此代理。",
|
enableProxyDescription: "此代理必须启用才能对监控项的网络请求起作用。您可以通过修改激活状态,临时在所有监控项中禁用此代理。",
|
||||||
setAsDefaultProxyDescription: "此代理会对新创建的监控项默认激活,您仍可以在监控项配置中单独禁用此代理。",
|
setAsDefaultProxyDescription: "此代理会对新创建的监控项默认激活,您仍可以在监控项配置中单独禁用此代理。",
|
||||||
"Proxy Protocol": "代理协议",
|
|
||||||
"Proxy Server": "代理服务器",
|
|
||||||
"Server Address": "服务器地址",
|
|
||||||
"Certificate Chain": "证书链",
|
"Certificate Chain": "证书链",
|
||||||
Valid: "有效",
|
Valid: "有效",
|
||||||
Invalid: "无效",
|
Invalid: "无效",
|
||||||
|
@ -407,9 +444,14 @@ export default {
|
||||||
PhoneNumbers: "PhoneNumbers",
|
PhoneNumbers: "PhoneNumbers",
|
||||||
TemplateCode: "TemplateCode",
|
TemplateCode: "TemplateCode",
|
||||||
SignName: "SignName",
|
SignName: "SignName",
|
||||||
|
"Sms template must contain parameters: ": "短信模板必须包含以下变量:",
|
||||||
"Bark Endpoint": "Bark 接入点",
|
"Bark Endpoint": "Bark 接入点",
|
||||||
"Bark Group": "Bark 群组",
|
"Bark Group": "Bark 群组",
|
||||||
"Bark Sound": "Bark 铃声",
|
"Bark Sound": "Bark 铃声",
|
||||||
|
DingDing: "钉钉自定义机器人",
|
||||||
|
WebHookUrl: "钉钉自定义机器人 Webhook 地址",
|
||||||
|
SecretKey: "钉钉自定义机器人加签密钥",
|
||||||
|
"For safety, must use secret key": "出于安全考虑,必须使用加签密钥",
|
||||||
"Device Token": "Apple Device Token",
|
"Device Token": "Apple Device Token",
|
||||||
Platform: "平台",
|
Platform: "平台",
|
||||||
iOS: "iOS",
|
iOS: "iOS",
|
||||||
|
@ -418,21 +460,18 @@ export default {
|
||||||
High: "高",
|
High: "高",
|
||||||
Retry: "重试次数",
|
Retry: "重试次数",
|
||||||
Topic: "Gorush Topic",
|
Topic: "Gorush Topic",
|
||||||
|
WeCom: "企业微信群机器人",
|
||||||
|
"WeCom Bot Key": "企业微信群机器人 Key",
|
||||||
"Setup Proxy": "设置代理",
|
"Setup Proxy": "设置代理",
|
||||||
|
"Proxy Protocol": "代理协议",
|
||||||
|
"Proxy Server": "代理服务器",
|
||||||
|
"Server Address": "服务器地址",
|
||||||
"Proxy server has authentication": "代理服务器启用了身份验证功能",
|
"Proxy server has authentication": "代理服务器启用了身份验证功能",
|
||||||
User: "用户名",
|
User: "用户名",
|
||||||
Installed: "已安装",
|
Installed: "已安装",
|
||||||
"Not installed": "未安装",
|
"Not installed": "未安装",
|
||||||
Running: "运行中",
|
Running: "运行中",
|
||||||
"Not running": "未运行",
|
"Not running": "未运行",
|
||||||
"Message:": "信息:",
|
|
||||||
wayToGetCloudflaredURL: "(可从 {0} 下载 cloudflared)",
|
|
||||||
cloudflareWebsite: "Cloudflare 网站",
|
|
||||||
"Don't know how to get the token? Please read the guide:": "不知道如何获取 Token?请阅读指南:",
|
|
||||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "如果您正在通过 Cloudflare Tunnel 访问网站,则停止可能会导致当前连接断开。您确定要停止吗?请输入密码以确认。",
|
|
||||||
"Other Software": "其他软件",
|
|
||||||
"For example: nginx, Apache and Traefik.": "例如:nginx、Apache 和 Traefik。",
|
|
||||||
"Please read": "请阅读",
|
|
||||||
"Remove Token": "移除 Token",
|
"Remove Token": "移除 Token",
|
||||||
Start: "启动",
|
Start: "启动",
|
||||||
Stop: "停止",
|
Stop: "停止",
|
||||||
|
@ -450,6 +489,18 @@ export default {
|
||||||
"New Status Page": "新的状态页",
|
"New Status Page": "新的状态页",
|
||||||
"Page Not Found": "未找到该页面",
|
"Page Not Found": "未找到该页面",
|
||||||
"Reverse Proxy": "反向代理",
|
"Reverse Proxy": "反向代理",
|
||||||
|
Backup: "备份",
|
||||||
|
About: "关于",
|
||||||
|
wayToGetCloudflaredURL: "(可从 {0} 下载 cloudflared)",
|
||||||
|
cloudflareWebsite: "Cloudflare 网站",
|
||||||
|
"Message:": "信息:",
|
||||||
|
"Don't know how to get the token? Please read the guide:": "不知道如何获取 Token?请阅读指南:",
|
||||||
|
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "如果您正在通过 Cloudflare Tunnel 访问网站,则停止可能会导致当前连接断开。您确定要停止吗?请输入密码以确认。",
|
||||||
|
"HTTP Headers": "HTTP 头",
|
||||||
|
"Trust Proxy": "可信的代理类字段",
|
||||||
|
"Other Software": "其他软件",
|
||||||
|
"For example: nginx, Apache and Traefik.": "例如:nginx、Apache 和 Traefik。",
|
||||||
|
"Please read": "请阅读",
|
||||||
"Subject:": "颁发给:",
|
"Subject:": "颁发给:",
|
||||||
"Valid To:": "有效期至:",
|
"Valid To:": "有效期至:",
|
||||||
"Days Remaining:": "剩余有效天数:",
|
"Days Remaining:": "剩余有效天数:",
|
||||||
|
@ -459,26 +510,28 @@ export default {
|
||||||
"Domain Name Expiry Notification": "域名到期时通知",
|
"Domain Name Expiry Notification": "域名到期时通知",
|
||||||
Proxy: "代理",
|
Proxy: "代理",
|
||||||
"Date Created": "创建于",
|
"Date Created": "创建于",
|
||||||
|
HomeAssistant: "Home Assistant",
|
||||||
onebotHttpAddress: "OneBot HTTP 地址",
|
onebotHttpAddress: "OneBot HTTP 地址",
|
||||||
onebotMessageType: "OneBot 消息类型",
|
onebotMessageType: "OneBot 消息类型",
|
||||||
onebotGroupMessage: "群聊",
|
onebotGroupMessage: "群聊",
|
||||||
onebotPrivateMessage: "私聊",
|
onebotPrivateMessage: "私聊",
|
||||||
onebotUserOrGroupId: "群组/用户ID",
|
onebotUserOrGroupId: "群组/用户 ID",
|
||||||
onebotSafetyTips: "出于安全原因,请务必设置 AccessToken",
|
onebotSafetyTips: "出于安全原因,请务必设置 AccessToken",
|
||||||
topic: "Topic",
|
|
||||||
topicExplanation: "MQTT 传递给监控的 Topic",
|
|
||||||
successMessage: "成功时消息",
|
|
||||||
successMessageExplanation: "MQTT 成功时所传递的消息",
|
|
||||||
Customize: "自定义",
|
|
||||||
"Custom Footer": "自定义底部",
|
|
||||||
"Custom CSS": "自定义 CSS",
|
|
||||||
"PushDeer Key": "PushDeer Key",
|
"PushDeer Key": "PushDeer Key",
|
||||||
"Footer Text": "底部自定义文本",
|
"Footer Text": "底部自定义文本",
|
||||||
"Show Powered By": "显示 Powered By",
|
"Show Powered By": "显示 Powered By",
|
||||||
"Domain Names": "域名",
|
"Domain Names": "域名",
|
||||||
|
signedInDisp: "当前用户: {0}",
|
||||||
|
signedInDispDisabled: "已禁用身份验证",
|
||||||
|
RadiusSecret: "Radius 共享机密",
|
||||||
|
RadiusSecretDescription: "客户端和服务器之间共享的密钥",
|
||||||
|
RadiusCalledStationId: "NAS 网络访问服务器号码(Called Station Id)",
|
||||||
|
RadiusCalledStationIdDescription: "所访问的服务器的标识",
|
||||||
|
RadiusCallingStationId: "呼叫方号码(Calling Station Id)",
|
||||||
|
RadiusCallingStationIdDescription: "发出请求的设备的标识",
|
||||||
"Certificate Expiry Notification": "证书到期时通知",
|
"Certificate Expiry Notification": "证书到期时通知",
|
||||||
"API Username": "API 凭证 Username",
|
"API Username": "API Username",
|
||||||
"API Key": "API 凭证 Key",
|
"API Key": "API Key",
|
||||||
"Recipient Number": "收件人手机号码",
|
"Recipient Number": "收件人手机号码",
|
||||||
"From Name/Number": "发件人名称/手机号码",
|
"From Name/Number": "发件人名称/手机号码",
|
||||||
"Leave blank to use a shared sender number.": "留空以使用平台共享的发件人手机号码",
|
"Leave blank to use a shared sender number.": "留空以使用平台共享的发件人手机号码",
|
||||||
|
@ -526,38 +579,11 @@ export default {
|
||||||
"Retype the address.": "重新输入地址;",
|
"Retype the address.": "重新输入地址;",
|
||||||
"Go back to the previous page.": "返回到上一页面。",
|
"Go back to the previous page.": "返回到上一页面。",
|
||||||
"Coming Soon": "即将推出",
|
"Coming Soon": "即将推出",
|
||||||
wayToGetClickSendSMSToken: "您可以从 {0} 获取 API 凭证 Username 和 凭证 Key。",
|
wayToGetClickSendSMSToken: "您可以在{0}获取 API Username 和 API Key。",
|
||||||
signedInDisp: "当前用户: {0}",
|
|
||||||
signedInDispDisabled: "已禁用身份验证",
|
|
||||||
dnsPortDescription: "DNS 服务器端口,默认为 53,你可以在任何时候更改此端口.",
|
|
||||||
error: "错误",
|
|
||||||
critical: "关键",
|
|
||||||
wayToGetPagerDutyKey: "你可以在 Service -> Service Directory -> (选择一个 Service) -> Integrations -> Add integration 页面中搜索 \"Events API V2\" 以获取此 Integration Key,更多信息请参见 {0}",
|
|
||||||
"Integration Key": "Integration Key",
|
|
||||||
"Integration URL": "Integration URL",
|
|
||||||
"Auto resolve or acknowledged": "自动标记为已解决或已读",
|
|
||||||
"do nothing": "不做任何操作",
|
|
||||||
"auto acknowledged": "自动标记为已读",
|
|
||||||
"auto resolve": "自动标记为已解决",
|
|
||||||
"Connection String": "连接字符串",
|
"Connection String": "连接字符串",
|
||||||
Query: "查询语句",
|
Query: "查询语句",
|
||||||
settingsCertificateExpiry: "TLS 证书过期通知",
|
settingsCertificateExpiry: "TLS 证书过期通知",
|
||||||
certificationExpiryDescription: "HTTPS 监控项发现被监控目标的 TLS 证书剩余有效期少于以下天数时将发出通知:",
|
certificationExpiryDescription: "HTTPS 监控项发现被监控目标的 TLS 证书剩余有效期少于以下天数时将发出通知:",
|
||||||
"ntfy Topic": "ntfy 主题",
|
|
||||||
Domain: "域名",
|
|
||||||
Workstation: "工作站",
|
|
||||||
resendEveryXTimes: "每 {0} 次失败则重复发送一次",
|
|
||||||
resendDisabled: "为 0 时禁用重复发送",
|
|
||||||
"Resend Notification if Down X times consequently": "连续失败时重复发送通知的间隔次数",
|
|
||||||
"HTTP Headers": "HTTP 头",
|
|
||||||
"Trust Proxy": "可信的代理类字段",
|
|
||||||
HomeAssistant: "Home Assistant",
|
|
||||||
RadiusSecret: "Radius 共享机密",
|
|
||||||
RadiusSecretDescription: "客户端和服务器之间共享的密钥",
|
|
||||||
RadiusCalledStationId: "NAS 网络访问服务器号码(Called Station Id)",
|
|
||||||
RadiusCalledStationIdDescription: "所访问的服务器的标识",
|
|
||||||
RadiusCallingStationId: "呼叫方号码(Calling Station Id)",
|
|
||||||
RadiusCallingStationIdDescription: "发出请求的设备的标识",
|
|
||||||
"Setup Docker Host": "配置 Docker 宿主信息",
|
"Setup Docker Host": "配置 Docker 宿主信息",
|
||||||
"Connection Type": "连接方式",
|
"Connection Type": "连接方式",
|
||||||
"Docker Daemon": "Docker 守护进程",
|
"Docker Daemon": "Docker 守护进程",
|
||||||
|
@ -568,6 +594,9 @@ export default {
|
||||||
"Container Name / ID": "容器名称 / ID",
|
"Container Name / ID": "容器名称 / ID",
|
||||||
"Docker Host": "Docker 宿主",
|
"Docker Host": "Docker 宿主",
|
||||||
"Docker Hosts": "Docker 宿主",
|
"Docker Hosts": "Docker 宿主",
|
||||||
|
"ntfy Topic": "ntfy Topic",
|
||||||
|
Domain: "域名",
|
||||||
|
Workstation: "工作站",
|
||||||
disableCloudflaredNoAuthMsg: "您现在正处于 No Auth 模式,无需输入密码",
|
disableCloudflaredNoAuthMsg: "您现在正处于 No Auth 模式,无需输入密码",
|
||||||
trustProxyDescription: "信任 'X-Forwarded-*' 头。如果您的 Uptime Kuma 是通过 Nginx 或 Apache 等反代服务对外提供访问的话,则您应当启用本功能以获取正确的客户端 IP。",
|
trustProxyDescription: "信任 'X-Forwarded-*' 头。如果您的 Uptime Kuma 是通过 Nginx 或 Apache 等反代服务对外提供访问的话,则您应当启用本功能以获取正确的客户端 IP。",
|
||||||
wayToGetLineNotifyToken: "您可以在 {0} 获取 Access token",
|
wayToGetLineNotifyToken: "您可以在 {0} 获取 Access token",
|
||||||
|
@ -584,7 +613,7 @@ export default {
|
||||||
"Event data:": "事件数据:",
|
"Event data:": "事件数据:",
|
||||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "然后您可以选择关联操作,例如切换到 RGB 灯发出红光的场景",
|
"Then choose an action, for example switch the scene to where an RGB light is red.": "然后您可以选择关联操作,例如切换到 RGB 灯发出红光的场景",
|
||||||
"Frontend Version": "前端版本",
|
"Frontend Version": "前端版本",
|
||||||
"Frontend Version do not match backend version!": "前端版本与后端版本不符!",
|
"Frontend Version do not match backend version!": "前端版本与后端版本不匹配!",
|
||||||
"Base URL": "API 基础地址",
|
"Base URL": "API 基础地址",
|
||||||
goAlertInfo: "GoAlert 是一个用于呼叫调度、自动汇报和通知(如 SMS 或语音呼叫)的开源应用程序。在正确的时间以正确的方式自动让正确的人参与!{0}",
|
goAlertInfo: "GoAlert 是一个用于呼叫调度、自动汇报和通知(如 SMS 或语音呼叫)的开源应用程序。在正确的时间以正确的方式自动让正确的人参与!{0}",
|
||||||
goAlertIntegrationKeyInfo: "使用形如 aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee 的通用 API 集成密钥,通常是复制来的链接中的 token 参数值。",
|
goAlertIntegrationKeyInfo: "使用形如 aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee 的通用 API 集成密钥,通常是复制来的链接中的 token 参数值。",
|
||||||
|
@ -598,5 +627,57 @@ export default {
|
||||||
"Gateway Type": "网关类型",
|
"Gateway Type": "网关类型",
|
||||||
SMSManager: "SMSManager",
|
SMSManager: "SMSManager",
|
||||||
"You can divide numbers with": "可用的分隔符:",
|
"You can divide numbers with": "可用的分隔符:",
|
||||||
"or": "或",
|
or: "或",
|
||||||
|
recurringInterval: "时间间隔",
|
||||||
|
Recurring: "重复",
|
||||||
|
strategyManual: "手动启用/禁用",
|
||||||
|
warningTimezone: "使用服务器时区",
|
||||||
|
weekdayShortMon: "周一",
|
||||||
|
weekdayShortTue: "周二",
|
||||||
|
weekdayShortWed: "周三",
|
||||||
|
weekdayShortThu: "周四",
|
||||||
|
weekdayShortFri: "周五",
|
||||||
|
weekdayShortSat: "周六",
|
||||||
|
weekdayShortSun: "周日",
|
||||||
|
dayOfWeek: "每周计划",
|
||||||
|
dayOfMonth: "每月计划",
|
||||||
|
lastDay: "结束日",
|
||||||
|
lastDay1: "每月最后一天",
|
||||||
|
lastDay2: "每月倒数第二天",
|
||||||
|
lastDay3: "每月倒数第三天",
|
||||||
|
lastDay4: "每月倒数第四天",
|
||||||
|
"No Maintenance": "无维护计划",
|
||||||
|
pauseMaintenanceMsg: "确定要暂停吗?",
|
||||||
|
"maintenanceStatus-under-maintenance": "正在维护",
|
||||||
|
"maintenanceStatus-inactive": "未启用",
|
||||||
|
"maintenanceStatus-scheduled": "已计划",
|
||||||
|
"maintenanceStatus-ended": "已结束",
|
||||||
|
"maintenanceStatus-unknown": "未知",
|
||||||
|
"Display Timezone": "显示时区",
|
||||||
|
"Server Timezone": "服务器时区",
|
||||||
|
statusPageMaintenanceEndDate: "结束时间",
|
||||||
|
IconUrl: "图标 URL",
|
||||||
|
"Enable DNS Cache": "启用 DNS 缓存",
|
||||||
|
Enable: "启用",
|
||||||
|
Disable: "禁用",
|
||||||
|
dnsCacheDescription: "可能无法在某些 IPv6 环境工作,如果遇到问题请禁用。",
|
||||||
|
"Single Maintenance Window": "单一时间窗口",
|
||||||
|
"Maintenance Time Window of a Day": "每日维护时间窗口",
|
||||||
|
"Effective Date Range": "生效日期范围",
|
||||||
|
"Schedule Maintenance": "计划维护",
|
||||||
|
"Date and Time": "日期时间",
|
||||||
|
"DateTime Range": "日期时间范围",
|
||||||
|
Strategy: "策略",
|
||||||
|
"Free Mobile User Identifier": "Free Mobile User Identifier",
|
||||||
|
"Free Mobile API Key": "Free Mobile API Key",
|
||||||
|
"Enable TLS": "启用 TLS",
|
||||||
|
"Proto Service Name": "Proto 服务名称",
|
||||||
|
"Proto Method": "Proto 方法",
|
||||||
|
"Proto Content": "Proto 内容",
|
||||||
|
Economy: "经济",
|
||||||
|
Lowcost: "低价",
|
||||||
|
high: "高价",
|
||||||
|
"General Monitor Type": "常规监控类型",
|
||||||
|
"Passive Monitor Type": "被动监控类型",
|
||||||
|
"Specific Monitor Type": "针对监控类型",
|
||||||
};
|
};
|
||||||
|
|
|
@ -473,6 +473,12 @@ table {
|
||||||
|
|
||||||
.dropdown-clear-data {
|
.dropdown-clear-data {
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
width: 100%;
|
||||||
|
min-width: unset;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
|
|
|
@ -189,14 +189,36 @@ export default {
|
||||||
* @param {string} [currentPassword] Only need for disableAuth to true
|
* @param {string} [currentPassword] Only need for disableAuth to true
|
||||||
*/
|
*/
|
||||||
saveSettings(callback, currentPassword) {
|
saveSettings(callback, currentPassword) {
|
||||||
this.$root.getSocket().emit("setSettings", this.settings, currentPassword, (res) => {
|
let valid = this.validateSettings();
|
||||||
this.$root.toastRes(res);
|
if (valid.success) {
|
||||||
this.loadSettings();
|
this.$root.getSocket().emit("setSettings", this.settings, currentPassword, (res) => {
|
||||||
|
this.$root.toastRes(res);
|
||||||
|
this.loadSettings();
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this.$root.toastError(valid.msg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure settings are valid
|
||||||
|
* @returns {Object} Contains success state and error msg
|
||||||
|
*/
|
||||||
|
validateSettings() {
|
||||||
|
if (this.settings.keepDataPeriodDays < 0) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
msg: this.$t("dataRetentionTimeError"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
msg: "",
|
||||||
|
};
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue