Merge branch 'master' into cert-notification

This commit is contained in:
Louis Lam 2021-10-27 14:16:37 +08:00
commit 110ec491ee
42 changed files with 1377 additions and 514 deletions

View file

@ -1,21 +0,0 @@
---
name: Ask for help
about: You can ask any question related to Uptime Kuma.
title: ''
labels: help
assignees: ''
---
**Is it a duplicated question?**
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
**Describe your problem**
Please describe what you are asking for
**Info**
Uptime Kuma Version:
Using Docker?: Yes/No
Docker Version:
Node.js Version (Without Docker only):
OS:
Browser:

View file

@ -0,0 +1,76 @@
name: "❓ Ask for help"
description: "Submit any question related to Uptime Kuma"
title: "[Help]: <title>"
labels: [help]
body:
- type: textarea
id: steps-to-reproduce
validations:
required: true
attributes:
label: "📝 Describe your problem"
description: "Please walk us through it step by step."
placeholder: "Describe what are you asking for..."
- type: input
id: uptime-kuma-version
attributes:
label: "🐻 Uptime-Kuma version"
description: "Which version of Uptime-Kuma are you running?"
placeholder: "Ex. 1.9.x"
validations:
required: true
- type: input
id: operating-system
attributes:
label: "💻 Operating System"
description: "Which OS is your server/device running on?"
placeholder: "Ex. Ubuntu 20.04"
validations:
required: true
- type: input
id: browser-vendor
attributes:
label: "🌐 Browser"
description: "Which browser are you running on?"
placeholder: "Ex. Firefox"
validations:
required: true
- type: input
id: docker-version
attributes:
label: "🐋 Docker"
description: "If running with Docker, which version are you running?"
placeholder: "Ex. 20.10.9"
validations:
required: false
- type: input
id: docker-image-tag
attributes:
label: "🏷️ Docker Image Tag"
description: "Which Docker image tag are you using? If running '1' or 'latest', please specify image hash."
placeholder: "Ex. 1.9.1"
validations:
required: false
- type: input
id: nodejs-version
attributes:
label: "🟩 NodeJS Version"
description: "If running with Node.js? which version are you running?"
placeholder: "14.x"
validations:
required: false
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "👀 Have you spent some time to check if this question has been raised before?"
description: "Please search in the issues without filters [here](https://github.com/louislam/uptime-kuma/issues?q=)"
options:
- label: "I checked and didn't find similar question"
required: true
- type: checkboxes
attributes:
label: "🛡️ Security Policy"
description: Please review the security policy before reporting security related issues/bugs.
options:
- label: I agree to have read this project [Security Policy](https://github.com/louislam/uptime-kuma/security/policy)
required: true

View file

@ -1,42 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Is it a duplicated question?**
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Info**
Uptime Kuma Version:
Using Docker?: Yes/No
Docker Version:
Node.js Version (Without Docker only):
OS:
Browser:
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Error Log**
It is easier for us to find out the problem.
Docker: `docker logs <container id>`
PM2: `~/.pm2/logs/` (e.g. `/home/ubuntu/.pm2/logs`)

100
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View file

@ -0,0 +1,100 @@
name: "🐛 Bug Report"
description: "Submit a bug report to help us improve"
title: "[Bug]: <title>"
labels: [bug]
body:
- type: textarea
id: steps-to-reproduce
validations:
required: true
attributes:
label: "👟 Reproduction steps"
description: "How do you trigger this bug? Please walk us through it step by step."
placeholder: "..."
- type: textarea
id: expected-behavior
validations:
required: true
attributes:
label: "👍 Expected behavior"
description: "What did you think would happen?"
placeholder: "..."
- type: textarea
id: actual-behavior
validations:
required: true
attributes:
label: "👎 Actual Behavior"
description: "What actually happen?"
placeholder: "..."
- type: input
id: uptime-kuma-version
attributes:
label: "🐻 Uptime-Kuma version"
description: "Which version of Uptime-Kuma are you running?"
placeholder: "Ex. 1.9.x"
validations:
required: true
- type: input
id: operating-system
attributes:
label: "💻 Operating System"
description: "Which OS is your server/device running on?"
placeholder: "Ex. Ubuntu 20.04"
validations:
required: true
- type: input
id: browser-vendor
attributes:
label: "🌐 Browser"
description: "Which browser are you running on?"
placeholder: "Ex. Firefox"
validations:
required: true
- type: input
id: docker-version
attributes:
label: "🐋 Docker"
description: "If running with Docker, which version are you running?"
placeholder: "Ex. 20.10.9"
validations:
required: false
- type: input
id: docker-image-tag
attributes:
label: "🏷️ Docker Image Tag"
description: "Which Docker image tag are you using? If running '1' or 'latest', please specify image hash."
placeholder: "Ex. 1.9.1"
validations:
required: false
- type: input
id: nodejs-version
attributes:
label: "🟩 NodeJS Version"
description: "If running with Node.js? which version are you running?"
placeholder: "14.x"
validations:
required: false
- type: textarea
id: logs
attributes:
label: "📝 Relevant log output"
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: false
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "👀 Have you spent some time to check if this issue has been raised before?"
description: "Please search in the issues without filters [here](https://github.com/louislam/uptime-kuma/issues?q=)"
options:
- label: "I checked and didn't find similar issue"
required: true
- type: checkboxes
attributes:
label: "🛡️ Security Policy"
description: Please review the security policy before reporting security related issues/bugs.
options:
- label: I agree to have read this project [Security Policy](https://github.com/louislam/uptime-kuma/security/policy)
required: true

View file

@ -1,22 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is it a duplicated question?**
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -0,0 +1,59 @@
name: 🚀 Feature Request
description: "Submit a proposal for a new feature"
title: "[Feature]: <title>"
labels: [enhancement]
body:
- type: dropdown
id: feature-area
attributes:
label: "🏷️ Feature Request Type"
description: "What kind of feature request is this?"
multiple: true
options:
- API
- New Notification
- New Monitor
- UI Feature
- Other
validations:
required: true
- type: textarea
id: feature-description
validations:
required: true
attributes:
label: "🔖 Feature description"
description: "A clear and concise description of what the feature request is."
placeholder: "You should add ..."
- type: textarea
id: solution
validations:
required: true
attributes:
label: "✔️ Solution"
description: "A clear and concise description of what you want to happen."
placeholder: "In my use-case, ..."
- type: textarea
id: alternatives
validations:
required: false
attributes:
label: "❓ Alternatives"
description: "A clear and concise description of any alternative solutions or features you've considered."
placeholder: "I have considered ..."
- type: textarea
id: additional-context
validations:
required: false
attributes:
label: "📝 Additional Context"
description: "Add any other context or screenshots about the feature request here."
placeholder: "..."
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "👀 Have you spent some time to check if this feature request has been raised before?"
description: "Please search in the issues without filters [here](https://github.com/louislam/uptime-kuma/issues?q=)"
options:
- label: "I checked and didn't find similar feature request"
required: true

26
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,26 @@
# Description
Fixes #(issue)
## Type of change
Please delete options that are not relevant.
- Bug fix (non-breaking change which fixes an issue)
- User Interface
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
- Translation update
- Other
- This change requires a documentation update
## Checklist
- [ ] My code follows the style guidelines of this project
- [ ] I ran ESLint and other linters for modified files
- [ ] I have performed a self-review of my own code and test it
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] My changes generate no new warnings
- [ ] My code needed automated testing. I have added them (this is optional task)
## Screenshots (if any)

View file

@ -16,7 +16,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
node-version: [14.x, 16.x]
node-version: [14.x, 16.x, 17.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:

View file

@ -29,16 +29,34 @@ The frontend code build into "dist" directory. The server (express.js) exposes t
Generally, if the pull request is working fine and it do not affect any existing logic, workflow and perfomance, I will merge into the master branch once it is tested.
If you are not sure, feel free to create an empty pull request draft first.
If you are not sure whether I will accept your pull request, feel free to create an empty pull request draft first.
### Recommended Pull Request Guideline
1. Fork the project
1. Clone your fork repo to local
1. Create a new branch
1. Create an empty commit
`git commit -m "[empty commit] pull request for <YOUR TASK NAME>" --allow-empty`
1. Push to your fork repo
1. Create a pull request: https://github.com/louislam/uptime-kuma/compare
1. Write a proper description
1. Click "Change to draft"
### Pull Request Examples
Here are some example situations in the past.
#### ✅ High - Medium Priority
Easy to review, no breaking change and not touching the existing code
- Add a new notification
- Add a chart
- Fix a bug
- Translations
- Add a independent new feature
#### *️⃣ Requires one more reviewer
@ -46,6 +64,17 @@ I do not have such knowledge to test it.
- Add k8s supports
#### ⚠ Low Priority - Harsh Mode
Some pull requests are required to modifiy the core. To be honest, I do not want anyone to try to do that, because it would spend a lot of your time. I will review your pull request harshly. Also you may need to write a lot of unit tests to ensure that there is no breaking change.
- Touch large parts of code of any very important features
- Touch monitoring logic
- Drop a table or drop a column for any reason
- Touch the entry point of Docker or Node.js
- Modifiy auth
#### *️⃣ Low Priority
It changed my current workflow and require further studies.
@ -54,6 +83,7 @@ It changed my current workflow and require further studies.
#### ❌ Won't Merge
- Any breaking changes
- Duplicated pull request
- Buggy
- Existing logic is completely modified or deleted
@ -180,6 +210,13 @@ Patch release = the third digit ([Semantic Versioning](https://semver.org/))
Please read: https://github.com/louislam/uptime-kuma/tree/master/src/languages
## Wiki
Since there is no way to make a pull request to wiki's repo, I have setup another repo to do that.
https://github.com/louislam/uptime-kuma-wiki
## Maintainer
Check the latest issues and pull requests:
@ -199,3 +236,19 @@ Checking:
- Check all tags is fine on https://hub.docker.com/r/louislam/uptime-kuma/tags
- Try the Docker image with tag 1.X.X (Clean install / amd64 / arm64 / armv7)
- Try clean install with Node.js
### Release Wiki
#### Setup Repo
```
git clone https://github.com/louislam/uptime-kuma-wiki.git
cd uptime-kuma-wiki
git remote add production https://github.com/louislam/uptime-kuma.wiki.git
```
#### Push to Production Wiki
```
git pull
git push production master
```

View file

@ -1,6 +1,7 @@
# Uptime Kuma
<a target="_blank" href="https://github.com/louislam/uptime-kuma"><img src="https://img.shields.io/github/stars/louislam/uptime-kuma" /></a> <a target="_blank" href="https://hub.docker.com/r/louislam/uptime-kuma"><img src="https://img.shields.io/docker/pulls/louislam/uptime-kuma" /></a> <a target="_blank" href="https://hub.docker.com/r/louislam/uptime-kuma"><img src="https://img.shields.io/docker/v/louislam/uptime-kuma/latest?label=docker%20image%20ver." /></a> <a target="_blank" href="https://github.com/louislam/uptime-kuma"><img src="https://img.shields.io/github/last-commit/louislam/uptime-kuma" /></a> <a target="_blank" href="https://opencollective.com/uptime-kuma"><img src="https://opencollective.com/uptime-kuma/total/badge.svg?label=Backers&color=brightgreen" /></a>
<a target="_blank" href="https://github.com/louislam/uptime-kuma"><img src="https://img.shields.io/github/stars/louislam/uptime-kuma" /></a> <a target="_blank" href="https://hub.docker.com/r/louislam/uptime-kuma"><img src="https://img.shields.io/docker/pulls/louislam/uptime-kuma" /></a> <a target="_blank" href="https://hub.docker.com/r/louislam/uptime-kuma"><img src="https://img.shields.io/docker/v/louislam/uptime-kuma/latest?label=docker%20image%20ver." /></a> <a target="_blank" href="https://github.com/louislam/uptime-kuma"><img src="https://img.shields.io/github/last-commit/louislam/uptime-kuma" /></a> <a target="_blank" href="https://opencollective.com/uptime-kuma"><img src="https://opencollective.com/uptime-kuma/total/badge.svg?label=Open%20Collective%20Backers&color=brightgreen" /></a>
[![GitHub Sponsors](https://img.shields.io/github/sponsors/louislam?label=GitHub%20Sponsors)](https://github.com/sponsors/louislam)
<div align="center" width="100%">
<img src="./public/icon.svg" width="128" alt="" />
@ -42,7 +43,7 @@ docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name upti
Browse to http://localhost:3001 after starting.
### 💪🏻 Without Docker
### 💪🏻 Non-Docker
Required Tools: Node.js >= 14, git and pm2.

View file

@ -9,8 +9,8 @@ currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 1.8.X | :white_check_mark: |
| <= 1.7.X | ❌ |
| 1.9.X | :white_check_mark: |
| <= 1.8.X | ❌ |
### Upgradable Docker Tags

View file

@ -34,9 +34,11 @@ function download(url) {
});
tarStream.on("close", () => {
if (fs.existsSync("./dist-backup")) {
fs.rmdirSync("./dist-backup", {
recursive: true
});
}
console.log("Done");
});
@ -44,7 +46,7 @@ function download(url) {
if (fs.existsSync("./dist-backup")) {
fs.renameSync("./dist-backup", "./dist");
}
console.log("Done");
console.error("Error from tarStream");
});
response.pipe(tarStream);

11
package-lock.json generated
View file

@ -33,6 +33,7 @@
"http-graceful-shutdown": "~3.1.4",
"iconv-lite": "^0.6.3",
"jsonwebtoken": "~8.5.1",
"jwt-decode": "^3.1.2",
"limiter": "^2.1.0",
"nodemailer": "~6.6.5",
"notp": "~2.0.3",
@ -7846,6 +7847,11 @@
"safe-buffer": "^5.0.1"
}
},
"node_modules/jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"node_modules/kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -18495,6 +18501,11 @@
"safe-buffer": "^5.0.1"
}
},
"jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",

View file

@ -76,6 +76,7 @@
"http-graceful-shutdown": "~3.1.4",
"iconv-lite": "^0.6.3",
"jsonwebtoken": "~8.5.1",
"jwt-decode": "^3.1.2",
"limiter": "^2.1.0",
"nodemailer": "~6.6.5",
"notp": "~2.0.3",

View file

@ -114,6 +114,7 @@ class Database {
// Change to WAL
await R.exec("PRAGMA journal_mode = WAL");
await R.exec("PRAGMA cache_size = -12000");
await R.exec("PRAGMA auto_vacuum = FULL");
console.log("SQLite config:");
console.log(await R.getAll("PRAGMA journal_mode"));
@ -374,6 +375,17 @@ class Database {
console.log("Nothing to restore");
}
}
static getSize() {
debug("Database.getSize()");
let stats = fs.statSync(Database.path);
debug(stats);
return stats.size;
}
static async shrink() {
await R.exec("VACUUM");
}
}
module.exports = Database;

View file

@ -351,6 +351,10 @@ class Monitor extends BeanModel {
if (isImportant) {
bean.important = true;
await Monitor.sendNotification(isFirstBeat, this, bean);
// Clear Status Page Cache
apicache.clear();
} else {
bean.important = false;
}
@ -383,18 +387,32 @@ class Monitor extends BeanModel {
}
}
this.heartbeatInterval = setTimeout(beat, beatInterval * 1000);
this.heartbeatInterval = setTimeout(safeBeat, beatInterval * 1000);
}
};
const safeBeat = async () => {
try {
await beat();
} catch (e) {
console.trace(e);
console.error("Please report to https://github.com/louislam/uptime-kuma/issues");
if (! this.isStop) {
console.log("Try to restart the monitor");
this.heartbeatInterval = setTimeout(safeBeat, this.interval * 1000);
}
}
};
// Delay Push Type
if (this.type === "push") {
setTimeout(() => {
beat();
safeBeat();
}, this.interval * 1000);
} else {
beat();
safeBeat();
}
}
@ -598,9 +616,6 @@ class Monitor extends BeanModel {
console.log(e);
}
}
// Clear Status Page Cache
apicache.clear();
}
}

View file

@ -0,0 +1,89 @@
//
// bark.js
// UptimeKuma
//
// Created by Lakr Aream on 2021/10/24.
// Copyright © 2021 Lakr Aream. All rights reserved.
//
const NotificationProvider = require("./notification-provider");
const { DOWN, UP } = require("../../src/util");
const { default: axios } = require("axios");
// 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 barkNotificationSound = "telegraph";
const successMessage = "Successes!";
class Bark extends NotificationProvider {
name = "Bark";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
try {
var barkEndpoint = notification.barkEndpoint;
// check if the endpoint has a "/" suffix, if so, delete it first
if (barkEndpoint.endsWith("/")) {
barkEndpoint = barkEndpoint.substring(0, barkEndpoint.length - 1);
}
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == UP) {
let title = "UptimeKuma Monitor Up";
return await this.postNotification(title, msg, barkEndpoint);
}
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == DOWN) {
let title = "UptimeKuma Monitor Down";
return await this.postNotification(title, msg, barkEndpoint);
}
if (msg != null) {
let title = "UptimeKuma Message";
return await this.postNotification(title, msg, barkEndpoint);
}
} catch (error) {
throw error;
}
}
// add additional parameter for better on device styles (iOS 15 optimized)
appendAdditionalParameters(postUrl) {
// grouping all our notifications
postUrl += "?group=" + barkNotificationGroup;
// set icon to uptime kuma icon, 11kb should be fine
postUrl += "&icon=" + barkNotificationAvatar;
// picked a sound, this should follow system's mute status when arrival
postUrl += "&sound=" + barkNotificationSound;
return postUrl;
}
// thrown if failed to check result, result code should be in range 2xx
checkResult(result) {
if (result.status == null) {
throw new Error("Bark notification failed with invalid response!");
}
if (result.status < 200 || result.status >= 300) {
throw new Error("Bark notification failed with status code " + result.status);
}
}
async postNotification(title, subtitle, endpoint) {
// url encode title and subtitle
title = encodeURIComponent(title);
subtitle = encodeURIComponent(subtitle);
let postUrl = endpoint + "/" + title + "/" + subtitle;
postUrl = this.appendAdditionalParameters(postUrl);
let result = await axios.get(postUrl);
this.checkResult(result);
if (result.statusText != null) {
return "Bark notification succeed: " + result.statusText;
}
// because returned in range 200 ..< 300
return successMessage;
}
}
module.exports = Bark;

View file

@ -0,0 +1,42 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class ClickSendSMS extends NotificationProvider {
name = "clicksendsms";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully.";
try {
console.log({ notification });
let config = {
headers: {
"Content-Type": "application/json",
"Authorization": "Basic " + Buffer.from(notification.clicksendsmsLogin + ":" + notification.clicksendsmsPassword).toString('base64'),
"Accept": "text/json",
}
};
let data = {
messages: [
{
"body": msg.replace(/[^\x00-\x7F]/g, ""),
"to": notification.clicksendsmsToNumber,
"source": "uptime-kuma",
"from": notification.clicksendsmsSenderName,
}
]
};
let resp = await axios.post("https://rest.clicksend.com/v3/sms/send", data, config);
if (resp.data.data.messages[0].status !== "SUCCESS") {
let error = "Something gone wrong. Api returned " + resp.data.data.messages[0].status + ".";
this.throwGeneralAxiosError(error);
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = ClickSendSMS;

View file

@ -8,6 +8,7 @@ const Mattermost = require("./notification-providers/mattermost");
const Matrix = require("./notification-providers/matrix");
const Octopush = require("./notification-providers/octopush");
const PromoSMS = require("./notification-providers/promosms");
const ClickSendSMS = require("./notification-providers/clicksendsms");
const Pushbullet = require("./notification-providers/pushbullet");
const Pushover = require("./notification-providers/pushover");
const Pushy = require("./notification-providers/pushy");
@ -21,6 +22,7 @@ const Webhook = require("./notification-providers/webhook");
const Feishu = require("./notification-providers/feishu");
const AliyunSms = require("./notification-providers/aliyun-sms");
const DingDing = require("./notification-providers/dingding");
const Bark = require("./notification-providers/bark");
class Notification {
@ -45,6 +47,7 @@ class Notification {
new Matrix(),
new Octopush(),
new PromoSMS(),
new ClickSendSMS(),
new Pushbullet(),
new Pushover(),
new Pushy(),
@ -54,6 +57,7 @@ class Notification {
new SMTP(),
new Telegram(),
new Webhook(),
new Bark(),
];
for (let item of list) {

View file

@ -119,6 +119,7 @@ module.exports.io = io;
// Must be after io instantiation
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo } = require("./client");
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
const databaseSocketHandler = require("./socket-handlers/database-socket-handler");
app.use(express.json());
@ -644,6 +645,38 @@ exports.entryPage = "dashboard";
}
});
socket.on("getMonitorBeats", async (monitorID, period, callback) => {
try {
checkLogin(socket);
console.log(`Get Monitor Beats: ${monitorID} User ID: ${socket.userID}`);
if (period == null) {
throw new Error("Invalid period.");
}
let list = await R.getAll(`
SELECT * FROM heartbeat
WHERE monitor_id = ? AND
time > DATETIME('now', '-' || ? || ' hours')
ORDER BY time ASC
`, [
monitorID,
period,
]);
callback({
ok: true,
data: list,
});
} catch (e) {
callback({
ok: false,
msg: e.message,
});
}
});
// Start or Resume the monitor
socket.on("resumeMonitor", async (monitorID, callback) => {
try {
@ -1263,6 +1296,7 @@ exports.entryPage = "dashboard";
// Status Page Socket Handler for admin only
statusPageSocketHandler(socket);
databaseSocketHandler(socket);
debug("added all socket handlers");

View file

@ -0,0 +1,37 @@
const { checkLogin } = require("../util-server");
const Database = require("../database");
module.exports = (socket) => {
// Post or edit incident
socket.on("getDatabaseSize", async (callback) => {
try {
checkLogin(socket);
callback({
ok: true,
size: Database.getSize(),
});
} catch (error) {
callback({
ok: false,
msg: error.message,
});
}
});
socket.on("shrinkDatabase", async (callback) => {
try {
checkLogin(socket);
Database.shrink();
callback({
ok: true,
});
} catch (error) {
callback({
ok: false,
msg: error.message,
});
}
});
};

View file

@ -1,16 +1,34 @@
<template>
<div>
<div class="period-options">
<button type="button" class="btn btn-light dropdown-toggle btn-period-toggle" data-bs-toggle="dropdown" aria-expanded="false">
{{ chartPeriodOptions[chartPeriodHrs] }}&nbsp;
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li v-for="(item, key) in chartPeriodOptions" :key="key">
<a class="dropdown-item" :class="{ active: chartPeriodHrs == key }" href="#" @click="chartPeriodHrs = key">{{ item }}</a>
</li>
</ul>
</div>
<div class="chart-wrapper" :class="{ loading : loading}">
<LineChart :chart-data="chartData" :options="chartOptions" />
</div>
</div>
</template>
<script>
<script lang="ts">
import { BarController, BarElement, Chart, Filler, LinearScale, LineController, LineElement, PointElement, TimeScale, Tooltip } from "chart.js";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
import "chartjs-adapter-dayjs";
import { LineChart } from "vue-chart-3";
import { useToast } from "vue-toastification";
import { UP, DOWN, PENDING } from "../util.ts";
dayjs.extend(utc);
dayjs.extend(timezone);
const toast = useToast();
Chart.register(LineController, BarController, LineElement, PointElement, TimeScale, BarElement, LinearScale, Tooltip, Filler);
@ -24,8 +42,23 @@ export default {
},
data() {
return {
loading: false,
// Configurable filtering on top of the returned data
chartPeriodHrs: 6,
chartPeriodHrs: 0,
chartPeriodOptions: {
0: this.$t("recent"),
3: "3h",
6: "6h",
24: "24h",
168: "1w",
},
// A heartbeatList for 3h, 6h, 24h, 1w
// Uses the $root.heartbeatList when value is null
heartbeatList: null
};
},
computed: {
@ -117,7 +150,7 @@ export default {
},
callbacks: {
label: (context) => {
return ` ${new Intl.NumberFormat().format(context.parsed.y)} ms`
return ` ${new Intl.NumberFormat().format(context.parsed.y)} ms`;
},
}
},
@ -125,15 +158,24 @@ export default {
display: false,
},
},
}
};
},
chartData() {
let pingData = []; // Ping Data for Line Chart, y-axis contains ping time
let downData = []; // Down Data for Bar Chart, y-axis is 1 if target is down, 0 if target is up
if (this.monitorId in this.$root.heartbeatList) {
this.$root.heartbeatList[this.monitorId]
let heartbeatList = this.heartbeatList ||
(this.monitorId in this.$root.heartbeatList && this.$root.heartbeatList[this.monitorId]) ||
[];
heartbeatList
.filter(
(beat) => dayjs.utc(beat.time).tz(this.$root.timezone).isAfter(dayjs().subtract(this.chartPeriodHrs, "hours")))
// Filtering as data gets appended
// not the most efficient, but works for now
(beat) => dayjs.utc(beat.time).tz(this.$root.timezone).isAfter(
dayjs().subtract(Math.max(this.chartPeriodHrs, 6), "hours")
)
)
.map((beat) => {
const x = this.$root.datetime(beat.time);
pingData.push({
@ -142,10 +184,10 @@ export default {
});
downData.push({
x,
y: beat.status === 0 ? 1 : 0,
})
y: beat.status === DOWN ? 1 : 0,
});
}
});
return {
datasets: [
{
@ -172,5 +214,110 @@ export default {
};
},
},
watch: {
// Update chart data when the selected chart period changes
chartPeriodHrs: function (newPeriod) {
if (newPeriod == "0") {
newPeriod = null;
this.heartbeatList = null;
} else {
this.loading = true;
this.$root.getMonitorBeats(this.monitorId, newPeriod, (res) => {
if (!res.ok) {
toast.error(res.msg);
} else {
this.heartbeatList = res.data;
}
this.loading = false;
});
}
}
},
created() {
// Setup Watcher on the root heartbeatList,
// And mirror latest change to this.heartbeatList
this.$watch(() => this.$root.heartbeatList[this.monitorId],
(heartbeatList) => {
if (this.chartPeriodHrs != 0) {
const newBeat = heartbeatList.at(-1);
if (newBeat && dayjs.utc(newBeat.time) > dayjs.utc(this.heartbeatList.at(-1)?.time)) {
this.heartbeatList.push(heartbeatList.at(-1));
}
}
},
{ deep: true }
);
}
};
</script>
<style lang="scss" scoped>
@import "../assets/vars.scss";
.form-select {
width: unset;
display: inline-flex;
}
.period-options {
padding: 0.1em 1em;
margin-bottom: -1.2em;
float: right;
position: relative;
z-index: 10;
.dropdown-menu {
padding: 0;
min-width: 50px;
font-size: 0.9em;
.dark & {
background: $dark-bg;
}
.dropdown-item {
border-radius: 0.3rem;
padding: 2px 16px 4px 16px;
.dark & {
background: $dark-bg;
}
.dark &:hover {
background: $dark-font-color;
}
}
.dark & .dropdown-item.active {
background: $primary;
color: $dark-font-color2;
}
}
.btn-period-toggle {
padding: 2px 15px;
background: transparent;
border: 0;
color: $link-color;
opacity: 0.7;
font-size: 0.9em;
&::after {
vertical-align: 0.155em;
}
.dark & {
color: $dark-font-color;
}
}
}
.chart-wrapper {
margin-bottom: 0.5em;
&.loading {
filter: blur(10px);
}
}
</style>

View file

@ -0,0 +1,15 @@
<template>
<div class="mb-3">
<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>
<div class="form-text">
<p><span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}</p>
</div>
<i18n-t tag="div" keypath="wayToGetTeamsURL" class="form-text">
<a
href="https://github.com/Finb/Bark"
target="_blank"
>{{ $t("here") }}</a>
</i18n-t>
</div>
</template>

View file

@ -0,0 +1,38 @@
<template>
<div class="mb-3">
<label for="clicksendsms-login" class="form-label">API Username</label>
<div class="form-text">
{{ $t("apiCredentials") }}
<a href="http://dashboard.clicksend.com/account/subaccounts" target="_blank">here</a>
</div>
<input id="clicksendsms-login" v-model="$parent.notification.clicksendsmsLogin" type="text" class="form-control" required>
<label for="clicksendsms-key" class="form-label">API Key</label>
<HiddenInput id="clicksendsms-key" v-model="$parent.notification.clicksendsmsPassword" :required="true" autocomplete="one-time-code"></HiddenInput>
</div>
<div class="mb-3">
<div class="form-text">
{{ $t("checkPrice", [$t("clicksendsms")]) }}
<a href="https://www.clicksend.com/us/pricing" target="_blank">https://clicksend.com/us/pricing</a>
</div>
</div>
<div class="mb-3">
<label for="clicksendsms-to-number" class="form-label">Recipient Number</label>
<input id="clicksendsms-to-number" v-model="$parent.notification.clicksendsmsToNumber" type="text" minlength="8" maxlength="14" class="form-control" required>
</div>
<div class="mb-3">
<label for="clicksendsms-sender-name" class="form-label">From Name/Number -
<a href="https://help.clicksend.com/article/4kgj7krx00-what-is-a-sender-id-or-sender-number" target="_blank">More Info</a>
</label>
<input id="clicksendsms-sender-name" v-model="$parent.notification.clicksendsmsSenderName" type="text" minlength="3" maxlength="11" class="form-control">
<div class="form-text">Leave blank to use a shared sender number.</div>
</div>
</template>
<script>
import HiddenInput from "../HiddenInput.vue";
export default {
components: {
HiddenInput,
},
};
</script>

View file

@ -11,6 +11,7 @@ import Pushover from "./Pushover.vue";
import Pushy from "./Pushy.vue";
import Octopush from "./Octopush.vue";
import PromoSMS from "./PromoSMS.vue";
import ClickSendSMS from "./ClickSendSMS.vue";
import LunaSea from "./LunaSea.vue";
import Feishu from "./Feishu.vue";
import Apprise from "./Apprise.vue";
@ -20,6 +21,7 @@ import Mattermost from "./Mattermost.vue";
import Matrix from "./Matrix.vue";
import AliyunSMS from "./AliyunSms.vue";
import DingDing from "./DingDing.vue";
import Bark from "./Bark.vue";
/**
* Manage all notification form.
@ -40,6 +42,7 @@ const NotificationFormList = {
"pushy": Pushy,
"octopush": Octopush,
"promosms": PromoSMS,
"clicksendsms": ClickSendSMS,
"lunasea": LunaSea,
"Feishu": Feishu,
"AliyunSMS": AliyunSMS,
@ -48,7 +51,8 @@ const NotificationFormList = {
"line": Line,
"mattermost": Mattermost,
"matrix": Matrix,
"DingDing": DingDing
"DingDing": DingDing,
"Bark": Bark
}
export default NotificationFormList

View file

@ -6,7 +6,7 @@ export default {
ignoreTLSError: "Игнорирай TLS/SSL грешки за HTTPS уебсайтове",
upsideDownModeDescription: "Обръща статуса от достъпен на недостъпен. Ако услугата е достъпна, ще се вижда като НЕДОСТЪПНА.",
maxRedirectDescription: "Максимален брой пренасочвания, които да бъдат следвани. Въведете 0 за да изключите пренасочване.",
acceptedStatusCodesDescription: "Изберете статус кодове, които се считат за успешен отговор.",
acceptedStatusCodesDescription: "Изберете статус кодове, които да се считат за успешен отговор.",
passwordNotMatchMsg: "Повторената парола не съвпада.",
notificationDescription: "Моля, задайте известието към монитор(и), за да функционира.",
keywordDescription: "Търси ключова дума в чист html или JSON отговор - чувствителна е към регистъра",
@ -130,7 +130,7 @@ export default {
"Clear Data": "Изтрий данни",
Events: "Събития",
Heartbeats: "Проверки",
"Auto Get": "Автоматияно получаване",
"Auto Get": "Авт. попълване",
backupDescription: "Можете да архивирате всички монитори и всички известия в JSON файл.",
backupDescription2: "PS: Данни за история и събития не са включени.",
backupDescription3: "Чувствителни данни, като токен кодове за известяване, се съдържат в експортирания файл. Моля, бъдете внимателни с неговото съхранение.",
@ -199,7 +199,7 @@ export default {
"Status Page": "Статус страница",
"Primary Base URL": "Основен базов URL адрес",
"Push URL": "Генериран Push URL адрес",
needPushEvery: "Необходимо е да извършвате заявка към този URL адрес на всеки {0} секунди.",
needPushEvery: "Необходимо е да извършвате заявка към този URL адрес на всеки {0} секунди",
pushOptionalParams: "Допълнителни, но незадължителни параметри: {0}",
defaultNotificationName: "Моето {notification} известяване ({number})",
here: "тук",
@ -252,14 +252,14 @@ export default {
"More info on:": "Повече информация на: {0}",
pushoverDesc1: "Приоритет Спешно (2) по подразбиране изчаква 30 секунди между повторните опити и изтича след 1 час.",
pushoverDesc2: "Ако желаете да изпратите известявания до различни устройства, попълнете полето Устройство.",
"SMS Type": "СМС тип",
"SMS Type": "SMS тип",
octopushTypePremium: "Премиум (Бърз - препоръчителен в случай на тревога)",
octopushTypeLowCost: "Евтин (Бавен - понякога бива блокиран от оператора)",
checkPrice: "Тарифни планове на {0}:",
octopushLegacyHint: "Дали използвате съвместима версия на Octopush (2011-2020) или нова версия?",
"Check octopush prices": "Тарифни планове на octopush {0}.",
octopushPhoneNumber: "Телефонен номер (в международен формат, например: +33612345678) ",
octopushSMSSender: "СМС подател Име: 3-11 знака - букви, цифри и интервал (a-zA-Z0-9)",
octopushSMSSender: "SMS подател Име: 3-11 знака - букви, цифри и интервал (a-zA-Z0-9)",
"LunaSea Device ID": "LunaSea ID на устройство",
"Apprise URL": "Apprise URL адрес",
"Example:": "Пример: {0}",
@ -280,12 +280,12 @@ export default {
aboutIconURL: "Може да предоставите линк към картинка в поле \"URL Адрес за иконка\" за да отмените картинката на профила по подразбиране. Няма да се използва, ако вече сте настроили емотикон.",
aboutMattermostChannelName: "Може да замените канала по подразбиране, към който публикува уеб куката, като въведете името на канала в полето \"Канал име\". Tрябва да бъде активирано в настройките за уеб кука на Mattermost. Например: #other-channel",
matrix: "Matrix",
promosmsTypeEco: "СМС ECO - евтин, но бавен. Често е претоварен. Само за получатели от Полша.",
promosmsTypeFlash: "СМС FLASH - Съобщението автоматично се показва на устройството на получателя. Само за получатели от Полша.",
promosmsTypeFull: "СМС FULL - Високо ниво на СМС услуга. Може да използвате Вашето име като подател (Необходимо е първо да регистрирате името). Надежден метод за съобщения тип тревога.",
promosmsTypeSpeed: "СМС SPEED - Най-висок приоритет в системата. Много бърза и надеждна, но същвременно скъпа услуга. (Около два пъти по-висока цена в сравнение с SMS FULL).",
promosmsTypeEco: "SMS ECO - евтин, но бавен. Често е претоварен. Само за получатели от Полша.",
promosmsTypeFlash: "SMS FLASH - Съобщението автоматично се показва на устройството на получателя. Само за получатели от Полша.",
promosmsTypeFull: "SMS FULL - Високо ниво на SMS услуга. Може да използвате Вашето име като подател (Необходимо е първо да регистрирате името). Надежден метод за съобщения тип тревога.",
promosmsTypeSpeed: "SMS SPEED - Най-висок приоритет в системата. Много бърза и надеждна, но същвременно скъпа услуга. (Около два пъти по-висока цена в сравнение с SMS FULL).",
promosmsPhoneNumber: "Телефонен номер (за получатели от Полша, може да пропуснете въвеждането на код за населено място)",
promosmsSMSSender: "СМС Подател име: Предварително регистрирано име или някое от имената по подразбиране: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
promosmsSMSSender: "SMS Подател име: Предварително регистрирано име или някое от имената по подразбиране: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
"Feishu WebHookUrl": "Feishu URL адрес за уеб кука",
matrixHomeserverURL: "Сървър URL адрес (започва с http(s):// и порт по желание)",
"Internal Room Id": "ID на вътрешна стая",
@ -297,7 +297,7 @@ export default {
PushUrl: "Push URL адрес",
HeadersInvalidFormat: "Заявените хедъри не са валидни JSON: ",
BodyInvalidFormat: "Заявеното съобщение не е валиден JSON: ",
"Monitor History": "История на мониторите:",
"Monitor History": "История на мониторите",
clearDataOlderThan: "Ще се съхранява за {0} дни.",
records: "записа",
"One record": "Един запис",

View file

@ -197,4 +197,112 @@ export default {
pushbullet: "Pushbullet",
line: "Line Messenger",
mattermost: "Mattermost",
"Primary Base URL": "Primär URL",
"Push URL": "Push URL",
needPushEvery: "Du solltest diese URL alle {0} Sekunden aufrufen",
pushOptionalParams: "Optionale Parameter: {0}",
defaultNotificationName: "Meine {notification} Alarm ({number})",
here: "hier",
Required: "Erforderlich",
"Bot Token": "Bot Token",
wayToGetTelegramToken: "Hier kannst du einen Token erhalten {0}.",
"Chat ID": "Chat ID",
supportTelegramChatID: "Unterstützt Direkt Chat / Gruppe / Kanal Chat-ID's",
wayToGetTelegramChatID: "Du kannst die Chat-ID erhalten, indem du eine Nachricht an den Bot sendest und zu dieser URL gehst, um die chat_id: zu sehen.",
"YOUR BOT TOKEN HERE": "HIER DEIN BOT TOKEN",
chatIDNotFound: "Chat-ID wurde nicht gefunden: bitte sende zuerst eine Nachricht an diesen Bot",
"Post URL": "Post URL",
"Content Type": "Content Type",
webhookJsonDesc: "{0} ist gut für alle modernen HTTP-Server sowie Express.js",
webhookFormDataDesc: "{multipart} ist gut für PHP. Die JSON muss mit {decodeFunction} geparst werden",
secureOptionNone: "Keine / STARTTLS (25, 587)",
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "TLS-Fehler ignorieren",
"From Email": "Von Email",
emailCustomSubject: "Benutzerdefinierter Betreff",
"To Email": "Zu Email",
smtpCC: "CC",
smtpBCC: "BCC",
"Discord Webhook URL": "Discord Webhook URL",
wayToGetDiscordURL: "Du kannst diesen erhalten, indem du zu den Servereinstellungen gehst -> Integrationen -> Neuer Webhook",
"Bot Display Name": "Bot-Anzeigename",
"Prefix Custom Message": "Benutzerdefinierter Nachrichten Präfix",
"Hello @everyone is...": "Hallo {'@'}everyone ist...",
"Webhook URL": "Webhook URL",
wayToGetTeamsURL: "Hier erfährst du, wie eine Webhook-URL erstellt werden kann {0}.",
Number: "Nummer",
Recipients: "Empfänger",
needSignalAPI: "Es wird ein Signal Client mit REST-API benötigt.",
wayToCheckSignalURL: "Du kannst diese URL aufrufen, um zu sehen, wie du eine einrichtest:",
signalImportant: "WICHTIG: Gruppen und Nummern können in Empfängern nicht gemischt werden!",
"Application Token": "Anwendungs Token",
"Server URL": "Server URL",
Priority: "Priorität",
"Icon Emoji": "Icon Emoji",
"Channel Name": "Kanalname",
"Uptime Kuma URL": "Uptime Kuma URL",
aboutWebhooks: "Weitere Informationen zu Webhooks auf: {0}",
aboutChannelName: "Gebe den Kanalnamen ein auf {0} Feld Kanalname, wenn du den Webhook-Kanal umgehen möchtest. Ex: #other-channel",
aboutKumaURL: "Wenn das Feld für die Uptime Kuma URL leer gelassen wird, wird es standardmäßig die GitHub Projekt Seite verwenden.",
emojiCheatSheet: "Emoji Cheat Sheet: {0}",
"User Key": "Benutzerschlüssel",
Device: "Gerät",
"Message Title": "Nachrichtentitel",
"Notification Sound": "Benachrichtigungston",
"More info on:": "Mehr Infos auf: {0}",
pushoverDesc1: "Notfallpriorität (2) hat Standardmäßig 30 Sekunden Auszeit, zwischen den Versuchen und läuft nach 1 Stunde ab.",
pushoverDesc2: "Fülle das Geräte Feld aus, wenn du Benachrichtigungen an verschiedene Geräte senden möchtest.",
"SMS Type": "SMS Typ",
octopushTypePremium: "Premium (Schnell - zur Benachrichtigung empfohlen)",
octopushTypeLowCost: "Kostengünstig (Langsam - manchmal vom Betreiber gesperrt)",
checkPrice: "Prüfe {0} Preise:",
octopushLegacyHint: "Verwendest du die Legacy-Version von Octopush (2011-2020) oder die neue Version?",
"Check octopush prices": "Überprüfe die Oktopush Preise {0}.",
octopushPhoneNumber: "Telefonnummer (Internationales Format, z.B : +49612345678) ",
octopushSMSSender: "Name des SMS-Absenders : 3-11 alphanumerische Zeichen und Leerzeichen (a-zA-Z0-9)",
"LunaSea Device ID": "LunaSea Geräte ID",
"Apprise URL": "Apprise URL",
"Example:": "Beispiel: {0}",
"Read more:": "Weiterlesen: {0}",
"Status:": "Status: {0}",
"Read more": "Weiterlesen",
appriseInstalled: "Apprise ist installiert.",
appriseNotInstalled: "Apprise ist nicht installiert. {0}",
"Access Token": "Access Token",
"Channel access token": "Channel access token",
"Line Developers Console": "Line Developers Console",
lineDevConsoleTo: "Line Developers Console - {0}",
"Basic Settings": "Basic Settings",
"User ID": "User ID",
"Messaging API": "Messaging API",
wayToGetLineChannelToken: "Rufe zuerst {0} auf, erstelle dann einen Provider und Channel (Messaging API). Als nächstes kannst du den Channel access token und die User ID aus den oben genannten Menüpunkten abrufen.",
"Icon URL": "Icon URL",
aboutIconURL: "Du kannst einen Link zu einem Bild in 'Icon URL' übergeben um das Standardprofilbild zu überschreiben. Wird nicht verwendet, wenn ein Icon Emoji gesetzt ist.",
aboutMattermostChannelName: "Du kannst den Standardkanal, auf dem der Webhook postet überschreiben, indem der Kanalnamen in das Feld 'Channel Name' eingeben wird. Dies muss in den Mattermost Webhook-Einstellungen aktiviert werden. Ex: #other-channel",
matrix: "Matrix",
promosmsTypeEco: "SMS ECO - billig, aber langsam und oft überladen. Nur auf polnische Empfänger beschränkt.",
promosmsTypeFlash: "SMS FLASH - Die Nachricht wird automatisch auf dem Empfängergerät angezeigt. Nur auf polnische Empfänger beschränkt.",
promosmsTypeFull: "SMS FULL - Premium Stufe von SMS, es kann der Absendernamen verwendet werden (Der Name musst zuerst registriert werden). Zuverlässig für Warnungen.",
promosmsTypeSpeed: "SMS SPEED - Höchste Priorität im System. Sehr schnell und zuverlässig, aber teuer (Ungefähr das doppelte von SMS FULL).",
promosmsPhoneNumber: "Phone number (Für polnische Empfänger können die Vorwahlen übersprungen werden)",
promosmsSMSSender: "Name des SMS-Absenders : vorregistrierter Name oder einer der Standardwerte: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
"Feishu WebHookUrl": "Feishu Webhook URL",
matrixHomeserverURL: "Heimserver URL (mit http(s):// und optionalen Ports)",
"Internal Room Id": "Interne Raum-ID",
matrixDesc1: "Die interne Raum-ID findest du im erweiterten Bereich der Raumeinstellungen im Matrix-Client. Es sollte es aussehen wie z.B. !QMdRCpUIfLwsfjxye6:home.server.",
matrixDesc2: "Es wird dringend empfohlen, dass ein neuen Benutzer erstellt wird und nicht den Zugriffstoken deines eigenen Matrix-Benutzers verwendest. Anderfalls ermöglicht es vollen Zugriff auf dein Konto und alle Räume, denen du beigetreten bist. Erstelle stattdessen einen neuen Benutzer und lade ihn nur in den Raum ein, in dem du die Benachrichtigung erhalten möchtest. Du kannst den Zugriffstoken erhalten, indem du folgendes ausführst {0}",
Method: "Method",
Body: "Body",
Headers: "Headers",
PushUrl: "Push URL",
HeadersInvalidFormat: "Die Header ist kein gültiges JSON: ",
BodyInvalidFormat: "Der Body ist kein gültiges JSON: ",
"Monitor History": "Monitor Verlauf",
clearDataOlderThan: "Bewahre die Monitor-Verlaufsdaten für {0} Tage auf.",
PasswordsDoNotMatch: "Passwörter stimmen nicht überein.",
records: "Einträge",
"One record": "Ein Eintrag",
"Showing {from} to {to} of {count} records": "Zeige {from} zu {to} von {count} Einträge",
steamApiKeyDescription: "Um einen Steam Game Server zu überwachen, wird ein Steam Web-API-Schlüssel benötigt. Dieser kann hier registriert werden: ",
"Current User": "Aktueller Benutzer",
};

View file

@ -183,11 +183,10 @@ export default {
"Edit Status Page": "Edit Status Page",
"Go to Dashboard": "Go to Dashboard",
"Status Page": "Status Page",
// Start notification form
defaultNotificationName: "My {notification} Alert ({number})",
here: "here",
"Required": "Required",
"telegram": "Telegram",
Required: "Required",
telegram: "Telegram",
"Bot Token": "Bot Token",
wayToGetTelegramToken: "You can get a token from {0}.",
"Chat ID": "Chat ID",
@ -195,12 +194,12 @@ export default {
wayToGetTelegramChatID: "You can get your chat ID by sending a message to the bot and going to this URL to view the chat_id:",
"YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE",
chatIDNotFound: "Chat ID is not found; please send a message to this bot first",
"webhook": "Webhook",
webhook: "Webhook",
"Post URL": "Post URL",
"Content Type": "Content Type",
webhookJsonDesc: "{0} is good for any modern HTTP servers such as Express.js",
webhookFormDataDesc: "{multipart} is good for PHP. The JSON will need to be parsed with {decodeFunction}",
"smtp": "Email (SMTP)",
smtp: "Email (SMTP)",
secureOptionNone: "None / STARTTLS (25, 587)",
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "Ignore TLS Error",
@ -209,26 +208,26 @@ export default {
"To Email": "To Email",
smtpCC: "CC",
smtpBCC: "BCC",
"discord": "Discord",
discord: "Discord",
"Discord Webhook URL": "Discord Webhook URL",
wayToGetDiscordURL: "You can get this by going to Server Settings -> Integrations -> Create Webhook",
"Bot Display Name": "Bot Display Name",
"Prefix Custom Message": "Prefix Custom Message",
"Hello @everyone is...": "Hello {'@'}everyone is...",
"teams": "Microsoft Teams",
teams: "Microsoft Teams",
"Webhook URL": "Webhook URL",
wayToGetTeamsURL: "You can learn how to create a webhook URL {0}.",
"signal": "Signal",
"Number": "Number",
"Recipients": "Recipients",
signal: "Signal",
Number: "Number",
Recipients: "Recipients",
needSignalAPI: "You need to have a signal client with REST API.",
wayToCheckSignalURL: "You can check this URL to view how to set one up:",
signalImportant: "IMPORTANT: You cannot mix groups and numbers in recipients!",
"gotify": "Gotify",
gotify: "Gotify",
"Application Token": "Application Token",
"Server URL": "Server URL",
"Priority": "Priority",
"slack": "Slack",
Priority: "Priority",
slack: "Slack",
"Icon Emoji": "Icon Emoji",
"Channel Name": "Channel Name",
"Uptime Kuma URL": "Uptime Kuma URL",
@ -241,13 +240,14 @@ export default {
pushy: "Pushy",
octopush: "Octopush",
promosms: "PromoSMS",
clicksendsms: "ClickSend SMS",
lunasea: "LunaSea",
apprise: "Apprise (Support 50+ Notification services)",
pushbullet: "Pushbullet",
line: "Line Messenger",
mattermost: "Mattermost",
"User Key": "User Key",
"Device": "Device",
Device: "Device",
"Message Title": "Message Title",
"Notification Sound": "Notification Sound",
"More info on:": "More info on: {0}",
@ -257,6 +257,7 @@ export default {
octopushTypePremium: "Premium (Fast - recommended for alerting)",
octopushTypeLowCost: "Low Cost (Slow - sometimes blocked by operator)",
checkPrice: "Check {0} prices:",
apiCredentials: "API credentials",
octopushLegacyHint: "Do you use the legacy version of Octopush (2011-2020) or the new version?",
"Check octopush prices": "Check octopush prices {0}.",
octopushPhoneNumber: "Phone number (intl format, eg : +33612345678) ",
@ -280,7 +281,7 @@ export default {
"Icon URL": "Icon URL",
aboutIconURL: "You can provide a link to a picture in \"Icon URL\" to override the default profile picture. Will not be used if Icon Emoji is set.",
aboutMattermostChannelName: "You can override the default channel that the Webhook posts to by entering the channel name into \"Channel Name\" field. This needs to be enabled in the Mattermost Webhook settings. Ex: #other-channel",
"matrix": "Matrix",
matrix: "Matrix",
promosmsTypeEco: "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.",
promosmsTypeFlash: "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.",
promosmsTypeFull: "SMS FULL - Premium tier of SMS, You can use your Sender Name (You need to register name first). Reliable for alerts.",
@ -292,18 +293,18 @@ export default {
"Internal Room Id": "Internal Room ID",
matrixDesc1: "You can find the internal room ID by looking in the advanced section of the room settings in your Matrix client. It should look like !QMdRCpUIfLwsfjxye6:home.server.",
matrixDesc2: "It is highly recommended you create a new user and do not use your own Matrix user's access token as it will allow full access to your account and all the rooms you joined. Instead, create a new user and only invite it to the room that you want to receive the notification in. You can get the access token by running {0}",
// End notification form
Method: "Method",
Body: "Body",
Headers: "Headers",
PushUrl: "Push URL",
HeadersInvalidFormat: "The request headers are not valid JSON: ",
BodyInvalidFormat: "The request body is not valid JSON: ",
"Monitor History": "Monitor History:",
"Monitor History": "Monitor History",
clearDataOlderThan: "Keep monitor history data for {0} days.",
PasswordsDoNotMatch: "Passwords do not match.",
records: "records",
"One record": "One record",
"Showing {from} to {to} of {count} records": "Showing {from} to {to} of {count} records",
steamApiKeyDescription: "For monitoring a Steam Game Server you need a Steam Web-API key. You can register your API key here: ",
"Current User": "Current User",
};

View file

@ -198,7 +198,7 @@ export default {
pushbullet: "Pushbullet",
line: "Line Messenger",
mattermost: "Mattermost",
"Monitor History": "Historial de monitor:",
"Monitor History": "Historial de monitor",
clearDataOlderThan: "Mantener los datos del historial del monitor durante {0} días.",
records: "registros",
"One record": "Un registro",

View file

@ -179,11 +179,10 @@ export default {
"Edit Status Page": "Modifier la page de statut",
"Go to Dashboard": "Accéder au tableau de bord",
"Status Page": "Status Page",
// Start notification form
defaultNotificationName: "Ma notification {notification} numéro ({number})",
here: "ici",
"Required": "Requis",
"telegram": "Telegram",
Required: "Requis",
telegram: "Telegram",
"Bot Token": "Bot Token",
wayToGetTelegramToken: "Vous pouvez obtenir un token depuis {0}.",
"Chat ID": "Chat ID",
@ -191,12 +190,12 @@ export default {
wayToGetTelegramChatID: "Vous pouvez obtenir l'ID du chat en envoyant un message avec le bot puis en récupérant l'URL pour voir l'ID du salon :",
"YOUR BOT TOKEN HERE": "VOTRE TOKEN BOT ICI",
chatIDNotFound: "ID du salon introuvable, envoyez un message via le bot avant",
"webhook": "Webhook",
webhook: "Webhook",
"Post URL": "Post URL",
"Content Type": "Content Type",
webhookJsonDesc: "{0} est bien/bon pour tous les serveurs HTTP modernes comme express.js",
webhookFormDataDesc: "{multipart} est bien/bon pour du PHP, vous avez juste besoin de mettre le json via/depuis {decodeFunction}",
"smtp": "Email (SMTP)",
smtp: "Email (SMTP)",
secureOptionNone: "Aucun / STARTTLS (25, 587)",
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "Ignorer les erreurs TLS",
@ -204,26 +203,26 @@ export default {
"To Email": "Vers l'Email",
smtpCC: "CC",
smtpBCC: "BCC",
"discord": "Discord",
discord: "Discord",
"Discord Webhook URL": "Discord Webhook URL",
wayToGetDiscordURL: "Vous pouvez l'obtenir en allant dans 'Paramètres du Serveur' -> 'Intégrations' -> 'Créer un Webhook'",
"Bot Display Name": "Nom du bot (affiché)",
"Prefix Custom Message": "Prefix Custom Message",
"Hello @everyone is...": "Bonjour {'@'}everyone il...",
"teams": "Microsoft Teams",
teams: "Microsoft Teams",
"Webhook URL": "Webhook URL",
wayToGetTeamsURL: "Vous pouvez apprendre comment créer un Webhook {0}.",
"signal": "Signal",
"Number": "Numéro",
"Recipients": "Destinataires",
signal: "Signal",
Number: "Numéro",
Recipients: "Destinataires",
needSignalAPI: "Vous avez besoin d'un client Signal avec l'API REST.",
wayToCheckSignalURL: "Vous pouvez regarder l'URL sur comment le mettre en place :",
signalImportant: "IMPORTANT: Vous ne pouvez pas mixer les groupes et les numéros en destinataires !",
"gotify": "Gotify",
gotify: "Gotify",
"Application Token": "Application Token",
"Server URL": "Server URL",
"Priority": "Priorité",
"slack": "Slack",
Priority: "Priorité",
slack: "Slack",
"Icon Emoji": "Icon Emoji",
"Channel Name": "Nom du salon",
"Uptime Kuma URL": "Uptime Kuma URL",
@ -242,7 +241,7 @@ export default {
line: "Line Messenger",
mattermost: "Mattermost",
"User Key": "Clé d'utilisateur",
"Device": "Appareil",
Device: "Appareil",
"Message Title": "Titre du message",
"Notification Sound": "Son de notification",
"More info on:": "Plus d'informations sur: {0}",
@ -273,12 +272,11 @@ export default {
"Icon URL": "Icon URL",
aboutIconURL: "Vous pouvez mettre un lien vers l'image dans \"Icon URL\" pour remplacer l'image de profil par défaut. Ne sera pas utilisé si Icon Emoji est défini.",
aboutMattermostChannelName: "Vous pouvez remplacer le salon par défaut que le Webhook utilise en mettant le nom du salon dans le champ \"Channel Name\". Vous aurez besoin de l'activer depuis les paramètres de Mattermost. Ex : #autre-salon",
"matrix": "Matrix",
matrix: "Matrix",
promosmsTypeEco: "SMS ECO - Pas cher mais lent et souvent surchargé. Limité uniquement aux déstinataires Polonais.",
promosmsTypeFlash: "SMS FLASH - Le message sera automatiquement affiché sur l'appareil du destinataire. Limité uniquement aux déstinataires Polonais.",
promosmsTypeFull: "SMS FULL - Version Premium des SMS, Vous pouvez mettre le nom de l'expéditeur (Vous devez vous enregistrer avant). Fiable pour les alertes.",
promosmsTypeSpeed: "SMS SPEED - La plus haute des priorités dans le système. Très rapide et fiable mais cher (environ le double du prix d'un SMS FULL).",
promosmsPhoneNumber: "Numéro de téléphone (Poiur les déstinataires Polonais, vous pouvez enlever les codes interna.)",
promosmsSMSSender: "SMS Expéditeur : Nom pré-enregistré ou l'un de base: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
// End notification form
};

View file

@ -179,11 +179,10 @@ export default {
"Edit Status Page": "Edit Halaman Status",
"Go to Dashboard": "Pergi ke Dasbor",
"Status Page": "Halaman Status",
// Start notification form
defaultNotificationName: "{notification} saya Peringatan ({number})",
here: "di sini",
"Required": "Dibutuhkan",
"telegram": "Telegram",
Required: "Dibutuhkan",
telegram: "Telegram",
"Bot Token": "Bot Token",
"You can get a token from": "Anda bisa mendapatkan token dari",
"Chat ID": "Chat ID",
@ -191,12 +190,12 @@ export default {
wayToGetTelegramChatID: "Anda bisa mendapatkan chat id Anda dengan mengirim pesan ke bot dan pergi ke url ini untuk melihat chat_id:",
"YOUR BOT TOKEN HERE": "BOT TOKEN ANDA DI SINI",
chatIDNotFound: "Chat ID tidak ditemukan, tolong kirim pesan ke bot ini dulu",
"webhook": "Webhook",
webhook: "Webhook",
"Post URL": "Post URL",
"Content Type": "Tipe konten",
webhookJsonDesc: "{0} bagus untuk peladen http modern seperti express.js",
webhookFormDataDesc: "{multipart} bagus untuk PHP, Anda hanya perlu mengurai json dengan {decodeFunction}",
"smtp": "Surel (SMTP)",
smtp: "Surel (SMTP)",
secureOptionNone: "None / STARTTLS (25, 587)",
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "Abaikan Kesalahan TLS",
@ -204,26 +203,26 @@ export default {
"To Email": "Ke Surel",
smtpCC: "CC",
smtpBCC: "BCC",
"discord": "Discord",
discord: "Discord",
"Discord Webhook URL": "Discord Webhook URL",
wayToGetDiscordURL: "Anda bisa mendapatkan ini dengan pergi ke Server Settings -> Integrations -> Create Webhook",
"Bot Display Name": "Nama Bot",
"Prefix Custom Message": "Awalan Pesan",
"Hello @everyone is...": "Halo {'@'}everyone is...",
"teams": "Microsoft Teams",
teams: "Microsoft Teams",
"Webhook URL": "Webhook URL",
wayToGetTeamsURL: "Anda dapat mempelajari cara membuat url webhook {0}.",
"signal": "Sinyal",
"Number": "Nomer",
"Recipients": "Penerima",
signal: "Sinyal",
Number: "Nomer",
Recipients: "Penerima",
needSignalAPI: "Anda harus memiliki klien sinyal dengan REST API.",
wayToCheckSignalURL: "Anda dapat memeriksa url ini untuk melihat cara menyiapkannya:",
signalImportant: "PENTING: Anda tidak dapat mencampur grup dan nomor di penerima!",
"gotify": "Gotify",
gotify: "Gotify",
"Application Token": "Token Aplikasi",
"Server URL": "URL Peladen",
"Priority": "Prioritas",
"slack": "Slack",
Priority: "Prioritas",
slack: "Slack",
"Icon Emoji": "Ikon Emoji",
"Channel Name": "Nama Saluran",
"Uptime Kuma URL": "Uptime Kuma URL",
@ -242,7 +241,7 @@ export default {
line: "Line Messenger",
mattermost: "Mattermost",
"User Key": "Kunci pengguna",
"Device": "Perangkat",
Device: "Perangkat",
"Message Title": "Judul Pesan",
"Notification Sound": "Suara Nofifikasi",
"More info on:": "Info lebih lanjut tentang: {0}",
@ -273,7 +272,7 @@ export default {
"Icon URL": "Icon URL",
aboutIconURL: "Anda dapat memberikan tautan ke gambar di \"Icon URL\" untuk mengganti gambar profil bawaan. Tidak akan digunakan jika Ikon Emoji diset.",
aboutMattermostChannelName: "Anda dapat mengganti saluran bawaan tujuan posting webhook dengan memasukkan nama saluran ke dalam Kolom \"Channel Name\". Ini perlu diaktifkan di pengaturan webhook Mattermost. contoh: #other-channel",
"matrix": "Matrix",
matrix: "Matrix",
promosmsTypeEco: "SMS ECO - murah tapi lambat dan sering kelebihan beban. Terbatas hanya untuk penerima Polandia.",
promosmsTypeFlash: "SMS FLASH - Pesan akan otomatis muncul di perangkat penerima. Terbatas hanya untuk penerima Polandia.",
promosmsTypeFull: "SMS FULL - SMS tingkat premium, Anda dapat menggunakan Nama Pengirim Anda (Anda harus mendaftarkan nama terlebih dahulu). Dapat diAndalkan untuk peringatan.",
@ -281,5 +280,4 @@ export default {
promosmsPhoneNumber: "Nomor telepon (untuk penerima Polandia Anda dapat melewati kode area)",
promosmsSMSSender: "Nama Pengirim SMS : Nama pra-registrasi atau salah satu bawaan: InfoSMS, Info SMS, MaxSMS, INFO, SMS",
"Feishu WebHookUrl": "Feishu WebHookUrl",
// End notification form
};

View file

@ -179,11 +179,10 @@ export default {
"Edit Status Page": "Rediger statusside",
"Go to Dashboard": "Gå til Dashboard",
"Status Page": "Statusside",
// Start notification form
defaultNotificationName: "Min {notification} varsling ({number})",
here: "here",
"Required": "Obligatorisk",
"telegram": "Telegram",
Required: "Obligatorisk",
telegram: "Telegram",
"Bot Token": "Bot Token",
wayToGetTelegramToken: "Du kan få et token fra {0}.",
"Chat ID": "Chat ID",
@ -191,12 +190,12 @@ export default {
wayToGetTelegramChatID: "Du kan få chat-ID-en din ved å sende meldingen til boten og gå til denne nettadressen for å se chat_id:",
"YOUR BOT TOKEN HERE": "DITT BOT TOKEN HER",
chatIDNotFound: "Chat-ID ble ikke funnet. Send en melding til denne boten først",
"webhook": "Webhook",
webhook: "Webhook",
"Post URL": "Post URL",
"Content Type": "Content Type",
webhookJsonDesc: "{0} er bra for alle moderne HTTP-servere som express.js",
webhookFormDataDesc: "{multipart} er bra for PHP, du trenger bare å analysere JSON etter {decodeFunction}",
"smtp": "E-post (SMTP)",
smtp: "E-post (SMTP)",
secureOptionNone: "None / STARTTLS (25, 587)",
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "Ignorer TLS feilmelding",
@ -204,26 +203,26 @@ export default {
"To Email": "Til E-post",
smtpCC: "CC",
smtpBCC: "BCC",
"discord": "Discord",
discord: "Discord",
"Discord Webhook URL": "Discord Webhook URL",
wayToGetDiscordURL: "Du kan få dette ved å gå til Serverinnstillinger -> Integrasjoner -> Webhooks -> Ny webhook",
"Bot Display Name": "Bot Visningsnavn",
"Prefix Custom Message": "Prefiks tilpasset melding",
"Hello @everyone is...": "Hei {'@'}everyone det er...",
"teams": "Microsoft Teams",
teams: "Microsoft Teams",
"Webhook URL": "Webhook URL",
wayToGetTeamsURL: "Du kan lære hvordan du oppretter en webhook-URL {0}.",
"signal": "Signal",
"Number": "Nummer",
"Recipients": "Mottakere",
signal: "Signal",
Number: "Nummer",
Recipients: "Mottakere",
needSignalAPI: "Du må ha en Signal-klient med REST API.",
wayToCheckSignalURL: "Du kan sjekke denne nettadressen for å se hvordan du konfigurerer en:",
signalImportant: "VIKTIG: Du kan ikke blande grupper og nummere i mottakere!",
"gotify": "Gotify",
gotify: "Gotify",
"Application Token": "Application Token",
"Server URL": "Server URL",
"Priority": "Prioritet",
"slack": "Slack",
Priority: "Prioritet",
slack: "Slack",
"Icon Emoji": "Icon Emoji",
"Channel Name": "Kanal navn",
"Uptime Kuma URL": "Uptime Kuma URL",
@ -242,7 +241,7 @@ export default {
line: "Line Messenger",
mattermost: "Mattermost",
"User Key": "User Key",
"Device": "Device",
Device: "Device",
"Message Title": "Message Title",
"Notification Sound": "Notification Sound",
"More info on:": "More info on: {0}",
@ -273,12 +272,11 @@ export default {
"Icon URL": "Icon URL",
aboutIconURL: "You can provide a link to a picture in \"Icon URL\" to override the default profile picture. Will not be used if Icon Emoji is set.",
aboutMattermostChannelName: "You can override the default channel that webhook posts to by entering the channel name into \"Channel Name\" field. This needs to be enabled in Mattermost webhook settings. Ex: #other-channel",
"matrix": "Matrix",
matrix: "Matrix",
promosmsTypeEco: "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.",
promosmsTypeFlash: "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.",
promosmsTypeFull: "SMS FULL - Premium tier of SMS, You can use Your Sender Name (You need to register name first). Reliable for alerts.",
promosmsTypeSpeed: "SMS SPEED - Highest priority in system. Very quick and reliable but costly (about twice of SMS FULL price).",
promosmsPhoneNumber: "Phone number (for Polish recipient You can skip area codes)",
promosmsSMSSender: "SMS Sender Name : Pre-registred name or one of defaults: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
// End notification form
};

View file

@ -203,5 +203,5 @@ export default {
Headers: "Headers",
PushUrl: "Push URL",
HeadersInvalidFormat: "The request headers is geen geldige JSON: ",
BodyInvalidFormat: "De request body is geen geldige JSON: "
BodyInvalidFormat: "De request body is geen geldige JSON: ",
};

View file

@ -118,8 +118,8 @@ export default {
"Last Result": "Ostatni wynik",
"Create your admin account": "Utwórz swoje konto administratora",
"Repeat Password": "Powtórz hasło",
"Import Backup": "Importuj Kopię",
"Export Backup": "Eksportuj Kopię",
"Import Backup": "Importuj kopię zapasową",
"Export Backup": "Eksportuj kopię zapasową",
Export: "Eksportuj",
Import: "Importuj",
respTime: "Czas Odp. (ms)",
@ -127,7 +127,7 @@ export default {
"Default enabled": "Włącz domyślnie",
"Apply on all existing monitors": "Zastosuj do istniejących monitorów",
Create: "Stwórz",
"Clear Data": "Usuń Dane",
"Clear Data": "Usuń dane",
Events: "Wydarzenia",
Heartbeats: "Bicia serca",
"Auto Get": "Wykryj",
@ -179,11 +179,10 @@ export default {
"Edit Status Page": "Edytuj stronę statusu",
"Go to Dashboard": "Idź do panelu",
"Status Page": "Strona statusu",
// Start notification form
defaultNotificationName: "Moje powiadomienie {notification} ({number})",
here: "tutaj",
"Required": "Wymagane",
"telegram": "Telegram",
Required: "Wymagane",
telegram: "Telegram",
"Bot Token": "Token Bota",
wayToGetTelegramToken: "Token można uzyskać z {0}.",
"Chat ID": "Identyfikator Czatu",
@ -191,12 +190,12 @@ export default {
wayToGetTelegramChatID: "Możesz uzyskać swój identyfikator czatu, wysyłając wiadomość do bota i przechodząc pod ten adres URL, aby wyświetlić identyfikator czatu:",
"YOUR BOT TOKEN HERE": "TWOJ TOKEN BOTA",
chatIDNotFound: "Identyfikator czatu nie znaleziony, najpierw napisz do bota",
"webhook": "Webhook",
webhook: "Webhook",
"Post URL": "Adres URL",
"Content Type": "Rodzaj danych",
webhookJsonDesc: "{0} jest dobry w przypadku serwerów HTTP, takich jak express.js",
webhookFormDataDesc: "{multipart} jest dobry dla PHP, musisz jedynie przetowrzyć dane przez {decodeFunction}",
"smtp": "Email (SMTP)",
smtp: "Email (SMTP)",
secureOptionNone: "Brak / STARTTLS (25, 587)",
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "Zignrouj Błędy TLS",
@ -204,26 +203,26 @@ export default {
"To Email": "Odbiorca (DO)",
smtpCC: "DW",
smtpBCC: "UDW",
"discord": "Discord",
discord: "Discord",
"Discord Webhook URL": "URL Webhook Discorda",
wayToGetDiscordURL: "Możesz go uzyskać przechodząc do Ustawienia Serwera -> Integracje -> Tworzenie Webhooka",
"Bot Display Name": "Wyświetlana Nazwa Bota",
"Prefix Custom Message": "Własny Początek Wiadomości",
"Hello @everyone is...": "Hej {'@'}everyone ...",
"teams": "Microsoft Teams",
teams: "Microsoft Teams",
"Webhook URL": "URL Webhooka",
wayToGetTeamsURL: "You can learn how to create a webhook url {0}.",
"signal": "Signal",
"Number": "Numer",
"Recipients": "Odbiorcy",
signal: "Signal",
Number: "Numer",
Recipients: "Odbiorcy",
needSignalAPI: "Musisz posiadać klienta Signal z REST API.",
wayToCheckSignalURL: "W celu dowiedzenia się, jak go skonfigurować, odwiedź poniższy link:",
signalImportant: "UWAGA: Nie można mieszać nazw grup i numerów odbiorców!",
"gotify": "Gotify",
gotify: "Gotify",
"Application Token": "Token Aplikacji",
"Server URL": "Server URL",
"Priority": "Priorytet",
"slack": "Slack",
Priority: "Priorytet",
slack: "Slack",
"Icon Emoji": "Ikona Emoji",
"Channel Name": "Nazwa Kanału",
"Uptime Kuma URL": "Adres Uptime Kuma",
@ -242,7 +241,7 @@ export default {
line: "Line Messenger",
mattermost: "Mattermost",
"User Key": "Klucz Użytkownika",
"Device": "Urządzenie",
Device: "Urządzenie",
"Message Title": "Tytuł Wiadomości",
"Notification Sound": "Dźwięk Powiadomienia",
"More info on:": "Więcej informacji na: {0}",
@ -271,14 +270,38 @@ export default {
"Messaging API": "API Wiadomości",
wayToGetLineChannelToken: "Najpierw uzyskaj dostęp do {0}, utwórz dostawcę i kanał (Messaging API), a następnie możesz uzyskać token dostępu do kanału i identyfikator użytkownika z wyżej wymienionych pozycji menu.",
"Icon URL": "Adres Ikony",
aboutIconURL: "You can provide a link to a picture in \"Icon URL\" to override the default profile picture. Will not be used if Icon Emoji is set.",
aboutMattermostChannelName: "You can override the default channel that webhook posts to by entering the channel name into \"Channel Name\" field. This needs to be enabled in Mattermost webhook settings. Ex: #other-channel",
"matrix": "Matrix",
aboutIconURL: "Możesz podać link do zdjęcia w \"Adres URL ikony\", aby zastąpić domyślne zdjęcie profilowe. Nie będzie używany, jeśli ustawiona jest ikona Emoji.",
aboutMattermostChannelName: "Możesz zastąpić domyślny kanał, na którym publikowane są posty webhooka, wpisując nazwę kanału w polu \"Nazwa Kanału\". Należy to włączyć w ustawieniach webhooka Mattermost. Np.: #inny-kanał",
matrix: "Matrix",
promosmsTypeEco: "SMS ECO - Tanie, lecz wolne. Dostępne tylko w Polsce",
promosmsTypeFlash: "SMS FLASH - Wiadomość automatycznie wyświetli się na urządzeniu. Dostępne tylko w Polsce.",
promosmsTypeFull: "SMS FULL - Szybkie i dostępne międzynarodowo. Wersja premium usługi, która pozwala min. ustawić własną nazwę nadawcy.",
promosmsTypeSpeed: "SMS SPEED - Wysyłka priorytetowa, posiada wszystkie zalety SMS FULL",
promosmsPhoneNumber: "Numer Odbiorcy",
promosmsSMSSender: "Nadawca SMS (Wcześniej zatwierdzone nazwy z panelu PromoSMS)",
// End notification form
"Primary Base URL": "Główny URL",
"Push URL": "Push URL",
needPushEvery: "Powinieneś wywoływać ten URL co {0} sekund",
pushOptionalParams: "Parametry opcjonalne: {0}",
emailCustomSubject: "Niestandardowy temat",
checkPrice: "Sprawdź ceny {0}:",
octopushLegacyHint: "Czy używasz starszej wersji Octopush (2011-2020) czy nowej wersji?",
"Feishu WebHookUrl": "Feishu WebHookURL",
matrixHomeserverURL: "Adres URL serwera domowego (z http(s):// i opcjonalnie port)",
"Internal Room Id": "Wewnętrzne ID pokoju",
matrixDesc1: "Możesz znaleźć wewnętrzne ID pokoju patrząc w zaawansowanej sekcji ustawień pokoju w twoim kliencie Matrix. Powinien on wyglądać jak !QMdRCpUIfLwsfjxye6:home.server.",
matrixDesc2: "Jest wysoce zalecane, abyś stworzył nowego użytkownika i nie używał tokena dostępu swojego użytkownika Matrix, ponieważ pozwoli on na pełny dostęp do twojego konta i wszystkich pokoi, do których dołączyłeś. Zamiast tego, utwórz nowego użytkownika i zaproś go tylko do pokoju, w którym chcesz otrzymywać powiadomienia. Możesz uzyskać token dostępu przez uruchomienie {0}",
Method: "Metoda",
Body: "Treść",
Headers: "Nagłówki",
PushUrl: "Push URL",
HeadersInvalidFormat: "Nagłówki żądania nie są w poprawnym formacie JSON: ",
BodyInvalidFormat: "Treść żądania nie jest w poprawnym formacie JSON: ",
"Monitor History": "Historia monitorów",
clearDataOlderThan: "Przechowuj dane dotyczące historii monitorowania {0} dni.",
PasswordsDoNotMatch: "Hasła nie pasują.",
records: "rekordy",
"One record": "Jeden rekord",
"Showing {from} to {to} of {count} records": "Wyświetlanie {from} do {to} z {count} rekordów",
steamApiKeyDescription: "Do monitorowania serwera gier Steam potrzebny jest klucz Steam Web-API. Możesz zarejestrować swój klucz API tutaj: ",
};

View file

@ -204,7 +204,7 @@ export default {
mattermost: "Mattermost",
"Primary Base URL": "Основной URL",
"Push URL": "URL пуша",
needPushEvery: "К этому URL необходимо обращаться каждые {0} секунд.",
needPushEvery: "К этому URL необходимо обращаться каждые {0} секунд",
pushOptionalParams: "Опциональные параметры: {0}",
defaultNotificationName: "Моё уведомление {notification} ({number})",
here: "здесь",

View file

@ -179,11 +179,10 @@ export default {
"Edit Status Page": "Sửa trang trạng thái",
"Go to Dashboard": "Đi tới Dashboard",
"Status Page": "Trang trạng thái",
// Start notification form
defaultNotificationName: "My {notification} Alerts ({number})",
here: "tại đây",
"Required": "Bắt buộc",
"telegram": "Telegram",
Required: "Bắt buộc",
telegram: "Telegram",
"Bot Token": "Bot Token",
"You can get a token from": "Bạn có thể lấy mã token từ",
"Chat ID": "Chat ID",
@ -191,12 +190,12 @@ export default {
wayToGetTelegramChatID: "Bạn có thể lấy chat id của mình bằng cách gửi tin nhắn tới bot và truy cập url này để xem chat_id:",
"YOUR BOT TOKEN HERE": "MÃ BOT TOKEN CỦA BẠN",
chatIDNotFound: "Không tìm thấy Chat ID, vui lòng gửi tin nhắn cho bot này trước",
"webhook": "Webhook",
webhook: "Webhook",
"Post URL": "URL đăng",
"Content Type": "Loại nội dung",
webhookJsonDesc: "{0} phù hợp với bất kỳ máy chủ http hiện đại nào như express.js",
webhookFormDataDesc: "{multipart} phù hợp với PHP, bạn chỉ cần phân tích cú pháp json bằng {decodeFunction}",
"smtp": "Email (SMTP)",
smtp: "Email (SMTP)",
secureOptionNone: "None / STARTTLS (25, 587)",
secureOptionTLS: "TLS (465)",
"Ignore TLS Error": "Bỏ qua lỗi TLS",
@ -204,26 +203,26 @@ export default {
"To Email": "Tới Email",
smtpCC: "CC",
smtpBCC: "BCC",
"discord": "Discord",
discord: "Discord",
"Discord Webhook URL": "Discord Webhook URL",
wayToGetDiscordURL: "Để lấy Discord, hãy vào: Server Settings -> Integrations -> Create Webhook",
"Bot Display Name": "Tên hiển thị của Bot",
"Prefix Custom Message": "Tiền tố tin nhắn tuỳ chọn",
"Hello @everyone is...": "Xin chào {'@'} mọi người đang...",
"teams": "Microsoft Teams",
teams: "Microsoft Teams",
"Webhook URL": "Webhook URL",
wayToGetTeamsURL: "Bạn có thể học cách tạo webhook url {0}.",
"signal": "Signal",
"Number": "Số",
"Recipients": "Người nhận",
signal: "Signal",
Number: "Số",
Recipients: "Người nhận",
needSignalAPI: "Bạn cần một tín hiệu client với REST API.",
wayToCheckSignalURL: "Bạn có thể kiểm tra url này để xem cách thiết lập:",
signalImportant: "QUAN TRỌNG: Bạn không thể kết hợp các nhóm và số trong người nhận!",
"gotify": "Gotify",
gotify: "Gotify",
"Application Token": "Mã Token ứng dụng",
"Server URL": "URL máy chủ",
"Priority": "Mức ưu tiên",
"slack": "Slack",
Priority: "Mức ưu tiên",
slack: "Slack",
"Icon Emoji": "Icon Emoji",
"Channel Name": "Tên Channel",
"Uptime Kuma URL": "Uptime Kuma URL",
@ -242,7 +241,7 @@ export default {
line: "Line Messenger",
mattermost: "Mattermost",
"User Key": "User Key",
"Device": "Thiết bị",
Device: "Thiết bị",
"Message Title": "Tiêu đề tin nhắn",
"Notification Sound": "Âm thanh thông báo",
"More info on:": "Thông tin chi tiết tại: {0}",
@ -273,7 +272,7 @@ export default {
"Icon URL": "Icon URL",
aboutIconURL: "Bạn có thể cung cấp liên kết đến ảnh trong \"Icon URL\" để ghi đè ảnh hồ sơ mặc định. Sẽ không được sử dụng nếu Biểu tượng cảm xúc được thiết lập.",
aboutMattermostChannelName: "Bạn có thể ghi đè kênh mặc định mà webhook đăng lên bằng cách nhập tên kênh vào trường \"Channel Name\". Điều này cần được bật trong cài đặt Mattermost webhook. Ví dụ: #other-channel",
"matrix": "Matrix",
matrix: "Matrix",
promosmsTypeEco: "SMS ECO - rẻ nhưng chậm và thường xuyên quá tải. Chỉ dành cho người Ba Lan.",
promosmsTypeFlash: "SMS FLASH - Tin nhắn sẽ tự động hiển thị trên thiết bị của người nhận. Chỉ dành cho người Ba Lan.",
promosmsTypeFull: "SMS FULL - SMS cao cấp, Bạn có thể sử dụng Tên Người gửi (Bạn cần đăng ký tên trước). Đáng tin cậy cho các cảnh báo.",
@ -281,5 +280,4 @@ export default {
promosmsPhoneNumber: "Số điện thoại (Bỏ qua mã vùng với người Ba Lan)",
promosmsSMSSender: "SMS Tên người gửi: Tên đã đăng ký trước hoặc tên mặc định: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
"Feishu WebHookUrl": "Feishu WebHookUrl",
// End notification form
};

View file

@ -65,7 +65,7 @@ export default {
"Max. Redirects": "重定向次数",
"Accepted Status Codes": "有效状态码",
"Push URL": "推送链接",
needPushEvery: "你需要每 {0} 秒调用一次",
needPushEvery: "你需要每 {0} 秒调用一次",
pushOptionalParams: "可选参数:{0}",
Save: "保存",
Notifications: "消息通知",

View file

@ -328,6 +328,10 @@ export default {
clearStatistics(callback) {
socket.emit("clearStatistics", callback);
},
getMonitorBeats(monitorID, period, callback) {
socket.emit("getMonitorBeats", monitorID, period, callback);
}
},
computed: {

View file

@ -340,11 +340,17 @@ export default {
},
bodyPlaceholder() {
return "{\n\t\"id\": 124357,\n\t\"username\": \"admin\",\n\t\"password\": \"myAdminPassword\"\n}";
return `Example:
{
"key": "value"
}`;
},
headersPlaceholder() {
return "{\n\t\"Authorization\": \"Bearer abc123\",\n\t\"Content-Type\": \"application/json\"\n}";
return `Example:
{
"HeaderName": "HeaderValue"
}`;
}
},

View file

@ -112,7 +112,7 @@
<div class="input-group mb-3">
<input id="primaryBaseURL" v-model="settings.primaryBaseURL" class="form-control" name="primaryBaseURL" placeholder="https://" pattern="https?://.+">
<button class="btn btn-outline-primary" type="button" @click="autoGetPrimaryBaseURL">Auto Get</button>
<button class="btn btn-outline-primary" type="button" @click="autoGetPrimaryBaseURL">{{ $t("Auto Get") }}</button>
</div>
<div class="form-text">
@ -149,6 +149,7 @@
<!-- Change Password -->
<template v-if="! settings.disableAuth">
<h2 class="mt-5 mb-2">{{ $t("Change Password") }}</h2>
<p>{{ $t("Current User") }}: <strong>{{ this.username }}</strong></p>
<form class="mb-3" @submit.prevent="savePassword">
<div class="mb-3">
<label for="current-password" class="form-label">{{ $t("Current Password") }}</label>
@ -231,13 +232,15 @@
{{ importAlert }}
</div>
<!-- Advanced -->
<h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
<div class="mb-3">
<button v-if="settings.disableAuth" class="btn btn-outline-primary me-2 mb-2" @click="enableAuth">{{ $t("Enable Auth") }}</button>
<button v-if="! settings.disableAuth" class="btn btn-primary me-2 mb-2" @click="confirmDisableAuth">{{ $t("Disable Auth") }}</button>
<button v-if="! settings.disableAuth" class="btn btn-danger me-2 mb-2" @click="$root.logout">{{ $t("Logout") }}</button>
<button class="btn btn-outline-danger me-1 mb-1" @click="confirmClearStatistics">{{ $t("Clear all statistics") }}</button>
<button class="btn btn-outline-danger me-2 mb-2" @click="confirmClearStatistics">{{ $t("Clear all statistics") }}</button>
<button class="btn btn-info me-2 mb-2" @click="shrinkDatabase">{{ $t("Shrink Database") }} ({{ databaseSizeDisplay }})</button>
</div>
</template>
</div>
@ -413,11 +416,13 @@ import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
import NotificationDialog from "../components/NotificationDialog.vue";
import TwoFADialog from "../components/TwoFADialog.vue";
import jwt_decode from "jwt-decode";
dayjs.extend(utc);
dayjs.extend(timezone);
import { timezoneList, setPageLocale } from "../util-frontend";
import { useToast } from "vue-toastification";
import { debug } from "../util.ts";
const toast = useToast();
@ -427,6 +432,7 @@ export default {
TwoFADialog,
Confirm,
},
data() {
return {
timezoneList: timezoneList(),
@ -445,8 +451,16 @@ export default {
importAlert: null,
importHandle: "skip",
processing: false,
databaseSize: 0,
};
},
computed: {
databaseSizeDisplay() {
return Math.round(this.databaseSize / 1024 / 1024 * 10) / 10 + " MB";
}
},
watch: {
"password.repeatNewPassword"() {
this.invalidPassword = false;
@ -459,7 +473,9 @@ export default {
},
mounted() {
this.loadUsername();
this.loadSettings();
this.loadDatabaseSize();
},
methods: {
@ -484,6 +500,12 @@ export default {
}
},
loadUsername() {
const jwtToken = this.$root.storage().token;
const jwtPayload = jwt_decode(jwtToken);
this.username = jwtPayload.username;
},
loadSettings() {
this.$root.getSocket().emit("getSettings", (res) => {
this.settings = res.data;
@ -592,7 +614,33 @@ export default {
autoGetPrimaryBaseURL() {
this.settings.primaryBaseURL = location.protocol + "//" + location.host;
},
shrinkDatabase() {
this.$root.getSocket().emit("shrinkDatabase", (res) => {
if (res.ok) {
this.loadDatabaseSize();
toast.success("Done");
} else {
debug(res);
}
});
},
loadDatabaseSize() {
debug("load database size");
this.$root.getSocket().emit("getDatabaseSize", (res) => {
if (res.ok) {
this.databaseSize = res.size;
debug("database size: " + res.size);
} else {
debug(res);
}
});
}
},
};
</script>

View file

@ -54,4 +54,4 @@ export function setPageLocale() {
const html = document.documentElement
html.setAttribute('lang', currentLocale() )
html.setAttribute('dir', localeDirection() )
}
}