mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-09-11 05:16:55 +08:00
Compare commits
164 Commits
fix-knex
...
2.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
|
74448d39e8 | ||
|
049005d2d2 | ||
|
ad444cdbcf | ||
|
325bec42ee | ||
|
95780656df | ||
|
45ab84e1f9 | ||
|
71d0e7c15a | ||
|
5c68c2b5d9 | ||
|
c800638ea1 | ||
|
fb3031edf0 | ||
|
f46379b48a | ||
|
084617ff4d | ||
|
c5c21668a2 | ||
|
eb9fc9a68d | ||
|
937177177e | ||
|
061406d7d1 | ||
|
f563f49bf0 | ||
|
93bcfe76da | ||
|
35dfd5c684 | ||
|
dbec3fcc13 | ||
|
b71c44efa0 | ||
|
b0d1d913bc | ||
|
da8a697b51 | ||
|
bb7c0d9e09 | ||
|
db835a0309 | ||
|
44db422128 | ||
|
30f82b9cb4 | ||
|
10a518e72e | ||
|
a7d1b99719 | ||
|
f50e26edd6 | ||
|
b0610c02ac | ||
|
6f8f8f955f | ||
|
9857770cc7 | ||
|
fce824f5a8 | ||
|
cf44d39e1b | ||
|
230832c382 | ||
|
c7d7fdd632 | ||
|
0fc6998a31 | ||
|
bfd4b84a19 | ||
|
eef742fe93 | ||
|
4307f7f79b | ||
|
1bf98aa114 | ||
|
d03de1fca4 | ||
|
681530dc1a | ||
|
86362a802f | ||
|
de8e42b748 | ||
|
196c9cae57 | ||
|
79ffb6e159 | ||
|
d8418a8949 | ||
|
e496f37b15 | ||
|
457626c715 | ||
|
17f3d5214a | ||
|
d7c76abff7 | ||
|
1dd8c16fb2 | ||
|
f932531320 | ||
|
cbb2ae7139 | ||
|
084efe3d17 | ||
|
db112d9c47 | ||
|
cec6b2e79a | ||
|
a8ccc730b1 | ||
|
5bd3b02a4e | ||
|
24d76489a7 | ||
|
9afac23029 | ||
|
cef81ecc5a | ||
|
1e297e2867 | ||
|
efce9072f6 | ||
|
46b3bd314f | ||
|
427cf2a7ac | ||
|
e5af814ab3 | ||
|
a0ab37554f | ||
|
468f7c2aeb | ||
|
ae202ae272 | ||
|
fa6f717a5e | ||
|
d57e1d315f | ||
|
25b224ed19 | ||
|
0e9020d0e3 | ||
|
8b774da885 | ||
|
d14ccb0a14 | ||
|
09f4ac57f2 | ||
|
5c87b3c78a | ||
|
27041b337f | ||
|
7d0f095bb4 | ||
|
65e6f10820 | ||
|
b45dc6787d | ||
|
7482d5824d | ||
|
44f5a896d0 | ||
|
784ac9ca35 | ||
|
20820f5a5a | ||
|
66908c7055 | ||
|
7a9191761d | ||
|
7dc6191b0a | ||
|
03beef8006 | ||
|
223cde831f | ||
|
be2faf64ce | ||
|
0b76e19401 | ||
|
97cbaac5d9 | ||
|
fd55659c2b | ||
|
20da4d29ab | ||
|
845c6e1189 | ||
|
46f771e9a2 | ||
|
ccede11e1c | ||
|
c872929b8a | ||
|
4d16575599 | ||
|
5bb329fa0e | ||
|
09dedc07fb | ||
|
6cfae01a0d | ||
|
489b73a7a6 | ||
|
1a7a738418 | ||
|
4a25be875e | ||
|
5edd22ffbe | ||
|
ba1031327e | ||
|
de141f1f26 | ||
|
3114db18e9 | ||
|
a6e46c6ed7 | ||
|
71a361c86c | ||
|
e5ed32c9cb | ||
|
340a5c8d5e | ||
|
35f68decb2 | ||
|
1417983b9c | ||
|
9dec2cee26 | ||
|
8631c8da07 | ||
|
6aa09fb76a | ||
|
a89e1735b8 | ||
|
d4e51fe557 | ||
|
7a710b4ab7 | ||
|
1dfbce3961 | ||
|
2f5453017e | ||
|
14df207d55 | ||
|
2ecd7af89b | ||
|
efdffca06c | ||
|
c0fe669cd8 | ||
|
cdb8ad321d | ||
|
4228dd0a29 | ||
|
8a432ac937 | ||
|
778363a948 | ||
|
6899603eb7 | ||
|
13ea190298 | ||
|
a7407a1b65 | ||
|
5bcde56a0f | ||
|
5864c6dd88 | ||
|
595b35fb15 | ||
|
0254e72177 | ||
|
06a272c119 | ||
|
93cf63cb06 | ||
|
03bdaf70ca | ||
|
65663e201b | ||
|
351a48c6a4 | ||
|
88b312c882 | ||
|
186f150cba | ||
|
121b235056 | ||
|
3df37151d8 | ||
|
d6d13936f7 | ||
|
6786466b65 | ||
|
7ab7000253 | ||
|
1a75267138 | ||
|
fea02d0512 | ||
|
c79a3ef794 | ||
|
fed6e4bdb3 | ||
|
e99fbf1ab7 | ||
|
be6e5211e5 | ||
|
5ee986c58e | ||
|
ca094296f2 | ||
|
32dc76a085 | ||
|
c6d6061a9f |
@@ -32,7 +32,6 @@ tsconfig.json
|
||||
/extra/healthcheck.exe
|
||||
/extra/healthcheck
|
||||
/extra/exe-builder
|
||||
/extra/push-examples
|
||||
/extra/uptime-kuma-push
|
||||
|
||||
# Comment the following line if you want to rebuild the healthcheck binary
|
||||
|
2
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
2
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
blank_issues_enabled: false
|
17
.github/ISSUE_TEMPLATE/security.md
vendored
17
.github/ISSUE_TEMPLATE/security.md
vendored
@@ -1,17 +0,0 @@
|
||||
---
|
||||
|
||||
name: "Security Issue"
|
||||
about: "Just for alerting @louislam, do not provide any details here"
|
||||
title: "Security Issue"
|
||||
ref: "main"
|
||||
labels:
|
||||
|
||||
- security
|
||||
|
||||
---
|
||||
|
||||
DO NOT PROVIDE ANY DETAILS HERE. Please privately report to https://github.com/louislam/uptime-kuma/security/advisories/new.
|
||||
|
||||
Why need this issue? It is because GitHub Advisory do not send a notification to @louislam, it is a workaround to do so.
|
||||
|
||||
Your GitHub Advisory URL:
|
45
.github/ISSUE_TEMPLATE/security_issue.yml
vendored
Normal file
45
.github/ISSUE_TEMPLATE/security_issue.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: "🛡️ Security Issue"
|
||||
description: |
|
||||
Notify Louis Lam about a security concern. Please do NOT include any sensitive details in this issue.
|
||||
# title: "Security Issue"
|
||||
labels: [security]
|
||||
assignees: [louislam]
|
||||
body:
|
||||
- type: "markdown"
|
||||
attributes:
|
||||
value: |
|
||||
## **⚠️ Report a Security Vulnerability**
|
||||
|
||||
### **IMPORTANT: DO NOT SHARE VULNERABILITY DETAILS HERE**
|
||||
|
||||
If you have discovered a security vulnerability, please report it securely using the GitHub Security Advisory.
|
||||
|
||||
**Note**: This issue is only for notifying the maintainers of the repository, as the GitHub Security Advisory does not automatically send notifications.
|
||||
|
||||
- **Confidentiality**: The information you provide in the GitHub Security Advisory will initially remain confidential. However, once the vulnerability is addressed, the advisory will be publicly disclosed on GitHub.
|
||||
- **Access and Visibility**: Until the advisory is published, it will only be visible to the maintainers of the repository and invited collaborators.
|
||||
- **Credit**: You will be automatically credited as a contributor for identifying and reporting the vulnerability. Your contribution will be reflected in the MITRE Credit System.
|
||||
- **Important Reminder**: **Do not include any sensitive or detailed vulnerability information in this issue.** This issue is only for sharing the advisory URL to notify the maintainers of the repository, not for discussing the vulnerability itself.
|
||||
|
||||
**Thank you for helping us keep Uptime Kuma secure!**
|
||||
|
||||
## **Step 1: Submit a GitHub Security Advisory**
|
||||
|
||||
Right-click the link below and select `Open link in new tab` to access the page. This will keep the security issue open, allowing you to easily return and paste the Advisory URL here later.
|
||||
|
||||
➡️ [Create a New Security Advisory](https://github.com/louislam/uptime-kuma/security/advisories/new)
|
||||
|
||||
## **Step 2: Share the Advisory URL**
|
||||
|
||||
Once you've created your advisory, please share the URL below. This will notify Louis Lam and enable them to take the appropriate action.
|
||||
|
||||
- type: "textarea"
|
||||
id: github-advisory-url
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "GitHub Advisory URL for @louislam"
|
||||
placeholder: |
|
||||
Please paste the GitHub Advisory URL here. Only the URL is required.
|
||||
Example: https://github.com/louislam/uptime-kuma/security/advisories/GHSA-8h5r-7t6l-q3kz
|
2
.github/workflows/auto-test.yml
vendored
2
.github/workflows/auto-test.yml
vendored
@@ -78,7 +78,7 @@ jobs:
|
||||
|
||||
e2e-test:
|
||||
needs: [ ]
|
||||
runs-on: ARM64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- run: git config --global core.autocrlf false # Mainly for Windows
|
||||
- uses: actions/checkout@v4
|
||||
|
@@ -1,4 +1,4 @@
|
||||
name: json-yaml-validate
|
||||
name: validate
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -26,7 +26,8 @@ jobs:
|
||||
comment: "true" # enable comment mode
|
||||
exclude_file: ".github/config/exclude.txt" # gitignore style file for exclusions
|
||||
|
||||
check-lang-json:
|
||||
# General validations
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -34,4 +35,9 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: node ./extra/check-lang-json.js
|
||||
|
||||
- name: Validate language JSON files
|
||||
run: node ./extra/check-lang-json.js
|
||||
|
||||
- name: Validate knex migrations filename
|
||||
run: node ./extra/check-knex-filenames.mjs
|
@@ -62,6 +62,7 @@ Requirements:
|
||||
- Platform
|
||||
- ✅ Major Linux distros such as Debian, Ubuntu, CentOS, Fedora and ArchLinux etc.
|
||||
- ✅ Windows 10 (x64), Windows Server 2012 R2 (x64) or higher
|
||||
- ❌ FreeBSD / OpenBSD / NetBSD
|
||||
- ❌ Replit / Heroku
|
||||
- [Node.js](https://nodejs.org/en/download/) 18 / 20.4
|
||||
- [npm](https://docs.npmjs.com/cli/) 9
|
||||
|
7
db/knex_migrations/2024-10-31-0000-fix-snmp-monitor.js
Normal file
7
db/knex_migrations/2024-10-31-0000-fix-snmp-monitor.js
Normal file
@@ -0,0 +1,7 @@
|
||||
exports.up = function (knex) {
|
||||
return knex("monitor").whereNull("json_path_operator").update("json_path_operator", "==");
|
||||
};
|
||||
exports.down = function (knex) {
|
||||
// changing the json_path_operator back to null for all "==" is not possible anymore
|
||||
// we have lost the context which fields have been set explicitely in >= v2.0 and which would need to be reverted
|
||||
};
|
13
db/knex_migrations/2025-03-25-0127-fix-5721.js
Normal file
13
db/knex_migrations/2025-03-25-0127-fix-5721.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Fix #5721: Change proxy port column type to integer to support larger port numbers
|
||||
exports.up = function (knex) {
|
||||
return knex.schema
|
||||
.alterTable("proxy", function (table) {
|
||||
table.integer("port").alter();
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = function (knex) {
|
||||
return knex.schema.alterTable("proxy", function (table) {
|
||||
table.smallint("port").alter();
|
||||
});
|
||||
};
|
@@ -5,7 +5,7 @@ const util = require("../../src/util");
|
||||
|
||||
util.polyfill();
|
||||
|
||||
const version = process.env.VERSION;
|
||||
const version = process.env.RELEASE_BETA_VERSION;
|
||||
|
||||
console.log("Beta Version: " + version);
|
||||
|
||||
|
72
extra/check-knex-filenames.mjs
Normal file
72
extra/check-knex-filenames.mjs
Normal file
@@ -0,0 +1,72 @@
|
||||
import fs from "fs";
|
||||
const dir = "./db/knex_migrations";
|
||||
|
||||
// Get the file list (ending with .js) from the directory
|
||||
const files = fs.readdirSync(dir).filter((file) => file !== "README.md");
|
||||
|
||||
// They are wrong, but they had been merged, so allowed.
|
||||
const exceptionList = [
|
||||
"2024-08-24-000-add-cache-bust.js",
|
||||
"2024-10-1315-rabbitmq-monitor.js",
|
||||
];
|
||||
|
||||
// Correct format: YYYY-MM-DD-HHmm-description.js
|
||||
|
||||
for (const file of files) {
|
||||
if (exceptionList.includes(file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check ending with .js
|
||||
if (!file.endsWith(".js")) {
|
||||
console.error(`It should end with .js: ${file}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const parts = file.split("-");
|
||||
|
||||
// Should be at least 5 parts
|
||||
if (parts.length < 5) {
|
||||
console.error(`Invalid format: ${file}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// First part should be a year >= 2024
|
||||
const year = parseInt(parts[0], 10);
|
||||
if (isNaN(year) || year < 2023) {
|
||||
console.error(`Invalid year: ${file}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Second part should be a month
|
||||
const month = parseInt(parts[1], 10);
|
||||
if (isNaN(month) || month < 1 || month > 12) {
|
||||
console.error(`Invalid month: ${file}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Third part should be a day
|
||||
const day = parseInt(parts[2], 10);
|
||||
if (isNaN(day) || day < 1 || day > 31) {
|
||||
console.error(`Invalid day: ${file}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Fourth part should be HHmm
|
||||
const time = parts[3];
|
||||
|
||||
// Check length is 4
|
||||
if (time.length !== 4) {
|
||||
console.error(`Invalid time: ${file}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const hour = parseInt(time.substring(0, 2), 10);
|
||||
const minute = parseInt(time.substring(2), 10);
|
||||
if (isNaN(hour) || hour < 0 || hour > 23 || isNaN(minute) || minute < 0 || minute > 59) {
|
||||
console.error(`Invalid time: ${file}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("All knex filenames are correct.");
|
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const childProcess = require("child_process");
|
||||
let env = process.env;
|
||||
|
||||
let cmd = process.argv[2];
|
||||
let args = process.argv.slice(3);
|
||||
let replacedArgs = [];
|
||||
|
||||
for (let arg of args) {
|
||||
for (let key in env) {
|
||||
arg = arg.replaceAll(`$${key}`, env[key]);
|
||||
}
|
||||
replacedArgs.push(arg);
|
||||
}
|
||||
|
||||
let child = childProcess.spawn(cmd, replacedArgs);
|
||||
child.stdout.pipe(process.stdout);
|
||||
child.stderr.pipe(process.stderr);
|
1
extra/exe-builder/.gitignore
vendored
1
extra/exe-builder/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
packages/
|
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Diagnostics.Tracing" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.1" newVersion="4.1.1.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
84
extra/exe-builder/DownloadForm.Designer.cs
generated
84
extra/exe-builder/DownloadForm.Designer.cs
generated
@@ -1,84 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace UptimeKuma {
|
||||
partial class DownloadForm {
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if (disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DownloadForm));
|
||||
this.progressBar = new System.Windows.Forms.ProgressBar();
|
||||
this.label = new System.Windows.Forms.Label();
|
||||
this.labelData = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// progressBar
|
||||
//
|
||||
this.progressBar.Location = new System.Drawing.Point(12, 12);
|
||||
this.progressBar.Name = "progressBar";
|
||||
this.progressBar.Size = new System.Drawing.Size(472, 41);
|
||||
this.progressBar.TabIndex = 0;
|
||||
//
|
||||
// label
|
||||
//
|
||||
this.label.Location = new System.Drawing.Point(12, 59);
|
||||
this.label.Name = "label";
|
||||
this.label.Size = new System.Drawing.Size(472, 23);
|
||||
this.label.TabIndex = 1;
|
||||
this.label.Text = "Preparing...";
|
||||
//
|
||||
// labelData
|
||||
//
|
||||
this.labelData.Location = new System.Drawing.Point(12, 82);
|
||||
this.labelData.Name = "labelData";
|
||||
this.labelData.Size = new System.Drawing.Size(472, 23);
|
||||
this.labelData.TabIndex = 2;
|
||||
//
|
||||
// DownloadForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(496, 117);
|
||||
this.Controls.Add(this.labelData);
|
||||
this.Controls.Add(this.label);
|
||||
this.Controls.Add(this.progressBar);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "DownloadForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Uptime Kuma";
|
||||
this.Load += new System.EventHandler(this.DownloadForm_Load);
|
||||
this.ResumeLayout(false);
|
||||
}
|
||||
|
||||
private System.Windows.Forms.Label labelData;
|
||||
|
||||
private System.Windows.Forms.Label label;
|
||||
|
||||
private System.Windows.Forms.ProgressBar progressBar;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@@ -1,204 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace UptimeKuma {
|
||||
public partial class DownloadForm : Form {
|
||||
private readonly Queue<DownloadItem> downloadQueue = new();
|
||||
private readonly WebClient webClient = new();
|
||||
private DownloadItem currentDownloadItem;
|
||||
|
||||
public DownloadForm() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void DownloadForm_Load(object sender, EventArgs e) {
|
||||
webClient.DownloadProgressChanged += DownloadProgressChanged;
|
||||
webClient.DownloadFileCompleted += DownloadFileCompleted;
|
||||
|
||||
label.Text = "Reading latest version...";
|
||||
|
||||
// Read json from https://uptime.kuma.pet/version
|
||||
var versionJson = new WebClient().DownloadString("https://uptime.kuma.pet/version");
|
||||
var versionObj = JsonConvert.DeserializeObject<Version>(versionJson);
|
||||
|
||||
var nodeVersion = versionObj.nodejs;
|
||||
var uptimeKumaVersion = versionObj.latest;
|
||||
var hasUpdateFile = File.Exists("update");
|
||||
|
||||
if (!Directory.Exists("node")) {
|
||||
downloadQueue.Enqueue(new DownloadItem {
|
||||
URL = $"https://nodejs.org/dist/v{nodeVersion}/node-v{nodeVersion}-win-x64.zip",
|
||||
Filename = "node.zip",
|
||||
TargetFolder = "node"
|
||||
});
|
||||
}
|
||||
|
||||
if (!Directory.Exists("core") || hasUpdateFile) {
|
||||
|
||||
// It is update, rename the core folder to core.old
|
||||
if (Directory.Exists("core")) {
|
||||
// Remove the old core.old folder
|
||||
if (Directory.Exists("core.old")) {
|
||||
Directory.Delete("core.old", true);
|
||||
}
|
||||
|
||||
Directory.Move("core", "core.old");
|
||||
}
|
||||
|
||||
downloadQueue.Enqueue(new DownloadItem {
|
||||
URL = $"https://github.com/louislam/uptime-kuma/archive/refs/tags/{uptimeKumaVersion}.zip",
|
||||
Filename = "core.zip",
|
||||
TargetFolder = "core"
|
||||
});
|
||||
|
||||
File.WriteAllText("version.json", versionJson);
|
||||
|
||||
// Delete the update file
|
||||
if (hasUpdateFile) {
|
||||
File.Delete("update");
|
||||
}
|
||||
}
|
||||
|
||||
DownloadNextFile();
|
||||
}
|
||||
|
||||
void DownloadNextFile() {
|
||||
if (downloadQueue.Count > 0) {
|
||||
var item = downloadQueue.Dequeue();
|
||||
|
||||
currentDownloadItem = item;
|
||||
|
||||
// Download if the zip file is not existing
|
||||
if (!File.Exists(item.Filename)) {
|
||||
label.Text = item.URL;
|
||||
webClient.DownloadFileAsync(new Uri(item.URL), item.Filename);
|
||||
} else {
|
||||
progressBar.Value = 100;
|
||||
label.Text = "Use local " + item.Filename;
|
||||
DownloadFileCompleted(null, null);
|
||||
}
|
||||
} else {
|
||||
npmSetup();
|
||||
}
|
||||
}
|
||||
|
||||
void npmSetup() {
|
||||
labelData.Text = "";
|
||||
|
||||
var npm = "..\\node\\npm.cmd";
|
||||
var cmd = $"{npm} ci --production & {npm} run download-dist & exit";
|
||||
|
||||
var startInfo = new ProcessStartInfo {
|
||||
FileName = "cmd.exe",
|
||||
Arguments = $"/k \"{cmd}\"",
|
||||
RedirectStandardOutput = false,
|
||||
RedirectStandardError = false,
|
||||
RedirectStandardInput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = false,
|
||||
WorkingDirectory = "core"
|
||||
};
|
||||
|
||||
var process = new Process();
|
||||
process.StartInfo = startInfo;
|
||||
process.EnableRaisingEvents = true;
|
||||
process.Exited += (_, e) => {
|
||||
progressBar.Value = 100;
|
||||
|
||||
if (process.ExitCode == 0) {
|
||||
Task.Delay(2000).ContinueWith(_ => {
|
||||
Application.Restart();
|
||||
});
|
||||
label.Text = "Done";
|
||||
} else {
|
||||
label.Text = "Failed, exit code: " + process.ExitCode;
|
||||
}
|
||||
|
||||
};
|
||||
process.Start();
|
||||
label.Text = "Installing dependencies and download dist files";
|
||||
progressBar.Value = 50;
|
||||
process.WaitForExit();
|
||||
}
|
||||
|
||||
void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) {
|
||||
progressBar.Value = e.ProgressPercentage;
|
||||
var total = e.TotalBytesToReceive / 1024;
|
||||
var current = e.BytesReceived / 1024;
|
||||
|
||||
if (total > 0) {
|
||||
labelData.Text = $"{current}KB/{total}KB";
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) {
|
||||
Extract(currentDownloadItem);
|
||||
DownloadNextFile();
|
||||
}
|
||||
|
||||
void Extract(DownloadItem item) {
|
||||
if (Directory.Exists(item.TargetFolder)) {
|
||||
var dir = new DirectoryInfo(item.TargetFolder);
|
||||
dir.Delete(true);
|
||||
}
|
||||
|
||||
if (Directory.Exists("temp")) {
|
||||
var dir = new DirectoryInfo("temp");
|
||||
dir.Delete(true);
|
||||
}
|
||||
|
||||
labelData.Text = $"Extracting {item.Filename}...";
|
||||
|
||||
ZipFile.ExtractToDirectory(item.Filename, "temp");
|
||||
|
||||
string[] dirList;
|
||||
|
||||
// Move to the correct level
|
||||
dirList = Directory.GetDirectories("temp");
|
||||
|
||||
|
||||
|
||||
if (dirList.Length > 0) {
|
||||
var dir = dirList[0];
|
||||
|
||||
// As sometime ExtractToDirectory is still locking the directory, loop until ok
|
||||
while (true) {
|
||||
try {
|
||||
Directory.Move(dir, item.TargetFolder);
|
||||
break;
|
||||
} catch (Exception exception) {
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
MessageBox.Show("Unexcepted Error: Cannot move extracted files, folder not found.");
|
||||
}
|
||||
|
||||
labelData.Text = $"Extracted";
|
||||
|
||||
if (Directory.Exists("temp")) {
|
||||
var dir = new DirectoryInfo("temp");
|
||||
dir.Delete(true);
|
||||
}
|
||||
|
||||
File.Delete(item.Filename);
|
||||
}
|
||||
}
|
||||
|
||||
public class DownloadItem {
|
||||
public string URL { get; set; }
|
||||
public string Filename { get; set; }
|
||||
public string TargetFolder { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -1,377 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAA
|
||||
AABgAAAAAQAgAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA////BPT09Bfu7u4e8fHxJPPz8yv19fUy9fX1M/Pz8yvx8fEk9vb2HPPz8xXMzMwFAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
|
||||
/wHv7+8f7u7uPPPz81Tx8fFs8fHxgPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGB8fHxcfHx8V3x8fFI9PT0MOvr6w0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AADy8vIU8fHxS/Dw8Hbx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fFr9PT0R/Dw8CIAAAABAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA8vLyFPHx8Vnx8fGB8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fFs9fX1Mb+/vwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAICAgALy8vI88fHxfvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvLy8nby8vI8gICAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAzMzMBfHx8Vrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyYf///wwAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMwF8vLyYPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8W/z8/MWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7+9R8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLw8PB26urqDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLy8ijx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgu7w7Ifj79ud2u7PtNLrw83P677dzeu85c3r
|
||||
u+rM67rwzOu68c7rverQ68Dj0uvD3NbuyM3b7c+64u7apujv5ZPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxXgAAAAEAAAAAAAAAAAAAAAAAAAAA4+PjCfDw
|
||||
8Hfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLd7tSmzeu92MbqsvvG6bH/xumy/8fq
|
||||
s//H6rP/yOq0/8jqtf/J6rb/yeq2/8rrt//K67j/y+u4/8vruf/M67r/zOu7/83ru//Q7MDx1u7Kz9/t
|
||||
163s8OuJ8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgu/v7y8AAAAAAAAAAAAA
|
||||
AAAAAAAA7u7uPfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC5PDdl8jqtuTE6a7/xOmv/8Xp
|
||||
sP/G6bH/xumx/8bpsv/H6rP/x+qz/8jqtP/I6rX/yeq2/8nqtv/K67f/yuu4/8vruP/L67n/zOu6/8zr
|
||||
u//N67v/zey8/87svf/P67742e3Mx+jv5ZLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvDw
|
||||
8HWAgIACAAAAAAAAAACqqqoD8vLyc/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLf7degxOiu+cPo
|
||||
rf/D6a7/xOmu/8Xpr//F6bD/xumx/8bpsf/G6bL/x+qz/8fqs//I6rT/yOq1/8nqtv/J6rb/yuu3/8rr
|
||||
uP/L67j/y+u5/8zruv/M67v/zeu7/83svP/O7L3/zuy9/87svfzc7tK28fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fEkAAAAAAAAAADz8/Mq8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgunv
|
||||
5o3D6a/0wuis/8Lorf/D6K3/xOmu/8Tprv/F6a//xemw/8bpsf/G6bH/xumy/8fqs//H6rP/yOq0/8jq
|
||||
tf/J6rb/yeq2/8rrt//K67j/y+u4/8vruf/M67r/zOu7/83ru//N7Lz/zuy9/87svf/O7L3/3e/TtPHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJNAAAAAAAAAADy8vJM8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgszqutDB6Kv/weir/8LorP/D6K3/w+it/8Tprv/E6a7/xemv/8XpsP/G6bH/xumx/8bp
|
||||
sv/H6rP/x+qz/8jqtP/I6rX/yeq2/8nqtv/K67f/yuu4/8vruP/L67n/zOu6/8zru//N67v/zey8/87s
|
||||
vf/O7L3/zuy++u3w6Yzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJ1AAAAAAAAAADx8fFr8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC6O/kjsDoqvzA6Kr/weir/8Loq//C6Kz/w+it/8Porf/E6a7/xOmu/8Xp
|
||||
r//F6bD/xumx/8bpsf/G6bL/x+qz/8fqtP/I6rT/yOq1/8nqtv/J6rb/yuu3/8rruP/L67n/y+u5/8zr
|
||||
uv/M67v/zeu7/83svP/O7L3/zuy9/93u07Xx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC////Bv//
|
||||
/wfx8fGB8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC1ezJsr/nqf/A56n/weiq/8Hoq//C6Kv/wuis/8Po
|
||||
rf/D6K3/xOmu/8Pprv+856T/uOed/7bmmv+05Zf/teWZ/7jnnf+86KP/wOio/8fqs//J6rb/yeq2/8rr
|
||||
t//K67j/y+u5/8vruf/M67r/zOu7/83ru//N7Lz/zuy9/9buyNLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8vLyE/Ly8hPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCy+q6zr/nqP/A56n/wOep/8Ho
|
||||
qv/B6Kv/wuir/8LorP+u5Y//neF2/5bgav+V4Gr/luBr/5fhbP+Y4W7/meFv/5rhcf+b4nL/nOJ0/53i
|
||||
dv+j5H//reaM/7nnnf/E6q//y+y4/8vruf/L67n/zOu6/8zru//N67v/zey8/9Lsxd/x8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC7+/vIPb29hzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCx+m03L/n
|
||||
qP+/56j/wOep/8Dnqf/B6Kr/weir/7nmn/+R32T/kt9l/5PfZ/+U4Gj/leBq/5bga/+X4W3/mOFu/5nh
|
||||
b/+a4XH/m+Jy/5zidP+d4nX/nuN3/5/jeP+f4nn/weqq/8rruP/L67n/y+u5/8zruv/M67v/zeu7/9Ls
|
||||
w+Lx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8PDwI/Hx8SXx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGCxeix5L/nqP+/56j/v+eo/8Dnqf/A56n/weiq/7Pllv+Q3mP/kd9k/5LfZf+T32f/lOBo/5Xg
|
||||
av+W4Gv/l+Ft/5jhbv+Z4W//muFx/5vicv+c4nT/neJ1/57jd/+f43j/xOmu/8rrt//K67j/y+u5/8vr
|
||||
uf/M67r/zOu7/9Tsxtfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC9PT0GO/v7yDx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGCx+m037/nqP+/56j/v+eo/7/nqP/A56n/wOip/7TmmP+P3mH/kN5j/5Hf
|
||||
ZP+S32b/k99n/5TgaP+V4Gr/luBr/5fhbf+Y4W7/meFw/5rhcf+b4nL/nOJ0/53idf+h5Hz/yuu2/8nq
|
||||
t//K67f/yuu4/8vruf/L67n/zOu6/9ftysrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC7e3tDvT0
|
||||
9Bfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCyOq117/nqP+/56j/v+eo/7/nqP+/56j/wOep/7vn
|
||||
of+O3mD/j95h/5DeY/+R32T/kt9m/5PfZ/+U4Gj/leBq/5bga/+X4W3/mOFu/5nhcP+a4nH/m+Jy/5zi
|
||||
dP+r5Yr/yOq1/8nqtv/J6rf/yuu3/8rruP/L67n/y+u5/9zu1LHx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLz8/OA////A+7u7g/x8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCz+q+xb/nqP+/56j/v+eo/7/n
|
||||
qP+/56j/v+eo/8Dnqf+S4Gb/jt5g/4/eYf+Q3mP/kd9k/5LfZv+T32f/lOBo/5Xgav+W4Gv/l+Ft/5jh
|
||||
bv+Z4XD/muJx/5vic/+4553/yOq0/8jqtf/J6rb/yeq3/8rrt//K67j/y+u5/+bw4Zfx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fFrAAAAAP///wHz8/N88fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC1+zMrr/n
|
||||
qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+f4Xn/jd5f/47eYP+P3mH/kN5j/5HfZP+S32b/k99n/5Tg
|
||||
af+V4Gr/luBr/5fhbf+Y4W7/meFw/5vic//F6rD/x+q0/8jqtP/I6rX/yeq2/8nqt//K67f/zOu88u/x
|
||||
74Px8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLv7+9QAAAAAAAAAADw8PBm8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC5e7gk7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+u5I//jN1d/43eX/+O3mD/j95h/5De
|
||||
Y/+R32T/kt9m/5PfZ/+U4Gn/leBq/5bga/+X4W3/mOFu/6rliP/G6rL/x+qz/8fqtP/I6rT/yOq1/8nq
|
||||
tv/J6rf/1OzGy/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YL19fUzAAAAAAAAAADy8vJO8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgsPoru2/56j/v+eo/7/nqP+/56j/v+eo/7/nqP++6Kf/j95i/4zd
|
||||
Xf+N3l//jt5g/4/eYv+Q3mP/kd9k/5LfZv+T32f/lOBp/5Xgav+W4Gz/l+Ft/7voov/G6bL/xuqy/8fq
|
||||
s//H6rT/yOq1/8jqtf/J6rb/4e/Zo/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLw8PARAAAAAAAA
|
||||
AADu7u4u8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgszpvMm/56j/v+eo/7/nqP+/56j/v+eo/7/n
|
||||
qP+/56j/q+SL/4vdXP+M3V3/jd5f/47eYP+P3mL/kN9j/5HfZP+S32b/k99n/5Tgaf+V4Gr/qOOH/8Xp
|
||||
sP/G6bH/xumy/8bqsv/H6rP/x+q0/8jqtf/K67jy8PHwhPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8WoAAAAAAAAAAAAAAADo6OgL8fHxgfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxguDv2J2/56j/v+eo/7/n
|
||||
qP+/56j/v+eo/7/nqP+/56j/v+eo/6Xjgv+L3Vz/jN1d/43eX/+O3mD/j95i/5DfY/+R32T/kt9m/5Pf
|
||||
Z/+k44D/xOmu/8XpsP/F6bD/xumx/8bpsv/G6rL/x+qz/8fqtP/W7cnB8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvPz80AAAAAAAAAAAAAAAAAAAAAA8PDwZ/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLD6K/rv+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+u5I//kt5n/4zdXf+N3l//jt5g/4/e
|
||||
Yv+Q32P/luFs/67kj//D6K3/xOmu/8Tpr//F6bD/xemw/8bpsf/G6bL/xuqy/8fqtP7o7+WR8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8xYAAAAAAAAAAAAAAAAAAAAA8vLyPPHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLV7ci0v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/wOio/7Xl
|
||||
mv+u5I7/rOSM/67kj/+35pz/wumr/8Lorf/D6K3/w+it/8Tprv/E6a//xemw/8XpsP/G6bH/xumy/9Ds
|
||||
wNPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyZQAAAAAAAAAAAAAAAAAAAAAAAAAA////DPHx
|
||||
8YDx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCx+m03L/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/n
|
||||
qP+/56j/v+eo/7/nqP+/56j/wOep/8Doqv/B6Kr/weir/8LorP/C6K3/w+it/8Porv/E6a7/xOmv/8Xp
|
||||
sP/F6bD/yOq18uvw6Yvx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC7+/vMQAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAPHx8Vzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC6O/ij8LorPG/56j/v+eo/7/n
|
||||
qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/8Dnqf/A6Kr/weiq/8Hoq//C6Kz/wuit/8Po
|
||||
rf/D6K7/xOmu/8Tpr//F6bH74u/anvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLw8PB6////BQAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPz8yrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxguHu
|
||||
2pnB56v2v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP/A56n/wOiq/8Ho
|
||||
q//B6Kv/wuis/8Lorf/D6K3/w+mu/8Tprv3b7dKq8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fFJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHy8vJf8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLi7tyXwumt8L/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/n
|
||||
qP+/56j/wOep/8Doqv/B6Kv/weir/8LorP/C6K3/xOiv+d7u1aTx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvLy8nb///8KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7+8Q8/Pze/Hx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC6/Dpiszqu82/56j/v+eo/7/nqP+/56j/v+eo/7/n
|
||||
qP+/56j/v+eo/7/nqP+/56j/v+eo/8Dnqf/A6Kr/weir/8Hoq//H6bTj5e7elfHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8yoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA9fX1MvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLe7tShx+mz3r/n
|
||||
qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP/A56n/xumy5drtz6rv8e+D8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPHx8Unx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgubv45DU68e2y+q6z8XoseTD6a7uweir9MPpru7F6bHly+q50tLsxLrl796U8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJh////AwAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wHx8fFZ8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8Wzf398IAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8D8/PzVfHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8PDwZujo
|
||||
6AsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA////AfHx8Ujx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fFa////BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz8/Mp8vLydvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8/PzfPHx8TcAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CvLy8lDz8/N/8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvPz84Hx8fFa8PDwEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AADw8PAR8vLyTvHx8X3x8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fF/8/PzVvT09BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wXz8/Mq8/PzU/Hx8XDx8fGB8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLy8vJz8fHxWO/v7y////8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8G7e3tHfLy
|
||||
8ifu7u4u8PDwNPT09C/y8vIo7+/vH+Pj4wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAP///////wAA////////AAD///////8AAP//gAf//wAA//gAAD//AAD/wAAAB/8AAP+A
|
||||
AAAB/wAA/gAAAAB/AAD8AAAAAD8AAPgAAAAAHwAA8AAAAAAPAADwAAAAAAcAAOAAAAAABwAA4AAAAAAD
|
||||
AADAAAAAAAMAAMAAAAAAAwAAwAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA
|
||||
AAAAAQAAgAAAAAABAACAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAABwAAwAAAAAAH
|
||||
AADgAAAAAAcAAOAAAAAADwAA4AAAAAAPAADwAAAAAB8AAPAAAAAAHwAA+AAAAAA/AAD8AAAAAD8AAPwA
|
||||
AAAAfwAA/gAAAAD/AAD/AAAAAf8AAP+AAAAD/wAA/8AAAAf/AAD/8AAAH/8AAP/8AAA//wAA//8AAf//
|
||||
AAD//+AP//8AAP///////wAA////////AAD///////8AACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAgICAAu/v7xD09PQX7u7uHvDw8CP29vYb8vLyFOrq6gwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICA
|
||||
gALy8vIm7+/vT/Pz82fz8/N98fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvDw8Hrw8PBm7+/vUPT0
|
||||
9C3o6OgLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOPj
|
||||
4wnz8/NC8vLydPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YHy8vJj8/PzKoCAgAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AADx8fEl8vLydfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxcfHx8SUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA9PT0LfHx8YDx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8/PzgPLy8j0AAAABAAAAAAAA
|
||||
AAAAAAAAAAAAAO3t7Rzx8fGA8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLr8OmM5O7emeTv
|
||||
3Z7h79mj5fDem+nv45Tu8u6H8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvLy
|
||||
8joAAAAAAAAAAAAAAAD///8E8fHxbvHx8YLx8fGC8fHxgvHx8YLx8fGC7vDshtns0K7N67zayeq288fq
|
||||
s//I6rT/yOq1/8nqtv/K67f/y+u4/8vruf/P7L7w0+zF29vv0Lrn8OKX8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8/PzfvPz8xUAAAAAAAAAAPX19TLx8fGC8fHxgvHx8YLx8fGC8fHxgt3u1KXF6rHzxOmv/8Xp
|
||||
sP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vruf/M67v/zey8/87svf/S7MPj4u7Zp/Hx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8/PzVQAAAAAAAAAA8fHxavHx8YLx8fGC8fHxgvHx8YLf7defwuis/cPo
|
||||
rf/E6a7/xOmv/8XpsP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vruv/M67v/zey8/87s
|
||||
vf/N67z/3e7SufHx8YLx8fGC8fHxgvHx8YLz8/N8////Bf///w3x8fGC8fHxgvHx8YLx8fGC8fHxgsXp
|
||||
sOnB6Kv/wuis/8Porf/E6a7/xOmv/8XpsP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vr
|
||||
uv/M67v/zey8/87svf/O67z96/Hoj/Hx8YLx8fGC8fHxgvHx8YLy8vIm8/PzK/Hx8YLx8fGC8fHxgvHx
|
||||
8YLg79icwOep/8Hoqv/B6Kv/wuis/8Porf/E6a7/wuit/73opP+76KL/u+eh/77opv/D6a3/yeu1/8nq
|
||||
tv/K67f/y+u5/8zruv/M67v/zey8/87svf/d7tSz8fHxgvHx8YLx8fGC8fHxgvHx8Tby8vI68fHxgvHx
|
||||
8YLx8fGC8fHxgtTrxre/56j/wOep/8Hoqv/B6Kv/uOad/53idv+V4Gn/leBq/5fhbP+Y4W//muFx/5vi
|
||||
c/+e4Xb/puWD/7PmlP/D6a3/y+u5/8zruv/M67v/zey8/9rtzsHx8fGC8fHxgvHx8YLx8fGC8/PzQfPz
|
||||
80Lx8fGC8fHxgvHx8YLx8fGC0OvAwr/nqP+/56j/wOep/8Hoqv+o44b/kd9k/5LfZv+U4Gj/leBq/5fh
|
||||
bf+Y4W//muFx/5vic/+d4nX/n+N3/7fnm//K67j/y+u5/8zruv/M67v/2u3QvPHx8YLx8fGC8fHxgvHx
|
||||
8YLy8vI98/PzP/Hx8YLx8fGC8fHxgvHx8YLQ6sK/v+eo/7/nqP+/56j/wOep/6jjhv+P3mL/kd9k/5Lf
|
||||
Zv+U4Gj/leBr/5fhbf+Y4W//muFx/5zic/+d4nX/v+mm/8nqt//K67j/y+u5/8zruv/f79au8fHxgvHx
|
||||
8YLx8fGC8fHxgvX19TLx8fE38fHxgvHx8YLx8fGC8fHxgtTrybO/56j/v+eo/7/nqP+/56j/sOSS/47e
|
||||
YP+P3mL/kd9k/5LfZv+U4Gj/leBr/5fhbf+Z4W//muJx/5/jd//H6bP/yeq2/8nqt//K67j/y+u5/+nv
|
||||
45Tx8fGC8fHxgvHx8YLx8fGC7+/vIPHx8SXx8fGC8fHxgvHx8YLx8fGC4e/Zm7/nqP+/56j/v+eo/7/n
|
||||
qP+956X/jt5h/47eYP+P3mL/kd9k/5LfZv+U4Gn/luBr/5fhbf+Z4W//q+aK/8fqs//I6rT/yeq2/8nq
|
||||
t//N7Lvw8fHxgvHx8YLx8fGC8fHxgvPz84D///8G6+vrDfHx8YLx8fGC8fHxgvHx8YLv8e+Dweis87/n
|
||||
qP+/56j/v+eo/7/nqP+d4XX/jN1e/47eYP+P3mL/kd9k/5PfZ/+U4Gn/luBr/5fhbf+86KP/xuqy/8fq
|
||||
s//I6rX/yeq2/9Tsx8nx8fGC8fHxgvHx8YLx8fGC8PDwaAAAAAAAAAAA8fHxbPHx8YLx8fGC8fHxgvHx
|
||||
8YLM6rrMv+eo/7/nqP+/56j/v+eo/7blmv+N3V//jN1e/47eYP+Q3mL/kd9k/5PfZ/+U4Gn/qeSH/8Xp
|
||||
sP/G6bH/xuqy/8fqs//I6rX/5fDem/Hx8YLx8fGC8fHxgvHx8YLz8/M/AAAAAAAAAADz8/NB8fHxgvHx
|
||||
8YLx8fGC8fHxgt3s06O/56j/v+eo/7/nqP+/56j/v+eo/7Xmmf+U32n/jN1e/47eYP+Q3mL/k99o/6zk
|
||||
i//D6a7/xemv/8XpsP/G6bH/xuqy/8vqu+jx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8xUAAAAAAAAAAPT0
|
||||
9Bfx8fGC8fHxgvHx8YLx8fGC8fHvg8Tpsee/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+35pz/suWV/7Xm
|
||||
mf/A6Kj/wuit/8Porf/E6a7/xemv/8XpsP/G6bH/3e3UqvHx8YLx8fGC8fHxgvHx8YLw8PBmAAAAAAAA
|
||||
AAAAAAAAAAAAAPHx8W7x8fGC8fHxgvHx8YLx8fGC4u7cmMHnqvm/56j/v+eo/7/nqP+/56j/v+eo/7/n
|
||||
qP+/56j/wOep/8Hoqv/C6Kz/wuit/8Porf/E6a7/xemv/9Hrwszx8fGC8fHxgvHx8YLx8fGC8fHxgvX1
|
||||
9TEAAAAAAAAAAAAAAAAAAAAA7u7uO/Hx8YLx8fGC8fHxgvHx8YLx8fGC3e7SpMHoqfq/56j/v+eo/7/n
|
||||
qP+/56j/v+eo/7/nqP+/56j/wOip/8Hoq//C6Kz/wuit/8Porf/O67zV8PHwhPHx8YLx8fGC8fHxgvHx
|
||||
8YLy8vJ2////BQAAAAAAAAAAAAAAAAAAAACqqqoD8PDwafHx8YLx8fGC8fHxgvHx8YLx8fGC4O/YnMTo
|
||||
ruy/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/wOip/8Hoq//C6Kz90uvEwe/x74Px8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvPz8ykAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz8/MW8fHxfPHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8PLuhdXtyLXF6bHlv+eo/7/nqP+/56j/v+eo/7/nqP/B6Kv0zeq8zOXv4JTx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLy8vJNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADy8vIm8fHxgPHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLs8OmJ4e/Zm93u06Pf7def5+/hkvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxXf///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AADy8vIo8/PzffHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8VnMzMwFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAD29vYb8fHxbvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz83/v7+9BgICAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMwF8/PzQPLy8nnx8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz84Hx8fFc9PT0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////B/X19TLx8fFc8PDwevHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8fHxgPHx8Wv09PRE9PT0FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA7+/vEPb29hvw8PAj7+/vH/T09Be/v78EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////8B///wAA//wAAD/wAAAP4AAAB+AA
|
||||
AAfAAAADwAAAA4AAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAADwAAAA8AAAAPAAAAH4AAAB+AA
|
||||
AA/wAAAP+AAAH/gAAD/+AAB//wAB///AA///+B////////////8oAAAAEAAAACAAAAABACAAAAAAAAAE
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CfDw8BH///8GAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAAu7u7i7x8fFe8PDwevHx8YLx8fGC8fHxgvDw
|
||||
8Hvx8fFs7+/vT/Dw8CMAAAABAAAAAAAAAAAAAAAA5ubmCvLy8l/x8fGC8fHxgvHx8YLx8fGC8fHxgvHx
|
||||
8YLx8fGC8fHxgvHx8YLx8fGC8/PzZu7u7g8AAAAAAAAAAPHx8V3x8fGC8fHxgunv5o7Z7c200+vFytTs
|
||||
xc7W7cnH2+7QueLu2qbu8OyH8fHxgvHx8YLx8fFu////BfHx8STx8fGC8fHxgtrtzq3D6a/8xemw/8bp
|
||||
sv/I6rT/yeq2/8vruP/M67v/z+u++Nzu0bjx8fGC8fHxgu/v7zDx8fFI8fHxguzw6ojC56z3wuis/8Tp
|
||||
rv/E6q3/weiq/8fqsv/J6rb/y+u5/8zru//N67z/6/HpjfHx8YLy8vJN8fHxXPHx8YLg79icv+eo/8Ho
|
||||
qv+k4n//lOBo/5fhbf+a4XH/n+J5/7Pmlv/L67n/zOu7/+Xw353x8fGC8fHxXvHx8Vrx8fGC4O3Zm7/n
|
||||
qP+/56j/nuF3/5HfZP+U4Gj/l+Ft/5ricf+x5pL/yeq3/8vruf/r8emN8fHxgu/v70/x8fFK8fHxguzw
|
||||
6ojA6Kn8v+eo/6njiP+O3mD/kd9k/5Tgaf+X4W3/vuim/8jqtP/N67zr8fHxgvHx8YLy8vI68/PzK/Hx
|
||||
8YLx8fGCx+m03L/nqP++6Kb/meBw/47eYP+S32X/q+SL/8XpsP/G6rL/1+zLvvHx8YLz8/OB8PDwEdXV
|
||||
1Qbx8fF98fHxgt/t1Z/A56j9v+eo/7/nqP+656H/vuim/8Lorf/E6a7/yOq18Ovw6Yvx8fGC8vLyYwAA
|
||||
AAAAAAAA8fHxR/Hx8YLx8fGC2O3NrMDnqfq/56j/v+eo/7/nqP/B6Kv/xumy7OTu3Zfx8fGC8/PzgfLy
|
||||
8icAAAAAAAAAAP///wPz8/Nm8fHxgvHx8YLo7+SO0+zFuczquszM6bzJ1+zMru7w7Ibx8fGC8fHxgvHx
|
||||
8UcAAAAAAAAAAAAAAAAAAAAA4+PjCfHx8Vzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgfPz
|
||||
80D///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8/PzK/Ly8mDz8/N+8fHxgvHx8YLy8vJ68vLyUezs
|
||||
7BsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAevr6w3j4+MJAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD8fwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIAB
|
||||
AADAAwAAwAMAAOAHAADwDwAA/n8AAP//AAA=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
@@ -1,3 +0,0 @@
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<Costura DisableCompression='true' IncludeDebugSymbols='false' />
|
||||
</Weavers>
|
@@ -1,141 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||
<xs:element name="Weavers">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="IncludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeRuntimeReferences" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls if runtime assemblies are also embedded.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="UseRuntimeReferencePaths" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableCompression" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableCleanup" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="ExcludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="ExcludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="PreloadOrder" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
@@ -1,262 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.Win32;
|
||||
using Newtonsoft.Json;
|
||||
using UptimeKuma.Properties;
|
||||
|
||||
namespace UptimeKuma {
|
||||
static class Program {
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main(string[] args) {
|
||||
var cwd = Path.GetDirectoryName(Application.ExecutablePath);
|
||||
|
||||
if (cwd != null) {
|
||||
Environment.CurrentDirectory = cwd;
|
||||
}
|
||||
|
||||
bool isIntranet = args.Contains("--intranet");
|
||||
|
||||
if (isIntranet) {
|
||||
Console.WriteLine("The --intranet argument was provided, so we will not try to access the internet. The first time this application runs you'll need to run it without the --intranet param or copy the result from another machine to the intranet server.");
|
||||
}
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new UptimeKumaApplicationContext(isIntranet));
|
||||
}
|
||||
}
|
||||
|
||||
public class UptimeKumaApplicationContext : ApplicationContext
|
||||
{
|
||||
private static Mutex mutex = null;
|
||||
|
||||
const string appName = "Uptime Kuma";
|
||||
|
||||
private NotifyIcon trayIcon;
|
||||
private Process process;
|
||||
|
||||
private MenuItem statusMenuItem;
|
||||
private MenuItem runWhenStarts;
|
||||
private MenuItem openMenuItem;
|
||||
|
||||
private RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
|
||||
|
||||
private readonly bool intranetOnly;
|
||||
|
||||
public UptimeKumaApplicationContext(bool intranetOnly) {
|
||||
|
||||
// Single instance only
|
||||
bool createdNew;
|
||||
mutex = new Mutex(true, appName, out createdNew);
|
||||
if (!createdNew) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.intranetOnly = intranetOnly;
|
||||
|
||||
var startingText = "Starting server...";
|
||||
trayIcon = new NotifyIcon();
|
||||
trayIcon.Text = startingText;
|
||||
|
||||
runWhenStarts = new MenuItem("Run when system starts", RunWhenStarts);
|
||||
runWhenStarts.Checked = registryKey.GetValue(appName) != null;
|
||||
|
||||
statusMenuItem = new MenuItem(startingText);
|
||||
statusMenuItem.Enabled = false;
|
||||
|
||||
openMenuItem = new MenuItem("Open", Open);
|
||||
openMenuItem.Enabled = false;
|
||||
|
||||
trayIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
|
||||
trayIcon.ContextMenu = new ContextMenu(new MenuItem[] {
|
||||
statusMenuItem,
|
||||
openMenuItem,
|
||||
//new("Debug Console", DebugConsole),
|
||||
runWhenStarts,
|
||||
new("Check for Update...", CheckForUpdate),
|
||||
new("Visit GitHub...", VisitGitHub),
|
||||
new("About", About),
|
||||
new("Exit", Exit),
|
||||
});
|
||||
|
||||
trayIcon.MouseDoubleClick += new MouseEventHandler(Open);
|
||||
trayIcon.Visible = true;
|
||||
|
||||
var hasUpdateFile = File.Exists("update");
|
||||
|
||||
if (!hasUpdateFile && Directory.Exists("core") && Directory.Exists("node") && Directory.Exists("core/node_modules") && Directory.Exists("core/dist")) {
|
||||
// Go go go
|
||||
StartProcess();
|
||||
} else {
|
||||
DownloadFiles();
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadFiles() {
|
||||
if (intranetOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
var form = new DownloadForm();
|
||||
form.Closed += Exit;
|
||||
form.Show();
|
||||
}
|
||||
|
||||
private void RunWhenStarts(object sender, EventArgs e) {
|
||||
if (registryKey == null) {
|
||||
MessageBox.Show("Error: Unable to set startup registry key.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (runWhenStarts.Checked) {
|
||||
registryKey.DeleteValue(appName, false);
|
||||
runWhenStarts.Checked = false;
|
||||
} else {
|
||||
registryKey.SetValue(appName, Application.ExecutablePath);
|
||||
runWhenStarts.Checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
void StartProcess() {
|
||||
var startInfo = new ProcessStartInfo {
|
||||
FileName = "node/node.exe",
|
||||
Arguments = "server/server.js --data-dir=\"../data/\"",
|
||||
RedirectStandardOutput = false,
|
||||
RedirectStandardError = false,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
WorkingDirectory = "core"
|
||||
};
|
||||
|
||||
process = new Process();
|
||||
process.StartInfo = startInfo;
|
||||
process.EnableRaisingEvents = true;
|
||||
process.Exited += ProcessExited;
|
||||
|
||||
try {
|
||||
process.Start();
|
||||
//Open(null, null);
|
||||
|
||||
// Async task to check if the server is ready
|
||||
Task.Run(() => {
|
||||
var runningText = "Server is running";
|
||||
using TcpClient tcpClient = new TcpClient();
|
||||
while (true) {
|
||||
try {
|
||||
tcpClient.Connect("127.0.0.1", 3001);
|
||||
statusMenuItem.Text = runningText;
|
||||
openMenuItem.Enabled = true;
|
||||
trayIcon.Text = runningText;
|
||||
break;
|
||||
} catch (Exception) {
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
MessageBox.Show("Startup failed: " + e.Message, "Uptime Kuma Error");
|
||||
}
|
||||
}
|
||||
|
||||
void StopProcess() {
|
||||
process?.Kill();
|
||||
}
|
||||
|
||||
void Open(object sender, EventArgs e) {
|
||||
Process.Start("http://localhost:3001");
|
||||
}
|
||||
|
||||
void DebugConsole(object sender, EventArgs e) {
|
||||
|
||||
}
|
||||
|
||||
void CheckForUpdate(object sender, EventArgs e) {
|
||||
if (intranetOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check version.json exists
|
||||
if (File.Exists("version.json")) {
|
||||
// Load version.json and compare with the latest version from GitHub
|
||||
var currentVersionObj = JsonConvert.DeserializeObject<Version>(File.ReadAllText("version.json"));
|
||||
|
||||
var versionJson = new WebClient().DownloadString("https://uptime.kuma.pet/version");
|
||||
var latestVersionObj = JsonConvert.DeserializeObject<Version>(versionJson);
|
||||
|
||||
// Compare version, if the latest version is newer, then update
|
||||
if (new System.Version(latestVersionObj.latest).CompareTo(new System.Version(currentVersionObj.latest)) > 0) {
|
||||
var result = MessageBox.Show("A new version is available. Do you want to update?", "Update", MessageBoxButtons.YesNo);
|
||||
if (result == DialogResult.Yes) {
|
||||
// Create a empty file `update`, so the app will download the core files again at startup
|
||||
File.Create("update").Close();
|
||||
|
||||
trayIcon.Visible = false;
|
||||
process?.Kill();
|
||||
|
||||
// Restart the app, it will download the core files again at startup
|
||||
Application.Restart();
|
||||
}
|
||||
} else {
|
||||
MessageBox.Show("You are using the latest version.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void VisitGitHub(object sender, EventArgs e) {
|
||||
if (intranetOnly) {
|
||||
MessageBox.Show("You have parsed in --intranet so we will not try to access the internet or visit github.com, please go to https://github.com/louislam/uptime-kuma if you want to visit github.");
|
||||
return;
|
||||
}
|
||||
|
||||
Process.Start("https://github.com/louislam/uptime-kuma");
|
||||
}
|
||||
|
||||
void About(object sender, EventArgs e)
|
||||
{
|
||||
MessageBox.Show("Uptime Kuma Windows Runtime v1.0.0" + Environment.NewLine + "© 2023 Louis Lam", "Info");
|
||||
}
|
||||
|
||||
void Exit(object sender, EventArgs e)
|
||||
{
|
||||
// Hide tray icon, otherwise it will remain shown until user mouses over it
|
||||
trayIcon.Visible = false;
|
||||
process?.Kill();
|
||||
Application.Exit();
|
||||
}
|
||||
|
||||
void ProcessExited(object sender, EventArgs e) {
|
||||
|
||||
if (process.ExitCode != 0) {
|
||||
var line = "";
|
||||
while (!process.StandardOutput.EndOfStream)
|
||||
{
|
||||
line += process.StandardOutput.ReadLine();
|
||||
}
|
||||
|
||||
MessageBox.Show("Uptime Kuma exited unexpectedly. Exit code: " + process.ExitCode + " " + line);
|
||||
}
|
||||
|
||||
trayIcon.Visible = false;
|
||||
Application.Exit();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,36 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Uptime Kuma")]
|
||||
[assembly: AssemblyDescription("A portable executable for running Uptime Kuma")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Uptime Kuma")]
|
||||
[assembly: AssemblyProduct("Uptime Kuma")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023 Louis Lam")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("86B40AFB-61FC-433D-8C31-650B0F32EA8F")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.2.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.2.0")]
|
62
extra/exe-builder/Properties/Resources.Designer.cs
generated
62
extra/exe-builder/Properties/Resources.Designer.cs
generated
@@ -1,62 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace UptimeKuma.Properties {
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder",
|
||||
"4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance",
|
||||
"CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState
|
||||
.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if ((resourceMan == null)) {
|
||||
global::System.Resources.ResourceManager temp =
|
||||
new global::System.Resources.ResourceManager("UptimeKuma.Properties.Resources",
|
||||
typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState
|
||||
.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get { return resourceCulture; }
|
||||
set { resourceCulture = value; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
23
extra/exe-builder/Properties/Settings.Designer.cs
generated
23
extra/exe-builder/Properties/Settings.Designer.cs
generated
@@ -1,23 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace UptimeKuma.Properties {
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(
|
||||
"Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
private static Settings defaultInstance =
|
||||
((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get { return defaultInstance; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
@@ -1,203 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>UptimeKuma</RootNamespace>
|
||||
<AssemblyName>uptime-kuma</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<ApplicationIcon>..\..\public\favicon.ico</ApplicationIcon>
|
||||
<LangVersion>9</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "%UserProfile%\Desktop\uptime-kuma-win64\"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.AppContext, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Console, Version=4.0.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Console.4.3.1\lib\net46\System.Console.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Diagnostics.DiagnosticSource, Version=7.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Diagnostics.DiagnosticSource.7.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Diagnostics.Tracing, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Globalization.Calendars, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Linq, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Linq.4.3.0\lib\net463\System.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Linq.Expressions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reflection, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Extensions, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Runtime.Extensions.4.3.1\lib\net462\System.Runtime.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.InteropServices, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Text.RegularExpressions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Text.RegularExpressions.4.3.1\lib\net463\System.Text.RegularExpressions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DownloadForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="DownloadForm.Designer.cs">
|
||||
<DependentUpon>DownloadForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Version.cs" />
|
||||
<EmbeddedResource Include="DownloadForm.resx">
|
||||
<DependentUpon>DownloadForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="..\..\public\favicon.ico">
|
||||
<Link>favicon.ico</Link>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include=".gitignore" />
|
||||
<Content Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" />
|
||||
</Target>
|
||||
<Import Project="packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" />
|
||||
</Project>
|
@@ -1,16 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UptimeKuma", "UptimeKuma.csproj", "{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@@ -1,3 +0,0 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=UptimeKuma_002FProperties_002FResources/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
|
@@ -1,9 +0,0 @@
|
||||
namespace UptimeKuma {
|
||||
public class Version {
|
||||
public string latest { get; set; }
|
||||
public string slow { get; set; }
|
||||
public string beta { get; set; }
|
||||
public string nodejs { get; set; }
|
||||
public string exe { get; set; }
|
||||
}
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC Manifest Options
|
||||
If you want to change the Windows User Account Control level replace the
|
||||
requestedExecutionLevel node with one of the following.
|
||||
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
Specifying requestedExecutionLevel element will disable file and registry virtualization.
|
||||
Remove this element if your application requires this virtualization for backwards
|
||||
compatibility.
|
||||
-->
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
@@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.NETCore.Platforms" version="7.0.0" targetFramework="net472" />
|
||||
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net472" />
|
||||
<package id="NETStandard.Library" version="2.0.3" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net472" />
|
||||
<package id="System.AppContext" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Console" version="4.3.1" targetFramework="net472" />
|
||||
<package id="System.Diagnostics.DiagnosticSource" version="7.0.1" targetFramework="net472" />
|
||||
<package id="System.Net.Http" version="4.3.4" targetFramework="net472" />
|
||||
<package id="System.Runtime.Extensions" version="4.3.1" targetFramework="net472" />
|
||||
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net472" />
|
||||
<package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net472" />
|
||||
<package id="System.Text.RegularExpressions" version="4.3.1" targetFramework="net472" />
|
||||
<package id="System.Xml.ReaderWriter" version="4.3.1" targetFramework="net472" />
|
||||
<package id="System.Memory" version="4.5.5" targetFramework="net472" />
|
||||
<package id="System.Net.Primitives" version="4.3.1" targetFramework="net472" />
|
||||
<package id="System.Runtime" version="4.3.1" targetFramework="net472" />
|
||||
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
|
||||
<package id="System.Collections" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Globalization" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.IO" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.IO.Compression" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Linq" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Net.Sockets" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
|
||||
<package id="System.ObjectModel" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Reflection" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.Handles" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Threading" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Threading.Timer" version="4.3.0" targetFramework="net472" />
|
||||
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net472" />
|
||||
</packages>
|
@@ -15,7 +15,6 @@ if (newVersion) {
|
||||
// Process package.json
|
||||
pkg.version = newVersion;
|
||||
pkg.scripts.setup = pkg.scripts.setup.replaceAll(oldVersion, newVersion);
|
||||
pkg.scripts["build-docker"] = pkg.scripts["build-docker"].replaceAll(oldVersion, newVersion);
|
||||
fs.writeFileSync("package.json", JSON.stringify(pkg, null, 4) + "\n");
|
||||
|
||||
// Process README.md
|
||||
|
@@ -1,6 +0,0 @@
|
||||
console.log("Git Push and Publish the release note on github, then press any key to continue");
|
||||
|
||||
process.stdin.setRawMode(true);
|
||||
process.stdin.resume();
|
||||
process.stdin.on("data", process.exit.bind(process, 0));
|
||||
|
64
extra/release/beta.mjs
Normal file
64
extra/release/beta.mjs
Normal file
@@ -0,0 +1,64 @@
|
||||
import "dotenv/config";
|
||||
import {
|
||||
ver,
|
||||
buildDist,
|
||||
buildImage,
|
||||
checkDocker,
|
||||
checkTagExists,
|
||||
checkVersionFormat,
|
||||
getRepoNames,
|
||||
pressAnyKey,
|
||||
execSync, uploadArtifacts,
|
||||
} from "./lib.mjs";
|
||||
import semver from "semver";
|
||||
|
||||
const repoNames = getRepoNames();
|
||||
const version = process.env.RELEASE_BETA_VERSION;
|
||||
const githubToken = process.env.RELEASE_GITHUB_TOKEN;
|
||||
|
||||
console.log("RELEASE_BETA_VERSION:", version);
|
||||
|
||||
if (!githubToken) {
|
||||
console.error("GITHUB_TOKEN is required");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check if the version is a valid semver
|
||||
checkVersionFormat(version);
|
||||
|
||||
// Check if the semver identifier is "beta"
|
||||
const semverIdentifier = semver.prerelease(version);
|
||||
console.log("Semver identifier:", semverIdentifier);
|
||||
if (semverIdentifier[0] !== "beta") {
|
||||
console.error("VERSION should have a semver identifier of 'beta'");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check if docker is running
|
||||
checkDocker();
|
||||
|
||||
// Check if the tag exists
|
||||
await checkTagExists(repoNames, version);
|
||||
|
||||
// node extra/beta/update-version.js
|
||||
execSync("node ./extra/beta/update-version.js");
|
||||
|
||||
// Build frontend dist
|
||||
buildDist();
|
||||
|
||||
// Build slim image (rootless)
|
||||
buildImage(repoNames, [ "beta-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base2-slim");
|
||||
|
||||
// Build full image (rootless)
|
||||
buildImage(repoNames, [ "beta-rootless", ver(version, "rootless") ], "rootless");
|
||||
|
||||
// Build slim image
|
||||
buildImage(repoNames, [ "beta-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base2-slim");
|
||||
|
||||
// Build full image
|
||||
buildImage(repoNames, [ "beta", version ], "release");
|
||||
|
||||
await pressAnyKey();
|
||||
|
||||
// npm run upload-artifacts
|
||||
uploadArtifacts(version, githubToken);
|
57
extra/release/final.mjs
Normal file
57
extra/release/final.mjs
Normal file
@@ -0,0 +1,57 @@
|
||||
import "dotenv/config";
|
||||
import {
|
||||
ver,
|
||||
buildDist,
|
||||
buildImage,
|
||||
checkDocker,
|
||||
checkTagExists,
|
||||
checkVersionFormat,
|
||||
getRepoNames,
|
||||
pressAnyKey, execSync, uploadArtifacts
|
||||
} from "./lib.mjs";
|
||||
|
||||
const repoNames = getRepoNames();
|
||||
const version = process.env.RELEASE_VERSION;
|
||||
const githubToken = process.env.RELEASE_GITHUB_TOKEN;
|
||||
|
||||
console.log("RELEASE_VERSION:", version);
|
||||
|
||||
if (!githubToken) {
|
||||
console.error("GITHUB_TOKEN is required");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check if the version is a valid semver
|
||||
checkVersionFormat(version);
|
||||
|
||||
// Check if docker is running
|
||||
checkDocker();
|
||||
|
||||
// Check if the tag exists
|
||||
await checkTagExists(repoNames, version);
|
||||
|
||||
// node extra/beta/update-version.js
|
||||
execSync("node extra/update-version.js");
|
||||
|
||||
// Build frontend dist
|
||||
buildDist();
|
||||
|
||||
// Build slim image (rootless)
|
||||
buildImage(repoNames, [ "2-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base2-slim");
|
||||
|
||||
// Build full image (rootless)
|
||||
buildImage(repoNames, [ "2-rootless", ver(version, "rootless") ], "rootless");
|
||||
|
||||
// Build slim image
|
||||
buildImage(repoNames, [ "next-slim", "2-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base2-slim");
|
||||
|
||||
// Build full image
|
||||
buildImage(repoNames, [ "next", "2", version ], "release");
|
||||
|
||||
await pressAnyKey();
|
||||
|
||||
// npm run upload-artifacts
|
||||
uploadArtifacts(version, githubToken);
|
||||
|
||||
// node extra/update-wiki-version.js
|
||||
execSync("node extra/update-wiki-version.js");
|
251
extra/release/lib.mjs
Normal file
251
extra/release/lib.mjs
Normal file
@@ -0,0 +1,251 @@
|
||||
import "dotenv/config";
|
||||
import * as childProcess from "child_process";
|
||||
import semver from "semver";
|
||||
|
||||
export const dryRun = process.env.RELEASE_DRY_RUN === "1";
|
||||
|
||||
if (dryRun) {
|
||||
console.info("Dry run enabled.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if docker is running
|
||||
* @returns {void}
|
||||
*/
|
||||
export function checkDocker() {
|
||||
try {
|
||||
childProcess.execSync("docker ps");
|
||||
} catch (error) {
|
||||
console.error("Docker is not running. Please start docker and try again.");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Docker Hub repository name
|
||||
*/
|
||||
export function getRepoNames() {
|
||||
if (process.env.RELEASE_REPO_NAMES) {
|
||||
// Split by comma
|
||||
return process.env.RELEASE_REPO_NAMES.split(",").map((name) => name.trim());
|
||||
}
|
||||
return [
|
||||
"louislam/uptime-kuma",
|
||||
"ghcr.io/louislam/uptime-kuma",
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build frontend dist
|
||||
* @returns {void}
|
||||
*/
|
||||
export function buildDist() {
|
||||
if (!dryRun) {
|
||||
childProcess.execSync("npm run build", { stdio: "inherit" });
|
||||
} else {
|
||||
console.info("[DRY RUN] npm run build");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build docker image and push to Docker Hub
|
||||
* @param {string[]} repoNames Docker Hub repository names
|
||||
* @param {string[]} tags Docker image tags
|
||||
* @param {string} target Dockerfile's target name
|
||||
* @param {string} buildArgs Docker build args
|
||||
* @param {string} dockerfile Path to Dockerfile
|
||||
* @param {string} platform Build platform
|
||||
* @returns {void}
|
||||
*/
|
||||
export function buildImage(repoNames, tags, target, buildArgs = "", dockerfile = "docker/dockerfile", platform = "linux/amd64,linux/arm64,linux/arm/v7") {
|
||||
let args = [
|
||||
"buildx",
|
||||
"build",
|
||||
"-f",
|
||||
dockerfile,
|
||||
"--platform",
|
||||
platform,
|
||||
];
|
||||
|
||||
for (let repoName of repoNames) {
|
||||
// Add tags
|
||||
for (let tag of tags) {
|
||||
args.push("-t", `${repoName}:${tag}`);
|
||||
}
|
||||
}
|
||||
|
||||
args = [
|
||||
...args,
|
||||
"--target",
|
||||
target,
|
||||
];
|
||||
|
||||
// Add build args
|
||||
if (buildArgs) {
|
||||
args.push("--build-arg", buildArgs);
|
||||
}
|
||||
|
||||
args = [
|
||||
...args,
|
||||
".",
|
||||
"--push",
|
||||
];
|
||||
|
||||
if (!dryRun) {
|
||||
childProcess.spawnSync("docker", args, { stdio: "inherit" });
|
||||
} else {
|
||||
console.log(`[DRY RUN] docker ${args.join(" ")}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the version already exists on Docker Hub
|
||||
* TODO: use semver to compare versions if it is greater than the previous?
|
||||
* @param {string[]} repoNames repository name (Only check the name with single slash)
|
||||
* @param {string} version Version to check
|
||||
* @returns {void}
|
||||
*/
|
||||
export async function checkTagExists(repoNames, version) {
|
||||
// Skip if the tag is not on Docker Hub
|
||||
// louislam/uptime-kuma
|
||||
let dockerHubRepoNames = repoNames.filter((name) => {
|
||||
return name.split("/").length === 2;
|
||||
});
|
||||
|
||||
for (let repoName of dockerHubRepoNames) {
|
||||
await checkTagExistsSingle(repoName, version);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the version already exists on Docker Hub
|
||||
* @param {string} repoName repository name
|
||||
* @param {string} version Version to check
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function checkTagExistsSingle(repoName, version) {
|
||||
console.log(`Checking if version ${version} exists on Docker Hub:`, repoName);
|
||||
|
||||
// Get a list of tags from the Docker Hub repository
|
||||
let tags = [];
|
||||
|
||||
// It is mainly to check my careless mistake that I forgot to update the release version in .env, so `page_size` is set to 100 is enough, I think.
|
||||
const response = await fetch(`https://hub.docker.com/v2/repositories/${repoName}/tags/?page_size=100`);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
tags = data.results.map((tag) => tag.name);
|
||||
} else {
|
||||
console.error("Failed to get tags from Docker Hub");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check if the version already exists
|
||||
if (tags.includes(version)) {
|
||||
console.error(`Version ${version} already exists`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the version format
|
||||
* @param {string} version Version to check
|
||||
* @returns {void}
|
||||
*/
|
||||
export function checkVersionFormat(version) {
|
||||
if (!version) {
|
||||
console.error("VERSION is required");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check the version format, it should be a semver and must be like this: "2.0.0-beta.0"
|
||||
if (!semver.valid(version)) {
|
||||
console.error("VERSION is not a valid semver version");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Press any key to continue
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export function pressAnyKey() {
|
||||
console.log("Git Push and Publish the release note on github, then press any key to continue");
|
||||
process.stdin.setRawMode(true);
|
||||
process.stdin.resume();
|
||||
return new Promise(resolve => process.stdin.once("data", data => {
|
||||
process.stdin.setRawMode(false);
|
||||
process.stdin.pause();
|
||||
resolve();
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append version identifier
|
||||
* @param {string} version Version
|
||||
* @param {string} identifier Identifier
|
||||
* @returns {string} Version with identifier
|
||||
*/
|
||||
export function ver(version, identifier) {
|
||||
const obj = semver.parse(version);
|
||||
|
||||
if (obj.prerelease.length === 0) {
|
||||
obj.prerelease = [ identifier ];
|
||||
} else {
|
||||
obj.prerelease[0] = [ obj.prerelease[0], identifier ].join("-");
|
||||
}
|
||||
return obj.format();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload artifacts to GitHub
|
||||
* 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
|
||||
* @param {string} version Version
|
||||
* @param {string} githubToken GitHub token
|
||||
* @returns {void}
|
||||
*/
|
||||
export function uploadArtifacts(version, githubToken) {
|
||||
let args = [
|
||||
"buildx",
|
||||
"build",
|
||||
"-f",
|
||||
"docker/dockerfile",
|
||||
"--platform",
|
||||
"linux/amd64",
|
||||
"-t",
|
||||
"louislam/uptime-kuma:upload-artifact",
|
||||
"--build-arg",
|
||||
`VERSION=${version}`,
|
||||
"--build-arg",
|
||||
"GITHUB_TOKEN",
|
||||
"--target",
|
||||
"upload-artifact",
|
||||
".",
|
||||
"--progress",
|
||||
"plain",
|
||||
];
|
||||
|
||||
if (!dryRun) {
|
||||
childProcess.spawnSync("docker", args, {
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
GITHUB_TOKEN: githubToken,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
console.log(`[DRY RUN] docker ${args.join(" ")}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command
|
||||
* @param {string} cmd Command to execute
|
||||
* @returns {void}
|
||||
*/
|
||||
export function execSync(cmd) {
|
||||
if (!dryRun) {
|
||||
childProcess.execSync(cmd, { stdio: "inherit" });
|
||||
} else {
|
||||
console.info(`[DRY RUN] ${cmd}`);
|
||||
}
|
||||
}
|
16
extra/release/nightly.mjs
Normal file
16
extra/release/nightly.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import { buildDist, buildImage, checkDocker, getRepoNames } from "./lib.mjs";
|
||||
|
||||
// Docker Hub repository name
|
||||
const repoNames = getRepoNames();
|
||||
|
||||
// Check if docker is running
|
||||
checkDocker();
|
||||
|
||||
// Build frontend dist (it will build on the host machine, TODO: build on a container?)
|
||||
buildDist();
|
||||
|
||||
// Build full image (rootless)
|
||||
buildImage(repoNames, [ "nightly2-rootless" ], "nightly-rootless");
|
||||
|
||||
// Build full image
|
||||
buildImage(repoNames, [ "nightly2" ], "nightly");
|
6
extra/release/upload-artifacts-beta.mjs
Normal file
6
extra/release/upload-artifacts-beta.mjs
Normal file
@@ -0,0 +1,6 @@
|
||||
import { uploadArtifacts } from "./lib.mjs";
|
||||
|
||||
const version = process.env.RELEASE_BETA_VERSION;
|
||||
const githubToken = process.env.RELEASE_GITHUB_TOKEN;
|
||||
|
||||
uploadArtifacts(version, githubToken);
|
6
extra/release/upload-artifacts.mjs
Normal file
6
extra/release/upload-artifacts.mjs
Normal file
@@ -0,0 +1,6 @@
|
||||
import { uploadArtifacts } from "./lib.mjs";
|
||||
|
||||
const version = process.env.RELEASE_VERSION;
|
||||
const githubToken = process.env.RELEASE_GITHUB_TOKEN;
|
||||
|
||||
uploadArtifacts(version, githubToken);
|
@@ -1,9 +0,0 @@
|
||||
// Check if docker is running
|
||||
const { exec } = require("child_process");
|
||||
|
||||
exec("docker ps", (err, stdout, stderr) => {
|
||||
if (err) {
|
||||
console.error("Docker is not running. Please start docker and try again.");
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
@@ -5,7 +5,7 @@ const util = require("../src/util");
|
||||
|
||||
util.polyfill();
|
||||
|
||||
const newVersion = process.env.VERSION;
|
||||
const newVersion = process.env.RELEASE_VERSION;
|
||||
|
||||
console.log("New Version: " + newVersion);
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const childProcess = require("child_process");
|
||||
const fs = require("fs");
|
||||
|
||||
const newVersion = process.env.VERSION;
|
||||
const newVersion = process.env.RELEASE_VERSION;
|
||||
|
||||
if (!newVersion) {
|
||||
console.log("Missing version");
|
||||
|
4991
package-lock.json
generated
4991
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
39
package.json
39
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "2.0.0-dev",
|
||||
"version": "2.0.0-beta.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -34,20 +34,14 @@
|
||||
"playwright-show-report": "playwright show-report ./private/playwright-report",
|
||||
"tsc": "tsc",
|
||||
"vite-preview-dist": "vite preview --host --config ./config/vite.config.js",
|
||||
"build-docker": "npm run build && npm run build-docker-full && npm run build-docker-slim",
|
||||
"build-docker-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base2 --target base2 . --push",
|
||||
"build-docker-base-slim": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base2-slim --target base2-slim . --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-slim": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:next-slim -t louislam/uptime-kuma:2-slim -t louislam/uptime-kuma:$VERSION-slim --target release --build-arg BASE_IMAGE=louislam/uptime-kuma:base2-slim . --push",
|
||||
"build-docker-full": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:next -t louislam/uptime-kuma:2 -t louislam/uptime-kuma:$VERSION --target release . --push",
|
||||
"build-docker-nightly": "node ./extra/test-docker.js && npm run build && docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly2 --target nightly . --push",
|
||||
"build-docker-slim-rootless": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:2-slim-rootless -t louislam/uptime-kuma:$VERSION-slim-rootless --target rootless --build-arg BASE_IMAGE=louislam/uptime-kuma:base2-slim . --push",
|
||||
"build-docker-full-rootless": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:2-rootless -t louislam/uptime-kuma:$VERSION-rootless --target rootless . --push",
|
||||
"build-docker-nightly-rootless": "node ./extra/test-docker.js && npm run build && docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly2-rootless --target nightly-rootless . --push",
|
||||
"build-docker-nightly-local": "npm run build && docker build -f docker/dockerfile -t louislam/uptime-kuma:nightly2 --target nightly .",
|
||||
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test2 --target pr-test2 . --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",
|
||||
"setup": "git checkout 1.23.14 && npm ci --production && npm run download-dist",
|
||||
"upload-artifacts": "node extra/release/upload-artifacts.mjs",
|
||||
"upload-artifacts-beta": "node extra/release/upload-artifacts-beta.mjs",
|
||||
"setup": "git checkout 1.23.16 && npm ci --omit dev && npm run download-dist",
|
||||
"download-dist": "node extra/download-dist.js",
|
||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||
"reset-password": "node extra/reset-password.js",
|
||||
@@ -58,8 +52,9 @@
|
||||
"simple-postgres": "docker run --rm -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres",
|
||||
"simple-mariadb": "docker run --rm -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mariadb# mariadb",
|
||||
"update-language-files": "cd extra/update-language-files && node index.js && cross-env-shell eslint ../../src/languages/$npm_config_language.js --fix",
|
||||
"release-final": "node ./extra/test-docker.js && node extra/update-version.js && npm run build-docker && node ./extra/press-any-key.js && npm run upload-artifacts && node ./extra/update-wiki-version.js",
|
||||
"release-beta": "node ./extra/test-docker.js && node extra/beta/update-version.js && npm run build && node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:beta . --target release --push && node ./extra/press-any-key.js && npm run upload-artifacts",
|
||||
"release-final": "node ./extra/release/final.mjs",
|
||||
"release-beta": "node ./extra/release/beta.mjs",
|
||||
"release-nightly": "node ./extra/release/nightly.mjs",
|
||||
"git-remove-tag": "git tag -d",
|
||||
"build-dist-and-restart": "npm run build && npm run start-server-dev",
|
||||
"start-pr-test": "node extra/checkout-pr.js && npm install && npm run dev",
|
||||
@@ -77,7 +72,7 @@
|
||||
"@louislam/sqlite3": "15.1.6",
|
||||
"@vvo/tzdb": "^6.125.0",
|
||||
"args-parser": "~1.3.0",
|
||||
"axios": "~0.28.1",
|
||||
"axios": "~0.29.0",
|
||||
"badge-maker": "~3.3.1",
|
||||
"bcryptjs": "~2.4.3",
|
||||
"chardet": "~1.4.0",
|
||||
@@ -100,8 +95,8 @@
|
||||
"html-escaper": "^3.0.3",
|
||||
"http-cookie-agent": "~5.0.4",
|
||||
"http-graceful-shutdown": "~3.1.7",
|
||||
"http-proxy-agent": "~5.0.0",
|
||||
"https-proxy-agent": "~5.0.1",
|
||||
"http-proxy-agent": "~7.0.2",
|
||||
"https-proxy-agent": "~7.0.6",
|
||||
"iconv-lite": "~0.6.3",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"jsesc": "~3.0.2",
|
||||
@@ -123,7 +118,7 @@
|
||||
"node-cloudflared-tunnel": "~1.0.9",
|
||||
"node-radius-client": "~1.0.0",
|
||||
"nodemailer": "~6.9.13",
|
||||
"nostr-tools": "^1.13.1",
|
||||
"nostr-tools": "^2.10.4",
|
||||
"notp": "~2.0.3",
|
||||
"openid-client": "^5.4.2",
|
||||
"password-hash": "~1.2.2",
|
||||
@@ -140,7 +135,7 @@
|
||||
"semver": "~7.5.4",
|
||||
"socket.io": "~4.8.0",
|
||||
"socket.io-client": "~4.8.0",
|
||||
"socks-proxy-agent": "6.1.1",
|
||||
"socks-proxy-agent": "~8.0.5",
|
||||
"tar": "~6.2.1",
|
||||
"tcp-ping": "~0.1.1",
|
||||
"thirty-two": "~1.0.2",
|
||||
@@ -148,7 +143,7 @@
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "~5.1.1",
|
||||
"@actions/github": "~6.0.0",
|
||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
@@ -174,7 +169,7 @@
|
||||
"cross-env": "~7.0.3",
|
||||
"delay": "^5.0.0",
|
||||
"dns2": "~2.0.1",
|
||||
"dompurify": "~3.1.7",
|
||||
"dompurify": "~3.2.4",
|
||||
"eslint": "~8.14.0",
|
||||
"eslint-plugin-jsdoc": "~46.4.6",
|
||||
"eslint-plugin-vue": "~8.7.1",
|
||||
@@ -184,7 +179,7 @@
|
||||
"postcss-html": "~1.5.0",
|
||||
"postcss-rtlcss": "~3.7.2",
|
||||
"postcss-scss": "~4.0.4",
|
||||
"prismjs": "~1.29.0",
|
||||
"prismjs": "~1.30.0",
|
||||
"qrcode": "~1.5.0",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"sass": "~1.42.1",
|
||||
@@ -195,14 +190,14 @@
|
||||
"testcontainers": "^10.13.1",
|
||||
"typescript": "~4.4.4",
|
||||
"v-pagination-3": "~0.1.7",
|
||||
"vite": "~5.2.8",
|
||||
"vite": "~5.4.15",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-vue-devtools": "^7.0.15",
|
||||
"vue": "~3.4.2",
|
||||
"vue-chartjs": "~5.2.0",
|
||||
"vue-confirm-dialog": "~1.0.2",
|
||||
"vue-contenteditable": "~3.0.4",
|
||||
"vue-i18n": "~9.2.2",
|
||||
"vue-i18n": "~9.14.3",
|
||||
"vue-image-crop-upload": "~3.0.3",
|
||||
"vue-multiselect": "~3.0.0-alpha.2",
|
||||
"vue-prism-editor": "~2.0.0-alpha.2",
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 8.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 30 KiB |
@@ -296,7 +296,7 @@ class Database {
|
||||
client: "mysql2",
|
||||
connection: {
|
||||
socketPath: embeddedMariaDB.socketPath,
|
||||
user: "node",
|
||||
user: embeddedMariaDB.username,
|
||||
database: "kuma",
|
||||
timezone: "Z",
|
||||
typeCast: function (field, next) {
|
||||
@@ -892,11 +892,13 @@ class Database {
|
||||
AND important = 0
|
||||
AND time < ${sqlHourOffset}
|
||||
AND id NOT IN (
|
||||
SELECT id
|
||||
FROM heartbeat
|
||||
WHERE monitor_id = ?
|
||||
ORDER BY time DESC
|
||||
LIMIT ?
|
||||
SELECT id FROM ( -- written this way for Maria's support
|
||||
SELECT id
|
||||
FROM heartbeat
|
||||
WHERE monitor_id = ?
|
||||
ORDER BY time DESC
|
||||
LIMIT ?
|
||||
) AS limited_ids
|
||||
)
|
||||
`, [
|
||||
monitor.id,
|
||||
|
@@ -14,9 +14,15 @@ class EmbeddedMariaDB {
|
||||
|
||||
mariadbDataDir = "/app/data/mariadb";
|
||||
|
||||
runDir = "/app/data/run/mariadb";
|
||||
runDir = "/app/data/run";
|
||||
|
||||
socketPath = this.runDir + "/mysqld.sock";
|
||||
socketPath = this.runDir + "/mariadb.sock";
|
||||
|
||||
/**
|
||||
* The username to connect to the MariaDB
|
||||
* @type {string}
|
||||
*/
|
||||
username = null;
|
||||
|
||||
/**
|
||||
* @type {ChildProcessWithoutNullStreams}
|
||||
@@ -46,16 +52,42 @@ class EmbeddedMariaDB {
|
||||
|
||||
/**
|
||||
* Start the embedded MariaDB
|
||||
* @throws {Error} If the current user is not "node" or "root"
|
||||
* @returns {Promise<void>|void} A promise that resolves when the MariaDB is started or void if it is already started
|
||||
*/
|
||||
start() {
|
||||
// Check if the current user is "node" or "root"
|
||||
this.username = require("os").userInfo().username;
|
||||
if (this.username !== "node" && this.username !== "root") {
|
||||
throw new Error("Embedded Mariadb supports only 'node' or 'root' user, but the current user is: " + this.username);
|
||||
}
|
||||
|
||||
this.initDB();
|
||||
|
||||
this.startChildProcess();
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let interval = setInterval(() => {
|
||||
if (this.started) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
} else {
|
||||
log.info("mariadb", "Waiting for Embedded MariaDB to start...");
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the child process
|
||||
* @returns {void}
|
||||
*/
|
||||
startChildProcess() {
|
||||
if (this.childProcess) {
|
||||
log.info("mariadb", "Already started");
|
||||
return;
|
||||
}
|
||||
|
||||
this.initDB();
|
||||
|
||||
this.running = true;
|
||||
log.info("mariadb", "Starting Embedded MariaDB");
|
||||
this.childProcess = childProcess.spawn(this.exec, [
|
||||
@@ -63,6 +95,8 @@ class EmbeddedMariaDB {
|
||||
"--datadir=" + this.mariadbDataDir,
|
||||
`--socket=${this.socketPath}`,
|
||||
`--pid-file=${this.runDir}/mysqld.pid`,
|
||||
// Don't add the following option, the mariadb will not report message to the console, which affects initDBAfterStarted()
|
||||
// "--log-error=" + `${this.mariadbDataDir}/mariadb-error.log`,
|
||||
]);
|
||||
|
||||
this.childProcess.on("close", (code) => {
|
||||
@@ -72,8 +106,8 @@ class EmbeddedMariaDB {
|
||||
log.info("mariadb", "Stopped Embedded MariaDB: " + code);
|
||||
|
||||
if (code !== 0) {
|
||||
log.info("mariadb", "Try to restart Embedded MariaDB as it is not stopped by user");
|
||||
this.start();
|
||||
log.error("mariadb", "Try to restart Embedded MariaDB as it is not stopped by user");
|
||||
this.startChildProcess();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -86,7 +120,7 @@ class EmbeddedMariaDB {
|
||||
});
|
||||
|
||||
let handler = (data) => {
|
||||
log.debug("mariadb", data.toString("utf-8"));
|
||||
log.info("mariadb", data.toString("utf-8"));
|
||||
if (data.toString("utf-8").includes("ready for connections")) {
|
||||
this.initDBAfterStarted();
|
||||
}
|
||||
@@ -94,17 +128,6 @@ class EmbeddedMariaDB {
|
||||
|
||||
this.childProcess.stdout.on("data", handler);
|
||||
this.childProcess.stderr.on("data", handler);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let interval = setInterval(() => {
|
||||
if (this.started) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
} else {
|
||||
log.info("mariadb", "Waiting for Embedded MariaDB to start...");
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,9 +152,11 @@ class EmbeddedMariaDB {
|
||||
recursive: true,
|
||||
});
|
||||
|
||||
let result = childProcess.spawnSync("mysql_install_db", [
|
||||
let result = childProcess.spawnSync("mariadb-install-db", [
|
||||
"--user=node",
|
||||
"--ldata=" + this.mariadbDataDir,
|
||||
"--auth-root-socket-user=node",
|
||||
"--datadir=" + this.mariadbDataDir,
|
||||
"--auth-root-authentication-method=socket",
|
||||
]);
|
||||
|
||||
if (result.status !== 0) {
|
||||
@@ -143,6 +168,17 @@ class EmbeddedMariaDB {
|
||||
}
|
||||
}
|
||||
|
||||
// Check the owner of the mariadb directory, and change it if necessary
|
||||
let stat = fs.statSync(this.mariadbDataDir);
|
||||
if (stat.uid !== 1000 || stat.gid !== 1000) {
|
||||
fs.chownSync(this.mariadbDataDir, 1000, 1000);
|
||||
}
|
||||
|
||||
// Check the permission of the mariadb directory, and change it if it is not 755
|
||||
if (stat.mode !== 0o755) {
|
||||
fs.chmodSync(this.mariadbDataDir, 0o755);
|
||||
}
|
||||
|
||||
if (!fs.existsSync(this.runDir)) {
|
||||
log.info("mariadb", `Embedded MariaDB: ${this.runDir} is not found, create one now.`);
|
||||
fs.mkdirSync(this.runDir, {
|
||||
@@ -150,6 +186,13 @@ class EmbeddedMariaDB {
|
||||
});
|
||||
}
|
||||
|
||||
stat = fs.statSync(this.runDir);
|
||||
if (stat.uid !== 1000 || stat.gid !== 1000) {
|
||||
fs.chownSync(this.runDir, 1000, 1000);
|
||||
}
|
||||
if (stat.mode !== 0o755) {
|
||||
fs.chmodSync(this.runDir, 0o755);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +202,7 @@ class EmbeddedMariaDB {
|
||||
async initDBAfterStarted() {
|
||||
const connection = mysql.createConnection({
|
||||
socketPath: this.socketPath,
|
||||
user: "node",
|
||||
user: this.username,
|
||||
});
|
||||
|
||||
let result = await connection.execute("CREATE DATABASE IF NOT EXISTS `kuma`");
|
||||
|
@@ -1434,7 +1434,7 @@ class Monitor extends BeanModel {
|
||||
for (let notification of notificationList) {
|
||||
try {
|
||||
log.debug("monitor", "Sending to " + notification.name);
|
||||
await Notification.send(JSON.parse(notification.config), `[${this.name}][${this.url}] ${certType} certificate ${certCN} will be expired in ${daysRemaining} days`);
|
||||
await Notification.send(JSON.parse(notification.config), `[${this.name}][${this.url}] ${certType} certificate ${certCN} will expire in ${daysRemaining} days`);
|
||||
sent = true;
|
||||
} catch (e) {
|
||||
log.error("monitor", "Cannot send cert notification to " + notification.name);
|
||||
@@ -1522,7 +1522,7 @@ class Monitor extends BeanModel {
|
||||
*/
|
||||
static async getMonitorTag(monitorIDs) {
|
||||
return await R.getAll(`
|
||||
SELECT monitor_tag.monitor_id, monitor_tag.tag_id, tag.name, tag.color
|
||||
SELECT monitor_tag.monitor_id, monitor_tag.tag_id, monitor_tag.value, tag.name, tag.color
|
||||
FROM monitor_tag
|
||||
JOIN tag ON monitor_tag.tag_id = tag.id
|
||||
WHERE monitor_tag.monitor_id IN (${monitorIDs.map((_) => "?").join(",")})
|
||||
@@ -1567,6 +1567,8 @@ class Monitor extends BeanModel {
|
||||
}
|
||||
tagsMap.get(row.monitor_id).push({
|
||||
tag_id: row.tag_id,
|
||||
monitor_id: row.monitor_id,
|
||||
value: row.value,
|
||||
name: row.name,
|
||||
color: row.color
|
||||
});
|
||||
|
@@ -485,7 +485,7 @@ function ApiCache() {
|
||||
}
|
||||
|
||||
if (typeof duration === "string") {
|
||||
let split = duration.match(/^([\d\.,]+)\s?(\w+)$/);
|
||||
let split = duration.match(/^([\d\.,]+)\s?([a-zA-Z]+)$/);
|
||||
|
||||
if (split.length === 3) {
|
||||
let len = parseFloat(split[1]);
|
||||
|
@@ -240,6 +240,14 @@ class RealBrowserMonitorType extends MonitorType {
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
|
||||
// Prevent Local File Inclusion
|
||||
// Accept only http:// and https://
|
||||
// https://github.com/louislam/uptime-kuma/security/advisories/GHSA-2qgm-m29m-cj2h
|
||||
let url = new URL(monitor.url);
|
||||
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
||||
throw new Error("Invalid url protocol, only http and https are allowed.");
|
||||
}
|
||||
|
||||
const res = await page.goto(monitor.url, {
|
||||
waitUntil: "networkidle",
|
||||
timeout: monitor.interval * 1000 * 0.8,
|
||||
|
@@ -17,7 +17,7 @@ class AliyunSMS extends NotificationProvider {
|
||||
if (heartbeatJSON != null) {
|
||||
let msgBody = JSON.stringify({
|
||||
name: monitorJSON["name"],
|
||||
time: heartbeatJSON["time"],
|
||||
time: heartbeatJSON["localDateTime"],
|
||||
status: this.statusToString(heartbeatJSON["status"]),
|
||||
msg: heartbeatJSON["msg"],
|
||||
});
|
||||
|
@@ -72,6 +72,7 @@ class GoogleChat extends NotificationProvider {
|
||||
|
||||
// construct json data
|
||||
let data = {
|
||||
fallbackText: chatHeader["title"],
|
||||
cardsV2: [
|
||||
{
|
||||
card: {
|
||||
|
@@ -1,11 +1,10 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const {
|
||||
relayInit,
|
||||
getPublicKey,
|
||||
getEventHash,
|
||||
getSignature,
|
||||
finalizeEvent,
|
||||
Relay,
|
||||
kinds,
|
||||
nip04,
|
||||
nip19
|
||||
nip19,
|
||||
} = require("nostr-tools");
|
||||
|
||||
// polyfills for node versions
|
||||
@@ -31,7 +30,6 @@ class Nostr extends NotificationProvider {
|
||||
const createdAt = Math.floor(Date.now() / 1000);
|
||||
|
||||
const senderPrivateKey = await this.getPrivateKey(notification.sender);
|
||||
const senderPublicKey = getPublicKey(senderPrivateKey);
|
||||
const recipientsPublicKeys = await this.getPublicKeys(notification.recipients);
|
||||
|
||||
// Create NIP-04 encrypted direct message event for each recipient
|
||||
@@ -39,34 +37,41 @@ class Nostr extends NotificationProvider {
|
||||
for (const recipientPublicKey of recipientsPublicKeys) {
|
||||
const ciphertext = await nip04.encrypt(senderPrivateKey, recipientPublicKey, msg);
|
||||
let event = {
|
||||
kind: 4,
|
||||
pubkey: senderPublicKey,
|
||||
kind: kinds.EncryptedDirectMessage,
|
||||
created_at: createdAt,
|
||||
tags: [[ "p", recipientPublicKey ]],
|
||||
content: ciphertext,
|
||||
};
|
||||
event.id = getEventHash(event);
|
||||
event.sig = getSignature(event, senderPrivateKey);
|
||||
events.push(event);
|
||||
const signedEvent = finalizeEvent(event, senderPrivateKey);
|
||||
events.push(signedEvent);
|
||||
}
|
||||
|
||||
// Publish events to each relay
|
||||
const relays = notification.relays.split("\n");
|
||||
let successfulRelays = 0;
|
||||
|
||||
// Connect to each relay
|
||||
for (const relayUrl of relays) {
|
||||
const relay = relayInit(relayUrl);
|
||||
try {
|
||||
await relay.connect();
|
||||
successfulRelays++;
|
||||
const relay = await Relay.connect(relayUrl);
|
||||
let eventIndex = 0;
|
||||
|
||||
// Publish events
|
||||
for (const event of events) {
|
||||
relay.publish(event);
|
||||
}
|
||||
// Authenticate to the relay, if required
|
||||
try {
|
||||
await relay.publish(events[0]);
|
||||
eventIndex = 1;
|
||||
} catch (error) {
|
||||
continue;
|
||||
if (relay.challenge) {
|
||||
await relay.auth(async (evt) => {
|
||||
return finalizeEvent(evt, senderPrivateKey);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
for (let i = eventIndex; i < events.length; i++) {
|
||||
await relay.publish(events[i]);
|
||||
}
|
||||
successfulRelays++;
|
||||
} catch (error) {
|
||||
console.error(`Failed to publish event to ${relayUrl}:`, error);
|
||||
} finally {
|
||||
relay.close();
|
||||
}
|
||||
@@ -90,7 +95,7 @@ class Nostr extends NotificationProvider {
|
||||
const { data } = senderDecodeResult;
|
||||
return data;
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to get private key: ${error.message}`);
|
||||
throw new Error(`Failed to decode private key for sender ${sender}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,10 +114,10 @@ class Nostr extends NotificationProvider {
|
||||
if (type === "npub") {
|
||||
publicKeys.push(data);
|
||||
} else {
|
||||
throw new Error("not an npub");
|
||||
throw new Error(`Recipient ${recipient} is not an npub`);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error decoding recipient: ${error}`);
|
||||
throw new Error(`Error decoding recipient ${recipient}: ${error}`);
|
||||
}
|
||||
}
|
||||
return publicKeys;
|
||||
|
@@ -1,3 +1,6 @@
|
||||
const { Liquid } = require("liquidjs");
|
||||
const { DOWN } = require("../../src/util");
|
||||
|
||||
class NotificationProvider {
|
||||
|
||||
/**
|
||||
@@ -49,6 +52,50 @@ class NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a message template with notification context
|
||||
* @param {string} template the template
|
||||
* @param {string} msg the message that will be included in the context
|
||||
* @param {?object} monitorJSON Monitor details (For Up/Down/Cert-Expiry only)
|
||||
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @returns {Promise<string>} rendered template
|
||||
*/
|
||||
async renderTemplate(template, msg, monitorJSON, heartbeatJSON) {
|
||||
const engine = new Liquid();
|
||||
const parsedTpl = engine.parse(template);
|
||||
|
||||
// Let's start with dummy values to simplify code
|
||||
let monitorName = "Monitor Name not available";
|
||||
let monitorHostnameOrURL = "testing.hostname";
|
||||
|
||||
if (monitorJSON !== null) {
|
||||
monitorName = monitorJSON["name"];
|
||||
monitorHostnameOrURL = this.extractAddress(monitorJSON);
|
||||
}
|
||||
|
||||
let serviceStatus = "⚠️ Test";
|
||||
if (heartbeatJSON !== null) {
|
||||
serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up";
|
||||
}
|
||||
|
||||
const context = {
|
||||
// for v1 compatibility, to be removed in v3
|
||||
"STATUS": serviceStatus,
|
||||
"NAME": monitorName,
|
||||
"HOSTNAME_OR_URL": monitorHostnameOrURL,
|
||||
|
||||
// variables which are officially supported
|
||||
"status": serviceStatus,
|
||||
"name": monitorName,
|
||||
"hostnameOrURL": monitorHostnameOrURL,
|
||||
monitorJSON,
|
||||
heartbeatJSON,
|
||||
msg,
|
||||
};
|
||||
|
||||
return engine.render(parsedTpl, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error
|
||||
* @param {any} error The error to throw
|
||||
|
@@ -11,7 +11,8 @@ class PushDeer extends NotificationProvider {
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const okMsg = "Sent Successfully.";
|
||||
const serverUrl = notification.pushdeerServer || "https://api2.pushdeer.com";
|
||||
const url = `${serverUrl.trim().replace(/\/*$/, "")}/message/push`;
|
||||
// capture group below is nessesary to prevent an ReDOS-attack
|
||||
const url = `${serverUrl.trim().replace(/([^/])\/+$/, "$1")}/message/push`;
|
||||
|
||||
let valid = msg != null && monitorJSON != null && heartbeatJSON != null;
|
||||
|
||||
|
56
server/notification-providers/pushplus.js
Normal file
56
server/notification-providers/pushplus.js
Normal file
@@ -0,0 +1,56 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
|
||||
class PushPlus extends NotificationProvider {
|
||||
name = "PushPlus";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* @param {BeanModel} notification Notification object
|
||||
* @param {string} msg Message content
|
||||
* @param {?object} monitorJSON Monitor details
|
||||
* @param {?object} heartbeatJSON Heartbeat details
|
||||
* @returns {Promise<string>} Success message
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const okMsg = "Sent Successfully.";
|
||||
const url = "https://www.pushplus.plus/send";
|
||||
try {
|
||||
const config = {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
};
|
||||
const params = {
|
||||
"token": notification.pushPlusSendKey,
|
||||
"title": this.checkStatus(heartbeatJSON, monitorJSON),
|
||||
"content": msg,
|
||||
"template": "html"
|
||||
};
|
||||
await axios.post(url, params, config);
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatted title for message
|
||||
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @param {?object} monitorJSON Monitor details (For Up/Down only)
|
||||
* @returns {string} Formatted title
|
||||
*/
|
||||
checkStatus(heartbeatJSON, monitorJSON) {
|
||||
let title = "UptimeKuma Message";
|
||||
if (heartbeatJSON != null && heartbeatJSON["status"] === UP) {
|
||||
title = "UptimeKuma Monitor Up " + monitorJSON["name"];
|
||||
}
|
||||
if (heartbeatJSON != null && heartbeatJSON["status"] === DOWN) {
|
||||
title = "UptimeKuma Monitor Down " + monitorJSON["name"];
|
||||
}
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PushPlus;
|
@@ -1,7 +1,7 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { setSettings, setting } = require("../util-server");
|
||||
const { getMonitorRelativeURL, UP } = require("../../src/util");
|
||||
const { getMonitorRelativeURL, UP, log } = require("../../src/util");
|
||||
|
||||
class Slack extends NotificationProvider {
|
||||
name = "slack";
|
||||
@@ -50,15 +50,20 @@ class Slack extends NotificationProvider {
|
||||
|
||||
const address = this.extractAddress(monitorJSON);
|
||||
if (address) {
|
||||
actions.push({
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Visit site",
|
||||
},
|
||||
"value": "Site",
|
||||
"url": address,
|
||||
});
|
||||
try {
|
||||
actions.push({
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Visit site",
|
||||
},
|
||||
"value": "Site",
|
||||
"url": new URL(address),
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
log.debug("slack", `Failed to parse address ${address} as URL`);
|
||||
}
|
||||
}
|
||||
|
||||
return actions;
|
||||
|
@@ -1,7 +1,5 @@
|
||||
const nodemailer = require("nodemailer");
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const { DOWN } = require("../../src/util");
|
||||
const { Liquid } = require("liquidjs");
|
||||
|
||||
class SMTP extends NotificationProvider {
|
||||
name = "smtp";
|
||||
@@ -53,15 +51,11 @@ class SMTP extends NotificationProvider {
|
||||
const customSubject = notification.customSubject?.trim() || "";
|
||||
const customBody = notification.customBody?.trim() || "";
|
||||
|
||||
const context = this.generateContext(msg, monitorJSON, heartbeatJSON);
|
||||
const engine = new Liquid();
|
||||
if (customSubject !== "") {
|
||||
const tpl = engine.parse(customSubject);
|
||||
subject = await engine.render(tpl, context);
|
||||
subject = await this.renderTemplate(customSubject, msg, monitorJSON, heartbeatJSON);
|
||||
}
|
||||
if (customBody !== "") {
|
||||
const tpl = engine.parse(customBody);
|
||||
body = await engine.render(tpl, context);
|
||||
body = await this.renderTemplate(customBody, msg, monitorJSON, heartbeatJSON);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,43 +72,6 @@ class SMTP extends NotificationProvider {
|
||||
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate context for LiquidJS
|
||||
* @param {string} msg the message that will be included in the context
|
||||
* @param {?object} monitorJSON Monitor details (For Up/Down/Cert-Expiry only)
|
||||
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
|
||||
* @returns {{STATUS: string, status: string, HOSTNAME_OR_URL: string, hostnameOrUrl: string, NAME: string, name: string, monitorJSON: ?object, heartbeatJSON: ?object, msg: string}} the context
|
||||
*/
|
||||
generateContext(msg, monitorJSON, heartbeatJSON) {
|
||||
// Let's start with dummy values to simplify code
|
||||
let monitorName = "Monitor Name not available";
|
||||
let monitorHostnameOrURL = "testing.hostname";
|
||||
|
||||
if (monitorJSON !== null) {
|
||||
monitorName = monitorJSON["name"];
|
||||
monitorHostnameOrURL = this.extractAddress(monitorJSON);
|
||||
}
|
||||
|
||||
let serviceStatus = "⚠️ Test";
|
||||
if (heartbeatJSON !== null) {
|
||||
serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up";
|
||||
}
|
||||
return {
|
||||
// for v1 compatibility, to be removed in v3
|
||||
"STATUS": serviceStatus,
|
||||
"NAME": monitorName,
|
||||
"HOSTNAME_OR_URL": monitorHostnameOrURL,
|
||||
|
||||
// variables which are officially supported
|
||||
"status": serviceStatus,
|
||||
"name": monitorName,
|
||||
"hostnameOrURL": monitorHostnameOrURL,
|
||||
monitorJSON,
|
||||
heartbeatJSON,
|
||||
msg,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SMTP;
|
||||
|
@@ -9,7 +9,7 @@ class Telegram extends NotificationProvider {
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const okMsg = "Sent Successfully.";
|
||||
const url = "https://api.telegram.org";
|
||||
const url = notification.telegramServerUrl ?? "https://api.telegram.org";
|
||||
|
||||
try {
|
||||
let params = {
|
||||
@@ -22,6 +22,14 @@ class Telegram extends NotificationProvider {
|
||||
params.message_thread_id = notification.telegramMessageThreadID;
|
||||
}
|
||||
|
||||
if (notification.telegramUseTemplate) {
|
||||
params.text = await this.renderTemplate(notification.telegramTemplate, msg, monitorJSON, heartbeatJSON);
|
||||
|
||||
if (notification.telegramTemplateParseMode !== "plain") {
|
||||
params.parse_mode = notification.telegramTemplateParseMode;
|
||||
}
|
||||
}
|
||||
|
||||
await axios.get(`${url}/bot${notification.telegramBotToken}/sendMessage`, {
|
||||
params: params,
|
||||
});
|
||||
|
40
server/notification-providers/waha.js
Normal file
40
server/notification-providers/waha.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
|
||||
class WAHA extends NotificationProvider {
|
||||
name = "waha";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
const config = {
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"X-Api-Key": notification.wahaApiKey,
|
||||
}
|
||||
};
|
||||
|
||||
let data = {
|
||||
"session": notification.wahaSession,
|
||||
"chatId": notification.wahaChatId,
|
||||
"text": msg,
|
||||
};
|
||||
|
||||
let url = notification.wahaApiUrl.replace(/([^/])\/+$/, "$1") + "/api/sendText";
|
||||
|
||||
await axios.post(url, data, config);
|
||||
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = WAHA;
|
@@ -1,7 +1,6 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const FormData = require("form-data");
|
||||
const { Liquid } = require("liquidjs");
|
||||
|
||||
class Webhook extends NotificationProvider {
|
||||
name = "webhook";
|
||||
@@ -28,17 +27,7 @@ class Webhook extends NotificationProvider {
|
||||
config.headers = formData.getHeaders();
|
||||
data = formData;
|
||||
} else if (notification.webhookContentType === "custom") {
|
||||
// Initialize LiquidJS and parse the custom Body Template
|
||||
const engine = new Liquid();
|
||||
const tpl = engine.parse(notification.webhookCustomBody);
|
||||
|
||||
// Insert templated values into Body
|
||||
data = await engine.render(tpl,
|
||||
{
|
||||
msg,
|
||||
heartbeatJSON,
|
||||
monitorJSON
|
||||
});
|
||||
data = await this.renderTemplate(notification.webhookCustomBody, msg, monitorJSON, heartbeatJSON);
|
||||
}
|
||||
|
||||
if (notification.webhookAdditionalHeaders) {
|
||||
|
@@ -24,7 +24,7 @@ class Whapi extends NotificationProvider {
|
||||
"body": msg,
|
||||
};
|
||||
|
||||
let url = (notification.whapiApiUrl || "https://gate.whapi.cloud/").replace(/\/+$/, "") + "/messages/text";
|
||||
let url = (notification.whapiApiUrl || "https://gate.whapi.cloud/").replace(/([^/])\/+$/, "$1") + "/messages/text";
|
||||
|
||||
await axios.post(url, data, config);
|
||||
|
||||
|
57
server/notification-providers/yzj.js
Normal file
57
server/notification-providers/yzj.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
const { default: axios } = require("axios");
|
||||
|
||||
class YZJ extends NotificationProvider {
|
||||
name = "YZJ";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
if (heartbeatJSON !== null) {
|
||||
msg = `${this.statusToString(heartbeatJSON["status"])} ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`;
|
||||
}
|
||||
|
||||
const config = {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
};
|
||||
const params = {
|
||||
content: msg
|
||||
};
|
||||
// yzjtype=0 => general robot
|
||||
const url = `${notification.yzjWebHookUrl}?yzjtype=0&yzjtoken=${notification.yzjToken}`;
|
||||
|
||||
const result = await axios.post(url, params, config);
|
||||
if (!result.data?.success) {
|
||||
throw new Error(result.data?.errmsg ?? "yzj's server did not respond with the expected result");
|
||||
}
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert status constant to string
|
||||
* @param {string} status The status constant
|
||||
* @returns {string} status
|
||||
*/
|
||||
statusToString(status) {
|
||||
switch (status) {
|
||||
case DOWN:
|
||||
return "❌";
|
||||
case UP:
|
||||
return "✅";
|
||||
default:
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = YZJ;
|
@@ -39,6 +39,7 @@ const PromoSMS = require("./notification-providers/promosms");
|
||||
const Pushbullet = require("./notification-providers/pushbullet");
|
||||
const PushDeer = require("./notification-providers/pushdeer");
|
||||
const Pushover = require("./notification-providers/pushover");
|
||||
const PushPlus = require("./notification-providers/pushplus");
|
||||
const Pushy = require("./notification-providers/pushy");
|
||||
const RocketChat = require("./notification-providers/rocket-chat");
|
||||
const SerwerSMS = require("./notification-providers/serwersms");
|
||||
@@ -64,11 +65,13 @@ const ServerChan = require("./notification-providers/serverchan");
|
||||
const ZohoCliq = require("./notification-providers/zoho-cliq");
|
||||
const SevenIO = require("./notification-providers/sevenio");
|
||||
const Whapi = require("./notification-providers/whapi");
|
||||
const WAHA = require("./notification-providers/waha");
|
||||
const GtxMessaging = require("./notification-providers/gtx-messaging");
|
||||
const Cellsynt = require("./notification-providers/cellsynt");
|
||||
const Onesender = require("./notification-providers/onesender");
|
||||
const Wpush = require("./notification-providers/wpush");
|
||||
const SendGrid = require("./notification-providers/send-grid");
|
||||
const YZJ = require("./notification-providers/yzj");
|
||||
|
||||
class Notification {
|
||||
|
||||
@@ -126,6 +129,7 @@ class Notification {
|
||||
new Pushbullet(),
|
||||
new PushDeer(),
|
||||
new Pushover(),
|
||||
new PushPlus(),
|
||||
new Pushy(),
|
||||
new RocketChat(),
|
||||
new ServerChan(),
|
||||
@@ -151,10 +155,12 @@ class Notification {
|
||||
new ZohoCliq(),
|
||||
new SevenIO(),
|
||||
new Whapi(),
|
||||
new WAHA(),
|
||||
new GtxMessaging(),
|
||||
new Cellsynt(),
|
||||
new Wpush(),
|
||||
new SendGrid()
|
||||
new SendGrid(),
|
||||
new YZJ()
|
||||
];
|
||||
for (let item of list) {
|
||||
if (! item.name) {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const { R } = require("redbean-node");
|
||||
const HttpProxyAgent = require("http-proxy-agent");
|
||||
const HttpsProxyAgent = require("https-proxy-agent");
|
||||
const SocksProxyAgent = require("socks-proxy-agent");
|
||||
const { HttpProxyAgent } = require("http-proxy-agent");
|
||||
const { HttpsProxyAgent } = require("https-proxy-agent");
|
||||
const { SocksProxyAgent } = require("socks-proxy-agent");
|
||||
const { debug } = require("../src/util");
|
||||
const { UptimeKumaServer } = require("./uptime-kuma-server");
|
||||
const { CookieJar } = require("tough-cookie");
|
||||
@@ -100,17 +100,17 @@ class Proxy {
|
||||
let jar = new CookieJar();
|
||||
|
||||
const proxyOptions = {
|
||||
protocol: proxy.protocol,
|
||||
host: proxy.host,
|
||||
port: proxy.port,
|
||||
cookies: { jar },
|
||||
};
|
||||
|
||||
const proxyUrl = new URL(`${proxy.protocol}://${proxy.host}:${proxy.port}`);
|
||||
|
||||
if (proxy.auth) {
|
||||
proxyOptions.auth = `${proxy.username}:${proxy.password}`;
|
||||
proxyUrl.username = proxy.username;
|
||||
proxyUrl.password = proxy.password;
|
||||
}
|
||||
|
||||
debug(`Proxy Options: ${JSON.stringify(proxyOptions)}`);
|
||||
debug(`Proxy URL: ${proxyUrl.toString()}`);
|
||||
debug(`HTTP Agent Options: ${JSON.stringify(httpAgentOptions)}`);
|
||||
debug(`HTTPS Agent Options: ${JSON.stringify(httpsAgentOptions)}`);
|
||||
|
||||
@@ -122,15 +122,15 @@ class Proxy {
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const HttpsCookieProxyAgent = createCookieAgent(HttpsProxyAgent);
|
||||
|
||||
httpAgent = new HttpCookieProxyAgent({
|
||||
...httpAgentOptions || {},
|
||||
httpAgent = new HttpCookieProxyAgent(proxyUrl.toString(), {
|
||||
...(httpAgentOptions || {}),
|
||||
...proxyOptions,
|
||||
});
|
||||
httpsAgent = new HttpsCookieProxyAgent(proxyUrl.toString(), {
|
||||
...(httpsAgentOptions || {}),
|
||||
...proxyOptions,
|
||||
});
|
||||
|
||||
httpsAgent = new HttpsCookieProxyAgent({
|
||||
...httpsAgentOptions || {},
|
||||
...proxyOptions,
|
||||
});
|
||||
break;
|
||||
case "socks":
|
||||
case "socks5":
|
||||
@@ -138,10 +138,9 @@ class Proxy {
|
||||
case "socks4":
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const SocksCookieProxyAgent = createCookieAgent(SocksProxyAgent);
|
||||
agent = new SocksCookieProxyAgent({
|
||||
agent = new SocksCookieProxyAgent(proxyUrl.toString(), {
|
||||
...httpAgentOptions,
|
||||
...httpsAgentOptions,
|
||||
...proxyOptions,
|
||||
tls: {
|
||||
rejectUnauthorized: httpsAgentOptions.rejectUnauthorized,
|
||||
},
|
||||
|
@@ -15,11 +15,13 @@ const server = UptimeKumaServer.getInstance();
|
||||
|
||||
router.get("/status/:slug", cache("5 minutes"), async (request, response) => {
|
||||
let slug = request.params.slug;
|
||||
slug = slug.toLowerCase();
|
||||
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||
});
|
||||
|
||||
router.get("/status/:slug/rss", cache("5 minutes"), async (request, response) => {
|
||||
let slug = request.params.slug;
|
||||
slug = slug.toLowerCase();
|
||||
await StatusPage.handleStatusPageRSSResponse(response, slug);
|
||||
});
|
||||
|
||||
@@ -37,6 +39,7 @@ router.get("/status-page", cache("5 minutes"), async (request, response) => {
|
||||
router.get("/api/status-page/:slug", cache("5 minutes"), async (request, response) => {
|
||||
allowDevAllOrigin(response);
|
||||
let slug = request.params.slug;
|
||||
slug = slug.toLowerCase();
|
||||
|
||||
try {
|
||||
// Get Status Page
|
||||
@@ -69,6 +72,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
|
||||
let uptimeList = {};
|
||||
|
||||
let slug = request.params.slug;
|
||||
slug = slug.toLowerCase();
|
||||
let statusPageID = await StatusPage.slugToID(slug);
|
||||
|
||||
let monitorIDList = await R.getCol(`
|
||||
@@ -111,6 +115,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
|
||||
router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async (request, response) => {
|
||||
allowDevAllOrigin(response);
|
||||
let slug = request.params.slug;
|
||||
slug = slug.toLowerCase();
|
||||
|
||||
try {
|
||||
// Get Status Page
|
||||
@@ -145,7 +150,8 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async
|
||||
// overall status-page status badge
|
||||
router.get("/api/status-page/:slug/badge", cache("5 minutes"), async (request, response) => {
|
||||
allowDevAllOrigin(response);
|
||||
const slug = request.params.slug;
|
||||
let slug = request.params.slug;
|
||||
slug = slug.toLowerCase();
|
||||
const statusPageID = await StatusPage.slugToID(slug);
|
||||
const {
|
||||
label,
|
||||
|
@@ -220,13 +220,17 @@ module.exports.statusPageSocketHandler = (socket) => {
|
||||
|
||||
// Delete groups that are not in the list
|
||||
log.debug("socket", "Delete groups that are not in the list");
|
||||
const slots = groupIDList.map(() => "?").join(",");
|
||||
if (groupIDList.length === 0) {
|
||||
await R.exec("DELETE FROM `group` WHERE status_page_id = ?", [ statusPage.id ]);
|
||||
} else {
|
||||
const slots = groupIDList.map(() => "?").join(",");
|
||||
|
||||
const data = [
|
||||
...groupIDList,
|
||||
statusPage.id
|
||||
];
|
||||
await R.exec(`DELETE FROM \`group\` WHERE id NOT IN (${slots}) AND status_page_id = ?`, data);
|
||||
const data = [
|
||||
...groupIDList,
|
||||
statusPage.id
|
||||
];
|
||||
await R.exec(`DELETE FROM \`group\` WHERE id NOT IN (${slots}) AND status_page_id = ?`, data);
|
||||
}
|
||||
|
||||
const server = UptimeKumaServer.getInstance();
|
||||
|
||||
@@ -288,6 +292,7 @@ module.exports.statusPageSocketHandler = (socket) => {
|
||||
ok: true,
|
||||
msg: "successAdded",
|
||||
msgi18n: true,
|
||||
slug: slug
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
|
@@ -619,7 +619,7 @@ $shadow-box-padding: 20px;
|
||||
bottom: 0;
|
||||
margin-left: -$shadow-box-padding;
|
||||
margin-right: -$shadow-box-padding;
|
||||
z-index: 100;
|
||||
z-index: 10;
|
||||
background-color: rgba(white, 0.2);
|
||||
backdrop-filter: blur(2px);
|
||||
border-radius: 0 0 10px 10px;
|
||||
|
@@ -73,12 +73,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
if (this.model.length === 0) {
|
||||
this.addCondition();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getNewGroup() {
|
||||
return {
|
||||
|
@@ -163,6 +163,7 @@ export default {
|
||||
"ZohoCliq": "ZohoCliq",
|
||||
"SevenIO": "SevenIO",
|
||||
"whapi": "WhatsApp (Whapi)",
|
||||
"waha": "WhatsApp (WAHA)",
|
||||
"gtxmessaging": "GtxMessaging",
|
||||
"Cellsynt": "Cellsynt",
|
||||
"SendGrid": "SendGrid"
|
||||
@@ -181,8 +182,10 @@ export default {
|
||||
"SMSManager": "SmsManager (smsmanager.cz)",
|
||||
"WeCom": "WeCom (企业微信群机器人)",
|
||||
"ServerChan": "ServerChan (Server酱)",
|
||||
"PushPlus": "PushPlus (推送加)",
|
||||
"smsc": "SMSC",
|
||||
"WPush": "WPush(wpush.cn)",
|
||||
"YZJ": "YZJ (云之家自定义机器人)"
|
||||
};
|
||||
|
||||
// Sort by notification name
|
||||
|
@@ -197,7 +197,7 @@ export default {
|
||||
return tagOptions;
|
||||
},
|
||||
selectedTags() {
|
||||
return this.preSelectedTags.concat(this.newTags).filter(tag => !this.deleteTags.find(monitorTag => monitorTag.id === tag.id));
|
||||
return this.preSelectedTags.concat(this.newTags).filter(tag => !this.deleteTags.find(monitorTag => monitorTag.tag_id === tag.tag_id));
|
||||
},
|
||||
colorOptions() {
|
||||
return colorOptions(this);
|
||||
|
75
src/components/TemplatedInput.vue
Normal file
75
src/components/TemplatedInput.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="form-text mb-2">
|
||||
<i18n-t tag="div" keypath="liquidIntroduction">
|
||||
<a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a>
|
||||
</i18n-t>
|
||||
|
||||
<code v-pre>{{ msg }}</code>: {{ $t("templateMsg") }}<br />
|
||||
<code v-pre>{{ name }}</code>: {{ $t("templateServiceName") }}<br />
|
||||
<code v-pre>{{ status }}</code>: {{ $t("templateStatus") }}<br />
|
||||
<code v-pre>{{ hostnameOrURL }}</code>: {{ $t("templateHostnameOrURL") }}<br />
|
||||
<code v-pre>{{ heartbeatJSON }}</code>: {{ $t("templateHeartbeatJSON") }} <b>({{ $t("templateLimitedToUpDownNotifications") }})</b><br />
|
||||
<code v-pre>{{ monitorJSON }}</code>: {{ $t("templateMonitorJSON") }} <b>({{ $t("templateLimitedToUpDownCertNotifications") }})</b><br />
|
||||
</div>
|
||||
|
||||
<input
|
||||
:id="id"
|
||||
ref="templatedInput"
|
||||
v-model="model"
|
||||
type="text"
|
||||
class="form-control"
|
||||
:placeholder="placeholder"
|
||||
:required="required"
|
||||
autocomplete="false"
|
||||
>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
/**
|
||||
* The value of the templated input.
|
||||
*/
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* id for the templated input.
|
||||
*/
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
/**
|
||||
* Whether the templated input is required.
|
||||
* @example true
|
||||
*/
|
||||
required: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
/**
|
||||
* Placeholder text for the templated input.
|
||||
*/
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
},
|
||||
emits: [ "update:modelValue" ],
|
||||
computed: {
|
||||
/**
|
||||
* Send value update to parent on change.
|
||||
*/
|
||||
model: {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit("update:modelValue", value);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
80
src/components/TemplatedTextarea.vue
Normal file
80
src/components/TemplatedTextarea.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="form-text mb-2">
|
||||
<i18n-t tag="div" keypath="liquidIntroduction">
|
||||
<a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a>
|
||||
</i18n-t>
|
||||
|
||||
<code v-pre>{{ msg }}</code>: {{ $t("templateMsg") }}<br />
|
||||
<code v-pre>{{ name }}</code>: {{ $t("templateServiceName") }}<br />
|
||||
<code v-pre>{{ status }}</code>: {{ $t("templateStatus") }}<br />
|
||||
<code v-pre>{{ hostnameOrURL }}</code>: {{ $t("templateHostnameOrURL") }}<br />
|
||||
<code v-pre>{{ heartbeatJSON }}</code>: {{ $t("templateHeartbeatJSON") }} <b>({{ $t("templateLimitedToUpDownNotifications") }})</b><br />
|
||||
<code v-pre>{{ monitorJSON }}</code>: {{ $t("templateMonitorJSON") }} <b>({{ $t("templateLimitedToUpDownCertNotifications") }})</b><br />
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
:id="id"
|
||||
ref="templatedTextarea"
|
||||
v-model="model"
|
||||
class="form-control"
|
||||
:placeholder="placeholder"
|
||||
:required="required"
|
||||
autocomplete="false"
|
||||
></textarea>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
/**
|
||||
* The value of the templated textarea.
|
||||
*/
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* id for the templated textarea.
|
||||
*/
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
/**
|
||||
* Whether the templated textarea is required.
|
||||
* @example true
|
||||
*/
|
||||
required: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
/**
|
||||
* Placeholder text for the templated textarea.
|
||||
*/
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
},
|
||||
emits: [ "update:modelValue" ],
|
||||
computed: {
|
||||
/**
|
||||
* Send value update to parent on change.
|
||||
*/
|
||||
model: {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit("update:modelValue", value);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
textarea {
|
||||
min-height: 150px;
|
||||
}
|
||||
</style>
|
19
src/components/notifications/PushPlus.vue
Normal file
19
src/components/notifications/PushPlus.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="pushPlus-sendkey" class="form-label">{{ $t("SendKey") }}</label>
|
||||
<HiddenInput id="pushPlus-sendkey" v-model="$parent.notification.pushPlusSendKey" :required="true" autocomplete="new-password"></HiddenInput>
|
||||
</div>
|
||||
<i18n-t tag="div" keypath="More info on:" class="mb-3 form-text">
|
||||
<a href="https://www.pushplus.plus/" target="_blank">https://www.pushplus.plus/</a>
|
||||
</i18n-t>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
};
|
||||
</script>
|
@@ -67,25 +67,15 @@
|
||||
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
|
||||
</div>
|
||||
|
||||
<p class="form-text">
|
||||
<i18n-t tag="div" keypath="smtpLiquidIntroduction" class="form-text mb-3">
|
||||
<a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a>
|
||||
</i18n-t>
|
||||
<code v-pre>{{name}}</code>: {{ $t("emailTemplateServiceName") }}<br />
|
||||
<code v-pre>{{msg}}</code>: {{ $t("emailTemplateMsg") }}<br />
|
||||
<code v-pre>{{status}}</code>: {{ $t("emailTemplateStatus") }}<br />
|
||||
<code v-pre>{{heartbeatJSON}}</code>: {{ $t("emailTemplateHeartbeatJSON") }}<b>{{ $t("emailTemplateLimitedToUpDownNotification") }}</b><br />
|
||||
<code v-pre>{{monitorJSON}}</code>: {{ $t("emailTemplateMonitorJSON") }} <b>{{ $t("emailTemplateLimitedToUpDownNotification") }}</b><br />
|
||||
<code v-pre>{{hostnameOrURL}}</code>: {{ $t("emailTemplateHostnameOrURL") }}<br />
|
||||
</p>
|
||||
<div class="mb-3">
|
||||
<label for="subject-email" class="form-label">{{ $t("emailCustomSubject") }}</label>
|
||||
<input id="subject-email" v-model="$parent.notification.customSubject" type="text" class="form-control" autocomplete="false" placeholder="">
|
||||
<TemplatedInput id="subject-email" v-model="$parent.notification.customSubject" :required="false" placeholder=""></TemplatedInput>
|
||||
<div class="form-text">{{ $t("leave blank for default subject") }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="body-email" class="form-label">{{ $t("emailCustomBody") }}</label>
|
||||
<textarea id="body-email" v-model="$parent.notification.customBody" type="text" class="form-control" autocomplete="false" placeholder=""></textarea>
|
||||
<TemplatedTextarea id="body-email" v-model="$parent.notification.customBody" :required="false" placeholder=""></TemplatedTextarea>
|
||||
<div class="form-text">{{ $t("leave blank for default body") }}</div>
|
||||
</div>
|
||||
|
||||
@@ -124,11 +114,15 @@
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
import TemplatedInput from "../TemplatedInput.vue";
|
||||
import TemplatedTextarea from "../TemplatedTextarea.vue";
|
||||
import ToggleSection from "../ToggleSection.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
TemplatedInput,
|
||||
TemplatedTextarea,
|
||||
ToggleSection,
|
||||
},
|
||||
computed: {
|
||||
|
@@ -5,20 +5,20 @@
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="sendgrid-from-email" class="form-label">{{ $t("From Email") }}</label>
|
||||
<input id="sendgrid-from-email" v-model="$parent.notification.sendgridFromEmail" type="email" class="form-control" required>
|
||||
<input id="sendgrid-from-email" v-model="$parent.notification.sendgridFromEmail" type="text" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="sendgrid-to-email" class="form-label">{{ $t("To Email") }}</label>
|
||||
<input id="sendgrid-to-email" v-model="$parent.notification.sendgridToEmail" type="email" class="form-control" required>
|
||||
<input id="sendgrid-to-email" v-model="$parent.notification.sendgridToEmail" type="text" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="sendgrid-cc-email" class="form-label">{{ $t("smtpCC") }}</label>
|
||||
<input id="sendgrid-cc-email" v-model="$parent.notification.sendgridCcEmail" type="email" class="form-control">
|
||||
<input id="sendgrid-cc-email" v-model="$parent.notification.sendgridCcEmail" type="text" class="form-control">
|
||||
<div class="form-text">{{ $t("Separate multiple email addresses with commas") }}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="sendgrid-bcc-email" class="form-label">{{ $t("smtpBCC") }}</label>
|
||||
<input id="sendgrid-bcc-email" v-model="$parent.notification.sendgridBccEmail" type="email" class="form-control">
|
||||
<input id="sendgrid-bcc-email" v-model="$parent.notification.sendgridBccEmail" type="text" class="form-control">
|
||||
<small class="form-text text-muted">{{ $t("Separate multiple email addresses with commas") }}</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
|
@@ -4,6 +4,9 @@
|
||||
<input id="slack-webhook-url" v-model="$parent.notification.slackwebhookURL" type="text" class="form-control" required>
|
||||
<label for="slack-username" class="form-label">{{ $t("Username") }}</label>
|
||||
<input id="slack-username" v-model="$parent.notification.slackusername" type="text" class="form-control">
|
||||
<div class="form-text">
|
||||
{{ $t("aboutSlackUsername") }}
|
||||
</div>
|
||||
<label for="slack-iconemo" class="form-label">{{ $t("Icon Emoji") }}</label>
|
||||
<input id="slack-iconemo" v-model="$parent.notification.slackiconemo" type="text" class="form-control">
|
||||
<label for="slack-channel" class="form-label">{{ $t("Channel Name") }}</label>
|
||||
|
@@ -33,6 +33,56 @@
|
||||
<input id="message_thread_id" v-model="$parent.notification.telegramMessageThreadID" type="text" class="form-control">
|
||||
<p class="form-text">{{ $t("telegramMessageThreadIDDescription") }}</p>
|
||||
|
||||
<label for="server_url" class="form-label">{{ $t("telegramServerUrl") }}</label>
|
||||
<input id="server_url" v-model="$parent.notification.telegramServerUrl" type="text" class="form-control">
|
||||
<div class="form-text">
|
||||
<i18n-t keypath="telegramServerUrlDescription">
|
||||
<a
|
||||
href="https://core.telegram.org/bots/api#using-a-local-bot-api-server"
|
||||
target="_blank"
|
||||
>{{ $t("here") }}</a>
|
||||
<a
|
||||
href="https://api.telegram.org"
|
||||
target="_blank"
|
||||
>https://api.telegram.org</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-check form-switch">
|
||||
<input v-model="$parent.notification.telegramUseTemplate" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label">{{ $t("telegramUseTemplate") }}</label>
|
||||
</div>
|
||||
|
||||
<div class="form-text">
|
||||
{{ $t("telegramUseTemplateDescription") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="$parent.notification.telegramUseTemplate">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="message_parse_mode">{{ $t("Message Format") }}</label>
|
||||
<select
|
||||
id="message_parse_mode"
|
||||
v-model="$parent.notification.telegramTemplateParseMode"
|
||||
class="form-select"
|
||||
required
|
||||
>
|
||||
<option value="plain">{{ $t("Plain Text") }}</option>
|
||||
<option value="HTML">HTML</option>
|
||||
<option value="MarkdownV2">MarkdownV2</option>
|
||||
</select>
|
||||
<i18n-t tag="p" keypath="telegramTemplateFormatDescription" class="form-text">
|
||||
<a href="https://core.telegram.org/bots/api#formatting-options" target="_blank">{{ $t("documentation") }}</a>
|
||||
</i18n-t>
|
||||
|
||||
<label class="form-label" for="message_template">{{ $t('Message Template') }}</label>
|
||||
<TemplatedTextarea id="message_template" v-model="$parent.notification.telegramTemplate" :required="true" :placeholder="telegramTemplatedTextareaPlaceholder"></TemplatedTextarea>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-check form-switch">
|
||||
<input v-model="$parent.notification.telegramSendSilently" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label">{{ $t("telegramSendSilently") }}</label>
|
||||
@@ -57,11 +107,27 @@
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
import TemplatedTextarea from "../TemplatedTextarea.vue";
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
TemplatedTextarea,
|
||||
},
|
||||
computed: {
|
||||
telegramTemplatedTextareaPlaceholder() {
|
||||
return this.$t("Example:", [
|
||||
`
|
||||
Uptime Kuma Alert{% if monitorJSON %} - {{ monitorJSON['name'] }}{% endif %}
|
||||
|
||||
{{ msg }}
|
||||
`,
|
||||
]);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$parent.notification.telegramServerUrl ||= "https://api.telegram.org";
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
@@ -80,7 +146,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
return `https://api.telegram.org/bot${token}/getUpdates`;
|
||||
return `${this.$parent.notification.telegramServerUrl}/bot${token}/getUpdates`;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -115,3 +181,9 @@ export default {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
textarea {
|
||||
min-height: 150px;
|
||||
}
|
||||
</style>
|
||||
|
38
src/components/notifications/WAHA.vue
Normal file
38
src/components/notifications/WAHA.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="waha-api-url" class="form-label">{{ $t("API URL") }}</label>
|
||||
<input id="waha-api-url" v-model="$parent.notification.wahaApiUrl" placeholder="http://localhost:3000/" type="url" class="form-control" required>
|
||||
<div class="form-text">{{ $t("wayToGetWahaApiUrl") }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="waha-api-key" class="form-label">{{ $t("API Key") }}</label>
|
||||
<HiddenInput id="waha-api-key" v-model="$parent.notification.wahaApiKey" :required="false" autocomplete="new-password"></HiddenInput>
|
||||
<div class="form-text">{{ $t("wayToGetWahaApiKey") }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="waha-session" class="form-label">{{ $t("wahaSession") }}</label>
|
||||
<input id="waha-session" v-model="$parent.notification.wahaSession" type="text" placeholder="default" class="form-control" required>
|
||||
<div class="form-text">{{ $t("wayToGetWahaSession") }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="waha-chat-id" class="form-label">{{ $t("wahaChatId") }}</label>
|
||||
<input id="waha-chat-id" v-model="$parent.notification.wahaChatId" type="text" pattern="^[\d-]{10,31}$" class="form-control" required>
|
||||
<div class="form-text">{{ $t("wayToWriteWahaChatId", ["00117612345678", "00117612345678@c.us", "123456789012345678@g.us"]) }}</div>
|
||||
</div>
|
||||
|
||||
<i18n-t tag="div" keypath="More info on:" class="mb-3 form-text">
|
||||
<a href="https://waha.devlike.pro/" target="_blank">https://waha.devlike.pro/</a>
|
||||
</i18n-t>
|
||||
</template>
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
}
|
||||
};
|
||||
</script>
|
@@ -32,20 +32,7 @@
|
||||
</template>
|
||||
</i18n-t>
|
||||
<template v-else-if="$parent.notification.webhookContentType == 'custom'">
|
||||
<i18n-t tag="div" keypath="liquidIntroduction" class="form-text">
|
||||
<a href="https://liquidjs.com/" target="_blank">{{ $t("documentation") }}</a>
|
||||
</i18n-t>
|
||||
<code v-pre>{{msg}}</code>: {{ $t("templateMsg") }}<br />
|
||||
<code v-pre>{{heartbeatJSON}}</code>: {{ $t("templateHeartbeatJSON") }} <b>({{ $t("templateLimitedToUpDownNotifications") }})</b><br />
|
||||
<code v-pre>{{monitorJSON}}</code>: {{ $t("templateMonitorJSON") }} <b>({{ $t("templateLimitedToUpDownCertNotifications") }})</b><br />
|
||||
|
||||
<textarea
|
||||
id="customBody"
|
||||
v-model="$parent.notification.webhookCustomBody"
|
||||
class="form-control"
|
||||
:placeholder="customBodyPlaceholder"
|
||||
required
|
||||
></textarea>
|
||||
<TemplatedTextarea id="customBody" v-model="$parent.notification.webhookCustomBody" :required="true" :placeholder="customBodyPlaceholder"></TemplatedTextarea>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -67,7 +54,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TemplatedTextarea from "../TemplatedTextarea.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TemplatedTextarea,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAdditionalHeadersField: this.$parent.notification.webhookAdditionalHeaders != null,
|
||||
|
19
src/components/notifications/YZJ.vue
Normal file
19
src/components/notifications/YZJ.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="yzjWebHookUrl" class="form-label">{{ $t("YZJ Webhook URL") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="yzjWebHookUrl" v-model="$parent.notification.yzjWebHookUrl" type="url" class="form-control" required />
|
||||
<i18n-t class="form-text" keypath="wayToGetTeamsURL">
|
||||
<a href="https://www.yunzhijia.com/opendocs/docs.html#/tutorial/index/robot" target="_blank">{{ $t("here") }}</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="yzjToken" class="form-label">{{ $t("YZJ Robot Token") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<HiddenInput id="yzjToken" v-model="$parent.notification.yzjToken" :required="true" autocomplete="new-password"></HiddenInput>
|
||||
<i18n-t class="form-text" keypath="wayToGetLineNotifyToken">
|
||||
<a href="https://www.yunzhijia.com/opendocs/docs.html#/server-api/im/index?id=%e6%8e%a5%e5%8f%a3%e5%9c%b0%e5%9d%80%e5%92%8c%e6%8e%88%e6%9d%83%e7%a0%81" target="_blank">{{ $t("here") }}</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
</script>
|
@@ -39,6 +39,7 @@ import PromoSMS from "./PromoSMS.vue";
|
||||
import Pushbullet from "./Pushbullet.vue";
|
||||
import PushDeer from "./PushDeer.vue";
|
||||
import Pushover from "./Pushover.vue";
|
||||
import PushPlus from "./PushPlus.vue";
|
||||
import Pushy from "./Pushy.vue";
|
||||
import RocketChat from "./RocketChat.vue";
|
||||
import ServerChan from "./ServerChan.vue";
|
||||
@@ -63,10 +64,12 @@ import ZohoCliq from "./ZohoCliq.vue";
|
||||
import Splunk from "./Splunk.vue";
|
||||
import SevenIO from "./SevenIO.vue";
|
||||
import Whapi from "./Whapi.vue";
|
||||
import WAHA from "./WAHA.vue";
|
||||
import Cellsynt from "./Cellsynt.vue";
|
||||
import WPush from "./WPush.vue";
|
||||
import SIGNL4 from "./SIGNL4.vue";
|
||||
import SendGrid from "./SendGrid.vue";
|
||||
import YZJ from "./YZJ.vue";
|
||||
|
||||
/**
|
||||
* Manage all notification form.
|
||||
@@ -114,6 +117,7 @@ const NotificationFormList = {
|
||||
"PushByTechulus": TechulusPush,
|
||||
"PushDeer": PushDeer,
|
||||
"pushover": Pushover,
|
||||
"PushPlus": PushPlus,
|
||||
"pushy": Pushy,
|
||||
"rocket.chat": RocketChat,
|
||||
"serwersms": SerwerSMS,
|
||||
@@ -138,10 +142,12 @@ const NotificationFormList = {
|
||||
"ZohoCliq": ZohoCliq,
|
||||
"SevenIO": SevenIO,
|
||||
"whapi": Whapi,
|
||||
"waha": WAHA,
|
||||
"gtxmessaging": GtxMessaging,
|
||||
"Cellsynt": Cellsynt,
|
||||
"WPush": WPush,
|
||||
"SendGrid": SendGrid,
|
||||
"YZJ": YZJ,
|
||||
};
|
||||
|
||||
export default NotificationFormList;
|
||||
|
@@ -31,6 +31,7 @@ const languageList = {
|
||||
"sv-SE": "Svenska",
|
||||
"tr-TR": "Türkçe",
|
||||
"ko-KR": "한국어",
|
||||
"lt": "Lietuvių",
|
||||
"ru-RU": "Русский",
|
||||
"zh-CN": "简体中文",
|
||||
"pl": "Polski",
|
||||
|
@@ -733,5 +733,12 @@
|
||||
"Remove the expiry notification": "إزالة تنبيه يوم تاريخ الإنتهاء",
|
||||
"tailscalePingWarning": "من أجل استخدام مراقبة Tailscale Ping، تحتاج إلى تثبيت Uptime Kuma بدون Docker وكذلك تثبيت عميل Tailscale على الخادم الخاص بك.",
|
||||
"Clone Monitor": "نسخ المراقبة",
|
||||
"telegramMessageThreadIDDescription": "معرف فريد اختياري لسلسلة الرسائل المستهدفة (الموضوع) في المنتدى؛ لمجموعات المنتدى الكبرى فقط"
|
||||
"telegramMessageThreadIDDescription": "معرف فريد اختياري لسلسلة الرسائل المستهدفة (الموضوع) في المنتدى؛ لمجموعات المنتدى الكبرى فقط",
|
||||
"emailCustomBody": "نص مخصص",
|
||||
"emailTemplateStatus": "الحالة",
|
||||
"leave blank for default subject": "اترك فارغاً ليتم تعيين الموضوع تلقائياً",
|
||||
"leave blank for default body": "اترك فارغاً ليتم تعيين النص تلقائياً",
|
||||
"emailTemplateServiceName": "اسم الخدمة",
|
||||
"emailTemplateHostnameOrURL": "اسم المضيف أو عنوان URL",
|
||||
"smspartnerPhoneNumber": "رقم الهاتف"
|
||||
}
|
||||
|
@@ -1088,5 +1088,34 @@
|
||||
"From": "От",
|
||||
"Can be found on:": "Можте да се откриете на: {0}",
|
||||
"The phone number of the recipient in E.164 format.": "Телефонният номер на получателя във формат E.164.",
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "Идентификационен номер на подателя на текста или телефонен номер във формат E.164, в случай, че желаете да получавате отговори."
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "Идентификационен номер на подателя на текста или телефонен номер във формат E.164, в случай, че желаете да получавате отговори.",
|
||||
"rabbitmqNodesRequired": "Моля, задайте възлите за този монитор.",
|
||||
"rabbitmqNodesInvalid": "Моля, използвайте пълния URL адрес (започващ с 'http') за RabbitMQ възли.",
|
||||
"RabbitMQ Password": "RabbitMQ парола",
|
||||
"RabbitMQ Username": "RabbitMQ потребител",
|
||||
"SendGrid API Key": "SendGrid API ключ",
|
||||
"Separate multiple email addresses with commas": "Разделяйте отделните имейл адреси със запетаи",
|
||||
"RabbitMQ Nodes": "Възли за управление на RabbitMQ",
|
||||
"rabbitmqNodesDescription": "Въведете URL адреса на възлите за управление на RabbitMQ, включително протокол и порт. Пример: {0}",
|
||||
"rabbitmqHelpText": "За да използвате монитора, ще трябва да активирате добавката за управление във вашата настройка на RabbitMQ. За повече информация моля, вижте {rabitmq_documentation}.",
|
||||
"aboutSlackUsername": "Променя показваното име на подателя на съобщението. Ако желаете да споменете някого, вместо това го включете в приятелското име.",
|
||||
"YZJ Robot Token": "YZJ Robot токен код",
|
||||
"YZJ Webhook URL": "YZJ Уеб кука URL адрес",
|
||||
"templateServiceName": "име на услугата",
|
||||
"templateHostnameOrURL": "име на хоста или URL адрес",
|
||||
"Plain Text": "Обикновен текст",
|
||||
"Message Template": "Шаблон за съобщение",
|
||||
"templateStatus": "статус",
|
||||
"telegramUseTemplate": "Използвай персонализиран шаблон за съобщение",
|
||||
"telegramUseTemplateDescription": "Ако е активирано, съобщението ще бъде изпратено чрез персонализиран шаблон.",
|
||||
"telegramTemplateFormatDescription": "Telegram позволява използването на различни \"markup\" езици за съобщенията. Вижте Telegram {0} за детайли.",
|
||||
"Template Format": "Формат на шаблона",
|
||||
"wayToGetWahaApiUrl": "Вашият WAHA URL адрес.",
|
||||
"wahaSession": "Сесия",
|
||||
"wahaChatId": "Чат ID (телефонен номер / ID на контакт / ID на група)",
|
||||
"wayToGetWahaApiKey": "API ключът, е стойността на променливата WHATSAPP_API_KEY, която сте използвали за стартиране на WAHA.",
|
||||
"wayToWriteWahaChatId": "Телефонният номер с международния префикс, но без знака плюс в началото ({0}), ID на контакта ({1}) или ID на групата ({2}). Известията се изпращат до това чат ID от WAHA сесия.",
|
||||
"wayToGetWahaSession": "От тази сесия WAHA изпраща известия до чат ID. Можете да го намерите в таблото за управление на WAHA.",
|
||||
"telegramServerUrlDescription": "За премахване на API бот ограниченията за Telegram или за получаване на достъп в блокирани зони (Китай, Иран и др.). За повече информация щракнете върху {0}. По подразбиране: {1}",
|
||||
"telegramServerUrl": "(По избор) URL адрес на сървъра"
|
||||
}
|
||||
|
219
src/lang/bn.json
219
src/lang/bn.json
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"setupDatabaseChooseDatabase": "আপনি কোন ডাটাবেজটি ব্যবহার করতে চান?",
|
||||
"setupDatabaseEmbeddedMariaDB": "আপনাকে কিছু নিযুক্ত করতে হবে না। এই ডকার ইমেজটি (Docker image) স্বয়ংক্রিয়ভাবে আপনার জন্য মারিয়া ডিবি (MariaDB) বসিয়েছে এবং প্রস্তুত করেছে।Uptime Kuma ইউনিক্স সকেটের (Unix Socket) মাধ্যমে এই ডাটাবেসের সাথে সংযুক্ত হবে।",
|
||||
"setupDatabaseMariaDB": "একটি বহিরাগত মারিয়া ডিবি (MariaDB) ডাটাবেসের সাথে সংযোগ করুন। আপনাকে ডাটাবেস সংযোগ তথ্য নিযুক্ত করতে হবে।",
|
||||
"setupDatabaseEmbeddedMariaDB": "আপনাকে কিছু সেটআপ করার প্রয়োজন নেই। এই ডকার ইমেজে স্বয়ংক্রিয়ভাবে MariaDB এম্বেড এবং কনফিগার করা হয়েছে। Uptime Kuma এই ডাটাবেজের সাথে ইউনিক্স সকেটের মাধ্যমে সংযুক্ত হবে।",
|
||||
"setupDatabaseMariaDB": "বহিরাগত MariaDB ডাটাবেজের সাথে সংযোগ করতে হবে। আপনাকে ডাটাবেজের সংযোগ তথ্য সেট করতে হবে।",
|
||||
"Add": "সংযোগ করুন",
|
||||
"dbName": "ডাটাবেজের নাম",
|
||||
"languageName": "ইংরেজি",
|
||||
"languageName": "বাংলা",
|
||||
"Settings": "সেটিংস",
|
||||
"Dashboard": "ড্যাশবোর্ড",
|
||||
"Help": "সাহায্য",
|
||||
@@ -14,5 +14,216 @@
|
||||
"Check Update On GitHub": "GitHub-এ আপডেট চেক করুন",
|
||||
"List": "তালিকা",
|
||||
"General": "সাধারণ",
|
||||
"Game": "খেলা"
|
||||
"Game": "খেলা",
|
||||
"disable authentication": "প্রমাণীকরণ বন্ধ করুন",
|
||||
"pauseDashboardHome": "থামুন",
|
||||
"disableauth.message2": "এটি Uptime Kuma এর সামনে {intendThirdPartyAuth} এর মতো পরিস্থিতির জন্য ডিজাইন করা হয়েছে, যেমন Cloudflare Access, Authelia অথবা অন্যান্য প্রমাণীকরণ ব্যবস্থা।",
|
||||
"I understand, please disable": "আমি বুঝতে পারছি, দয়া করে অক্ষম করুন",
|
||||
"Certificate Info": "সার্টিফিকেট তথ্য",
|
||||
"Create your admin account": "আপনার অ্যাডমিন অ্যাকাউন্ট তৈরি করুন",
|
||||
"Import": "ইমপোর্ট",
|
||||
"Default enabled": "ডিফল্ট সক্রিয়",
|
||||
"Heartbeats": "হার্টবিট",
|
||||
"Affected Monitors": "প্রভাবিত মনিটরগুলো",
|
||||
"All Status Pages": "সমস্ত স্ট্যাটাস পেজ",
|
||||
"alertNoFile": "অনুগ্রহ করে আমদানির জন্য একটি ফাইল নির্বাচন করুন।",
|
||||
"alertWrongFileType": "অনুগ্রহ করে একটি JSON ফাইল নির্বাচন করুন।",
|
||||
"Clear all statistics": "সব পরিসংখ্যান মুছে ফেলুন",
|
||||
"Setup 2FA": "2FA সেট আপ করুন",
|
||||
"Two Factor Authentication": "দুই ফ্যাক্টর প্রমাণীকরণ",
|
||||
"Add New Tag": "নতুন ট্যাগ যোগ করুন",
|
||||
"Tag with this name already exist.": "এই নামের ট্যাগ আগে থেকেই আছে।",
|
||||
"Pink": "গোলাপী",
|
||||
"Search monitored sites": "পর্যবেক্ষণ করা সাইট অনুসন্ধান",
|
||||
"statusPageNothing": "এখানে কিছুই নেই, অনুগ্রহ করে একটি গ্রুপ বা মনিটর যোগ করুন।",
|
||||
"Degraded Service": "অধঃপতন সেবা",
|
||||
"Go to Dashboard": "ড্যাশবোর্ডে যান",
|
||||
"defaultNotificationName": "আমার {বিজ্ঞপ্তি} সতর্কতা ({number})",
|
||||
"webhookJsonDesc": "{0} যেকোনো আধুনিক HTTP সার্ভার যেমন Express.js-এর জন্য ভালো",
|
||||
"liquidIntroduction": "টেম্পলেটবিলিটি লিকুইড টেমপ্লেটিং ভাষার মাধ্যমে অর্জন করা হয়। ব্যবহারের নির্দেশাবলীর জন্য অনুগ্রহ করে {0} দেখুন। এই উপলব্ধ ভেরিয়েবল হল:",
|
||||
"Notifications": "নোটিফিকেশন",
|
||||
"Setup Notification": "নোটিফিকেশন সেটআপ করুন",
|
||||
"Light": "আলো",
|
||||
"Auto": "স্বয়ংক্রিয়",
|
||||
"Theme - Heartbeat Bar": "থিম - হার্টবিট বার",
|
||||
"styleElapsedTime": "হার্টবিট বারের নিচে ব্যবহৃত সময়",
|
||||
"styleElapsedTimeShowNoLine": "শোর করুন (কোনো লাইন নেই)",
|
||||
"styleElapsedTimeShowWithLine": "শো করুন (লাইন সহ)",
|
||||
"Normal": "স্বাভাবিক",
|
||||
"Bottom": "নীচে",
|
||||
"Timezone": "টাইমজোন",
|
||||
"Search Engine Visibility": "সার্চ ইঞ্জিন দৃশ্যমানতা",
|
||||
"Allow indexing": "ইন্ডেক্সিং অনুমোদন করুন",
|
||||
"Discourage search engines from indexing site": "সার্চ ইঞ্জিনগুলোকে সাইটের ইন্ডেক্সিং থেকে বিরত রাখুন",
|
||||
"Change Password": "পাসওয়ার্ড পরিবর্তন করুন",
|
||||
"Current Password": "বর্তমান পাসওয়ার্ড",
|
||||
"New Password": "নতুন পাসওয়ার্ড",
|
||||
"Repeat New Password": "নতুন পাসওয়ার্ডটি আবার দিন",
|
||||
"Update Password": "পাসওয়ার্ড আপডেট করুন",
|
||||
"Enable Auth": "প্রমাণীকরণ চালু করুন",
|
||||
"disableauth.message1": "আপনি কি সত্যিই {disableAuth} করতে চান?",
|
||||
"where you intend to implement third-party authentication": "যেখানে আপনি তৃতীয় পক্ষের প্রমাণীকরণ বাস্তবায়ন করতে চান",
|
||||
"Please use this option carefully!": "দয়া করে এই অপশনটি সাবধানে ব্যবহার করুন!",
|
||||
"Logout": "লগ আউট",
|
||||
"Leave": "লিভ",
|
||||
"Confirm": "নিশ্চিত",
|
||||
"Yes": "হ্যাঁ",
|
||||
"No": "না",
|
||||
"Username": "ইউজার নেম",
|
||||
"Password": "পাসওয়ার্ড",
|
||||
"Remember me": "আমাকে মনে রাখুন",
|
||||
"Login": "লগ ইন",
|
||||
"add one": "একটি যোগ করুন",
|
||||
"Notification Type": "নোটিফিকেশনের ধরন",
|
||||
"Email": "ইমেইল",
|
||||
"Test": "পরীক্ষা",
|
||||
"Resolver Server": "সমাধানকারী সার্ভার",
|
||||
"Resource Record Type": "রিসোর্স রেকর্ড টাইপ",
|
||||
"Last Result": "শেষ ফলাফল",
|
||||
"Repeat Password": "পাসওয়ার্ড পুনরায় দিন",
|
||||
"Import Backup": "ইমপোর্ট ব্যাকআপ",
|
||||
"Export Backup": "এক্সপোর্ট ব্যাকআপ",
|
||||
"Export": "এক্সপোর্ট",
|
||||
"respTime": "প্রতিক্রিয়া সময় (ms)",
|
||||
"notAvailableShort": "প্রযোজ্য নয়",
|
||||
"Apply on all existing monitors": "সমস্ত বিদ্যমান মনিটরে প্রয়োগ করুন",
|
||||
"Create": "তৈরি",
|
||||
"Clear Data": "ডেটা সাফ",
|
||||
"Events": "ইভেন্ট সমূহ",
|
||||
"Auto Get": "অটো গ্রহণ",
|
||||
"Schedule maintenance": "রক্ষণাবেক্ষণ সূচী করুন",
|
||||
"Pick Affected Monitors...": "প্রভাবিত মনিটর নির্বাচন করুন…",
|
||||
"Start of maintenance": "রক্ষণাবেক্ষণের শুরু",
|
||||
"Select status pages...": "স্ট্যাটাস পেজগুলো নির্বাচন করুন…",
|
||||
"Skip existing": "বিদ্যমান এড়িয়ে যান",
|
||||
"Overwrite": "ওভাররাইট",
|
||||
"Options": "অপশন",
|
||||
"Keep both": "দুটোই রাখুন",
|
||||
"Verify Token": "টোকেন যাচাই করুন",
|
||||
"Enable 2FA": "2FA সক্ষম করুন",
|
||||
"Disable 2FA": "2FA নিষ্ক্রিয় করুন",
|
||||
"2FA Settings": "2FA সেটিংস",
|
||||
"filterActive": "সক্রিয়",
|
||||
"filterActivePaused": "বিরতি",
|
||||
"Active": "সক্রিয়",
|
||||
"Inactive": "নিষ্ক্রিয়",
|
||||
"Token": "টোকেন",
|
||||
"Show URI": "URI দেখান",
|
||||
"Tags": "ট্যাগ",
|
||||
"Add New below or Select...": "নীচে নতুন যোগ করুন বা নির্বাচন করুন…",
|
||||
"Tag with this value already exist.": "এই মান সহ ট্যাগ ইতিমধ্যেই বিদ্যমান।",
|
||||
"color": "রং",
|
||||
"value (optional)": "মান (ঐচ্ছিক)",
|
||||
"Red": "লাল",
|
||||
"Orange": "কমলা",
|
||||
"Green": "সবুজ",
|
||||
"Blue": "নীল",
|
||||
"Indigo": "নীল",
|
||||
"Purple": "বেগুনি",
|
||||
"Custom": "কাস্টম",
|
||||
"Search...": "অনুসন্ধান…",
|
||||
"Avg. Ping": "গড় পিং",
|
||||
"Avg. Response": "গড় প্রতিক্রিয়া",
|
||||
"Entry Page": "প্রবেশ পৃষ্ঠা",
|
||||
"statusPageRefreshIn": "রিফ্রেশ হবে: {0}",
|
||||
"No Services": "কোনো পরিষেবা নেই",
|
||||
"All Systems Operational": "সমস্ত সিস্টেম অপারেশনাল",
|
||||
"Partially Degraded Service": "আংশিকভাবে অবনমিত পরিষেবা",
|
||||
"Add Group": "গ্রুপ যোগ করুন",
|
||||
"Add a monitor": "একটি মনিটর যোগ করুন",
|
||||
"Edit Status Page": "এডিট স্টেটাস পেজ",
|
||||
"Status Page": "স্ট্যাটাস পেজ",
|
||||
"Status Pages": "স্ট্যাটাস পেজ সমূহ",
|
||||
"here": "এখানে",
|
||||
"Required": "প্রয়োজন",
|
||||
"Post URL": "পোস্ট URL",
|
||||
"Content Type": "বিষয়বস্তুর প্রকার",
|
||||
"webhookFormDataDesc": "{multipart} PHP এর জন্য ভালো। JSON-কে {decodeFunction} দিয়ে পার্স করতে হবে",
|
||||
"templateMsg": "বিজ্ঞপ্তির বার্তা",
|
||||
"templateHeartbeatJSON": "হৃদস্পন্দন বর্ণনাকারী বস্তু",
|
||||
"templateMonitorJSON": "মনিটরের বর্ণনাকারী বস্তু",
|
||||
"templateLimitedToUpDownNotifications": "শুধুমাত্র UP/DOWN বিজ্ঞপ্তির জন্য উপলব্ধ",
|
||||
"Gray": "ধূসর",
|
||||
"Add New Monitor": "নতুন আপটাইম মনিটর যোগ করুন",
|
||||
"statusMaintenance": "রক্ষণাবেক্ষণ",
|
||||
"Friendly Name": "বন্ধুত্বপূর্ণ নাম",
|
||||
"URL": "ইউআরএল",
|
||||
"settingUpDatabaseMSG": "ডাটাবেস সেটআপ করা হচ্ছে। এটি কিছুটা সময় নিতে পারে, অনুগ্রহ করে ধৈর্য ধরুন।",
|
||||
"Response": "রেসপন্স",
|
||||
"Ping": "পিং",
|
||||
"Keyword": "কীওয়ার্ড",
|
||||
"Invert Keyword": "ইনভার্ট কীওয়ার্ড",
|
||||
"setupDatabaseSQLite": "একটি সাধারণ ডাটাবেস ফাইল, যা ছোট পরিসরের ডিপ্লয়মেন্টের জন্য সুপারিশ করা হয়। v2.0.0 এর পূর্বে, Uptime Kuma ডিফল্ট ডাটাবেস হিসেবে SQLite ব্যবহার করত।",
|
||||
"Unknown": "অজানা",
|
||||
"Cannot connect to the socket server": "সকেট সার্ভারের সাথে সংযোগ স্থাপন করা যাচ্ছে না",
|
||||
"Reconnecting...": "পুনরায় সংযোগ স্থাপন করা হচ্ছে...",
|
||||
"Passive Monitor Type": "নিষ্ক্রিয় মনিটরের ধরন",
|
||||
"markdownSupported": "মার্কডাউন সিনট্যাক্স সাপোর্ট",
|
||||
"Pause": "থামুন",
|
||||
"-day": "-দিন",
|
||||
"hour": "ঘন্টা",
|
||||
"Host URL": "হোস্ট ইউআরএল",
|
||||
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "আপনি যে সার্ভারে সংযোগ করতে চান তার হোস্টনেম প্রবেশ করুন অথবা যদি আপনি একটি {local_mta} ব্যবহার করার পরিকল্পনা করেন, তাহলে {localhost} লিখুন",
|
||||
"ignoreTLSErrorGeneral": "সংযোগের জন্য TLS/SSL ত্রুটি উপেক্ষা করুন",
|
||||
"Upside Down Mode": "আপসাইড ডাউন মোড",
|
||||
"Pending": "প্রক্রিয়াধীন",
|
||||
"Push URL": "পুশ URL",
|
||||
"needPushEvery": "আপনাকে এই URL টি প্রতি {0} সেকেন্ডে কল করতে হবে।",
|
||||
"Dark": "অন্ধকার",
|
||||
"Up": "আপ",
|
||||
"webhookAdditionalHeadersTitle": "অতিরিক্ত শিরোনাম",
|
||||
"pushOthers": "অন্যান্য",
|
||||
"programmingLanguages": "প্রোগ্রামিং ভাষাসমূহ",
|
||||
"Not available, please setup.": "উপলব্ধ নয়, অনুগ্রহ করে সেটআপ করুন।",
|
||||
"Down": "ডাউন",
|
||||
"Monitor Type": "মনিটরের ধরন",
|
||||
"Expected Value": "প্রত্যাশিত মান",
|
||||
"Home": "হোম",
|
||||
"Maintenance": "রক্ষণাবেক্ষণ",
|
||||
"General Monitor Type": "সাধারণ মনিটরের ধরন",
|
||||
"Specific Monitor Type": "নির্দিষ্ট মনিটরের ধরন",
|
||||
"Monitor": "মনিটর | মনিটরগুলো",
|
||||
"day": "দিন | দিনগুলো",
|
||||
"-hour": "-ঘন্টা",
|
||||
"Hostname": "হোস্টনেম",
|
||||
"locally configured mail transfer agent": "লোকালি কনফিগারড মেইল ট্রান্সফার এজেন্ট",
|
||||
"Port": "পোর্ট",
|
||||
"Heartbeat Interval": "হার্টবিট ইন্টারভাল",
|
||||
"Max. Redirects": "সর্বোচ্চ রিডাইরেক্ট",
|
||||
"Primary Base URL": "প্রাথমিক বেস URL",
|
||||
"Message": "বার্তা",
|
||||
"Resume": "পুনরায় শুরু",
|
||||
"Delete": "মুছে ফেলুন",
|
||||
"now": "এখন",
|
||||
"time ago": "{০} বয়স",
|
||||
"-year": "-বছর",
|
||||
"Json Query Expression": "JSON কোয়েরি এক্সপ্রেশন",
|
||||
"timeoutAfter": "{0} সেকেন্ড পর টাইমআউট",
|
||||
"Retries": "পুনরায় চেষ্টা করে",
|
||||
"checkEverySecond": "প্রতিটি {0} সেকেন্ডে চেক করুন",
|
||||
"retryCheckEverySecond": "প্রতিটি {0} সেকেন্ডে পুনরায় চেষ্টা করুন",
|
||||
"resendEveryXTimes": "প্রতিটি {0} বার পুনরায় পাঠান",
|
||||
"pushOptionalParams": "ঐচ্ছিক প্যারামিটারসমূহ: {0}",
|
||||
"Save": "সংরক্ষণ",
|
||||
"ignoredTLSError": "TLS/SSL ত্রুটিগুলি উপেক্ষা করা হয়েছে",
|
||||
"Accepted Status Codes": "গ্রহণযোগ্য স্ট্যাটাস কোডসমূহ",
|
||||
"Disable Auth": "প্রমাণীকরণ বন্ধ করুন",
|
||||
"Theme": "থিম",
|
||||
"Name": "নাম",
|
||||
"Status": "অবস্থা",
|
||||
"DateTime": "তারিখ ও সময়",
|
||||
"No important events": "কোনো গুরুত্বপূর্ণ ইভেন্ট নেই",
|
||||
"Edit": "সম্পাদনা",
|
||||
"Current": "বর্তমান",
|
||||
"Uptime": "আপটাইম",
|
||||
"Request Timeout": "রিকোয়েস্ট টাইমআউট",
|
||||
"Heartbeat Retry Interval": "হার্টবিট রিট্রাই ইন্টারভাল",
|
||||
"Advanced": "অ্যাডভান্স",
|
||||
"retriesDescription": "সার্ভিসটি ডাউন হিসেবে চিহ্নিত হওয়ার আগে এবং একটি নোটিফিকেশন পাঠানোর জন্য সর্বোচ্চ পুনরায় চেষ্টা করার সংখ্যা",
|
||||
"upsideDownModeDescription": "স্ট্যাটাসটি উল্টো করে দিন। যদি সার্ভিসটি পৌঁছানো যায়, তবে এটি DOWN হবে।",
|
||||
"maxRedirectDescription": "অনুসরণ করার জন্য সর্বোচ্চ রিডাইরেক্ট সংখ্যা। রিডাইরেক্ট নিষ্ক্রিয় করতে 0 সেট করুন।",
|
||||
"ignoreTLSError": "HTTPS ওয়েবসাইটগুলির জন্য TLS/SSL ত্রুটিগুলি উপেক্ষা করুন",
|
||||
"pushViewCode": "পুশ মনিটর কীভাবে ব্যবহার করবেন? (কোড দেখুন)",
|
||||
"Appearance": "দেখানোর ধরন",
|
||||
"Quick Stats": "তাৎক্ষণিক পরিসংখ্যান"
|
||||
}
|
||||
|
353
src/lang/ca.json
353
src/lang/ca.json
@@ -49,7 +49,7 @@
|
||||
"Delete": "Eliminar",
|
||||
"Current": "Actual",
|
||||
"Uptime": "Temps actiu",
|
||||
"Cert Exp.": "Caducitat del certificat",
|
||||
"Cert Exp.": "Caducitat del certificat.",
|
||||
"Monitor": "Monitor | Monitors",
|
||||
"day": "dia | dies",
|
||||
"-day": "-dia",
|
||||
@@ -65,7 +65,7 @@
|
||||
"URL": "URL",
|
||||
"Hostname": "Nom del servidor",
|
||||
"Port": "Port",
|
||||
"timeoutAfter": "¡Timeout' després de {0",
|
||||
"timeoutAfter": "¡Timeout' després de {0} segons",
|
||||
"locally configured mail transfer agent": "Agent de transferència de correu configurat localment",
|
||||
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Introduïu el nom del servidor al qual voleu connectar-vos o {localhost} si voleu utilitzar un {local_mta}",
|
||||
"Host URL": "URL del servidor",
|
||||
@@ -213,5 +213,352 @@
|
||||
"Email": "Correu",
|
||||
"Last Result": "Darrer Resultat",
|
||||
"Add New Tag": "Afegir nova etiqueta",
|
||||
"Tag with this value already exist.": "Ja existeix una etiqueta amb aquest valor."
|
||||
"Tag with this value already exist.": "Ja existeix una etiqueta amb aquest valor.",
|
||||
"defaultNotificationName": "La meva {notification} Alerta ({number})",
|
||||
"Required": "Obligatori",
|
||||
"Post URL": "Posar URL",
|
||||
"Content Type": "Content Type",
|
||||
"Json Query Expression": "Expressió de consulta Json",
|
||||
"now": "ara",
|
||||
"-year": "-any",
|
||||
"Status Pages": "Pàgines d'estat",
|
||||
"here": "aquí",
|
||||
"time ago": "fa {0}",
|
||||
"ignoredTLSError": "Errors TLS/SSL ignorats",
|
||||
"webhookFormDataDesc": "{multipart} es bo per PHP. El JSON haurà d'analitzar-se amb {decodeFunction}",
|
||||
"webhookJsonDesc": "{0} es bo per qualsevol servidor HTTP modern com Express.js",
|
||||
"templateMsg": "missatge de la notificació",
|
||||
"webhookAdditionalHeadersTitle": "Capçaleres addicionals",
|
||||
"Application Token": "Testimoni d'aplicació",
|
||||
"Server URL": "URL del servidor",
|
||||
"Priority": "Prioritat",
|
||||
"Webhook URL": "URL del Webhook",
|
||||
"emojiCheatSheet": "Full de trampa d'emoji: {0}",
|
||||
"Read more": "Llegeix més",
|
||||
"appriseInstalled": "S'ha instal·lat l'apèndix.",
|
||||
"templateHeartbeatJSON": "objecte que descriu el batec del cor",
|
||||
"templateMonitorJSON": "objecte que descriu el monitor",
|
||||
"templateLimitedToUpDownCertNotifications": "només disponible per a notificacions de venciment UP/DOWN/Certificate",
|
||||
"templateLimitedToUpDownNotifications": "només disponible per a notificacions UP/DOWN",
|
||||
"webhookAdditionalHeadersDesc": "Estableix les capçaleres addicionals enviades amb el webhook. Cada capçalera s'ha de definir com una clau/valor JSON.",
|
||||
"webhookBodyPresetOption": "Predefinit - {0}",
|
||||
"webhookBodyCustomOption": "Cos personalitzat",
|
||||
"Headers": "Capçaleres",
|
||||
"Monitor History": "Historial del monitor",
|
||||
"PasswordsDoNotMatch": "Les contrasenyes no coincideixen.",
|
||||
"records": "registres",
|
||||
"One record": "Un registre",
|
||||
"Current User": "Usuari actual",
|
||||
"topic": "Tema",
|
||||
"topicExplanation": "tema MQTT a monitorar",
|
||||
"successKeyword": "Paraula clau d'èxit",
|
||||
"successKeywordExplanation": "Paraula clau MQTT que es considerarà un èxit",
|
||||
"recent": "Recent",
|
||||
"Reset Token": "Restableix el testimoni",
|
||||
"Done": "Fet",
|
||||
"Info": "Info",
|
||||
"Steam API Key": "Clau API de Steam",
|
||||
"Shrink Database": "Redueix la base de dades",
|
||||
"Pick a RR-Type...": "Trieu un tipus RR…",
|
||||
"Default": "Per defecte",
|
||||
"HTTP Options": "Opcions HTTP",
|
||||
"Create Incident": "Crear Incident",
|
||||
"Title": "Títol",
|
||||
"Content": "Contingut",
|
||||
"Style": "Estil",
|
||||
"info": "info",
|
||||
"warning": "avís",
|
||||
"danger": "perill",
|
||||
"primary": "primària",
|
||||
"light": "lleuger",
|
||||
"dark": "fosc",
|
||||
"Post": "Post",
|
||||
"Created": "Creat",
|
||||
"Last Updated": "Darrera actualització",
|
||||
"Switch to Light Theme": "Canvia a tema clar",
|
||||
"Switch to Dark Theme": "Canviar a tema fosc",
|
||||
"Show Tags": "Mostra les etiquetes",
|
||||
"Hide Tags": "Amaga les etiquetes",
|
||||
"Description": "Descripció",
|
||||
"No monitors available.": "No hi ha monitors disponibles.",
|
||||
"Add one": "Afegeix-ne un",
|
||||
"No Monitors": "Sense monitors",
|
||||
"Untitled Group": "Grup sense títol",
|
||||
"Services": "Serveis",
|
||||
"Discard": "Descarta",
|
||||
"Cancel": "Canel·la",
|
||||
"Select": "Selecciona",
|
||||
"Check/Uncheck": "Comprova/desmarca",
|
||||
"Powered by": "Funciona amb",
|
||||
"Customize": "Personalitza",
|
||||
"Custom Footer": "Peu de pàgina personalitzat",
|
||||
"Custom CSS": "CSS personalitzat",
|
||||
"default": "Per defecte",
|
||||
"enabled": "Habilitat",
|
||||
"setAsDefault": "Estableix com a predeterminat",
|
||||
"deleteProxyMsg": "Esteu segur que voleu suprimir aquest servidor intermediari per a tots els monitors?",
|
||||
"setAsDefaultProxyDescription": "Aquest servidor intermediari s'habilitarà de manera predeterminada per als monitors nous. Encara podeu desactivar el servidor intermediari per separat per a cada monitor.",
|
||||
"Certificate Chain": "Cadena de certificats",
|
||||
"Valid": "Vàlid",
|
||||
"Invalid": "Invàlid",
|
||||
"User": "Usuari",
|
||||
"Installed": "Instal·lat",
|
||||
"Not installed": "No instal·lat",
|
||||
"Running": "En execució",
|
||||
"Not running": "No en execució",
|
||||
"Remove Token": "Elimina el testimoni",
|
||||
"Start": "Inicia",
|
||||
"Stop": "Aturar",
|
||||
"Add New Status Page": "Afegeix una pàgina d'estat nova",
|
||||
"Slug": "Àlies",
|
||||
"Accept characters:": "Accepta caràcters:",
|
||||
"startOrEndWithOnly": "Inicia o acaba només amb {0}",
|
||||
"No consecutive dashes": "Sense guions consecutius",
|
||||
"Next": "Següent",
|
||||
"The slug is already taken. Please choose another slug.": "L'àlias ja està agafat. Si us plau, escolliu un altre àlies.",
|
||||
"No Proxy": "Sense servidor intermediari",
|
||||
"Proxies": "Servidors intermediaris",
|
||||
"HTTP Basic Auth": "Autenticació bàsica HTTP",
|
||||
"New Status Page": "Pàgina d'estat nova",
|
||||
"Reverse Proxy": "Servidor intermediari invertit",
|
||||
"Backup": "Còpia de seguretat",
|
||||
"About": "Quant a",
|
||||
"wayToGetCloudflaredURL": "(Descarrega de cloudfared des de {0})",
|
||||
"cloudflareWebsite": "Lloc web de Cloudflare",
|
||||
"Message:": "Missatge:",
|
||||
"HTTP Headers": "Capçaleres HTTP",
|
||||
"Trust Proxy": "Confia en el servidor intermediari",
|
||||
"Other Software": "Un altre programari",
|
||||
"For example: nginx, Apache and Traefik.": "Per exemple: nginx, Apache i Traefik.",
|
||||
"Please read": "Llegiu",
|
||||
"Subject:": "Assumpte:",
|
||||
"Valid To:": "Vàlid per a:",
|
||||
"Days Remaining:": "Dies restants:",
|
||||
"Issuer:": "Emissor:",
|
||||
"Fingerprint:": "Empremta digital:",
|
||||
"No status pages": "Sense pàgines d'estat",
|
||||
"Domain Name Expiry Notification": "Notificació de venciment del nom de domini",
|
||||
"Add a new expiry notification day": "Notificació de venciment del nom de domini",
|
||||
"Remove the expiry notification": "Elimina el dia de notificació de venciment",
|
||||
"Proxy": "Servidor intermediari",
|
||||
"Date Created": "Data de creació",
|
||||
"Footer Text": "Text del peu de pàgina",
|
||||
"Refresh Interval Description": "La pàgina d'estat farà una actualització completa del lloc cada {0} segons",
|
||||
"Show Powered By": "Mostra Impulsat per",
|
||||
"Domain Names": "Noms de domini",
|
||||
"signedInDisp": "Sessió iniciada com a {0}",
|
||||
"RadiusSecret": "Secret de Radius",
|
||||
"RadiusSecretDescription": "Secret compartit entre client i servidor",
|
||||
"RadiusCalledStationId": "Id de l'estació cridada",
|
||||
"RadiusCallingStationId": "Id de l'estació de trucada",
|
||||
"RadiusCallingStationIdDescription": "Identificador del dispositiu de crida",
|
||||
"Certificate Expiry Notification": "Notificació de venciment del certificat",
|
||||
"API Username": "Nom d'usuari API",
|
||||
"API Key": "Clau API",
|
||||
"Show update if available": "Mostra l'actualització si està disponible",
|
||||
"Using a Reverse Proxy?": "Usar un servidor intermediari invers?",
|
||||
"Check how to config it for WebSocket": "Comprova com configurar-lo per a WebSocket",
|
||||
"Steam Game Server": "Servidor de jocs Steam",
|
||||
"Most likely causes:": "Causes més probables:",
|
||||
"There might be a typing error in the address.": "Pot haver-hi un error d'escriptura a l'adreça.",
|
||||
"What you can try:": "Què podeu provar:",
|
||||
"Retype the address.": "Torneu a teclejar l'adreça.",
|
||||
"Go back to the previous page.": "Torna a la pàgina anterior.",
|
||||
"Coming Soon": "Properament",
|
||||
"Connection String": "Cadena de connexió",
|
||||
"Query": "Consulta",
|
||||
"settingsCertificateExpiry": "Caducitat del certificat TLS",
|
||||
"Setup Docker Host": "Configura l'amfitrió Docker",
|
||||
"Connection Type": "Tipus de connexió",
|
||||
"Docker Daemon": "Dimoni Docker",
|
||||
"noDockerHostMsg": "No disponible. Primer configureu un amfitrió Docker.",
|
||||
"DockerHostRequired": "Establiu l'amfitrió Docker per a aquest monitor.",
|
||||
"socket": "Sòcol",
|
||||
"tcp": "TCP / HTTP",
|
||||
"Docker Container": "Contenidor Docker",
|
||||
"Container Name / ID": "Nom del contenidor / ID",
|
||||
"Docker Host": "Amfitrió Docker",
|
||||
"Docker Hosts": "Amfitrions Docker",
|
||||
"Domain": "Domini",
|
||||
"Workstation": "Estació de treball",
|
||||
"Packet Size": "Mida del paquet",
|
||||
"Bot Token": "Testimoni de bot",
|
||||
"wayToGetTelegramToken": "Podeu obtenir un testimoni de {0}.",
|
||||
"Chat ID": "ID de xat",
|
||||
"telegramMessageThreadID": "(Opcional) ID del fil del missatge",
|
||||
"telegramMessageThreadIDDescription": "Identificador únic opcional per al fil del missatge de destinació (tema) del fòrum; només per als supergrups del fòrum",
|
||||
"telegramSendSilently": "Envia silenciosament",
|
||||
"telegramProtectContent": "Protegeix la reenviament/desament",
|
||||
"supportTelegramChatID": "Admet xat directe / grup / ID de xat del canal",
|
||||
"YOUR BOT TOKEN HERE": "EL VOSTRE TESTIMONI DE BOT AQUÍ",
|
||||
"chatIDNotFound": "No s'ha trobat l'ID del xat; primer envieu un missatge a aquest bot",
|
||||
"disableCloudflaredNoAuthMsg": "Esteu en mode No Auth, no cal una contrasenya.",
|
||||
"wayToGetLineNotifyToken": "Podeu obtenir un testimoni d'accés des de {0}",
|
||||
"Examples": "Exemples",
|
||||
"Home Assistant URL": "URL de l'assistent d'inici",
|
||||
"Long-Lived Access Token": "Testimoni d'accés viu",
|
||||
"Notification Service": "Servei de notificacions",
|
||||
"Automations can optionally be triggered in Home Assistant:": "Les automatitzacions es poden activar opcionalment a l'assistent d'inici:",
|
||||
"Trigger type:": "Tipus d'activador:",
|
||||
"Event type:": "Tipus d'esdeveniment:",
|
||||
"Event data:": "Dades de l'esdeveniment:",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "A continuació, trieu una acció, per exemple, canvieu l'escena a on una llum RGB és vermella.",
|
||||
"Frontend Version": "Versió del frontal",
|
||||
"Frontend Version do not match backend version!": "La versió frontal no coincideix amb la versió del dorsal!",
|
||||
"backupRecommend": "Si us plau, feu una còpia de seguretat del volum o de la carpeta de dades (./data/) directament.",
|
||||
"Optional": "Opcional",
|
||||
"and": "i",
|
||||
"startDateTime": "Data/hora d'inici",
|
||||
"endDateTime": "Data/hora final",
|
||||
"cronExpression": "Expressió Cron",
|
||||
"cronSchedule": "Planificació: ",
|
||||
"invalidCronExpression": "Expressió Cron no vàlida: {0}",
|
||||
"recurringInterval": "Interval",
|
||||
"Recurring": "Recurrència",
|
||||
"strategyManual": "Activa/Inactiva manualment",
|
||||
"warningTimezone": "Està utilitzant la zona horària del servidor",
|
||||
"weekdayShortMon": "Dill",
|
||||
"weekdayShortTue": "Dim",
|
||||
"weekdayShortWed": "Dim",
|
||||
"weekdayShortThu": "Dij",
|
||||
"weekdayShortFri": "Div",
|
||||
"weekdayShortSat": "Diss",
|
||||
"weekdayShortSun": "Dg",
|
||||
"dayOfWeek": "Dia de la setmana",
|
||||
"dayOfMonth": "Dia del mes",
|
||||
"lastDay": "Últim dia",
|
||||
"lastDay2": "2n últim dia del mes",
|
||||
"lastDay3": "3r Darrer Dia del Mes",
|
||||
"lastDay4": "4t Darrer Dia del Mes",
|
||||
"No Maintenance": "Sense manteniment",
|
||||
"maintenanceStatus-under-maintenance": "Sota manteniment",
|
||||
"maintenanceStatus-inactive": "Inactiu",
|
||||
"maintenanceStatus-scheduled": "Programat",
|
||||
"maintenanceStatus-unknown": "Desconegut",
|
||||
"Server Timezone": "Zona horària del servidor",
|
||||
"statusPageMaintenanceEndDate": "Final",
|
||||
"IconUrl": "URL de la icona",
|
||||
"Enable DNS Cache": "(Obsolet) Habilita la memòria cau DNS per als monitors HTTP(s)",
|
||||
"Enable": "Habilita",
|
||||
"Disable": "Desactiva",
|
||||
"chromeExecutable": "Executable Chrome/Chromium",
|
||||
"chromeExecutableAutoDetect": "Detecció automàtica",
|
||||
"dnsCacheDescription": "Pot ser que no funcioni treballant amb entorns IPv6, desactiva'l si detectes qualsevol problema.",
|
||||
"Single Maintenance Window": "Finestra de Manteniment únic",
|
||||
"Maintenance Time Window of a Day": "Finestra de Temps del manteniment d'un Dia",
|
||||
"Effective Date Range": "Rang de data eficaç (Opcional)",
|
||||
"Schedule Maintenance": "Programa de manteniment",
|
||||
"Edit Maintenance": "Edita el manteniment",
|
||||
"Date and Time": "Data i hora",
|
||||
"DateTime Range": "Rang de data i temps",
|
||||
"loadingError": "Impossible obtenir la data, si us plau prova-ho més endavant.",
|
||||
"plugin": "Connector | Connectors",
|
||||
"install": "Instal·la",
|
||||
"installing": "Instal·lant",
|
||||
"uninstall": "Desinstal·la",
|
||||
"confirmUninstallPlugin": "Estàs segur de desinstal·lar aquest connector?",
|
||||
"notificationRegional": "Regional",
|
||||
"Clone Monitor": "Clona el monitor",
|
||||
"Clone": "Clona",
|
||||
"cloneOf": "Clon de {0}",
|
||||
"secureOptionNone": "Cap / STARTTLS (25, 587)",
|
||||
"secureOptionTLS": "TLS (465)",
|
||||
"Ignore TLS Error": "Ignora error TLS",
|
||||
"From Email": "Des de Correu",
|
||||
"emailCustomisableContent": "Contingut personalitzable",
|
||||
"emailCustomSubject": "Tema personalitzable",
|
||||
"leave blank for default subject": "deixar en blanc per tema per defecte",
|
||||
"emailCustomBody": "Cos personalitzat",
|
||||
"leave blank for default body": "deixa en blanc per un cos per defecte",
|
||||
"emailTemplateServiceName": "Nom de servei",
|
||||
"emailTemplateHostnameOrURL": "Nom de host o URL",
|
||||
"emailTemplateStatus": "Estat",
|
||||
"emailTemplateMonitorJSON": "objecte que descriu el monitor",
|
||||
"emailTemplateHeartbeatJSON": "objecte que descriu el batec del cor",
|
||||
"To Email": "Destí email",
|
||||
"smtpCC": "CC",
|
||||
"smtpBCC": "BCC",
|
||||
"Discord Webhook URL": "Discord Webhook URL",
|
||||
"wayToGetDiscordURL": "Pots rebre aquest per anar a Paràmetres de Servidor -> Integracions -> Vista *Webhooks -> Nou *Webhook",
|
||||
"Bot Display Name": "Nom de pantalla de bot",
|
||||
"Prefix Custom Message": "Prefix de missatge personalitzat",
|
||||
"Hello @everyone is...": "Hola {'@'} a tothom …",
|
||||
"Send to channel": "Envia al canal",
|
||||
"Create new forum post": "Crea una nova publicació",
|
||||
"postToExistingThread": "Publica a un fil existent",
|
||||
"forumPostName": "Nom de publicació de fòrum",
|
||||
"threadForumPostID": "Fil / identificador de fòrum",
|
||||
"e.g. {discordThreadID}": "exemple {discordThreadID}",
|
||||
"wayToGetTeamsURL": "Pot aprendre com crear una URL de webhook {0}.",
|
||||
"wayToGetZohoCliqURL": "Pot aprendre com crear una URL de webhook {0}.",
|
||||
"needSignalAPI": "Necessites tenir una senyal de client amb REST API.",
|
||||
"wayToCheckSignalURL": "Pot comprovar aquesta URL per veure com configurar:",
|
||||
"Number": "Número",
|
||||
"Recipients": "Receptors",
|
||||
"Access Token": "Fitxa d'accés",
|
||||
"Channel access token (Long-lived)": "Fitxa d'accés del canal (de llarga vida)",
|
||||
"Line Developers Console": "Consola de Desenvolupadors de la línia",
|
||||
"appriseNotInstalled": "L'apèndix no està instal·lat. {0}",
|
||||
"Method": "Mètode",
|
||||
"clearDataOlderThan": "Conserva les dades de l'historial del monitor durant {0} dies.",
|
||||
"steamApiKeyDescription": "Per a monitoritzar un servidor de jocs de vapor, necessiteu una clau Steam Web-API. Podeu registrar la vostra clau API aquí: ",
|
||||
"shrinkDatabaseDescriptionSqlite": "Activa la base de dades {vacuum} per a SQLite. {auto.vacuum} ja està activat, però això no desfragmenta la base de dades ni reempaqueta les pàgines individuals de la base de dades de la manera com ho fa l'ordre {vacuum}.",
|
||||
"liquidIntroduction": "S'aconsegueix la flexibilitat mitjançant el llenguatge de templatació líquid. Consulteu el {0} per a les instruccions d'ús. Aquestes són les variables disponibles:",
|
||||
"selectedMonitorCount": "Seleccionat: {0}",
|
||||
"deleteStatusPageMsg": "Esteu segur que voleu suprimir aquesta pàgina d'estat?",
|
||||
"proxyDescription": "Els intermediaris s'han d'assignar a un monitor perquè funcioni.",
|
||||
"enableProxyDescription": "Aquest servidor intermediari no afectarà les sol·licituds del monitor fins que estigui activat. Podeu controlar temporalment desactivar el servidor intermediari de tots els monitors per l'estat d'activació.",
|
||||
"statusPageSpecialSlugDesc": "Àlies especial {0}: aquesta pàgina es mostrarà quan no es proporcioni l'àlies",
|
||||
"Authentication": "Autenticació",
|
||||
"Page Not Found": "Pàgina no trobada",
|
||||
"Don't know how to get the token? Please read the guide:": "No saps com aconseguir el testimoni? Si us plau, llegiu la guia:",
|
||||
"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.": "La connexió actual es pot perdre si esteu connectant a través del túnel Cloudflare. Segur que voleu aturar-ho? Escriviu la contrasenya actual per confirmar-la.",
|
||||
"Refresh Interval": "Interval de refresc",
|
||||
"signedInDispDisabled": "Autenticació desactivada.",
|
||||
"RadiusCalledStationIdDescription": "Identificador del dispositiu anomenat",
|
||||
"Also check beta release": "Comprova també la versió beta",
|
||||
"The resource is no longer available.": "El recurs ja no està disponible.",
|
||||
"certificationExpiryDescription": "Els monitors HTTPS activen la notificació quan el certificat TLS caduca a:",
|
||||
"deleteDockerHostMsg": "Esteu segur que voleu suprimir aquest amfitrió de l'acoblador per a tots els monitors?",
|
||||
"tailscalePingWarning": "Per utilitzar el monitor de Ping Tailscale, heu d'instal·lar el Kuma Uptime sense Docker i també instal·lar el client Tailscale al vostre servidor.",
|
||||
"telegramSendSilentlyDescription": "Envia el missatge en silenci. Els usuaris rebran una notificació sense so.",
|
||||
"telegramProtectContentDescription": "Si està activat, els missatges del bot del Telegram estaran protegits contra reenviaments i desaments.",
|
||||
"wayToGetTelegramChatID": "Podeu obtenir el vostre ID de xat enviant un missatge al bot i anant a aquest URL per veure el xat id:",
|
||||
"trustProxyDescription": "Confia en les capçaleres «X-Forwarded-*». Si voleu obtenir la IP del client correcta i el vostre Kuma Uptime està darrere d'un servidor intermediari com Nginx o Apache, hauríeu d'activar-ho.",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Es pot crear un testimoni d'accés de llarga durada fent clic al nom del vostre perfil (a baix a l'esquerra) i desplaçant-vos a la part inferior i després feu clic a Crea un testimoni. ",
|
||||
"default: notify all devices": "per defecte: notifica tots els dispositius",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Podeu trobar una llista dels Serveis de Notificació a l'assistent d'inici a «Eines de revelador . Serveis» cerca «notificació» per trobar el nom del vostre dispositiu/telèfon.",
|
||||
"backupOutdatedWarning": "Obsolet: Atès que s'han afegit moltes característiques i aquesta funció de còpia de seguretat és una mica inexistent, no pot generar o restaurar una còpia de seguretat completa.",
|
||||
"lastDay1": "L'últim dia del mes",
|
||||
"pauseMaintenanceMsg": "Segur que voleu fer una pausa?",
|
||||
"maintenanceStatus-ended": "Finalitzat",
|
||||
"Display Timezone": "Mostra la zona horària",
|
||||
"enableNSCD": "Habilita NSCD (Dimoni de memòria cau de Servei del Nom ) per accelerar les sol·licituds de DNS",
|
||||
"chromeExecutableDescription": "Per a usuaris de Docker, si el Chrome no està encara instal·lat, pot dur uns quants minuts per instal·lar i mostrar el resultat de prova. Duu 1*GB d'espai de disc.",
|
||||
"uninstalling": "Desinstal·lant",
|
||||
"smtp": "Correu electrònic (SMTP)",
|
||||
"smtpLiquidIntroduction": "Els següents dos camps són personalitzables via \"Liquid templating Language\". Per favor refereix al {0} per a instruccions d'ús. Aquests són les variables disponibles:",
|
||||
"emailTemplateMsg": "missatge de la notificació",
|
||||
"emailTemplateLimitedToUpDownNotification": "només disponible per estats UP/Down, altrament null",
|
||||
"Select message type": "Selecciona el tipus de missatge",
|
||||
"whatHappensAtForumPost": "Crea una nova publicació de fòrum. Això no publica un missatge a un fòrum existent. Per publicar un fil existent utilitza \"{option}\"",
|
||||
"Channel access token": "Fitxa d'accés del canal",
|
||||
"Body": "Cos",
|
||||
"or": "o",
|
||||
"PushUrl": "URL de captura",
|
||||
"HeadersInvalidFormat": "Les capçaleres de sol·licitud no són JSON vàlides: ",
|
||||
"BodyInvalidFormat": "El cos de petició no és JSON vàlid: ",
|
||||
"Security": "Seguretat",
|
||||
"Pick Accepted Status Codes...": "Trieu els codis d'estat acceptats…",
|
||||
"error": "error",
|
||||
"critical": "crítica",
|
||||
"Please input title and content": "Introduïu el títol i el contingut",
|
||||
"telegramServerUrl": "(Opcional) Url del servidor",
|
||||
"telegramServerUrlDescription": "Per saltar-se les limitacions del bot de Telegram o tenir accés a regions bloquejades (China, Iran, etc). Per a més informació fes click {0}. Per defecte {1}",
|
||||
"templateServiceName": "Nom del servei",
|
||||
"templateHostnameOrURL": "Adreça URL o nom del host",
|
||||
"templateStatus": "Estat",
|
||||
"telegramUseTemplate": "Fes servir una plantilla de missatge personalitzada",
|
||||
"telegramUseTemplateDescription": "Si s'activa, el missatge s'enviarà fent servir una plantilla personalitzada.",
|
||||
"telegramTemplateFormatDescription": "Telegram permet l'ús de diferents tipus de llenguatges de marcat, llegeix Telegram {0} per més detalls."
|
||||
}
|
||||
|
@@ -802,8 +802,8 @@
|
||||
"Json Query": "Json dotaz",
|
||||
"Badge Duration (in hours)": "Zobrazení odznaku (v hodinách)",
|
||||
"Badge Preview": "Náhled odznaku",
|
||||
"Notify Channel": "Kanál nofitikací",
|
||||
"aboutNotifyChannel": "Upozornění kanálu spustí upozornění na počítači nebo v mobilu pro všechny členy kanálu, ať už jsou dostupní nebo ne.",
|
||||
"Notify Channel": "Upozornit kanál",
|
||||
"aboutNotifyChannel": "Upozornění na kanál spustí upozornění na počítači nebo v mobilním telefonu pro všechny členy kanálu, ať už je jejich dostupnost nastavena na aktivní nebo na nepřítomnost.",
|
||||
"filterActive": "Aktivní",
|
||||
"filterActivePaused": "Pozastaveno",
|
||||
"Enter the list of brokers": "Vytvořte seznam zprostředkovatelů",
|
||||
@@ -1051,5 +1051,45 @@
|
||||
"Client ID": "ID klienta",
|
||||
"Client Secret": "Tajemství klienta",
|
||||
"OAuth Scope": "OAuth rozsah",
|
||||
"Optional: Space separated list of scopes": "Volitelné: seznam rozsahů oddělte mezerami"
|
||||
"Optional: Space separated list of scopes": "Volitelné: seznam rozsahů oddělte mezerami",
|
||||
"Debug": "Ladění",
|
||||
"CopyToClipboardError": "Nelze zkopírovat do schránky: {error}",
|
||||
"ignoredTLSError": "Chyby TLS/SSL byly ignorovány",
|
||||
"Copy": "Kopírovat",
|
||||
"aboutSlackUsername": "Mění zobrazované jméno odesílatele zprávy. Pokud někoho chcete zmínit, použijte raději pole obecný název.",
|
||||
"Message format": "Formát zprávy",
|
||||
"Notification Channel": "Kanál notifikací",
|
||||
"Alphanumerical string and hyphens only": "Pouze alfanumerické řetězce a pomlčky",
|
||||
"Sound": "Zvuk",
|
||||
"Custom sound to override default notification sound": "Použít vlastní zvuk místo výchozího zvuku upozornění",
|
||||
"Correct": "Správně",
|
||||
"Fail": "Chyba",
|
||||
"Reveal": "Odhalení",
|
||||
"Doorbell": "Zvonek",
|
||||
"Flute": "Flétna",
|
||||
"Money": "Peníze",
|
||||
"Elevator": "Výtah",
|
||||
"Guitar": "Kytara",
|
||||
"Time Sensitive (iOS Only)": "Časově kritické (pouze pro iOS)",
|
||||
"Time sensitive notifications will be delivered immediately, even if the device is in do not disturb mode.": "Časově kritická upozornění budou doručena okamžitě, i když je zařízení v režimu nerušit.",
|
||||
"From": "Od",
|
||||
"Can be found on:": "Lze nalézt na: {0}",
|
||||
"The phone number of the recipient in E.164 format.": "Telefonní číslo příjemce ve formátu E.164 (+420...).",
|
||||
"RabbitMQ Nodes": "RabbitMQ uzly pro správu",
|
||||
"rabbitmqNodesDescription": "URL RabbitMQ uzlů pro správu zadávejte včetně protokolu a portu. Příklad: {0}",
|
||||
"rabbitmqNodesRequired": "Prosím, definujte uzly pro tento dohled.",
|
||||
"rabbitmqNodesInvalid": "Prosím, použijte plně kvalifikované URL (začínající na 'http)' RabbitMQ uzlů.",
|
||||
"RabbitMQ Username": "RabbitMQ uživatelské jméno",
|
||||
"Send rich messages": "Poslat rozsáhlé zprávy",
|
||||
"Arcade": "Arkáda",
|
||||
"Harp": "Harfa",
|
||||
"Bubble": "Bublinky",
|
||||
"Scifi": "Scifi",
|
||||
"Pop": "Prasknutí",
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "Pro zajištění příjmu odpovědí zadejte ID odesílatele textu nebo telefonní číslo ve formátu E.164.",
|
||||
"RabbitMQ Password": "RabbitMQ heslo",
|
||||
"rabbitmqHelpText": "Abyste mohli používat tento monitor, musíte v nastavení RabbitMQ povolit modul pro správu. Další informace naleznete na adrese {rabitmq_documentation}.",
|
||||
"SendGrid API Key": "SendGrid API klíč",
|
||||
"Separate multiple email addresses with commas": "Více e-mailových adres oddělte čárkami",
|
||||
"Clear": "Odstranění"
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@
|
||||
"Port": "Port",
|
||||
"Heartbeat Interval": "Hjerteslag interval",
|
||||
"Retries": "Gentagelser",
|
||||
"retriesDescription": "Maksimalt antal gentagelser, før tjenesten markeres som inaktiv og sender en meddelelse.",
|
||||
"retriesDescription": "Maksimalt antal gentagelser, før tjenesten markeres som inaktiv og sender en meddelelse",
|
||||
"Advanced": "Avanceret",
|
||||
"ignoreTLSError": "Ignorér TLS/SSL fejl for HTTPS websteder",
|
||||
"Upside Down Mode": "Omvendt tilstand",
|
||||
@@ -99,7 +99,7 @@
|
||||
"deleteNotificationMsg": "Er du sikker på, at du vil slette denne underretning for alle overvågere?",
|
||||
"resolverserverDescription": "Cloudflare er standardserveren, den kan til enhver tid ændres.",
|
||||
"Resolver Server": "Navne-server",
|
||||
"rrtypeDescription": "Vælg den type RR, du vil overvåge.",
|
||||
"rrtypeDescription": "Vælg den type RR, du vil overvåge",
|
||||
"Last Result": "Seneste resultat",
|
||||
"pauseMonitorMsg": "Er du sikker på at du vil standse overvågningen?",
|
||||
"Create your admin account": "Opret din administratorkonto",
|
||||
@@ -125,7 +125,7 @@
|
||||
"backupDescription3": "Følsom data, f.eks. underretnings-tokener, er inkluderet i eksportfilen. Gem den sikkert.",
|
||||
"alertNoFile": "Vælg en fil der skal importeres.",
|
||||
"alertWrongFileType": "Vælg venligst en JSON-fil.",
|
||||
"twoFAVerifyLabel": "Indtast venligst dit token for at bekræfte, at 2FA fungerer",
|
||||
"twoFAVerifyLabel": "Indtast venligst dit token for at bekræfte, at 2FA fungerer:",
|
||||
"tokenValidSettingsMsg": "Token er gyldigt! Du kan nu gemme 2FA -indstillingerne.",
|
||||
"confirmEnableTwoFAMsg": "Er du sikker på at du vil aktivere 2FA?",
|
||||
"confirmDisableTwoFAMsg": "Er du sikker på at du vil deaktivere 2FA?",
|
||||
@@ -141,7 +141,7 @@
|
||||
"Token": "Token",
|
||||
"Show URI": "Vis URI",
|
||||
"Clear all statistics": "Ryd alle Statistikker",
|
||||
"retryCheckEverySecond": "Prøv igen hvert {0} sekund.",
|
||||
"retryCheckEverySecond": "Prøv igen hvert {0} sekund",
|
||||
"importHandleDescription": "Vælg 'Spring over eksisterende', hvis du vil springe over hver overvåger eller underretning med samme navn. 'Overskriv' sletter alle eksisterende overvågere og underretninger.",
|
||||
"confirmImportMsg": "Er du sikker på at importere sikkerhedskopien? Sørg for, at du har valgt den rigtige importindstilling.",
|
||||
"Heartbeat Retry Interval": "Hjerteslag gentagelsesinterval",
|
||||
@@ -277,7 +277,7 @@
|
||||
"lineDevConsoleTo": "Line Udviklerkonsol - {0}",
|
||||
"Basic Settings": "Basisindstillinger",
|
||||
"User ID": "Bruger-ID",
|
||||
"Messaging API": "Messaging API",
|
||||
"Messaging API": "Besked API",
|
||||
"wayToGetLineChannelToken": "Tilgå først {0}, opret en udbyder og kanal (Messaging API), så kan du få kanaladgangstoken'et og bruger-ID'et fra de ovennævnte menupunkter.",
|
||||
"Icon URL": "Ikon URL",
|
||||
"aboutIconURL": "Du kan angive et link til et billede i \"Ikon URL\" for at tilsidesætte standardprofilbilledet. Vil ikke blive brugt, hvis Ikon Emoji er angivet.",
|
||||
@@ -415,7 +415,7 @@
|
||||
"signedInDisp": "Logget ind som {0}",
|
||||
"Certificate Expiry Notification": "Meddelelse om udløbsdato for certifikatet",
|
||||
"API Username": "API Brugernavn",
|
||||
"API Key": "API Key",
|
||||
"API Key": "API Nøgle",
|
||||
"Steam Game Server": "Steam Game Server",
|
||||
"What you can try:": "Hvad du kan prøve:",
|
||||
"Go back to the previous page.": "Gå tilbage til forrige side.",
|
||||
@@ -621,11 +621,11 @@
|
||||
"confirmDeleteTagMsg": "Er du sikker på at du vil slette denne etiket? Overvågninger med denne etiket vil ikke blive slettet.",
|
||||
"resendEveryXTimes": "Gensend hver {0} gang",
|
||||
"resendDisabled": "Gensendelse deaktiveret",
|
||||
"Reconnecting...": "Genforbinder...",
|
||||
"Reconnecting...": "Genopretter forbindelse...",
|
||||
"successPaused": "Standset med succes.",
|
||||
"Reset Token": "Nulstil nøgle",
|
||||
"Show Clickable Link": "Vis klikbart link",
|
||||
"atLeastOneMonitor": "Vælg mindst én berørt overvågning.",
|
||||
"atLeastOneMonitor": "Vælg mindst én berørt overvågning",
|
||||
"authInvalidToken": "Ugyldig nøgle.",
|
||||
"authIncorrectCreds": "Brugernavn eller adgangskode er ikke korrekt.",
|
||||
"2faAlreadyEnabled": "2FA er allerede aktiveret.",
|
||||
@@ -656,5 +656,147 @@
|
||||
"telegramSendSilentlyDescription": "Send beskeden lydløst. Brugerne vil modtage en notifikation uden lyd.",
|
||||
"pushoverMessageTtl": "Message TTL (Sekunder)",
|
||||
"setupDatabaseEmbeddedMariaDB": "Du skal ikke opsætte noget. Docker billedet har integreret og konfigureret MariaDB automatisk. Uptime Kuma vil forbinde til databasen vha. en Unix socket.",
|
||||
"setupDatabaseMariaDB": "Oprette forbindelse til en ekstern MariaDB database. Du skal indstille databasens forbindelsesinformation."
|
||||
"setupDatabaseMariaDB": "Oprette forbindelse til en ekstern MariaDB database. Du skal indstille databasens forbindelsesinformation.",
|
||||
"styleElapsedTimeShowWithLine": "Vis (med linjer)",
|
||||
"styleElapsedTime": "Forløbet tid under heartbeat-bjælken",
|
||||
"templateMsg": "besked fra notifikationen",
|
||||
"templateHeartbeatJSON": "objekt, der beskriver heartbeat",
|
||||
"templateMonitorJSON": "objekt, der beskriver monitoren",
|
||||
"templateLimitedToUpDownNotifications": "kun tilgængelig for UP/DOWN notifikationer",
|
||||
"webhookAdditionalHeadersTitle": "Yderligere Headers",
|
||||
"webhookAdditionalHeadersDesc": "Angiver yderligere headers, der sendes med webhooken. Hver header skal defineres som en JSON-nøgle/værdi.",
|
||||
"webhookBodyCustomOption": "Brugerdefineret Body",
|
||||
"successKeyword": "Succesnøgleord",
|
||||
"startOrEndWithOnly": "Kun start eller slut med {0}",
|
||||
"setAsDefaultProxyDescription": "Denne proxy vil som standard være aktiveret for nye monitorer. Du kan stadig deaktivere proxyen individuelt for hver monitor.",
|
||||
"No consecutive dashes": "Ingen på hinanden følgende bindestreger",
|
||||
"statusPageSpecialSlugDesc": "Speciel slug {0}: Denne side vises, når der ikke angives en slug",
|
||||
"Query": "Kø",
|
||||
"Add a new expiry notification day": "Tilføj en ny udløbsnotifikationsdag",
|
||||
"Remove the expiry notification": "Fjern udløbsnotifikationsdagen",
|
||||
"Refresh Interval": "Opdateringsinterval",
|
||||
"Refresh Interval Description": "Statussiden vil udføre en fuld opdatering af sitet hvert {0} sekunder",
|
||||
"RadiusSecret": "Radius-hemmelighed",
|
||||
"RadiusCalledStationId": "Called Station ID",
|
||||
"RadiusCalledStationIdDescription": "Identifikator for den kaldte enhed",
|
||||
"RadiusCallingStationId": "Calling Station Id",
|
||||
"RadiusCallingStationIdDescription": "Identifikator for den kaldende enhed",
|
||||
"Check how to config it for WebSocket": "Tjek, hvordan det konfigureres til WebSocket",
|
||||
"Connection String": "Forbindelsesstreng",
|
||||
"Workstation": "Arbejdsstation",
|
||||
"telegramMessageThreadID": "(Valgfrit) Beskedtråd-ID",
|
||||
"telegramMessageThreadIDDescription": "Valgfri unik identifikator for målbeskedtråden (emnet) i forummet; kun for forum-supergrupper",
|
||||
"telegramProtectContent": "Beskyt videresendelse/gemning",
|
||||
"telegramProtectContentDescription": "Hvis aktiveret, vil bot-beskeder i Telegram være beskyttet mod videresendelse og gemning.",
|
||||
"disableCloudflaredNoAuthMsg": "Du er i No Auth-tilstand, en adgangskode er ikke påkrævet.",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "En liste over notifikationstjenester kan findes i Home Assistant under “Developer Tools > Services”. Søg efter “notification” for at finde navnet på din enhed/telefon.",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "Vælg derefter en handling, for eksempel at skifte scenen til en, hvor et RGB-lys er rødt.",
|
||||
"backupRecommend": "Sikkerhedskopier venligst volumen eller data-mappen (./data/) direkte i stedet.",
|
||||
"and": "og",
|
||||
"startDateTime": "Startdato/-tidspunkt",
|
||||
"endDateTime": "Slutdato/-tidspunkt",
|
||||
"cronExpression": "Cron-udtryk",
|
||||
"cronSchedule": "Tidsplan: ",
|
||||
"warningTimezone": "Den bruger serverens tidszone",
|
||||
"enableNSCD": "Aktivér NSCD (Name Service Cache Daemon) for at cache alle DNS-forespørgsler",
|
||||
"chromeExecutable": "Chrome/Chromium-eksekverbar fil",
|
||||
"Single Maintenance Window": "Enkelt vedligeholdelsesvindue",
|
||||
"Edit Maintenance": "Rediger vedligeholdelse",
|
||||
"emailCustomisableContent": "Brugerdefinerbart indhold",
|
||||
"leave blank for default subject": "lad stå tomt for standardemne",
|
||||
"emailCustomBody": "Brugerdefineret body",
|
||||
"leave blank for default body": "lad stå tomt for standard-body",
|
||||
"emailTemplateServiceName": "Servicenavn",
|
||||
"emailTemplateHostnameOrURL": "Værtsnavn eller URL",
|
||||
"emailTemplateStatus": "Status",
|
||||
"emailTemplateMonitorJSON": "objekt, der beskriver monitoren",
|
||||
"emailTemplateHeartbeatJSON": "objekt, der beskriver heartbeat",
|
||||
"emailTemplateMsg": "besked fra notifikationen",
|
||||
"emailTemplateLimitedToUpDownNotification": "kun tilgængelig for UP/DOWN heartbeats, ellers null",
|
||||
"Select message type": "Vælg beskedtype",
|
||||
"Send to channel": "Send til kanal",
|
||||
"Create new forum post": "Opret nyt forumpost",
|
||||
"postToExistingThread": "Send til eksisterende tråd / forumpost",
|
||||
"forumPostName": "Forumpost-navn",
|
||||
"threadForumPostID": "Tråd- / Forumpost-ID",
|
||||
"e.g. {discordThreadID}": "f.eks. {discordThreadID}",
|
||||
"wayToGetDiscordThreadId": "At hente en tråd- / forumpost-ID ligner processen for at hente en kanal-ID. Læs mere om, hvordan du får IDs {0}",
|
||||
"Channel access token (Long-lived)": "Kanaladgangstoken (langvarig)",
|
||||
"Your User ID": "Din bruger-ID",
|
||||
"dataRetentionTimeError": "Opbevaringsperioden skal være 0 eller højere",
|
||||
"infiniteRetention": "Sæt til 0 for uendelig opbevaring.",
|
||||
"enableGRPCTls": "Tillad afsendelse af gRPC-forespørgsel med TLS-forbindelse",
|
||||
"affectedStatusPages": "Vis denne vedligeholdelsesbesked på udvalgte statussider",
|
||||
"invertKeywordDescription": "Se efter, at nøgleordet mangler i stedet for at være til stede.",
|
||||
"octopushAPIKey": "“API-nøgle” fra HTTP API-legitimationsoplysninger i kontrolpanelet",
|
||||
"octopushLogin": "“Login” fra HTTP API-legitimationsoplysninger i kontrolpanelet",
|
||||
"pushoversounds pushover": "Pushover (standard)",
|
||||
"pushoversounds bike": "Cykel",
|
||||
"pushoversounds bugle": "Signalhorn",
|
||||
"pushoversounds cashregister": "Kasseapparat",
|
||||
"pushoversounds cosmic": "Kosmisk",
|
||||
"pushoversounds falling": "Faldende",
|
||||
"pushoversounds gamelan": "Gamelan",
|
||||
"pushoversounds incoming": "Indkommende",
|
||||
"pushoversounds intermission": "Pause",
|
||||
"pushoversounds spacealarm": "Rumalarm",
|
||||
"pushoversounds tugboat": "Slæbebåd",
|
||||
"pushoversounds climb": "Klatring (lang)",
|
||||
"pushoversounds persistent": "Vedvarende (lang)",
|
||||
"pushoversounds echo": "Pushover Echo (lang)",
|
||||
"pushoversounds updown": "Op Ned (lang)",
|
||||
"GoogleChat": "Google Chat (kun Google Workspace)",
|
||||
"styleElapsedTimeShowNoLine": "Vis (ingen linjer)",
|
||||
"Slug": "Slug",
|
||||
"The slug is already taken. Please choose another slug.": "Denne slug er allerede i brug. Vælg venligst en anden.",
|
||||
"There might be a typing error in the address.": "Der er muligvis en stavfejl i adressen.",
|
||||
"Long-Lived Access Token": "Long-Lived Access Token",
|
||||
"Search monitored sites": "Søg overvågede sites",
|
||||
"liquidIntroduction": "Templatability opnås via Liquid-templeringssproget. Se venligst {0} for brugsanvisninger. Her er de tilgængelige variabler:",
|
||||
"templateLimitedToUpDownCertNotifications": "kun tilgængelig for UP/DOWN/Certifikatudløb notifikationer",
|
||||
"shrinkDatabaseDescriptionSqlite": "Udløs database-{vacuum} for SQLite. {auto_vacuum} er allerede aktiveret, men dette defragmenterer ikke databasen eller ompakker de enkelte database-sider på samme måde som {vacuum}-kommandoen gør.",
|
||||
"Check/Uncheck": "Markér/Afjern markering",
|
||||
"enableProxyDescription": "Denne proxy vil ikke påvirke monitor-forespørgsler, før den er aktiveret. Du kan midlertidigt deaktivere proxyen for alle monitorer via aktiveringsstatus.",
|
||||
"RadiusSecretDescription": "Delt hemmelighed mellem klient og server",
|
||||
"noDockerHostMsg": "Ikke tilgængelig. Opsæt en Docker-host først.",
|
||||
"DockerHostRequired": "Angiv venligst Docker-hosten for denne monitor.",
|
||||
"tailscalePingWarning": "For at bruge Tailscale Ping-monitoren skal du installere Uptime Kuma uden Docker og også installere Tailscale-klienten på din server.",
|
||||
"trustProxyDescription": "Tillid til ‘X-Forwarded-*’ headers. Hvis du vil hente den korrekte klient-IP, og din Uptime Kuma er bag en proxy såsom Nginx eller Apache, bør du aktivere dette.",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "En langvarig adgangstoken kan oprettes ved at klikke på dit profilnavn (nederst til venstre), rulle ned til bunden og derefter klikke på “Opret token”. ",
|
||||
"backupOutdatedWarning": "Forældet: Da mange funktioner er blevet tilføjet, og denne backup-funktion er lidt vedligeholdelsesfri, kan den ikke generere eller gendanne en komplet backup.",
|
||||
"invalidCronExpression": "Ugyldigt Cron-udtryk: {0}",
|
||||
"chromeExecutableDescription": "For Docker-brugere: Hvis Chromium endnu ikke er installeret, kan det tage et par minutter at installere og vise testresultatet. Det kræver 1 GB diskplads.",
|
||||
"Effective Date Range": "Gyldig datointerval (Valgfrit)",
|
||||
"DateTime Range": "Dato-/tidsinterval",
|
||||
"notificationRegional": "Regional",
|
||||
"smtpLiquidIntroduction": "De følgende to felter kan tilpasses via Liquid-templateringssproget. Se venligst {0} for brugsanvisninger. Her er de tilgængelige variabler:",
|
||||
"whatHappensAtForumPost": "Opret en ny forumpost. Dette sender IKKE beskeder i en eksisterende post. For at sende i en eksisterende post, brug ”{option}”",
|
||||
"grpcMethodDescription": "Metodenavnet konverteres til camelCase-format, såsom sayHello, check osv.",
|
||||
"affectedMonitorsDescription": "Vælg de monitorer, der er påvirket af den aktuelle vedligeholdelse",
|
||||
"jsonQueryDescription": "Parse og udtræk specifikke data fra serverens JSON-svar ved hjælp af en JSON-forespørgsel, eller brug ”$” for det rå svar, hvis JSON ikke forventes. Resultatet sammenlignes derefter med den forventede værdi som strenge. Se {0} for dokumentation, og brug {1} til at eksperimentere med forespørgsler.",
|
||||
"pushoversounds classical": "Klassisk",
|
||||
"pushoversounds pianobar": "Piano Bar",
|
||||
"wayToGetKookBotToken": "Opret en applikation og få din bot-token på {0}",
|
||||
"wayToGetKookGuildID": "Tænd for ‘Developer Mode’ i Kook-indstillingerne, og højreklik på guilden for at få dens ID",
|
||||
"successKeywordExplanation": "MQTT-nøgleord, der vil blive betragtet som succes",
|
||||
"endpoint": "endpoint",
|
||||
"topicExplanation": "MQTT-emne til overvågning",
|
||||
"settingUpDatabaseMSG": "Opsætter databasen. Det kan tage et stykke tid, så vær tålmodig.",
|
||||
"now": "nu",
|
||||
"Json Query Expression": "Json Query Expression",
|
||||
"locally configured mail transfer agent": "lokalt konfigureret mail overførsels agent",
|
||||
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Indtast enten værtsnavnet på serveren du vil forbinde til eller {localhost} hvis du planlægger at bruge en {local_mta}",
|
||||
"timeoutAfter": "Timeout efter {0} sekunder",
|
||||
"ignoredTLSError": "TLS/SSL-fejl er blevet ignoreret",
|
||||
"Invert Keyword": "Inverter Nøgleord",
|
||||
"Resend Notification if Down X times consecutively": "Send meddelelse igen, hvis Ned X gange i træk",
|
||||
"Expected Value": "Forventede Værdi",
|
||||
"setupDatabaseSQLite": "En simpel database-fil, anbefalet til mindre implementeringer. Før v2.0.0, brugte Uptime Kuma SQLite som standard database.",
|
||||
"ignoreTLSErrorGeneral": "Ignorér TLS/SSL-fejl for forbindelsen",
|
||||
"time ago": "{0} siden",
|
||||
"-year": "-år",
|
||||
"Host URL": "Host URL",
|
||||
"Request Timeout": "Anmod Timeout",
|
||||
"Cannot connect to the socket server": "Kan ikke oprette forbindelse til socket serveren",
|
||||
"pushViewCode": "Hvordan bruger man Push Monitor? (Se kode)"
|
||||
}
|
||||
|
@@ -1085,5 +1085,34 @@
|
||||
"Can be found on:": "Ist zu finden auf: {0}",
|
||||
"From": "Von",
|
||||
"Arcade": "Spielhalle",
|
||||
"Time sensitive notifications will be delivered immediately, even if the device is in do not disturb mode.": "Zeitkritische Benachrichtigungen werden sofort zugestellt, auch wenn sich das Gerät im Nicht stören-Modus befindet."
|
||||
"Time sensitive notifications will be delivered immediately, even if the device is in do not disturb mode.": "Zeitkritische Benachrichtigungen werden sofort zugestellt, auch wenn sich das Gerät im Nicht stören-Modus befindet.",
|
||||
"RabbitMQ Nodes": "RabbitMQ-Verwaltungsknoten",
|
||||
"rabbitmqNodesDescription": "Gib die URL für die RabbitMQ-Verwaltungsknoten einschliesslich Protokoll und Port ein. Beispiel: {0}",
|
||||
"rabbitmqNodesRequired": "Setze die Knoten für diesen Monitor.",
|
||||
"RabbitMQ Username": "RabbitMQ Benutzername",
|
||||
"RabbitMQ Password": "RabbitMQ Passwort",
|
||||
"SendGrid API Key": "SendGrid-API-Schlüssel",
|
||||
"Separate multiple email addresses with commas": "Mehrere E-Mail-Adressen mit Kommas trennen",
|
||||
"rabbitmqNodesInvalid": "Benutze eine vollständig qualifizierte URL (beginnend mit 'http') für RabbitMQ-Knoten.",
|
||||
"rabbitmqHelpText": "Um den Monitor zu benutzen, musst du das Management Plugin in deinem RabbitMQ-Setup aktivieren. Weitere Informationen siehe {rabitmq_documentation}.",
|
||||
"aboutSlackUsername": "Ändert den Anzeigenamen des Absenders. Wenn du jemanden erwähnen möchtest, füge ihn stattdessen in den Namen ein.",
|
||||
"templateHostnameOrURL": "Hostname oder URL",
|
||||
"telegramUseTemplate": "Benutzerdefinierte Nachrichtenvorlage verwenden",
|
||||
"telegramUseTemplateDescription": "Wenn diese Option aktiviert ist, wird die Nachricht unter Verwendung einer benutzerdefinierten Vorlage gesendet.",
|
||||
"templateServiceName": "Service-Name",
|
||||
"YZJ Webhook URL": "YZJ Webhook URL",
|
||||
"YZJ Robot Token": "YZJ Robot Token",
|
||||
"templateStatus": "Status",
|
||||
"telegramTemplateFormatDescription": "Telegram ermöglicht die Verwendung verschiedener Markup-Sprachen für Nachrichten, siehe Telegram {0} für spezifische Details.",
|
||||
"Plain Text": "Nur Text",
|
||||
"Message Template": "Nachrichtenvorlage",
|
||||
"Template Format": "Vorlagenformat",
|
||||
"wayToGetWahaApiUrl": "Die URL deiner WAHA-Instanz.",
|
||||
"wayToGetWahaSession": "Von dieser Sitzung aus sendet WAHA Benachrichtigungen an die Chat-ID. Du kannst sie im WAHA Dashboard finden.",
|
||||
"wahaSession": "Sitzung",
|
||||
"wahaChatId": "Chat-ID (Telefonnummer / Kontakt-ID / Gruppen-ID)",
|
||||
"wayToGetWahaApiKey": "API-Schlüssel ist der Wert der WHATSAPP_API_KEY-Umgebungsvariable, den du beim Ausführen von WAHA verwendet hast.",
|
||||
"wayToWriteWahaChatId": "Die Telefonnummer mit internationaler Vorwahl, ohne den anfänglichen Pluszeichen ({0}), die Kontakt-ID ({1}) oder die Gruppen-ID ({2}). Die Benachrichtigungen werden an diese Chat-ID von der WAHA-Sitzung gesendet.",
|
||||
"telegramServerUrl": "(Optional) Server URL",
|
||||
"telegramServerUrlDescription": "Um die Telegram-Bot-API-Beschränkungen aufzuheben oder in gesperrten Gebieten (China, Iran usw.) Zugriff zu erhalten. Weitere Informationen findest du unter {0}. Standard: {1}"
|
||||
}
|
||||
|
@@ -1088,5 +1088,34 @@
|
||||
"Bubble": "Blase",
|
||||
"Clear": "Klar",
|
||||
"Pop": "Pop",
|
||||
"Arcade": "Spielhalle"
|
||||
"Arcade": "Spielhalle",
|
||||
"rabbitmqNodesRequired": "Setze die Knoten für diesen Monitor.",
|
||||
"RabbitMQ Username": "RabbitMQ Benutzername",
|
||||
"RabbitMQ Password": "RabbitMQ Passwort",
|
||||
"SendGrid API Key": "SendGrid-API-Schlüssel",
|
||||
"Separate multiple email addresses with commas": "Mehrere E-Mail-Adressen mit Kommas trennen",
|
||||
"RabbitMQ Nodes": "RabbitMQ-Verwaltungsknoten",
|
||||
"rabbitmqNodesDescription": "Gib die URL für die RabbitMQ-Verwaltungsknoten einschließlich Protokoll und Port ein. Beispiel: {0}",
|
||||
"rabbitmqNodesInvalid": "Benutze eine vollständig qualifizierte URL (beginnend mit 'http') für RabbitMQ-Knoten.",
|
||||
"rabbitmqHelpText": "Um den Monitor zu benutzen, musst du das Management Plugin in deinem RabbitMQ-Setup aktivieren. Weitere Informationen siehe {rabitmq_documentation}.",
|
||||
"aboutSlackUsername": "Ändert den Anzeigenamen des Absenders. Wenn du jemanden erwähnen möchtest, füge ihn stattdessen in den Namen ein.",
|
||||
"templateHostnameOrURL": "Hostname oder URL",
|
||||
"telegramUseTemplate": "Benutzerdefinierte Nachrichtenvorlage verwenden",
|
||||
"telegramTemplateFormatDescription": "Telegram ermöglicht die Verwendung verschiedener Markup-Sprachen für Nachrichten, siehe Telegram {0} für spezifische Details.",
|
||||
"Plain Text": "Nur Text",
|
||||
"templateServiceName": "Service-Name",
|
||||
"YZJ Webhook URL": "YZJ Webhook URL",
|
||||
"YZJ Robot Token": "YZJ Robot Token",
|
||||
"templateStatus": "Status",
|
||||
"telegramUseTemplateDescription": "Wenn diese Option aktiviert ist, wird die Nachricht unter Verwendung einer benutzerdefinierten Vorlage gesendet.",
|
||||
"Message Template": "Nachrichtenvorlage",
|
||||
"Template Format": "Vorlagenformat",
|
||||
"wayToGetWahaApiUrl": "Die URL deiner WAHA-Instanz.",
|
||||
"wahaSession": "Sitzung",
|
||||
"wahaChatId": "Chat-ID (Telefonnummer / Kontakt-ID / Gruppen-ID)",
|
||||
"wayToGetWahaApiKey": "API-Schlüssel ist der Wert der WHATSAPP_API_KEY-Umgebungsvariable, den du beim Ausführen von WAHA verwendet hast.",
|
||||
"wayToGetWahaSession": "Von dieser Sitzung aus sendet WAHA Benachrichtigungen an die Chat-ID. Du kannst sie im WAHA Dashboard finden.",
|
||||
"wayToWriteWahaChatId": "Die Telefonnummer mit internationaler Vorwahl, ohne den anfänglichen Pluszeichen ({0}), die Kontakt-ID ({1}) oder die Gruppen-ID ({2}). Die Benachrichtigungen werden an diese Chat-ID von der WAHA-Sitzung gesendet.",
|
||||
"telegramServerUrlDescription": "Um die Telegram-Bot-API-Beschränkungen aufzuheben oder in gesperrten Gebieten (China, Iran usw.) Zugriff zu erhalten. Weitere Informationen findest du unter {0}. Standard: {1}",
|
||||
"telegramServerUrl": "(Optional) Server URL"
|
||||
}
|
||||
|
@@ -97,8 +97,6 @@
|
||||
"pushOthers": "Others",
|
||||
"programmingLanguages": "Programming Languages",
|
||||
"Save": "Save",
|
||||
"Debug": "Debug",
|
||||
"Copy": "Copy",
|
||||
"Notifications": "Notifications",
|
||||
"Not available, please setup.": "Not available, please set up.",
|
||||
"Setup Notification": "Set Up Notification",
|
||||
@@ -233,6 +231,9 @@
|
||||
"templateMonitorJSON": "object describing the monitor",
|
||||
"templateLimitedToUpDownCertNotifications": "only available for UP/DOWN/Certificate expiry notifications",
|
||||
"templateLimitedToUpDownNotifications": "only available for UP/DOWN notifications",
|
||||
"templateServiceName": "service name",
|
||||
"templateHostnameOrURL": "hostname or URL",
|
||||
"templateStatus": "status",
|
||||
"webhookAdditionalHeadersTitle": "Additional Headers",
|
||||
"webhookAdditionalHeadersDesc": "Sets additional headers sent with the webhook. Each header should be defined as a JSON key/value.",
|
||||
"webhookBodyPresetOption": "Preset - {0}",
|
||||
@@ -251,14 +252,6 @@
|
||||
"PushUrl": "Push URL",
|
||||
"HeadersInvalidFormat": "The request headers are not valid JSON: ",
|
||||
"BodyInvalidFormat": "The request body is not valid JSON: ",
|
||||
"CopyToClipboardError": "Couldn't copy to clipboard: {error}",
|
||||
"CopyToClipboardSuccess": "Copied!",
|
||||
"CurlDebugInfo": "To debug the monitor, you can either paste this into your own machines terminal or into the machines terminal which uptime kuma is running on and see what you are requesting.{newiline}Please be aware of networking differences like {firewalls}, {dns_resolvers} or {docker_networks}.",
|
||||
"firewalls": "firewalls",
|
||||
"dns resolvers": "dns resolvers",
|
||||
"docker networks": "docker networks",
|
||||
"CurlDebugInfoOAuth2CCUnsupported": "Full oauth client credential flow is not supported in {curl}.{newline}Please get a bearer token and pass it via the {oauth2_bearer} option.",
|
||||
"CurlDebugInfoProxiesUnsupported": "Proxy support in the above {curl} command is currently not implemented.",
|
||||
"Monitor History": "Monitor History",
|
||||
"clearDataOlderThan": "Keep monitor history data for {0} days.",
|
||||
"PasswordsDoNotMatch": "Passwords do not match.",
|
||||
@@ -431,8 +424,13 @@
|
||||
"telegramSendSilentlyDescription": "Sends the message silently. Users will receive a notification with no sound.",
|
||||
"telegramProtectContent": "Protect Forwarding/Saving",
|
||||
"telegramProtectContentDescription": "If enabled, the bot messages in Telegram will be protected from forwarding and saving.",
|
||||
"telegramUseTemplate": "Use custom message template",
|
||||
"telegramUseTemplateDescription": "If enabled, the message will be sent using a custom template.",
|
||||
"telegramTemplateFormatDescription": "Telegram allows using different markup languages for messages, see Telegram {0} for specifc details.",
|
||||
"supportTelegramChatID": "Support Direct Chat / Group / Channel's Chat ID",
|
||||
"wayToGetTelegramChatID": "You can get your chat ID by sending a message to the bot and going to this URL to view the chat_id:",
|
||||
"telegramServerUrl": "(Optional) Server Url",
|
||||
"telegramServerUrlDescription": "To lift Telegram's bot api limitations or gain access in blocked areas (China, Iran, etc). For more information click {0}. Default: {1}",
|
||||
"YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE",
|
||||
"chatIDNotFound": "Chat ID is not found; please send a message to this bot first",
|
||||
"disableCloudflaredNoAuthMsg": "You are in No Auth mode, a password is not required.",
|
||||
@@ -529,9 +527,6 @@
|
||||
"leave blank for default subject": "leave blank for default subject",
|
||||
"emailCustomBody": "Custom Body",
|
||||
"leave blank for default body": "leave blank for default body",
|
||||
"emailTemplateServiceName": "Service Name",
|
||||
"emailTemplateHostnameOrURL": "Hostname or URL",
|
||||
"emailTemplateStatus": "Status",
|
||||
"emailTemplateMonitorJSON": "object describing the monitor",
|
||||
"emailTemplateHeartbeatJSON": "object describing the heartbeat",
|
||||
"emailTemplateMsg": "message of the notification",
|
||||
@@ -731,6 +726,7 @@
|
||||
"Icon Emoji": "Icon Emoji",
|
||||
"signalImportant": "IMPORTANT: You cannot mix groups and numbers in recipients!",
|
||||
"aboutWebhooks": "More info about Webhooks on: {0}",
|
||||
"aboutSlackUsername": "Changes the display name of the message sender. If you want to mention someone, include it in the friendly name instead.",
|
||||
"aboutChannelName": "Enter the channel name on {0} Channel Name field if you want to bypass the Webhook channel. Ex: #other-channel",
|
||||
"aboutKumaURL": "If you leave the Uptime Kuma URL field blank, it will default to the Project GitHub page.",
|
||||
"smtpDkimSettings": "DKIM Settings",
|
||||
@@ -1060,5 +1056,16 @@
|
||||
"RabbitMQ Password": "RabbitMQ Password",
|
||||
"rabbitmqHelpText": "To use the monitor, you will need to enable the Management Plugin in your RabbitMQ setup. For more information, please consult the {rabitmq_documentation}.",
|
||||
"SendGrid API Key": "SendGrid API Key",
|
||||
"Separate multiple email addresses with commas": "Separate multiple email addresses with commas"
|
||||
"Separate multiple email addresses with commas": "Separate multiple email addresses with commas",
|
||||
"wahaSession": "Session",
|
||||
"wahaChatId": "Chat ID (Phone Number / Contact ID / Group ID)",
|
||||
"wayToGetWahaApiUrl": "Your WAHA Instance URL.",
|
||||
"wayToGetWahaApiKey": "API Key is WHATSAPP_API_KEY environment variable value you used to run WAHA.",
|
||||
"wayToGetWahaSession": "From this session WAHA sends notifications to Chat ID. You can find it in WAHA Dashboard.",
|
||||
"wayToWriteWahaChatId": "The phone number with the international prefix, but without the plus sign at the start ({0}), the Contact ID ({1}) or the Group ID ({2}). Notifications are sent to this Chat ID from WAHA Session.",
|
||||
"YZJ Webhook URL": "YZJ Webhook URL",
|
||||
"YZJ Robot Token": "YZJ Robot token",
|
||||
"Plain Text": "Plain Text",
|
||||
"Message Template": "Message Template",
|
||||
"Template Format": "Template Format"
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@
|
||||
"passwordNotMatchMsg": "La contraseña repetida no coincide.",
|
||||
"notificationDescription": "Por favor asigna una notificación a el/los monitor(es) para hacerlos funcional(es).",
|
||||
"keywordDescription": "Buscar palabra clave en HTML plano o respuesta JSON. La búsqueda es sensible a mayúsculas.",
|
||||
"pauseDashboardHome": "Pausado",
|
||||
"pauseDashboardHome": "Pausar",
|
||||
"deleteMonitorMsg": "¿Seguro que quieres eliminar este monitor?",
|
||||
"deleteNotificationMsg": "¿Seguro que quieres eliminar esta notificación para todos los monitores?",
|
||||
"resolverserverDescription": "Cloudflare es el servidor por defecto, puedes cambiar el servidor de resolución en cualquier momento.",
|
||||
@@ -654,7 +654,7 @@
|
||||
"gorush": "Gorush",
|
||||
"squadcast": "Squadcast",
|
||||
"Maintenance Time Window of a Day": "Ventana de tiempo de mantenimiento de un día",
|
||||
"Effective Date Range": "Rango de Fechas Efectivas (Opcional)",
|
||||
"Effective Date Range": "Rango de Fecha Efectivo(Opcional)",
|
||||
"Free Mobile User Identifier": "Identificador de Usuario de Free Mobile",
|
||||
"Gateway Type": "Tipo de puerta de enlace",
|
||||
"SMSManager": "SMSManager",
|
||||
@@ -677,7 +677,7 @@
|
||||
"alertaRecoverState": "Estado de Recuperación",
|
||||
"serwersms": "SerwerSMS.pl",
|
||||
"serwersmsAPIUser": "Nombre de usuario de API (inc. webapi_ prefix)",
|
||||
"smseagleGroup": "Nombre/s del grupo de la guía telefónica",
|
||||
"smseagleGroup": "Nombre(s) de grupo(s) de Guía Telefónica",
|
||||
"Unpin": "Dejar de Fijar",
|
||||
"Prefix Custom Message": "Prefijo personalizado",
|
||||
"markdownSupported": "Sintaxis de Markdown soportada",
|
||||
@@ -818,7 +818,7 @@
|
||||
"showCertificateExpiry": "Mostrar caducidad del certificado",
|
||||
"noOrBadCertificate": "Certificado Nulo/Incorrecto",
|
||||
"aboutNotifyChannel": "Notificar canal activará una notificación de escritorio o móvil para todos los miembros del canal, ya sea que su disponibilidad esté activa o ausente.",
|
||||
"Server URL should not contain the nfty topic": "La URL del servidor no debe contener el tema nfty",
|
||||
"Server URL should not contain the nfty topic": "La URL del servidor no puede incluír el tópico de ntfy",
|
||||
"PushDeer Server": "Servidor PushDeer",
|
||||
"pushDeerServerDescription": "Dejar en blanco para usar el servidor oficial",
|
||||
"Badge Duration (in hours)": "Duración de la insignia (en horas)",
|
||||
@@ -855,26 +855,26 @@
|
||||
"2faEnabled": "2FA habilitado.",
|
||||
"2faDisabled": "2FA deshabilitado.",
|
||||
"liquidIntroduction": "La plantilla se logra a través del lenguaje de plantillas Liquid. Consulte {0} para obtener instrucciones de uso. Estas son las variables disponibles:",
|
||||
"templateLimitedToUpDownCertNotifications": "disponible solo para notificaciones de arriba/abajo/caducidad del certificado",
|
||||
"templateLimitedToUpDownCertNotifications": "solo disponible para notificaciones FUNCIONAL/CAÍDO/Caducidad de certificado",
|
||||
"emailTemplateMsg": "mensaje de la notificación",
|
||||
"emailTemplateLimitedToUpDownNotification": "disponible solo para latidos de arriba/abajo, de lo contrario, nulo",
|
||||
"emailTemplateLimitedToUpDownNotification": "sólo disponible para latidos FUNCIONAL/CAÍDO, de lo contrario nulo",
|
||||
"setup a new monitor group": "configurar un nuevo grupo de monitores",
|
||||
"authUserInactiveOrDeleted": "El usuario está inactivo o eliminado.",
|
||||
"2faAlreadyEnabled": "2FA ya está activado.",
|
||||
"2faAlreadyEnabled": "2FA ya está habilitado.",
|
||||
"remoteBrowsersDescription": "Los navegadores remotos son una alternativa a ejecutar Chromium localmente. Configúralos con un servicio como browserless.io o conéctalos a tu propio servidor",
|
||||
"successKeyword": "Palabra clave de éxito",
|
||||
"successKeywordExplanation": "MQTT Palabra clave que se considerará como éxito",
|
||||
"Remove the expiry notification": "Eliminar la notificación de vencimiento",
|
||||
"Browser Screenshot": "Captura de pantalla del navegador",
|
||||
"emailCustomisableContent": "Contenido personalizable",
|
||||
"smtpLiquidIntroduction": "Los siguientes dos campos son personalizables a través del lenguaje de plantillas Liquid. Por favor, consulta {0} para las instrucciones de uso. Estas son las variables disponibles:",
|
||||
"leave blank for default subject": "dejar en blanco para asunto predeterminado",
|
||||
"smtpLiquidIntroduction": "Los dos campos siguientes pueden crear plantillas mediante el lenguaje de plantillas Liquid. Consulte {0} para obtener instrucciones de uso. Estas son las variables disponibles:",
|
||||
"leave blank for default subject": "dejar en blanco para el asunto predeterminado",
|
||||
"emailCustomBody": "Cuerpo personalizado",
|
||||
"successAuthChangePassword": "La contraseña se ha actualizado correctamente.",
|
||||
"successDeleted": "Eliminado con éxito.",
|
||||
"successDeleted": "Borrado exitosamente.",
|
||||
"successEdited": "Editado con éxito.",
|
||||
"successDisabled": "Desactivado con éxito.",
|
||||
"GrafanaOncallUrl": "Grafana URL de llamada",
|
||||
"successDisabled": "Deshabilitado con éxito.",
|
||||
"GrafanaOncallUrl": "URL de llamada de Grafana",
|
||||
"Reset Token": "Restablecer Token",
|
||||
"Remote Browsers": "Navegadores remotos",
|
||||
"Remote Browser": "Navegador remoto",
|
||||
@@ -885,17 +885,17 @@
|
||||
"successResumed": "Reanudado con éxito.",
|
||||
"successPaused": "Pausado con éxito.",
|
||||
"successBackupRestored": "Copia de seguridad restaurada correctamente.",
|
||||
"successEnabled": "Activado con éxito.",
|
||||
"successEnabled": "Habilitado exitosamente.",
|
||||
"tagNotFound": "Etiqueta no encontrada.",
|
||||
"foundChromiumVersion": "Encontrado Chromium/Chrome. Versión: {0}",
|
||||
"foundChromiumVersion": "Se encontró Chromium/Chrome. Versión: {0}",
|
||||
"pushViewCode": "¿Cómo utilizar el monitor Push? (Ver código)",
|
||||
"pushOthers": "Otros",
|
||||
"programmingLanguages": "Lenguajes de Programación",
|
||||
"templateMsg": "mensaje de la notificación",
|
||||
"templateMonitorJSON": "objeto que describe el monitor",
|
||||
"templateLimitedToUpDownNotifications": "disponible solo para notificaciones de arriba/abajo",
|
||||
"templateLimitedToUpDownNotifications": "sólo disponible para notificaciones FUNCIONAL/CAIDO",
|
||||
"Add a new expiry notification day": "Añadir una nueva notificación de vencimiento",
|
||||
"leave blank for default body": "dejar en blanco para el cuerpo por defecto",
|
||||
"leave blank for default body": "dejar en blanco para el cuerpo predeterminado",
|
||||
"emailTemplateServiceName": "Nombre del Servicio",
|
||||
"emailTemplateHostnameOrURL": "Nombre del Host o URL",
|
||||
"emailTemplateStatus": "Estado",
|
||||
@@ -916,7 +916,7 @@
|
||||
"ntfyPriorityHelptextAllExceptDown": "Todos los eventos son enviados con esta prioridad, excepto los eventos {0}, que tienen una prioridad de {1}",
|
||||
"templateHeartbeatJSON": "objeto que describe el latido",
|
||||
"What is a Remote Browser?": "¿Qué es un Navegador Remoto?",
|
||||
"Your User ID": "Tu ID de usuario",
|
||||
"Your User ID": "Su ID de usuario",
|
||||
"Alphanumeric (recommended)": "Alfanumérico (recomendado)",
|
||||
"Destination": "Destino",
|
||||
"wayToGetWhapiUrlAndToken": "Puedes obtener la URL de la API y el token accediendo al canal que desee desde {0}",
|
||||
@@ -927,7 +927,7 @@
|
||||
"Refresh Interval": "Intervalo de refresco",
|
||||
"ignoreTLSErrorGeneral": "Ignorar errores SSL/TLS durante la conexión",
|
||||
"documentationOf": "Documentación de {0}",
|
||||
"wayToGetHeiiOnCallDetails": "Cómo obtener el ID del Disparador y las Claves API se explica en la {documentación}",
|
||||
"wayToGetHeiiOnCallDetails": "Cómo obtener el Trigger ID y las API Keys se explica en la {documentación}",
|
||||
"Command": "Comando",
|
||||
"wayToGetThreemaGateway": "Puedes registrarte para Threema Gateway {0}.",
|
||||
"threemaRecipient": "Destinatario",
|
||||
@@ -941,7 +941,7 @@
|
||||
"Host URL": "URL del anfitrión",
|
||||
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Ingresa el nombre del host del servidor al que deseas conectarte o {localhost} si deseas usar un {local_mta}",
|
||||
"smspartnerPhoneNumberHelptext": "El número debe estar en el formato internacional {0}, {1}. Múltiples números deben estar separados por {2}",
|
||||
"smspartnerSenderName": "Nombre del remitente de SMS",
|
||||
"smspartnerSenderName": "Nombre del emisor del SMS",
|
||||
"smspartnerApiurl": "Puedes encontrar tu clave API en tu panel de control en {0}",
|
||||
"smspartnerPhoneNumber": "Número(s) de teléfono",
|
||||
"max 11 alphanumeric characters": "máximo 11 caracteres alfanuméricos",
|
||||
@@ -951,7 +951,7 @@
|
||||
"Originator type": "Tipo de originador",
|
||||
"Telephone number": "Número de teléfono",
|
||||
"Mentioning": "Mencionando",
|
||||
"Don't mention people": "No mencionar a las personas",
|
||||
"Don't mention people": "No mencionar personas",
|
||||
"Mention group": "Mencionar a {group}",
|
||||
"Bitrix24 Webhook URL": "URL del Webhook de Bitrix24",
|
||||
"wayToGetBitrix24Webhook": "Puedes crear un webhook siguiendo los pasos en {0}",
|
||||
@@ -961,11 +961,11 @@
|
||||
"wayToWriteWhapiRecipient": "El número de teléfono con el prefijo internacional, pero sin el signo más al inicio ({0}), el ID de Contacto ({1}) o el ID de Grupo ({2}).",
|
||||
"From Phone Number / Transmission Path Originating Address (TPOA)": "Número de Teléfono del Remitente / Dirección de Origen de la Ruta de Transmisión (TPOA)",
|
||||
"To Phone Number": "Al Número de Teléfono",
|
||||
"Select message type": "Seleccionar tipo de mensaje",
|
||||
"Select message type": "Seleccionar el tipo de mensaje",
|
||||
"Send to channel": "Enviar al canal",
|
||||
"max 15 digits": "máximo 15 dígitos",
|
||||
"mongodbCommandDescription": "Ejecuta un comando de MongoDB contra la base de datos. Para obtener información sobre los comandos disponibles, consulta la {documentación}",
|
||||
"whapiRecipient": "Número de Teléfono / ID de Contacto / ID de Grupo",
|
||||
"whapiRecipient": "Número de teléfono / ID del contacto / ID del grupo",
|
||||
"cellsyntSplitLongMessages": "Divide mensajes largos en hasta 6 partes. 153 x 6 = 918 caracteres.",
|
||||
"receiverSevenIO": "Número receptor",
|
||||
"apiKeySevenIO": "Clave API de SevenIO",
|
||||
@@ -974,7 +974,7 @@
|
||||
"gtxMessagingToHint": "Formato internacional, con el signo \"+\" al inicio ({e164}, {e212} o {e214})",
|
||||
"locally configured mail transfer agent": "agente de transferencia de correo configurado localmente",
|
||||
"wayToGetDiscordThreadId": "Obtener un ID de hilo / publicación en el foro es similar a obtener un ID de canal. Lee más sobre cómo obtener IDs {0}",
|
||||
"smspartnerSenderNameInfo": "Debe tener entre 3..=11 caracteres normales",
|
||||
"smspartnerSenderNameInfo": "Debe ser entre 3..=11 carácteres regulares",
|
||||
"receiverInfoSevenIO": "Si el número receptor no está ubicado en Alemania, debes agregar el código de país delante del número (por ejemplo, para el código de país 1 de EE. UU. usa 117612121212 en lugar de 017612121212)",
|
||||
"callMeBotGet": "Aquí puedes generar un endpoint para {0}, {1} y {2}. Ten en cuenta que podrías recibir limitaciones de tasa. Las limitaciones de tasa parecen ser: {3}",
|
||||
"cellsyntOriginator": "Visible en el teléfono móvil del destinatario como originador del mensaje. Los valores permitidos y la función dependen del parámetro originatortype.",
|
||||
@@ -982,11 +982,110 @@
|
||||
"threemaApiAuthenticationSecret": "Clave Secreta del Gateway-ID",
|
||||
"threemaBasicModeInfo": "Nota: Esta integración utiliza Threema Gateway en modo básico (encriptación basada en servidor). Puedes encontrar más detalles en {0}.",
|
||||
"apiKeysDisabledMsg": "Las claves API están desactivadas porque la autenticación está desactivada.",
|
||||
"Channel access token (Long-lived)": "Token de acceso al canal (de larga duración)",
|
||||
"Create new forum post": "Crear nueva publicación en el foro",
|
||||
"Channel access token (Long-lived)": "Token de acceso al canal (Larga duración)",
|
||||
"Create new forum post": "Crear un nuevo post en el foro",
|
||||
"postToExistingThread": "Publicar en hilo / publicación existente",
|
||||
"forumPostName": "Nombre de la publicación en el foro",
|
||||
"threadForumPostID": "ID del hilo / publicación en el foro",
|
||||
"e.g. {discordThreadID}": "por ejemplo, {discordThreadID}",
|
||||
"whatHappensAtForumPost": "Crear una nueva publicación en el foro. Esto NO publica mensajes en una publicación existente. Para publicar en una publicación existente usa \"{option}\""
|
||||
"whatHappensAtForumPost": "Crear una nueva publicación en el foro. Esto NO publica mensajes en una publicación existente. Para publicar en una publicación existente usa \"{option}\"",
|
||||
"jsonQueryDescription": "Analice y extraiga datos específicos de la respuesta JSON del servidor mediante una consulta JSON o utilice \"$\" para la respuesta sin formato, si no espera JSON. Luego, el resultado se compara con el valor esperado, como cadenas. Consulte {0} para obtener documentación y use {1} para experimentar con consultas.",
|
||||
"aboutSlackUsername": "Cambia el nombre que se muestra del remitente del mensaje. Si quieres mencionar a alguien, inclúyelo en el nombre descriptivo.",
|
||||
"cacheBusterParam": "Añade el parámetro {0}",
|
||||
"cacheBusterParamDescription": "Parámetro generado aleatoriamente para omitir cachés.",
|
||||
"Community String": "Cadena comunitaria",
|
||||
"snmpCommunityStringHelptext": "Esta cadena funciona como contraseña para autenticar y controlar el acceso a dispositivos habilitados para SNMP. Compárela con la configuración de su dispositivo SNMP.",
|
||||
"privateOnesenderDesc": "Asegúrese de que el número de teléfono sea válido. Para enviar un mensaje a un número de teléfono privado, por ejemplo: 628123456789",
|
||||
"wayToGetOnesenderUrlandToken": "Puedes obtener la URL y el token en el sitio web de Onesender. Más información {0}",
|
||||
"Optional: Space separated list of scopes": "Opcional: Lista de ámbitos separados por espacios",
|
||||
"No tags found.": "No se han encontrado etiquetas.",
|
||||
"signl4Docs": "Puede encontrar más información sobre cómo configurar SIGNL4 y cómo obtener la URL del webhook de SIGNL4 en {0}.",
|
||||
"shrinkDatabaseDescriptionSqlite": "Desencadena la base de datos {vacuum} para SQLite. {auto_vacuum} ya está habilitado, pero esto no desfragmenta la base de datos ni reempaqueta páginas de base de datos individuales como lo hace el comando {vacuum}.",
|
||||
"and": "y",
|
||||
"Message format": "Formato del mensaje",
|
||||
"Send rich messages": "Enviar mensajes enriquecidos",
|
||||
"OID (Object Identifier)": "(Identificador de Objeto) OID",
|
||||
"snmpOIDHelptext": "Ingrese el OID del sensor o el estado que desea monitorear. Use herramientas de administración de red como navegadores MIB o software SNMP si no está seguro acerca del OID.",
|
||||
"Condition": "Condición",
|
||||
"SNMP Version": "Versión SNMP",
|
||||
"Please enter a valid OID.": "Por favor escribe un OID válido.",
|
||||
"Host Onesender": "Host de Onesender",
|
||||
"Token Onesender": "Token de Onesender",
|
||||
"Recipient Type": "Tipo de Receptor",
|
||||
"Private Number": "Número Privado",
|
||||
"groupOnesenderDesc": "Asegúrese de que el ID del grupo sea válido. Para enviar un mensaje al grupo, por ejemplo: 628123456789-342345",
|
||||
"Group ID": "ID del grupo",
|
||||
"Add Remote Browser": "Agregar navegador remoto",
|
||||
"New Group": "Nuevo grupo",
|
||||
"Group Name": "Nombre del grupo",
|
||||
"OAuth2: Client Credentials": "OAuth2: Credenciales del Cliente",
|
||||
"Authentication Method": "Método de autentificación",
|
||||
"Authorization Header": "Cabecera de Autorización",
|
||||
"Form Data Body": "Cuerpo de datos del formulario",
|
||||
"OAuth Token URL": "OAuth Token URL",
|
||||
"Client ID": "ID del Cliente",
|
||||
"Client Secret": "Secreto de Cliente",
|
||||
"OAuth Scope": "Alcance OAuth",
|
||||
"Go back to home page.": "Volver a la página de inicio.",
|
||||
"Lost connection to the socket server.": "Se perdió la conexión con el servidor de socket.",
|
||||
"Cannot connect to the socket server.": "No se puede conectar al servidor de socket.",
|
||||
"SIGNL4": "SIGNL4",
|
||||
"SIGNL4 Webhook URL": "URL de SIGNL4 WebhooK",
|
||||
"Conditions": "Condiciones",
|
||||
"conditionAdd": "Añadir condición",
|
||||
"now": "ahora",
|
||||
"time ago": "hace {0}",
|
||||
"-year": "-año",
|
||||
"Json Query Expression": "Expresión de consulta Json",
|
||||
"ignoredTLSError": "Se han ignorado errores TLS/SSL",
|
||||
"conditionDelete": "Borrar condición",
|
||||
"conditionAddGroup": "Añadir grupo",
|
||||
"conditionDeleteGroup": "Borrar grupo",
|
||||
"conditionValuePlaceholder": "Valor",
|
||||
"equals": "igual",
|
||||
"not equals": "no es igual",
|
||||
"contains": "contiene",
|
||||
"not contains": "no contiene",
|
||||
"starts with": "empieza por",
|
||||
"not starts with": "no empieza por",
|
||||
"ends with": "termina con",
|
||||
"not ends with": "No termina en",
|
||||
"less than": "menor que",
|
||||
"greater than": "mayor que",
|
||||
"less than or equal to": "Menor o igual a",
|
||||
"greater than or equal to": "Mayor o igual a",
|
||||
"Notification Channel": "Canal de notificación",
|
||||
"Sound": "Sonido",
|
||||
"record": "Registro",
|
||||
"RabbitMQ Username": "Usuario RabbitMQ",
|
||||
"RabbitMQ Password": "Contraseña RabbitMQ",
|
||||
"RabbitMQ Nodes": "Nodos de Gestión RabbitMQ",
|
||||
"rabbitmqNodesRequired": "Por favor, configure los nodos para este monitor.",
|
||||
"rabbitmqNodesInvalid": "Por favor, utilice una URL totalmente cualificada (comenzando por 'http') para los nodos RabbitMQ.",
|
||||
"Separate multiple email addresses with commas": "Separa las múltiples direcciones de correo con comas",
|
||||
"rabbitmqHelpText": "Para utilizar el monitor, necesitará habilitar el Plugin de Gestión en su configuración RabbitMQ. Para más información, por favor consulte {rabitmq_documentation}.",
|
||||
"SendGrid API Key": "Clave de la API de SendGrid",
|
||||
"rabbitmqNodesDescription": "Introduzca la URL para los nodos de gestión de RabbitMQ incluyendo el protocolo y el puerto. Ejemplo: {0}",
|
||||
"Money": "Dinero",
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "O bien un texto de ID de origen o un número de teléfono en formato E.164 si quiere ser capaz de recibir respuestas.",
|
||||
"Harp": "Arpa",
|
||||
"Scifi": "Ciencia Ficción",
|
||||
"Alphanumerical string and hyphens only": "Sólo cadenas alfanuméricas y guiones",
|
||||
"Time Sensitive (iOS Only)": "Sensible a la Hora (Solo iOS)",
|
||||
"Doorbell": "Timbre",
|
||||
"Flute": "Flauta",
|
||||
"Guitar": "Guitarra",
|
||||
"Correct": "Correcto",
|
||||
"Bubble": "Burbuja",
|
||||
"Elevator": "Ascensor",
|
||||
"Fail": "Fallo",
|
||||
"Reveal": "Mostrar",
|
||||
"Pop": "Pop",
|
||||
"From": "De",
|
||||
"Clear": "Limpiar",
|
||||
"Can be found on:": "Se puede encontrar en: {0}",
|
||||
"Custom sound to override default notification sound": "Sonidos personalizados prevalecen sobre los sonidos por defecto de las notificaciones",
|
||||
"The phone number of the recipient in E.164 format.": "El número de teléfono del receptor en formato E.164.",
|
||||
"Time sensitive notifications will be delivered immediately, even if the device is in do not disturb mode.": "Las notificaciones sensibles en el tiempo se enviarán inmediatamente, incluso si el dispositivo está en modo no molestar.",
|
||||
"Arcade": "Arcade"
|
||||
}
|
||||
|
132
src/lang/eu.json
132
src/lang/eu.json
@@ -216,19 +216,19 @@
|
||||
"smtpCC": "CC",
|
||||
"smtpBCC": "BCC",
|
||||
"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",
|
||||
"Discord Webhook URL": "Discord Webhook URLa",
|
||||
"wayToGetDiscordURL": "Hona joanda lortu dezakezu: Server Settings -> Integrations -> View Webhooks -> New Webhook",
|
||||
"Bot Display Name": "Botaren erakusteko izena",
|
||||
"Prefix Custom Message": "Prefix Custom Message",
|
||||
"Hello @everyone is...": "Kaixo {'@'}edonor da…",
|
||||
"teams": "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
"Webhook URL": "Webhook URLa",
|
||||
"wayToGetTeamsURL": "You can learn how to create a webhook URL {0}.",
|
||||
"wayToGetZohoCliqURL": "You can learn how to create a webhook URL {0}.",
|
||||
"signal": "Signal",
|
||||
"Number": "Zenbakia",
|
||||
"Recipients": "Recipients",
|
||||
"needSignalAPI": "You need to have a signal client with REST API.",
|
||||
"Recipients": "Hartzaileak",
|
||||
"needSignalAPI": "REST APIarekin signal bezeroa eduki behar duzu.",
|
||||
"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",
|
||||
@@ -280,8 +280,8 @@
|
||||
"Read more": "Irakurri gehiago",
|
||||
"appriseInstalled": "Apprise instalatuta.",
|
||||
"appriseNotInstalled": "Apprise ez dago instalatuta. {0}",
|
||||
"Access Token": "Access Token",
|
||||
"Channel access token": "Channel access token",
|
||||
"Access Token": "Access Tokena",
|
||||
"Channel access token": "Kanalaren access tokena",
|
||||
"Line Developers Console": "Line Developers Console",
|
||||
"lineDevConsoleTo": "Line Developers Console - {0}",
|
||||
"Basic Settings": "Oinarrizko ezarpenak",
|
||||
@@ -316,7 +316,7 @@
|
||||
"One record": "One record",
|
||||
"steamApiKeyDescription": "For monitoring a Steam Game Server you need a Steam Web-API key. You can register your API key here: ",
|
||||
"Current User": "Uneko erabiltzailea",
|
||||
"topic": "Topic",
|
||||
"topic": "Gaia",
|
||||
"topicExplanation": "MQTT topic to monitor",
|
||||
"successMessage": "Arrakasta mezua",
|
||||
"successMessageExplanation": "MQTT message that will be considered as success",
|
||||
@@ -401,7 +401,7 @@
|
||||
"proxyDescription": "Proxies must be assigned to a monitor to function.",
|
||||
"enableProxyDescription": "This proxy will not effect on monitor requests until it is activated. You can control temporarily disable the proxy from all monitors by activation status.",
|
||||
"setAsDefaultProxyDescription": "This proxy will be enabled by default for new monitors. You can still disable the proxy separately for each monitor.",
|
||||
"Certificate Chain": "Certificate Chain",
|
||||
"Certificate Chain": "Zertifikatu katea",
|
||||
"Valid": "Baliozkoa",
|
||||
"Invalid": "Baliogabea",
|
||||
"AccessKeyId": "AccessKey ID",
|
||||
@@ -476,7 +476,7 @@
|
||||
"Footer Text": "Oineko testua",
|
||||
"Show Powered By": "Erakutsi Honekin egina:",
|
||||
"Domain Names": "Domeinu izenak",
|
||||
"signedInDisp": "Signed in as {0}",
|
||||
"signedInDisp": "{0} bezala logeatua",
|
||||
"signedInDispDisabled": "Auth desgaituta.",
|
||||
"Certificate Expiry Notification": "Zertifikatu iraungitze jakinarazpena",
|
||||
"API Username": "API Erabiltzailea",
|
||||
@@ -587,5 +587,113 @@
|
||||
"statusPageRefreshIn": "{0} barru freskatuko da.",
|
||||
"now": "orain",
|
||||
"time ago": "duela {0}",
|
||||
"-year": "-urte"
|
||||
"-year": "-urte",
|
||||
"styleElapsedTimeShowNoLine": "Erakutsi (Lerrorik ez)",
|
||||
"styleElapsedTimeShowWithLine": "Erakutsi (Lerroarekin)",
|
||||
"Select": "Hautatu",
|
||||
"Docker Container": "Docker edukiontzia",
|
||||
"Container Name / ID": "Edukiontzi izena / ID",
|
||||
"Packet Size": "Pakete tamaina",
|
||||
"telegramSendSilently": "Bidali isilik",
|
||||
"Examples": "Adibideak",
|
||||
"default: notify all devices": "Defektuz: jakinarazi gailu guztiak",
|
||||
"Event type:": "Ekintza mota:",
|
||||
"Event data:": "Ekintza mota:",
|
||||
"Optional": "Hautazkoa",
|
||||
"and": "eta",
|
||||
"sameAsServerTimezone": "Zerbitzariaren ordu-zona bera",
|
||||
"endDateTime": "Bukaera data/ordua",
|
||||
"cronExpression": "Cron espresioa",
|
||||
"cronSchedule": "Programatu: ",
|
||||
"invalidCronExpression": "Cron espresio baliogabea: {0}",
|
||||
"recurringInterval": "Tartea",
|
||||
"No Maintenance": "Mantenurik ez",
|
||||
"maintenanceStatus-under-maintenance": "Mantenuan",
|
||||
"maintenanceStatus-inactive": "Aktibatu gabe",
|
||||
"maintenanceStatus-scheduled": "Programatuta",
|
||||
"Display Timezone": "Erakutsi ordu zona",
|
||||
"statusPageMaintenanceEndDate": "Bukatu",
|
||||
"IconUrl": "Ikono URLa",
|
||||
"chromeExecutableAutoDetect": "Auto detektatu",
|
||||
"Schedule Maintenance": "Programatu mantenua",
|
||||
"Edit Maintenance": "Editatu mantenua",
|
||||
"Date and Time": "Data eta ordua",
|
||||
"plugin": "Plugin | Pluginak",
|
||||
"installing": "Instalatzen",
|
||||
"uninstalling": "Desinstalatzen",
|
||||
"confirmUninstallPlugin": "Ziur zaude plugin hau desinstalatu nahi duzula?",
|
||||
"Clone": "Klonatu",
|
||||
"cloneOf": "{0}-(a)ren klona",
|
||||
"emailTemplateStatus": "Egoera",
|
||||
"emailTemplateMsg": "jakinarazpenaren mezua",
|
||||
"Select message type": "Hautatu mezu mota",
|
||||
"Send to channel": "Bidali kanalera",
|
||||
"Enable TLS": "Gaitu TLS",
|
||||
"webhookAdditionalHeadersTitle": "Goiburu gehigarriak",
|
||||
"Reset Token": "Berrezarri tokena",
|
||||
"selectedMonitorCount": "Hautatuta: {0}",
|
||||
"HTTP Headers": "HTTP goiburuak",
|
||||
"Refresh Interval": "Eguneratze tartea",
|
||||
"tcp": "TCP / HTTP",
|
||||
"Notification Service": "Jakinarazpen zerbitzua",
|
||||
"or": "edo",
|
||||
"startDateTime": "Hasiera data/ordua",
|
||||
"pauseMaintenanceMsg": "Ziur zaude gelditu nahi duzula?",
|
||||
"install": "Instalatu",
|
||||
"uninstall": "Desinstalatu",
|
||||
"emailTemplateServiceName": "Zerbitzu izena",
|
||||
"Your User ID": "Zure erabiltzaile IDa",
|
||||
"Connection Type": "Konexio mota",
|
||||
"pushOthers": "Besteak",
|
||||
"programmingLanguages": "Programatze lengoaiak",
|
||||
"dbName": "Datubase izena",
|
||||
"resendEveryXTimes": "Berbidali {0} aldiz",
|
||||
"Reconnecting...": "Birkonektatzen...",
|
||||
"setupDatabaseChooseDatabase": "Zein datubase erabili nahi duzu?",
|
||||
"Recurring": "Errepikakorra",
|
||||
"Mentioning": "Aipatzen",
|
||||
"Condition": "Baldintza",
|
||||
"RabbitMQ Username": "RabbitMQ erabiltzailea",
|
||||
"Expiry": "Iraungitzea",
|
||||
"pagertreeSilent": "Isildu",
|
||||
"Group": "Taldea",
|
||||
"Saved.": "Gordeta.",
|
||||
"Conditions": "Baldintzak",
|
||||
"smseagleTo": "Telefono zenbakia(k)",
|
||||
"Enable Kafka SSL": "Gaitu Kafka SSL",
|
||||
"Continue": "Jarraitu",
|
||||
"apiKey-active": "Aktibo",
|
||||
"apiKey-expired": "Iraungita",
|
||||
"apiKey-inactive": "Ez-aktibo",
|
||||
"Expires": "Iraungitzen da",
|
||||
"Generate": "Sortu",
|
||||
"pagertreeUrgency": "Larritasuna",
|
||||
"pagertreeLow": "Baxua",
|
||||
"pagertreeHigh": "Altua",
|
||||
"pagertreeCritical": "Larria",
|
||||
"Destination": "Helburua",
|
||||
"conditionValuePlaceholder": "Balioa",
|
||||
"RabbitMQ Password": "RabbitMQ pasahitza",
|
||||
"Correct": "Zuzena",
|
||||
"Fail": "Akatsa",
|
||||
"Elevator": "Igogailua",
|
||||
"Guitar": "Gitarra",
|
||||
"pagertreeMedium": "Ertaina",
|
||||
"Host URL": "Host URLa",
|
||||
"Affected Monitors": "Kaltetutako monitoreak",
|
||||
"Pick Affected Monitors...": "Hautatu kaltetutako monitoreak…",
|
||||
"deleteMaintenanceMsg": "Ziur zaude mantentze lan hau ezabatu nahi duzula?",
|
||||
"smseagleEncoding": "Unicode gisa bidali",
|
||||
"Add Another": "Gehitu beste bat",
|
||||
"Google Analytics ID": "Google Analytics IDa",
|
||||
"Edit Tag": "Editatu etiketa",
|
||||
"PushDeer Server": "PushDeer zerbitzaria",
|
||||
"Show Clickable Link": "Erakutsi lotura klikagarria",
|
||||
"twilioToNumber": "zenbakira",
|
||||
"twilioFromNumber": "zenbakitik",
|
||||
"ntfyUsernameAndPassword": "Erabiltzailea eta pasahitza",
|
||||
"lunaseaUserID": "Erabiltzaile IDa",
|
||||
"pagertreeDoNothing": "Ez egin ezer",
|
||||
"Separate multiple email addresses with commas": "Banatu email helbideak koma ikurrekin",
|
||||
"settingUpDatabaseMSG": "Datubasea ezartzen. Denbora pixka bat iraun dezake, pazientzia eduki."
|
||||
}
|
||||
|
@@ -351,7 +351,7 @@
|
||||
"statusPageRefreshIn": "تا بارگذاری مجدد: {0}",
|
||||
"Content Type": "نوع محتوا (Content Type)",
|
||||
"Server URL": "آدرس سرور",
|
||||
"Priority": "اهمیت",
|
||||
"Priority": "اولویت",
|
||||
"emojiCheatSheet": "چیت شیت ایموجی ها: {0}",
|
||||
"Read more": "بیشتر بدانید",
|
||||
"webhookJsonDesc": "{0} برای هر HTTP سرور جدیدی مانند Express.js مناسب است",
|
||||
@@ -642,7 +642,7 @@
|
||||
"Push URL": "URL پوش",
|
||||
"Schedule maintenance": "زمانبندی نگهداری (غیرفعال سازی دستی)",
|
||||
"webhookFormDataDesc": "{multipart} برای PHP مناسب است. آرایه JSON نیاز است تا به این شکل باز شود {decodeFunction}",
|
||||
"webhookAdditionalHeadersTitle": "هدر اضافی",
|
||||
"webhookAdditionalHeadersTitle": "هدرهای اضافی",
|
||||
"webhookAdditionalHeadersDesc": "تنظیم هدر های اضافی که نیاز است با وب هوک ارسال شود. هر هدر باید به کیلد/مقدار JSON تعریف شده باشد.",
|
||||
"Webhook URL": "آدرس وب هوک",
|
||||
"Application Token": "توکن اپلیکیشن",
|
||||
@@ -1020,5 +1020,53 @@
|
||||
"OAuth Token URL": "URL توکن OAuth",
|
||||
"OAuth Scope": "اسکوپ OAuth",
|
||||
"Optional: Space separated list of scopes": "اختیاری: لیست جدا شده با فاصله از اسکوپها",
|
||||
"signl4Docs": "شما میتوانید اطلاعات بیشتر در رابطه با نحوه تنظیم SIGNL4 و به دست آوردن URL وبهوک SIGNL4 را در {0} پیدا کنید."
|
||||
"signl4Docs": "شما میتوانید اطلاعات بیشتر در رابطه با نحوه تنظیم SIGNL4 و به دست آوردن URL وبهوک SIGNL4 را در {0} پیدا کنید.",
|
||||
"ignoredTLSError": "خطاهای TLS/SSL نادیده گرفته میشود",
|
||||
"Bubble": "حباب",
|
||||
"Message format": "ساختار پیام",
|
||||
"Notification Channel": "کانال اطلاعرسانی",
|
||||
"Doorbell": "زنگ",
|
||||
"The phone number of the recipient in E.164 format.": "شماره تلفن گیرنده به فرمت E.164.",
|
||||
"Sound": "صدا",
|
||||
"Correct": "درست",
|
||||
"Reveal": "نمایش",
|
||||
"Flute": "فلوت",
|
||||
"Money": "پول",
|
||||
"Scifi": "علمیتخیلی",
|
||||
"Elevator": "آسانسور",
|
||||
"Guitar": "گیتار",
|
||||
"Pop": "پاپ",
|
||||
"From": "از",
|
||||
"telegramServerUrl": "(اختیاری) آدرس سرور",
|
||||
"telegramServerUrlDescription": "برای کاهش محدودیتهای بات تلگرام یا دسترسی در مناطقی که تلگرام فیلتر شده است (مثل ایران یا چین و ...). برای اطلاعات بیشتر {0} را ببینید. مقدار پیشفرض: {1}",
|
||||
"Alphanumerical string and hyphens only": "فقط حروف الفبا، اعداد و -",
|
||||
"Time sensitive notifications will be delivered immediately, even if the device is in do not disturb mode.": "اعلانهای حساس به زمان در لحظه ارسال خواهند شد، حتی اگر دستگاه در حالت بدون مزاحمت قرار داشته باشد.",
|
||||
"rabbitmqNodesRequired": "لطفا گرههای این پایشگر را تنظیم کنید.",
|
||||
"RabbitMQ Password": "گذرواژه RabbitMQ",
|
||||
"RabbitMQ Nodes": "گرههای مدیریت RabbitMQ",
|
||||
"rabbitmqHelpText": "برای پایش، لازم است افزونه مدیریت (Management) در RabbitMQ را فعال کنید. برای اطلاعات بیشتر به {rabitmq_documentation} مراجعه کنید.",
|
||||
"wayToWriteWahaChatId": "شماره موبایل در قالب بینالمللی و بدون علامت مثبت ابتدایی ({0})، شناسه مخاطب ({1}) یا شناسه گروه ({2}). اعلانها از نشست WAHA به این شناسه گفتگو ارسال خواهند شد.",
|
||||
"wahaSession": "نشست",
|
||||
"wahaChatId": "شناسه گفتگو (شماره موبایل / شناسه مخاطب / شناسه گروه)",
|
||||
"wayToGetWahaSession": "با این نشست WAHA اعلانها را به شناسه گفتگو ارسال میکند. قابل مشاهده در پنل کاربری WAHA.",
|
||||
"Message Template": "قالب پیام",
|
||||
"Template Format": "فرمت قالب",
|
||||
"YZJ Webhook URL": "آدرس وبهوک YZJ",
|
||||
"Fail": "شکست",
|
||||
"Custom sound to override default notification sound": "نوای دلخواه به جای نوای پیشفرض اعلان",
|
||||
"Time Sensitive (iOS Only)": "حساس به زمان (فقط iOS)",
|
||||
"Can be found on:": "در {0} یافت میشود",
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "شناسه ارسال کننده متنی و در صورتی که میخواهید پاسخها را دریافت کنید، شماره موبایل در قالب E.164.",
|
||||
"rabbitmqNodesDescription": "آدرس گرههای مدیریت RabbitMQ را به همراه پروتکل و شماره پورت وارد کنید. مثال: {0}",
|
||||
"RabbitMQ Username": "نام کاربری RabbitMQ",
|
||||
"Separate multiple email addresses with commas": "آدرسهای ایمیل را با استفاده از ویرگول انگلیسی یا کاما جدا کنید",
|
||||
"Plain Text": "متن ساده",
|
||||
"aboutSlackUsername": "نام نمایشی ارسال کننده پیام را تغییر میدهد. اگر میخواهید شخصی را نام ببرید، در قسمت نام دوستانه بنویسید.",
|
||||
"Clear": "پاکسازی",
|
||||
"templateServiceName": "نام خدمت",
|
||||
"templateHostnameOrURL": "آدرس یا نام میزبان",
|
||||
"templateStatus": "وضعیت",
|
||||
"telegramUseTemplate": "استفاده از قالب پیام دلخواه",
|
||||
"telegramUseTemplateDescription": "در صورت فعالسازی، پیام با قالب دلخواه ارسال خواهد شد.",
|
||||
"telegramTemplateFormatDescription": "در تلگرام امکان استفاده از زبانهای نشانهگذاری مختلفی وجود دارد، برای جزئیات بیشتر {0} را ببینید."
|
||||
}
|
||||
|
@@ -1086,5 +1086,15 @@
|
||||
"The phone number of the recipient in E.164 format.": "Vastaanottajan puhelinnumero E.164-muodossa.",
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "Joko lähettäjätunnus (sender ID) tai puhelinnumero E-164-muodossa jos haluat pystyä vastaanottamaan vastausviestejä.",
|
||||
"Scifi": "Tieteisseikkailu",
|
||||
"Pop": "Poksahdus"
|
||||
"Pop": "Poksahdus",
|
||||
"rabbitmqNodesRequired": "Aseta tämän seuraimen solmut.",
|
||||
"rabbitmqNodesInvalid": "Käytä RabbitMQ-solmuille täysin hyväksyttyä ('http' alkavaa) URL-osoitetta.",
|
||||
"RabbitMQ Username": "RabbitMQ Käyttäjänimi",
|
||||
"RabbitMQ Password": "RabbitMQ Salasana",
|
||||
"SendGrid API Key": "SendGrid API-avain",
|
||||
"Separate multiple email addresses with commas": "Erottele useammat sähköpostiosoitteet pilkuilla",
|
||||
"RabbitMQ Nodes": "RabbitMQ-hallintasolmut",
|
||||
"rabbitmqNodesDescription": "Anna URL RabbitMQ-hallintasolmuille sisältäen protokollan ja portin. Esimerkki: {0}",
|
||||
"rabbitmqHelpText": "Jotta voit käyttää seurainta, sinun on otettava hallintalaajennus käyttöön RabbitMQ-asetuksissa. Lisätietoja saat osoitteesta {rabitmq_documentation}.",
|
||||
"aboutSlackUsername": "Muuttaa viestin lähettäjän näyttönimeä. Jos haluat mainita jonkun, lisää se ystävälliseen nimeen."
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"retryCheckEverySecond": "Réessayer toutes les {0} secondes",
|
||||
"resendEveryXTimes": "Renvoyez toutes les {0} fois",
|
||||
"resendDisabled": "Renvoi désactivé",
|
||||
"retriesDescription": "Nombre d'essais avant que le service ne soit déclaré hors ligne et qu'une notification soit envoyée",
|
||||
"retriesDescription": "Nombre de tentatives avant que le service ne soit déclaré hors ligne et qu'une notification soit envoyée",
|
||||
"ignoreTLSError": "Ignorer les erreurs liées au certificat SSL/TLS",
|
||||
"upsideDownModeDescription": "Si le service est en ligne, il sera alors noté hors ligne et vice-versa.",
|
||||
"maxRedirectDescription": "Nombre maximal de redirections avant que le service ne soit marqué comme hors ligne.",
|
||||
@@ -87,8 +87,8 @@
|
||||
"Hostname": "Nom d'hôte / adresse IP",
|
||||
"Port": "Port",
|
||||
"Heartbeat Interval": "Intervalle de vérification",
|
||||
"Retries": "Essais",
|
||||
"Heartbeat Retry Interval": "Intervalle de ré-essai",
|
||||
"Retries": "Tentatives",
|
||||
"Heartbeat Retry Interval": "Intervalle entre chaque nouvelle tentative",
|
||||
"Resend Notification if Down X times consecutively": "Renvoyer la notification si hors ligne X fois consécutivement",
|
||||
"Advanced": "Avancé",
|
||||
"Upside Down Mode": "Mode inversé",
|
||||
@@ -310,7 +310,7 @@
|
||||
"lineDevConsoleTo": "Console développeurs Line - {0}",
|
||||
"Basic Settings": "Paramètres de base",
|
||||
"User ID": "Identifiant utilisateur",
|
||||
"Messaging API": "Messaging API",
|
||||
"Messaging API": "API de messagerie",
|
||||
"wayToGetLineChannelToken": "Premièrement accédez à {0}, créez un <i>provider</i> et définissez un type de salon à «Messaging API». Vous obtiendrez alors le jeton d'accès du salon et l'identifiant utilisateur demandés.",
|
||||
"Icon URL": "URL vers l'icône",
|
||||
"aboutIconURL": "Vous pouvez mettre un lien vers une image dans « URL vers l'icône » pour remplacer l'image de profil par défaut. Elle ne sera utilisé que si « Icône émoji » n'est pas défini.",
|
||||
@@ -455,7 +455,7 @@
|
||||
"Huawei": "Huawei",
|
||||
"High": "Haute",
|
||||
"Retry": "Recommencez",
|
||||
"Topic": "Topic",
|
||||
"Topic": "Sujet",
|
||||
"WeCom Bot Key": "Clé de robot WeCom",
|
||||
"Setup Proxy": "Configurer le proxy",
|
||||
"Proxy Protocol": "Protocole proxy",
|
||||
@@ -517,7 +517,7 @@
|
||||
"Domain Names": "Noms de domaine",
|
||||
"signedInDisp": "Connecté en tant que {0}",
|
||||
"signedInDispDisabled": "Authentification désactivée.",
|
||||
"RadiusSecret": "Radius Secret",
|
||||
"RadiusSecret": "Secret Radius",
|
||||
"RadiusSecretDescription": "Secret partagé entre le client et le serveur",
|
||||
"RadiusCalledStationId": "Identifiant de la station appelée",
|
||||
"RadiusCalledStationIdDescription": "Identifiant de l'appareil appelé",
|
||||
@@ -826,7 +826,7 @@
|
||||
"nostrSender": "Émetteur clé privée (nsec)",
|
||||
"nostrRecipientsHelp": "Format npub, un par ligne",
|
||||
"nostrRelays": "Relais Nostr",
|
||||
"PushDeer Server": "PushDeer Server",
|
||||
"PushDeer Server": "Serveur PushDeer",
|
||||
"showCertificateExpiry": "Afficher l'expiration du certificat",
|
||||
"noOrBadCertificate": "Pas/Mauvais certificat",
|
||||
"pushDeerServerDescription": "Laissez le champ vide pour utiliser le serveur officiel",
|
||||
@@ -1088,5 +1088,34 @@
|
||||
"From": "De",
|
||||
"Can be found on:": "Disponible sur : {0}",
|
||||
"The phone number of the recipient in E.164 format.": "Le numéro de téléphone du destinataire au format E.164.",
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "Soit un identifiant d'expéditeur de texte, soit un numéro de téléphone au format E.164 si vous souhaitez pouvoir recevoir des réponses."
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "Soit un identifiant d'expéditeur de texte, soit un numéro de téléphone au format E.164 si vous souhaitez pouvoir recevoir des réponses.",
|
||||
"RabbitMQ Nodes": "Nœuds de gestion RabbitMQ",
|
||||
"rabbitmqNodesDescription": "Entrez l'URL des nœuds de gestion RabbitMQ, y compris le protocole et le port. Exemple : {0}",
|
||||
"rabbitmqNodesRequired": "Veuillez définir les nœuds pour cette sonde.",
|
||||
"rabbitmqNodesInvalid": "Veuillez utiliser une URL complète (commençant par « http ») pour les nœuds RabbitMQ.",
|
||||
"RabbitMQ Username": "Nom d'utilisateur RabbitMQ",
|
||||
"RabbitMQ Password": "Mot de passe RabbitMQ",
|
||||
"rabbitmqHelpText": "Pour utiliser la sonde, vous devrez activer le plug-in de gestion dans votre configuration RabbitMQ. Pour plus d'informations, veuillez consulter la {rabitmq_documentation}.",
|
||||
"SendGrid API Key": "Clé API SendGrid",
|
||||
"Separate multiple email addresses with commas": "Séparez plusieurs adresses e-mail par des virgules",
|
||||
"aboutSlackUsername": "Modifie le nom d'affichage de l'expéditeur du message. Si vous souhaitez mentionner quelqu’un, incluez-le plutôt dans le nom convivial.",
|
||||
"templateHostnameOrURL": "Nom d'hôte ou URL",
|
||||
"telegramUseTemplate": "Utiliser un modèle de message personnalisé",
|
||||
"telegramTemplateFormatDescription": "Telegram permet d'utiliser différents langages de balisage pour les messages, voir Telegram {0} pour plus de détails.",
|
||||
"Plain Text": "Texte brut",
|
||||
"YZJ Webhook URL": "URL du webhook YZJ",
|
||||
"YZJ Robot Token": "Jeton robot YZJ",
|
||||
"templateServiceName": "Nom du service",
|
||||
"templateStatus": "Status",
|
||||
"telegramUseTemplateDescription": "Si cette option est activée, le message sera envoyé à l'aide d'un modèle personnalisé.",
|
||||
"Message Template": "Modèle de message",
|
||||
"Template Format": "Format du modèle",
|
||||
"wayToGetWahaApiUrl": "L’URL de votre instance WAHA.",
|
||||
"wayToGetWahaSession": "À partir de cette session, WAHA envoie des notifications à l'ID de discussion. Vous pouvez le trouver dans le tableau de bord WAHA.",
|
||||
"wahaSession": "Session",
|
||||
"wahaChatId": "ID de discussion (numéro de téléphone / ID de contact / ID de groupe)",
|
||||
"wayToGetWahaApiKey": "La clé API est la valeur de la variable d'environnement WHATSAPP_API_KEY que vous avez utilisée pour exécuter WAHA.",
|
||||
"wayToWriteWahaChatId": "Le numéro de téléphone avec le préfixe international, mais sans le signe plus ({0}), l'identifiant de contact ({1}) ni l'identifiant de groupe ({2}). Les notifications sont envoyées à cet identifiant de chat depuis la session WAHA.",
|
||||
"telegramServerUrlDescription": "Pour lever les limitations de l’API des bots Telegram ou accéder aux zones bloquées (Chine, Iran, etc.). Pour plus d’informations, cliquez sur {0}. Par défaut : {1}",
|
||||
"telegramServerUrl": "(Facultatif) URL du serveur"
|
||||
}
|
||||
|
@@ -976,7 +976,7 @@
|
||||
"SNMP Version": "Leagan SNMP",
|
||||
"Please enter a valid OID.": "Cuir isteach OID bailí.",
|
||||
"Host Onesender": "Óstach Onesender",
|
||||
"Token Onesender": "Token Onesender",
|
||||
"Token Onesender": "Licín Onesender",
|
||||
"Recipient Type": "Cineál Faighteoir",
|
||||
"Private Number": "Uimhir Phríobháideach",
|
||||
"privateOnesenderDesc": "Cinntigh go bhfuil an uimhir theileafóin bailí. Chun teachtaireacht a sheoladh chuig uimhir ghutháin phríobháideach, sean: 628123456789",
|
||||
@@ -1016,5 +1016,42 @@
|
||||
"greater than": "níos mó ná",
|
||||
"less than or equal to": "níos lú ná nó cothrom le",
|
||||
"record": "taifead",
|
||||
"shrinkDatabaseDescriptionSqlite": "Bunachar sonraí truicear {vacuum} le haghaidh SQLite. Tá {auto_vacuum} cumasaithe cheana féin ach ní dhéanann sé seo scoilt ar an mbunachar sonraí ná athphacáil leathanaigh aonair an bhunachair sonraí mar a dhéanann an t-ordú {vacuum}."
|
||||
"shrinkDatabaseDescriptionSqlite": "Bunachar sonraí truicear {vacuum} le haghaidh SQLite. Tá {auto_vacuum} cumasaithe cheana féin ach ní dhéanann sé seo scoilt ar an mbunachar sonraí ná athphacáil leathanaigh aonair an bhunachair sonraí mar a dhéanann an t-ordú {vacuum}.",
|
||||
"aboutSlackUsername": "Athraítear ainm taispeána sheoltóir na teachtaireachta. Más mian leat duine éigin a lua, cuir san ainm cairdiúil é ina ionad sin.",
|
||||
"Custom sound to override default notification sound": "Fuaim shaincheaptha chun fuaim fógra réamhshocraithe a shárú",
|
||||
"Time sensitive notifications will be delivered immediately, even if the device is in do not disturb mode.": "Déanfar fógraí atá íogair ó thaobh ama a sheachadadh láithreach, fiú má tá an gléas i mód ná cuir isteach.",
|
||||
"rabbitmqNodesInvalid": "Bain úsáid as URL láncháilithe (ag tosú le 'http') le haghaidh nóid RabbitMQ.",
|
||||
"rabbitmqHelpText": "Chun an monatóir a úsáid, beidh ort an Breiseán Bainistíochta a chumasú i do chumrú RabbitMQ. Le haghaidh tuilleadh faisnéise, féach ar an {rabitmq_documentation}.",
|
||||
"Pop": "Popcheol",
|
||||
"Time Sensitive (iOS Only)": "Am-íogair (iOS amháin)",
|
||||
"From": "Ó",
|
||||
"Can be found on:": "Is féidir é a fháil ar: {0}",
|
||||
"The phone number of the recipient in E.164 format.": "Uimhir theileafóin an fhaighteora san fhormáid E.164.",
|
||||
"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.": "Aitheantas seoltóir téacs nó uimhir theileafóin i bhformáid E.164 más mian leat a bheith in ann freagraí a fháil.",
|
||||
"RabbitMQ Nodes": "Nóid Bainistíochta RabbitMQ",
|
||||
"rabbitmqNodesDescription": "Cuir isteach an URL do na nóid bhainistíochta RabbitMQ lena n-áirítear prótacal agus port. Sampla: {0}",
|
||||
"rabbitmqNodesRequired": "Socraigh na nóid don mhonatóir seo le do thoil.",
|
||||
"RabbitMQ Username": "Ainm Úsáideora RabbitMQ",
|
||||
"RabbitMQ Password": "RabbitMQ Pasfhocal",
|
||||
"SendGrid API Key": "Eochair API SendGrid",
|
||||
"Separate multiple email addresses with commas": "Scar seoltaí ríomhphoist iolracha le camóga",
|
||||
"ignoredTLSError": "Níor tugadh aird ar earráidí TLS/SSL",
|
||||
"Message format": "Formáid teachtaireachta",
|
||||
"Send rich messages": "Seol teachtaireachtaí saibhir",
|
||||
"Notification Channel": "Cainéal Fógraí",
|
||||
"Sound": "Fuaim",
|
||||
"Alphanumerical string and hyphens only": "Teaghrán alfa-uimhriúil agus fleiscíní amháin",
|
||||
"Arcade": "Stuara",
|
||||
"Correct": "Ceart",
|
||||
"Fail": "Teip",
|
||||
"Harp": "Cláirseach",
|
||||
"Reveal": "Nocht",
|
||||
"Bubble": "Mboilgeog",
|
||||
"Doorbell": "Cloigín an dorais",
|
||||
"Flute": "Fliúit",
|
||||
"Money": "Airgead",
|
||||
"Clear": "Glan",
|
||||
"Elevator": "Ardaitheoir",
|
||||
"Guitar": "Giotár",
|
||||
"Scifi": "Ficsean eolaíochta"
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user