From 3a188017228b2437820133827c36b03a7b9597f7 Mon Sep 17 00:00:00 2001 From: Justin Tisdale <jtisdale@Admins-MacBook-Pro.local> Date: Wed, 10 Aug 2022 21:46:43 -0400 Subject: [PATCH 01/57] Add Body Encoding field --- src/languages/en.js | 1 + src/pages/EditMonitor.vue | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/languages/en.js b/src/languages/en.js index b9951612..4433e2a5 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -553,4 +553,5 @@ export default { disableCloudflaredNoAuthMsg: "You are in No Auth mode, password is not require.", trustProxyDescription: "Trust 'X-Forwarded-*' headers. If you want to get the correct client IP and your Uptime Kuma is behind such as Nginx or Apache, you should enable this.", wayToGetLineNotifyToken: "You can get an access token from {0}", + "Body Encoding": "Body Encoding" }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index ac6a3e2e..7dcc7d64 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -396,6 +396,22 @@ </select> </div> + <!-- Encoding --> + <div class="my-3"> + <label for="bodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> + <select id="bodyEncoding" v-model="monitor.bodyEncoding" class="form-select"> + <option value="json"> + JSON + </option> + <option value="form"> + x-www-form-urlencoded + </option> + <option value="xml"> + XML + </option> + </select> + </div> + <!-- Body --> <div class="my-3"> <label for="body" class="form-label">{{ $t("Body") }}</label> @@ -644,6 +660,7 @@ export default { mqttTopic: "", mqttSuccessMessage: "", authMethod: null, + bodyEncoding: null }; if (this.$root.proxyList && !this.monitor.proxyId) { From 2b9bf095a609bbf2f2c517209b13cb57dbd1e1b1 Mon Sep 17 00:00:00 2001 From: Justin Tisdale <justin@justintisdale.com> Date: Thu, 11 Aug 2022 20:57:03 -0400 Subject: [PATCH 02/57] Add non-json support for http body --- db/patch-http-body-encoding.sql | 6 ++++++ server/database.js | 1 + server/model/monitor.js | 20 +++++++++++++++++++- server/server.js | 1 + src/pages/EditMonitor.vue | 13 +++++++------ 5 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 db/patch-http-body-encoding.sql diff --git a/db/patch-http-body-encoding.sql b/db/patch-http-body-encoding.sql new file mode 100644 index 00000000..de02bede --- /dev/null +++ b/db/patch-http-body-encoding.sql @@ -0,0 +1,6 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. +BEGIN TRANSACTION; + +ALTER TABLE [monitor] ADD http_body_encoding TEXT; + +COMMIT; diff --git a/server/database.js b/server/database.js index b234d67d..ecf6af72 100644 --- a/server/database.js +++ b/server/database.js @@ -62,6 +62,7 @@ class Database { "patch-add-clickable-status-page-link.sql": true, "patch-add-sqlserver-monitor.sql": true, "patch-add-other-auth.sql": { parents: [ "patch-monitor-basic-auth.sql" ] }, + "patch-http-body-encoding.sql": true }; /** diff --git a/server/model/monitor.js b/server/model/monitor.js index 2feef135..af3d162a 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -103,6 +103,7 @@ class Monitor extends BeanModel { authMethod: this.authMethod, authWorkstation: this.authWorkstation, authDomain: this.authDomain, + httpBodyEncoding: this.httpBodyEncoding }; if (includeSensitiveData) { @@ -241,16 +242,33 @@ class Monitor extends BeanModel { log.debug("monitor", `[${this.name}] Prepare Options for axios`); + // Set content-type header and body values based on the httpBodyEncoding type selected + // TODO: Check if this.headers already contains a content-type header set by the user; if so, don't inject one + let bodyValue = null; + let contentType = null; + + if (this.body && !this.httpBodyEncoding || this.httpBodyEncoding === "json"){ + bodyValue = JSON.parse(this.body); + contentType = "application/json"; + } else if (this.body && (this.httpBodyEncoding === "xml")) { + bodyValue = this.body; + contentType = "text/xml"; + } else if (this.body && (this.httpBodyEncoding === "form")) { + bodyValue = this.body; + contentType = "application/x-www-form-urlencoded"; + } + const options = { url: this.url, method: (this.method || "get").toLowerCase(), - ...(this.body ? { data: JSON.parse(this.body) } : {}), + ...(bodyValue ? { data: bodyValue } : {}), timeout: this.interval * 1000 * 0.8, headers: { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "User-Agent": "Uptime-Kuma/" + version, ...(this.headers ? JSON.parse(this.headers) : {}), ...(basicAuthHeader), + ...(contentType ? { "Content-Type": contentType } : {}) }, maxRedirects: this.maxredirects, validateStatus: (status) => { diff --git a/server/server.js b/server/server.js index 2a2c4bf6..616a10cd 100644 --- a/server/server.js +++ b/server/server.js @@ -693,6 +693,7 @@ let needSetup = false; bean.authMethod = monitor.authMethod; bean.authWorkstation = monitor.authWorkstation; bean.authDomain = monitor.authDomain; + bean.httpBodyEncoding = monitor.httpBodyEncoding; await R.store(bean); diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 7dcc7d64..b4aceba7 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -398,8 +398,8 @@ <!-- Encoding --> <div class="my-3"> - <label for="bodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> - <select id="bodyEncoding" v-model="monitor.bodyEncoding" class="form-select"> + <label for="httpBodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> + <select id="httpBodyEncoding" v-model="monitor.httpBodyEncoding" class="form-select"> <option value="json"> JSON </option> @@ -660,7 +660,7 @@ export default { mqttTopic: "", mqttSuccessMessage: "", authMethod: null, - bodyEncoding: null + httpBodyEncoding: "json" }; if (this.$root.proxyList && !this.monitor.proxyId) { @@ -698,7 +698,8 @@ export default { * @returns {boolean} Is the form input valid? */ isInputValid() { - if (this.monitor.body) { + //TODO: Handle validation for all 3 possible options + null value + if (this.monitor.body && (!this.monitor.httpBodyEncoding || this.monitor.httpBodyEncoding === "json")) { try { JSON.parse(this.monitor.body); } catch (err) { @@ -729,8 +730,8 @@ export default { return; } - // Beautify the JSON format - if (this.monitor.body) { + // Beautify the JSON format (only if httpBodyEncoding is not set or === json) + if (this.monitor.body && (!this.monitor.httpBodyEncoding || this.monitor.httpBodyEncoding === "json")) { this.monitor.body = JSON.stringify(JSON.parse(this.monitor.body), null, 4); } From 31cc328839c9462169070b4b67ba4044fb6716d8 Mon Sep 17 00:00:00 2001 From: Justin Tisdale <justin@justintisdale.com> Date: Thu, 11 Aug 2022 21:08:13 -0400 Subject: [PATCH 03/57] fix lint --- server/model/monitor.js | 2 +- src/languages/en.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 5d9c4cd4..8f30a0c1 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -252,7 +252,7 @@ class Monitor extends BeanModel { let bodyValue = null; let contentType = null; - if (this.body && !this.httpBodyEncoding || this.httpBodyEncoding === "json"){ + if (this.body && !this.httpBodyEncoding || this.httpBodyEncoding === "json") { bodyValue = JSON.parse(this.body); contentType = "application/json"; } else if (this.body && (this.httpBodyEncoding === "xml")) { diff --git a/src/languages/en.js b/src/languages/en.js index e338d778..31d92628 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -559,5 +559,5 @@ export default { disableCloudflaredNoAuthMsg: "You are in No Auth mode, password is not require.", trustProxyDescription: "Trust 'X-Forwarded-*' headers. If you want to get the correct client IP and your Uptime Kuma is behind such as Nginx or Apache, you should enable this.", wayToGetLineNotifyToken: "You can get an access token from {0}", - "Body Encoding": "Body Encoding" + "Body Encoding": "Body Encoding", }; From 5809088f27eb9604b043b782ac375f1feecc2e5a Mon Sep 17 00:00:00 2001 From: Justin Tisdale <justin@justintisdale.com> Date: Mon, 26 Sep 2022 15:52:43 -0400 Subject: [PATCH 04/57] Don't override a user-defined content-type header --- server/model/monitor.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 509b841c..c541ecf3 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -249,20 +249,28 @@ class Monitor extends BeanModel { log.debug("monitor", `[${this.name}] Prepare Options for axios`); - // Set content-type header and body values based on the httpBodyEncoding type selected - // TODO: Check if this.headers already contains a content-type header set by the user; if so, don't inject one - let bodyValue = null; - let contentType = null; + + // Check if this.headers already contains a content-type header set by the user; if so, don't inject one + let contentTypeUserDefinedHeader = this.headers.find(function(header) { + return header[0].toLowerCase() == "content-type"; + }); + + let contentType = contentTypeUserDefinedHeader ? + contentTypeUserDefinedHeader[1] : + null; + + let bodyValue = null; + if (this.body && !this.httpBodyEncoding || this.httpBodyEncoding === "json") { bodyValue = JSON.parse(this.body); - contentType = "application/json"; + contentType = contentType ? contentType : "application/json"; } else if (this.body && (this.httpBodyEncoding === "xml")) { bodyValue = this.body; - contentType = "text/xml"; + contentType = contentType ? contentType : "text/xml"; } else if (this.body && (this.httpBodyEncoding === "form")) { bodyValue = this.body; - contentType = "application/x-www-form-urlencoded"; + contentType = contentType ? contentType : "application/x-www-form-urlencoded"; } const options = { From 6537f4fe746c157c8a87ff25bbcefeb7a62522f3 Mon Sep 17 00:00:00 2001 From: Justin Tisdale <justin@justintisdale.com> Date: Mon, 26 Sep 2022 17:09:10 -0400 Subject: [PATCH 05/57] content-type change --- server/model/monitor.js | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index c541ecf3..48b0b1d3 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -249,28 +249,18 @@ class Monitor extends BeanModel { log.debug("monitor", `[${this.name}] Prepare Options for axios`); - - - // Check if this.headers already contains a content-type header set by the user; if so, don't inject one - let contentTypeUserDefinedHeader = this.headers.find(function(header) { - return header[0].toLowerCase() == "content-type"; - }); - - let contentType = contentTypeUserDefinedHeader ? - contentTypeUserDefinedHeader[1] : - null; - + let contentType = null; let bodyValue = null; if (this.body && !this.httpBodyEncoding || this.httpBodyEncoding === "json") { bodyValue = JSON.parse(this.body); - contentType = contentType ? contentType : "application/json"; + contentType = "application/json"; } else if (this.body && (this.httpBodyEncoding === "xml")) { bodyValue = this.body; - contentType = contentType ? contentType : "text/xml"; + contentType = "text/xml"; } else if (this.body && (this.httpBodyEncoding === "form")) { bodyValue = this.body; - contentType = contentType ? contentType : "application/x-www-form-urlencoded"; + contentType = "application/x-www-form-urlencoded"; } const options = { From f6919aef1d3b59dd23229feef6f2815004f34a80 Mon Sep 17 00:00:00 2001 From: Justin Tisdale <justin@justintisdale.com> Date: Mon, 26 Sep 2022 17:10:56 -0400 Subject: [PATCH 06/57] remove TODO --- src/pages/EditMonitor.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index ba667670..ea246c60 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -741,7 +741,6 @@ export default { * @returns {boolean} Is the form input valid? */ isInputValid() { - //TODO: Handle validation for all 3 possible options + null value if (this.monitor.body && (!this.monitor.httpBodyEncoding || this.monitor.httpBodyEncoding === "json")) { try { JSON.parse(this.monitor.body); From 4a7e96f9ea6235d797b3a0f68b8300d82aadfea6 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Thu, 6 Oct 2022 12:08:10 +0800 Subject: [PATCH 07/57] Init C# Project for building exe --- .dockerignore | 5 +- .gitignore | 3 + extra/exe-builder/App.config | 10 ++ extra/exe-builder/Program.cs | 59 +++++++++ extra/exe-builder/Properties/AssemblyInfo.cs | 36 ++++++ .../Properties/Resources.Designer.cs | 62 ++++++++++ extra/exe-builder/Properties/Resources.resx | 117 ++++++++++++++++++ .../Properties/Settings.Designer.cs | 23 ++++ .../exe-builder/Properties/Settings.settings | 7 ++ extra/exe-builder/UptimeKuma.csproj | 79 ++++++++++++ extra/exe-builder/UptimeKuma.sln | 16 +++ .../UptimeKuma.sln.DotSettings.user | 3 + 12 files changed, 418 insertions(+), 2 deletions(-) create mode 100644 extra/exe-builder/App.config create mode 100644 extra/exe-builder/Program.cs create mode 100644 extra/exe-builder/Properties/AssemblyInfo.cs create mode 100644 extra/exe-builder/Properties/Resources.Designer.cs create mode 100644 extra/exe-builder/Properties/Resources.resx create mode 100644 extra/exe-builder/Properties/Settings.Designer.cs create mode 100644 extra/exe-builder/Properties/Settings.settings create mode 100644 extra/exe-builder/UptimeKuma.csproj create mode 100644 extra/exe-builder/UptimeKuma.sln create mode 100644 extra/exe-builder/UptimeKuma.sln.DotSettings.user diff --git a/.dockerignore b/.dockerignore index babc429a..22b71b38 100644 --- a/.dockerignore +++ b/.dockerignore @@ -31,6 +31,7 @@ tsconfig.json /tmp /babel.config.js /ecosystem.config.js +extra/exe-builder ### .gitignore content (commented rules are duplicated) @@ -45,6 +46,6 @@ dist-ssr #!/data/.gitkeep #.vscode - - ### End of .gitignore content + + diff --git a/.gitignore b/.gitignore index 8eb05867..8e0edeac 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ dist-ssr cypress/videos cypress/screenshots + +extra/exe-builder/bin +extra/exe-builder/obj diff --git a/extra/exe-builder/App.config b/extra/exe-builder/App.config new file mode 100644 index 00000000..09265d8b --- /dev/null +++ b/extra/exe-builder/App.config @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" ?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /> + </startup> + + <System.Windows.Forms.ApplicationConfigurationSection> + <add key="DpiAwareness" value="PerMonitorV2" /> + </System.Windows.Forms.ApplicationConfigurationSection> +</configuration> diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs new file mode 100644 index 00000000..5516a1ff --- /dev/null +++ b/extra/exe-builder/Program.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using System.Windows.Forms; +using UptimeKuma.Properties; + +namespace UptimeKuma { + static class Program { + /// <summary> + /// The main entry point for the application. + /// </summary> + [STAThread] + static void Main() { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new UptimeKumaApplicationContext()); + } + } + + public class UptimeKumaApplicationContext : ApplicationContext + { + private NotifyIcon trayIcon; + + public UptimeKumaApplicationContext() + { + // Initialize Tray Icon + trayIcon = new NotifyIcon(); + + trayIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); + trayIcon.ContextMenu = new ContextMenu(new MenuItem[] { + new MenuItem("Check for Update", CheckForUpdate), + new MenuItem("About", About), + new MenuItem("Exit", Exit), + }); + + trayIcon.Visible = true; + } + + void Exit(object sender, EventArgs e) + { + // Hide tray icon, otherwise it will remain shown until user mouses over it + trayIcon.Visible = false; + Application.Exit(); + } + + void About(object sender, EventArgs e) + { + MessageBox.Show("Uptime Kuma v1.0.0" + Environment.NewLine + "© 2022 Louis Lam", "Info"); + } + + void CheckForUpdate(object sneder, EventArgs e) { + + } + } +} + diff --git a/extra/exe-builder/Properties/AssemblyInfo.cs b/extra/exe-builder/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..2552870b --- /dev/null +++ b/extra/exe-builder/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +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("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Uptime Kuma")] +[assembly: AssemblyCopyright("Copyright © 2022 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("2DB53988-1D93-4AC0-90C4-96ADEAAC5C04")] + +// 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.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/extra/exe-builder/Properties/Resources.Designer.cs b/extra/exe-builder/Properties/Resources.Designer.cs new file mode 100644 index 00000000..8c8e559c --- /dev/null +++ b/extra/exe-builder/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// <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; } + } + } +} \ No newline at end of file diff --git a/extra/exe-builder/Properties/Resources.resx b/extra/exe-builder/Properties/Resources.resx new file mode 100644 index 00000000..ffecec85 --- /dev/null +++ b/extra/exe-builder/Properties/Resources.resx @@ -0,0 +1,117 @@ +<?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> \ No newline at end of file diff --git a/extra/exe-builder/Properties/Settings.Designer.cs b/extra/exe-builder/Properties/Settings.Designer.cs new file mode 100644 index 00000000..6c63b395 --- /dev/null +++ b/extra/exe-builder/Properties/Settings.Designer.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// <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; } + } + } +} \ No newline at end of file diff --git a/extra/exe-builder/Properties/Settings.settings b/extra/exe-builder/Properties/Settings.settings new file mode 100644 index 00000000..abf36c5d --- /dev/null +++ b/extra/exe-builder/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?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> diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj new file mode 100644 index 00000000..d62166e4 --- /dev/null +++ b/extra/exe-builder/UptimeKuma.csproj @@ -0,0 +1,79 @@ +<?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>10</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> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <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.Net.Http" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <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="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> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/extra/exe-builder/UptimeKuma.sln b/extra/exe-builder/UptimeKuma.sln new file mode 100644 index 00000000..201d7e23 --- /dev/null +++ b/extra/exe-builder/UptimeKuma.sln @@ -0,0 +1,16 @@ + +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 diff --git a/extra/exe-builder/UptimeKuma.sln.DotSettings.user b/extra/exe-builder/UptimeKuma.sln.DotSettings.user new file mode 100644 index 00000000..b4ca9dad --- /dev/null +++ b/extra/exe-builder/UptimeKuma.sln.DotSettings.user @@ -0,0 +1,3 @@ +<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> \ No newline at end of file From da778f05ac30a681eeb71735dd21fc86eaef4a23 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Fri, 7 Oct 2022 00:16:07 +0800 Subject: [PATCH 08/57] Update --- extra/exe-builder/Program.cs | 42 ++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs index 5516a1ff..840bc873 100644 --- a/extra/exe-builder/Program.cs +++ b/extra/exe-builder/Program.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.Linq; using System.Reflection; @@ -23,6 +24,7 @@ namespace UptimeKuma { public class UptimeKumaApplicationContext : ApplicationContext { private NotifyIcon trayIcon; + private Process process; public UptimeKumaApplicationContext() { @@ -31,19 +33,41 @@ namespace UptimeKuma { trayIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); trayIcon.ContextMenu = new ContextMenu(new MenuItem[] { + new MenuItem("Open", Open), new MenuItem("Check for Update", CheckForUpdate), new MenuItem("About", About), new MenuItem("Exit", Exit), }); trayIcon.Visible = true; + + var startInfo = new ProcessStartInfo(); + startInfo.FileName = "node/node.exe"; + startInfo.Arguments = "server/server.js"; + startInfo.RedirectStandardOutput = true; + startInfo.RedirectStandardError = true; + startInfo.UseShellExecute = false; + startInfo.CreateNoWindow = true; + startInfo.WorkingDirectory = "core"; + + process = new Process(); + process.StartInfo = startInfo; + process.EnableRaisingEvents = true; + try { + process.Start(); + Open(null, null); + } catch (Exception e) { + MessageBox.Show("Startup failed: " + e.Message, "Uptime Kuma Error"); + throw; + } } - void Exit(object sender, EventArgs e) - { - // Hide tray icon, otherwise it will remain shown until user mouses over it - trayIcon.Visible = false; - Application.Exit(); + void Open(object sender, EventArgs e) { + Process.Start("http://localhost:3001"); + } + + void CheckForUpdate(object sender, EventArgs e) { + } void About(object sender, EventArgs e) @@ -51,8 +75,12 @@ namespace UptimeKuma { MessageBox.Show("Uptime Kuma v1.0.0" + Environment.NewLine + "© 2022 Louis Lam", "Info"); } - void CheckForUpdate(object sneder, EventArgs e) { - + void Exit(object sender, EventArgs e) + { + // Hide tray icon, otherwise it will remain shown until user mouses over it + trayIcon.Visible = false; + process.Close(); + Application.Exit(); } } } From 4c456547807dc3fb4d6de0a4da741ef252cb5c7e Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Fri, 7 Oct 2022 18:38:14 +0800 Subject: [PATCH 09/57] WIP --- extra/exe-builder/Program.cs | 69 +++++++++++++++++++++-------- extra/exe-builder/UptimeKuma.csproj | 5 ++- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs index 840bc873..84ecda31 100644 --- a/extra/exe-builder/Program.cs +++ b/extra/exe-builder/Program.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Drawing; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; using UptimeKuma.Properties; @@ -14,7 +15,7 @@ namespace UptimeKuma { /// The main entry point for the application. /// </summary> [STAThread] - static void Main() { + static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new UptimeKumaApplicationContext()); @@ -28,37 +29,44 @@ namespace UptimeKuma { public UptimeKumaApplicationContext() { - // Initialize Tray Icon trayIcon = new NotifyIcon(); trayIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); trayIcon.ContextMenu = new ContextMenu(new MenuItem[] { - new MenuItem("Open", Open), - new MenuItem("Check for Update", CheckForUpdate), - new MenuItem("About", About), - new MenuItem("Exit", Exit), + new("Open", Open), + //new("Debug Console", DebugConsole), + new("Check for Update...", CheckForUpdate), + new("Visit GitHub...", VisitGitHub), + new("About", About), + new("Exit", Exit), }); + trayIcon.MouseDoubleClick += new MouseEventHandler(Open); + trayIcon.Visible = true; - var startInfo = new ProcessStartInfo(); - startInfo.FileName = "node/node.exe"; - startInfo.Arguments = "server/server.js"; - startInfo.RedirectStandardOutput = true; - startInfo.RedirectStandardError = true; - startInfo.UseShellExecute = false; - startInfo.CreateNoWindow = true; - startInfo.WorkingDirectory = "core"; + 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 += new EventHandler(ProcessExited); + + try { process.Start(); - Open(null, null); + //Open(null, null); + } catch (Exception e) { MessageBox.Show("Startup failed: " + e.Message, "Uptime Kuma Error"); - throw; } } @@ -66,10 +74,19 @@ namespace UptimeKuma { Process.Start("http://localhost:3001"); } - void CheckForUpdate(object sender, EventArgs e) { + void DebugConsole(object sender, EventArgs e) { } + void CheckForUpdate(object sender, EventArgs e) { + Process.Start("https://github.com/louislam/uptime-kuma/releases"); + } + + void VisitGitHub(object sender, EventArgs e) + { + Process.Start("https://github.com/louislam/uptime-kuma"); + } + void About(object sender, EventArgs e) { MessageBox.Show("Uptime Kuma v1.0.0" + Environment.NewLine + "© 2022 Louis Lam", "Info"); @@ -79,9 +96,25 @@ namespace UptimeKuma { { // Hide tray icon, otherwise it will remain shown until user mouses over it trayIcon.Visible = false; - process.Close(); + process.Kill(); + } + + 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(); } + } } diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj index d62166e4..c3c6aad2 100644 --- a/extra/exe-builder/UptimeKuma.csproj +++ b/extra/exe-builder/UptimeKuma.csproj @@ -13,7 +13,7 @@ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <Deterministic>true</Deterministic> <ApplicationIcon>..\..\public\favicon.ico</ApplicationIcon> - <LangVersion>10</LangVersion> + <LangVersion>9</LangVersion> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> @@ -34,6 +34,9 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> + <PropertyGroup> + <PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "C:\Users\LouisLam\Desktop\uptime-kuma-win64\"</PostBuildEvent> + </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Core" /> From 3eaccb560ed1a0590a6bb3bf7f73765bbe06db00 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sat, 8 Oct 2022 16:23:11 +0800 Subject: [PATCH 10/57] Implement Download Logic --- extra/exe-builder/DownloadForm.Designer.cs | 84 +++++ extra/exe-builder/DownloadForm.cs | 65 ++++ extra/exe-builder/DownloadForm.resx | 377 +++++++++++++++++++++ extra/exe-builder/Program.cs | 23 +- extra/exe-builder/UptimeKuma.csproj | 9 + 5 files changed, 554 insertions(+), 4 deletions(-) create mode 100644 extra/exe-builder/DownloadForm.Designer.cs create mode 100644 extra/exe-builder/DownloadForm.cs create mode 100644 extra/exe-builder/DownloadForm.resx diff --git a/extra/exe-builder/DownloadForm.Designer.cs b/extra/exe-builder/DownloadForm.Designer.cs new file mode 100644 index 00000000..26a474e9 --- /dev/null +++ b/extra/exe-builder/DownloadForm.Designer.cs @@ -0,0 +1,84 @@ +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 + } +} + diff --git a/extra/exe-builder/DownloadForm.cs b/extra/exe-builder/DownloadForm.cs new file mode 100644 index 00000000..9c740e31 --- /dev/null +++ b/extra/exe-builder/DownloadForm.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Net; +using System.Windows.Forms; + +namespace UptimeKuma { + public partial class DownloadForm : Form { + private readonly Queue<DownloadItem> downloadQueue = new(); + private readonly WebClient webClient = new(); + + public DownloadForm() { + InitializeComponent(); + } + + private void DownloadForm_Load(object sender, EventArgs e) { + webClient.DownloadProgressChanged += DownloadProgressChanged; + webClient.DownloadFileCompleted += DownloadFileCompleted; + + if (!File.Exists("node")) { + downloadQueue.Enqueue(new DownloadItem { + URL = "https://nodejs.org/dist/v16.17.1/node-v16.17.1-win-x64.zip", + Filename = "node.zip" + }); + } + + if (!File.Exists("node")) { + downloadQueue.Enqueue(new DownloadItem { + URL = "https://github.com/louislam/uptime-kuma/archive/refs/tags/1.18.3.zip", + Filename = "core.zip" + }); + } + + DownloadNextFile(); + } + + void DownloadNextFile() { + if (downloadQueue.Count > 0) { + var item = downloadQueue.Dequeue(); + label.Text = item.URL; + webClient.DownloadFileAsync(new Uri(item.URL), item.Filename); + } else { + // TODO: Finished, extract? + } + } + + void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { + progressBar.Value = e.ProgressPercentage; + var total = e.TotalBytesToReceive / 1024; + var current = e.BytesReceived / 1024; + labelData.Text = $"{current}KB/{total}KB"; + } + + void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { + DownloadNextFile(); + } + } + + public class DownloadItem { + public string URL { get; set; } + public string Filename { get; set; } + } +} + diff --git a/extra/exe-builder/DownloadForm.resx b/extra/exe-builder/DownloadForm.resx new file mode 100644 index 00000000..e87e0c0d --- /dev/null +++ b/extra/exe-builder/DownloadForm.resx @@ -0,0 +1,377 @@ +<?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> \ No newline at end of file diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs index 84ecda31..84aa6e45 100644 --- a/extra/exe-builder/Program.cs +++ b/extra/exe-builder/Program.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Drawing; +using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; @@ -42,9 +43,23 @@ namespace UptimeKuma { }); trayIcon.MouseDoubleClick += new MouseEventHandler(Open); - trayIcon.Visible = true; + if (File.Exists("core") && File.Exists("node")) { + // Go go go + StartProcess(); + } else { + DownloadFiles(); + } + } + + void DownloadFiles() { + var form = new DownloadForm(); + form.Closed += Exit; + form.Show(); + } + + void StartProcess() { var startInfo = new ProcessStartInfo { FileName = "node/node.exe", Arguments = "server/server.js --data-dir=\"../data/\"", @@ -58,8 +73,7 @@ namespace UptimeKuma { process = new Process(); process.StartInfo = startInfo; process.EnableRaisingEvents = true; - process.Exited += new EventHandler(ProcessExited); - + process.Exited += ProcessExited; try { process.Start(); @@ -96,7 +110,8 @@ namespace UptimeKuma { { // Hide tray icon, otherwise it will remain shown until user mouses over it trayIcon.Visible = false; - process.Kill(); + process?.Kill(); + Application.Exit(); } void ProcessExited(object sender, EventArgs e) { diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj index c3c6aad2..aa0a8bf8 100644 --- a/extra/exe-builder/UptimeKuma.csproj +++ b/extra/exe-builder/UptimeKuma.csproj @@ -51,8 +51,17 @@ <Reference Include="System.Xml" /> </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" /> + <EmbeddedResource Include="DownloadForm.resx"> + <DependentUpon>DownloadForm.cs</DependentUpon> + </EmbeddedResource> <EmbeddedResource Include="Properties\Resources.resx"> <Generator>ResXFileCodeGenerator</Generator> <LastGenOutput>Resources.Designer.cs</LastGenOutput> From 655ba015a07c87e7b1a24ce8cafbe171103acad1 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sat, 8 Oct 2022 23:47:27 +0800 Subject: [PATCH 11/57] WIP --- extra/exe-builder/DownloadForm.cs | 127 ++++++++++++++++++++++++++-- extra/exe-builder/Program.cs | 2 +- extra/exe-builder/UptimeKuma.csproj | 3 +- 3 files changed, 121 insertions(+), 11 deletions(-) diff --git a/extra/exe-builder/DownloadForm.cs b/extra/exe-builder/DownloadForm.cs index 9c740e31..5bb88b6d 100644 --- a/extra/exe-builder/DownloadForm.cs +++ b/extra/exe-builder/DownloadForm.cs @@ -1,14 +1,19 @@ 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; namespace UptimeKuma { public partial class DownloadForm : Form { private readonly Queue<DownloadItem> downloadQueue = new(); private readonly WebClient webClient = new(); + private DownloadItem currentDownloadItem; public DownloadForm() { InitializeComponent(); @@ -18,17 +23,19 @@ namespace UptimeKuma { webClient.DownloadProgressChanged += DownloadProgressChanged; webClient.DownloadFileCompleted += DownloadFileCompleted; - if (!File.Exists("node")) { + if (!Directory.Exists("node")) { downloadQueue.Enqueue(new DownloadItem { URL = "https://nodejs.org/dist/v16.17.1/node-v16.17.1-win-x64.zip", - Filename = "node.zip" + Filename = "node.zip", + TargetFolder = "node" }); } - if (!File.Exists("node")) { + if (!Directory.Exists("node")) { downloadQueue.Enqueue(new DownloadItem { URL = "https://github.com/louislam/uptime-kuma/archive/refs/tags/1.18.3.zip", - Filename = "core.zip" + Filename = "core.zip", + TargetFolder = "core" }); } @@ -38,28 +45,130 @@ namespace UptimeKuma { void DownloadNextFile() { if (downloadQueue.Count > 0) { var item = downloadQueue.Dequeue(); - label.Text = item.URL; - webClient.DownloadFileAsync(new Uri(item.URL), item.Filename); + + 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 { - // TODO: Finished, extract? + npmSetup(); } } + void npmSetup() { + if (Directory.Exists("core/node_modules")) { + // Application.Restart(); + } + + label.Text = "npm run setup"; + progressBar.Value = 50; + labelData.Text = ""; + + var startInfo = new ProcessStartInfo { + FileName = "cmd.exe", + Arguments = "run setup", + RedirectStandardOutput = false, + RedirectStandardError = false, + RedirectStandardInput = true, + UseShellExecute = false, + CreateNoWindow = false, + WorkingDirectory = "core" + }; + + var process = new Process(); + process.StartInfo = startInfo; + process.EnableRaisingEvents = true; + process.Exited += (object _, EventArgs e) => { + // Application.Restart(); + progressBar.Value = 100; + + if (process.ExitCode == 0) { + label.Text = "Done"; + } else { + label.Text = "Failed, exit code: " + process.ExitCode; + } + + }; + process.Start(); + process.StandardInput.WriteLine("\"../node/npm\" run setup"); + } + void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { progressBar.Value = e.ProgressPercentage; var total = e.TotalBytesToReceive / 1024; var current = e.BytesReceived / 1024; - labelData.Text = $"{current}KB/{total}KB"; + + if (total > 0) { + labelData.Text = $"{current}KB/{total}KB"; + } } - void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { + async 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; } } } diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs index 84aa6e45..1b78f038 100644 --- a/extra/exe-builder/Program.cs +++ b/extra/exe-builder/Program.cs @@ -45,7 +45,7 @@ namespace UptimeKuma { trayIcon.MouseDoubleClick += new MouseEventHandler(Open); trayIcon.Visible = true; - if (File.Exists("core") && File.Exists("node")) { + if (Directory.Exists("core") && Directory.Exists("node") && Directory.Exists("core/node_modules")) { // Go go go StartProcess(); } else { diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj index aa0a8bf8..2ad857b2 100644 --- a/extra/exe-builder/UptimeKuma.csproj +++ b/extra/exe-builder/UptimeKuma.csproj @@ -35,11 +35,12 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup> - <PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "C:\Users\LouisLam\Desktop\uptime-kuma-win64\"</PostBuildEvent> + <PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "%UserProfile%\Desktop\uptime-kuma-win64\"</PostBuildEvent> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Core" /> + <Reference Include="System.IO.Compression.FileSystem" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> From a487347b3316cc3192b312a195ac44a46160d310 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sun, 9 Oct 2022 03:47:06 +0800 Subject: [PATCH 12/57] [exe] install dependencies and download dist --- extra/exe-builder/DownloadForm.cs | 21 +++++++++++---------- extra/exe-builder/Program.cs | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/extra/exe-builder/DownloadForm.cs b/extra/exe-builder/DownloadForm.cs index 5bb88b6d..f16af422 100644 --- a/extra/exe-builder/DownloadForm.cs +++ b/extra/exe-builder/DownloadForm.cs @@ -63,12 +63,6 @@ namespace UptimeKuma { } void npmSetup() { - if (Directory.Exists("core/node_modules")) { - // Application.Restart(); - } - - label.Text = "npm run setup"; - progressBar.Value = 50; labelData.Text = ""; var startInfo = new ProcessStartInfo { @@ -86,10 +80,12 @@ namespace UptimeKuma { process.StartInfo = startInfo; process.EnableRaisingEvents = true; process.Exited += (object _, EventArgs e) => { - // Application.Restart(); - progressBar.Value = 100; + progressBar.Value = 100; if (process.ExitCode == 0) { + Task.Delay(2000).ContinueWith((task) => { + Application.Restart(); + }); label.Text = "Done"; } else { label.Text = "Failed, exit code: " + process.ExitCode; @@ -97,7 +93,12 @@ namespace UptimeKuma { }; process.Start(); - process.StandardInput.WriteLine("\"../node/npm\" run setup"); + label.Text = "Installing dependencies and download dist files"; + progressBar.Value = 50; + + process.StandardInput.WriteLine("\"../node/npm\" ci --production"); + process.StandardInput.WriteLine("\"../node/npm\" run download-dist"); + process.StandardInput.WriteLine("exit"); } void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { @@ -110,7 +111,7 @@ namespace UptimeKuma { } } - async void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { + void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { Extract(currentDownloadItem); DownloadNextFile(); } diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs index 1b78f038..82c76b05 100644 --- a/extra/exe-builder/Program.cs +++ b/extra/exe-builder/Program.cs @@ -45,7 +45,7 @@ namespace UptimeKuma { trayIcon.MouseDoubleClick += new MouseEventHandler(Open); trayIcon.Visible = true; - if (Directory.Exists("core") && Directory.Exists("node") && Directory.Exists("core/node_modules")) { + if (Directory.Exists("core") && Directory.Exists("node") && Directory.Exists("core/node_modules") && Directory.Exists("core/dist")) { // Go go go StartProcess(); } else { From da16796ec45a3ecb12f16a1855bca0813beb2571 Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko <git@nlutsenko.me> Date: Sat, 19 Nov 2022 16:10:30 -0800 Subject: [PATCH 13/57] Add ability to send Telegram notifications silently. --- server/notification-providers/telegram.js | 1 + src/components/notifications/Telegram.vue | 9 +++++++++ src/languages/en.js | 2 ++ 3 files changed, 12 insertions(+) diff --git a/server/notification-providers/telegram.js b/server/notification-providers/telegram.js index 2b057622..88923e66 100644 --- a/server/notification-providers/telegram.js +++ b/server/notification-providers/telegram.js @@ -13,6 +13,7 @@ class Telegram extends NotificationProvider { params: { chat_id: notification.telegramChatID, text: msg, + disable_notification: notification.telegramSendSilently, }, }); return okMsg; diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 9daf31ac..4eb014ff 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -28,6 +28,15 @@ <a :href="telegramGetUpdatesURL('withToken')" target="_blank" style="word-break: break-word;">{{ telegramGetUpdatesURL("masked") }}</a> </p> </div> + + <div class="form-check form-switch"> + <input v-model="$parentnotification.telegramSendSilently" class="form-check-input" type="checkbox"> + <label class="form-check-label">{{ $t("Send Silently") }}</label> + </div> + + <div class="form-text"> + {{ $t("telegramSendSilentlyDescription") }} + </div> </div> </template> diff --git a/src/languages/en.js b/src/languages/en.js index 86abb791..492689e5 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -214,6 +214,8 @@ export default { "Chat ID": "Chat ID", 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:", + "Send Silently": "Send Silently", + telegramSendSilentlyDescription: "Sends the message silently. Users will receive a notification with no sound.", "YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE", chatIDNotFound: "Chat ID is not found; please send a message to this bot first", webhook: "Webhook", From b91fe9d96d1b8be9f6abbb241432d53fd9b61247 Mon Sep 17 00:00:00 2001 From: shyneko <tminei@ukr.net> Date: Thu, 12 Jan 2023 15:09:05 +0200 Subject: [PATCH 14/57] Added a more telegram options such as thread id, silent notifications and forward protect --- server/notification-providers/telegram.js | 17 +++++++++--- src/components/notifications/Telegram.vue | 34 +++++++++++++++++++++++ src/languages/en.js | 6 ++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/server/notification-providers/telegram.js b/server/notification-providers/telegram.js index 2b057622..9c8f5750 100644 --- a/server/notification-providers/telegram.js +++ b/server/notification-providers/telegram.js @@ -9,11 +9,20 @@ class Telegram extends NotificationProvider { let okMsg = "Sent Successfully."; try { + const paramsObj = + { + chat_id: notification.telegramChatID, + text: msg, + disable_notification: notification.telegramSilentNotification ?? false, + protect_content: notification.telegramProtectContent ?? false, + + }; + // if telegramChatThread specified, then add it to paramsObj + if (notification.telegramChatThread && notification.telegramChatThread.length > 0) { + paramsObj.message_thread_id = notification.telegramChatThread; + } await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, { - params: { - chat_id: notification.telegramChatID, - text: msg, - }, + params: paramsObj }); return okMsg; diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 9daf31ac..9b373b99 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -29,6 +29,40 @@ </p> </div> </div> + + <div class="mb-3"> + <label for="telegram-chat-thread" class="form-label">{{ $t("Thread ID") }}</label> + + <div class="input-group mb-3"> + <input id="telegram-chat-thread" v-model="$parent.notification.telegramChatThread" type="text" class="form-control" required> + </div> + + <div class="form-text"> + {{ $t("Thread ID Description") }} + </div> + </div> + + <div class="mb-3"> + <div class="form-check form-switch"> + <input v-model="$parent.notification.telegramSilentNotification" class="form-check-input" type="checkbox"> + <label class="form-check-label">{{ $t("Silent Notification") }}</label> + </div> + + <div class="form-text"> + {{ $t("Silent Notification Description") }} + </div> + </div> + + <div class="mb-3"> + <div class="form-check form-switch"> + <input v-model="$parent.notification.telegramProtectContent" class="form-check-input" type="checkbox"> + <label class="form-check-label">{{ $t("Protect Forwarding") }}</label> + </div> + + <div class="form-text"> + {{ $t("Protect Forwarding Description") }} + </div> + </div> </template> <script> diff --git a/src/languages/en.js b/src/languages/en.js index 7a48d0d0..f09212b8 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -216,6 +216,12 @@ export default { 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:", "YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE", + "Silent Notification": "Silent Notification", + "Silent Notification Description": "If enabled, the notification in Telegram will be without sound.", + "Protect Forwarding": "Protect Forwarding", + "Protect Forwarding Description": "If enabled, the notification in Telegram will be protected from forwarding and saving.", + "Thread ID": "Thread ID (optional)", + "Thread ID Description": "Since November 5 2022, bots can send messages to a specific thread. You can get the thread ID by clicking on the thread name in the chat.", chatIDNotFound: "Chat ID is not found; please send a message to this bot first", webhook: "Webhook", "Post URL": "Post URL", From 521356e38a2a9386c1f981c3b56c0e2e22312de1 Mon Sep 17 00:00:00 2001 From: shyneko <tminei@ukr.net> Date: Thu, 12 Jan 2023 15:21:56 +0200 Subject: [PATCH 15/57] LINT fixes --- src/components/notifications/Telegram.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 9b373b99..7a1e659e 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -37,13 +37,13 @@ <input id="telegram-chat-thread" v-model="$parent.notification.telegramChatThread" type="text" class="form-control" required> </div> - <div class="form-text"> + <div class="form-text"> {{ $t("Thread ID Description") }} </div> </div> <div class="mb-3"> - <div class="form-check form-switch"> + <div class="form-check form-switch"> <input v-model="$parent.notification.telegramSilentNotification" class="form-check-input" type="checkbox"> <label class="form-check-label">{{ $t("Silent Notification") }}</label> </div> @@ -54,7 +54,7 @@ </div> <div class="mb-3"> - <div class="form-check form-switch"> + <div class="form-check form-switch"> <input v-model="$parent.notification.telegramProtectContent" class="form-check-input" type="checkbox"> <label class="form-check-label">{{ $t("Protect Forwarding") }}</label> </div> From 27e0b1eea103060202e79aa0ae2028165d11b006 Mon Sep 17 00:00:00 2001 From: shyneko <tminei@ukr.net> Date: Thu, 12 Jan 2023 15:52:50 +0200 Subject: [PATCH 16/57] Remove required attribute for optional field --- src/components/notifications/Telegram.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 7a1e659e..66bc7e93 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -34,7 +34,7 @@ <label for="telegram-chat-thread" class="form-label">{{ $t("Thread ID") }}</label> <div class="input-group mb-3"> - <input id="telegram-chat-thread" v-model="$parent.notification.telegramChatThread" type="text" class="form-control" required> + <input id="telegram-chat-thread" v-model="$parent.notification.telegramChatThread" type="text" class="form-control"> </div> <div class="form-text"> From e427c70fef567f6957ab681c550e71fd0f92282c Mon Sep 17 00:00:00 2001 From: shyneko <tminei@ukr.net> Date: Thu, 12 Jan 2023 16:00:02 +0200 Subject: [PATCH 17/57] Translate fixes --- src/languages/en.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/en.js b/src/languages/en.js index f09212b8..a1ac41b7 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -219,7 +219,7 @@ export default { "Silent Notification": "Silent Notification", "Silent Notification Description": "If enabled, the notification in Telegram will be without sound.", "Protect Forwarding": "Protect Forwarding", - "Protect Forwarding Description": "If enabled, the notification in Telegram will be protected from forwarding and saving.", + "Protect Forwarding Description": "If enabled, the bot messages in Telegram will be protected from forwarding and saving.", "Thread ID": "Thread ID (optional)", "Thread ID Description": "Since November 5 2022, bots can send messages to a specific thread. You can get the thread ID by clicking on the thread name in the chat.", chatIDNotFound: "Chat ID is not found; please send a message to this bot first", From 3adc9e65d6d5cd461abc461929f29513bc41e21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Sat, 14 Jan 2023 16:33:21 +0300 Subject: [PATCH 18/57] Add only xml support to http monitors --- server/model/monitor.js | 7 ++----- src/pages/EditMonitor.vue | 23 ++++++++--------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 48b0b1d3..d93fd6dd 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -251,16 +251,13 @@ class Monitor extends BeanModel { let contentType = null; let bodyValue = null; - + if (this.body && !this.httpBodyEncoding || this.httpBodyEncoding === "json") { bodyValue = JSON.parse(this.body); contentType = "application/json"; } else if (this.body && (this.httpBodyEncoding === "xml")) { bodyValue = this.body; - contentType = "text/xml"; - } else if (this.body && (this.httpBodyEncoding === "form")) { - bodyValue = this.body; - contentType = "application/x-www-form-urlencoded"; + contentType = "text/xml; charset=utf-8"; } const options = { diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index ea246c60..05b89ab0 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -438,21 +438,14 @@ </select> </div> - <!-- Encoding --> - <div class="my-3"> - <label for="httpBodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> - <select id="httpBodyEncoding" v-model="monitor.httpBodyEncoding" class="form-select"> - <option value="json"> - JSON - </option> - <option value="form"> - x-www-form-urlencoded - </option> - <option value="xml"> - XML - </option> - </select> - </div> + <!-- Encoding --> + <div class="my-3"> + <label for="httpBodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> + <select id="httpBodyEncoding" v-model="monitor.httpBodyEncoding" class="form-select"> + <option value="json">JSON</option> + <option value="xml">XML</option> + </select> + </div> <!-- Body --> <div class="my-3"> From 15c64d458b69489b455ee90b13dd610446a091ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Sat, 14 Jan 2023 16:48:12 +0300 Subject: [PATCH 19/57] Fix lint --- src/pages/EditMonitor.vue | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index a68a1206..65680109 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -463,13 +463,13 @@ </div> <!-- Encoding --> - <div class="my-3"> - <label for="httpBodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> - <select id="httpBodyEncoding" v-model="monitor.httpBodyEncoding" class="form-select"> - <option value="json">JSON</option> - <option value="xml">XML</option> - </select> - </div> + <div class="my-3"> + <label for="httpBodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> + <select id="httpBodyEncoding" v-model="monitor.httpBodyEncoding" class="form-select"> + <option value="json">JSON</option> + <option value="xml">XML</option> + </select> + </div> <!-- Body --> <div class="my-3"> From 9890a0754b409d458d7563c0d9a31dcbb20d76b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Sat, 14 Jan 2023 16:48:26 +0300 Subject: [PATCH 20/57] Fix lint --- src/pages/EditMonitor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 65680109..8d5e3e9d 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -462,7 +462,7 @@ </select> </div> - <!-- Encoding --> + <!-- Encoding --> <div class="my-3"> <label for="httpBodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> <select id="httpBodyEncoding" v-model="monitor.httpBodyEncoding" class="form-select"> From cf21aa37376bc3175f4302940b5945a0704f81be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Sat, 14 Jan 2023 16:51:07 +0300 Subject: [PATCH 21/57] Fix lint --- src/pages/EditMonitor.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 8d5e3e9d..8706c4aa 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -466,8 +466,8 @@ <div class="my-3"> <label for="httpBodyEncoding" class="form-label">{{ $t("Body Encoding") }}</label> <select id="httpBodyEncoding" v-model="monitor.httpBodyEncoding" class="form-select"> - <option value="json">JSON</option> - <option value="xml">XML</option> + <option value="json">JSON</option> + <option value="xml">XML</option> </select> </div> From aef85078eb5fbb0e48db31cd40f5d7eaf6c06792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Fri, 20 Jan 2023 12:29:56 +0300 Subject: [PATCH 22/57] reorder fix --- server/model/monitor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index c0721c48..ec56ba45 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -290,9 +290,9 @@ class Monitor extends BeanModel { headers: { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "User-Agent": "Uptime-Kuma/" + version, - ...(this.headers ? JSON.parse(this.headers) : {}), + ...(contentType ? { "Content-Type": contentType } : {}), ...(basicAuthHeader), - ...(contentType ? { "Content-Type": contentType } : {}) + ...(this.headers ? JSON.parse(this.headers) : {}) }, maxRedirects: this.maxredirects, validateStatus: (status) => { From f155ec9ba884607e889402fefbb1935adbd74d48 Mon Sep 17 00:00:00 2001 From: Thomas Spalinger <spali@spali.ch> Date: Tue, 24 Jan 2023 09:14:16 +0000 Subject: [PATCH 23/57] remember prometheus instance and expose it in preperation for #2491,#680 and #898 --- server/model/monitor.js | 14 +++++++------- server/server.js | 3 --- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 28fae9e6..53b7985e 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -200,7 +200,7 @@ class Monitor extends BeanModel { let previousBeat = null; let retries = 0; - let prometheus = new Prometheus(this); + this.prometheus = new Prometheus(this); const beat = async () => { @@ -729,7 +729,7 @@ class Monitor extends BeanModel { await R.store(bean); log.debug("monitor", `[${this.name}] prometheus.update`); - prometheus.update(bean, tlsInfo); + this.prometheus.update(bean, tlsInfo); previousBeat = bean; @@ -814,15 +814,15 @@ class Monitor extends BeanModel { clearTimeout(this.heartbeatInterval); this.isStop = true; - this.prometheus().remove(); + this.prometheus.remove(); } /** - * Get a new prometheus instance - * @returns {Prometheus} + * Get prometheus instance + * @returns {Prometheus|undefined} */ - prometheus() { - return new Prometheus(this); + getPrometheus() { + return this.prometheus; } /** diff --git a/server/server.js b/server/server.js index f43008e2..4574292b 100644 --- a/server/server.js +++ b/server/server.js @@ -674,9 +674,6 @@ let needSetup = false; throw new Error("Permission denied."); } - // Reset Prometheus labels - server.monitorList[monitor.id]?.prometheus()?.remove(); - bean.name = monitor.name; bean.type = monitor.type; bean.url = monitor.url; From 2673b509a598c9dc311b00cf9205a0353c9b5609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Wed, 25 Jan 2023 20:22:50 +0300 Subject: [PATCH 24/57] Add "Body Encoding" to en.json --- src/lang/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang/en.json b/src/lang/en.json index f2f16693..d01ccd20 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -682,5 +682,6 @@ "onebotUserOrGroupId": "Group/User ID", "onebotSafetyTips": "For safety, must set access token", "PushDeer Key": "PushDeer Key", - "wayToGetClickSendSMSToken": "You can get API Username and API Key from {0} ." + "wayToGetClickSendSMSToken": "You can get API Username and API Key from {0} .", + "Body Encoding": "Body Encoding" } From b2ddb5c9eb47105d9855106960e44295e04e427c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Thu, 2 Feb 2023 19:50:14 +0300 Subject: [PATCH 25/57] Dummy commit for build --- src/lang/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/en.json b/src/lang/en.json index dc5663f1..e1d7abec 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -691,5 +691,5 @@ "PushDeer Key": "PushDeer Key", "wayToGetClickSendSMSToken": "You can get API Username and API Key from {0} .", "Custom Monitor Type": "Custom Monitor Type", - "Body Encoding": "Body Encoding" + "Body Encoding": "Body Encoding", } From 603b3a7fb6145c196114f9786637430e65e6b561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Thu, 2 Feb 2023 19:50:29 +0300 Subject: [PATCH 26/57] Dummy commit for build --- src/lang/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/en.json b/src/lang/en.json index e1d7abec..dc5663f1 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -691,5 +691,5 @@ "PushDeer Key": "PushDeer Key", "wayToGetClickSendSMSToken": "You can get API Username and API Key from {0} .", "Custom Monitor Type": "Custom Monitor Type", - "Body Encoding": "Body Encoding", + "Body Encoding": "Body Encoding" } From 1bfb29071874651d1364edd5cd9d4138fe31d46e Mon Sep 17 00:00:00 2001 From: Haytham Salama <haythamasalama@gmail.com> Date: Sat, 4 Feb 2023 22:53:38 +0200 Subject: [PATCH 27/57] feat: add message thread id for telegram nonfiction --- server/notification-providers/telegram.js | 1 + src/components/notifications/Telegram.vue | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/server/notification-providers/telegram.js b/server/notification-providers/telegram.js index 2b057622..fb53b971 100644 --- a/server/notification-providers/telegram.js +++ b/server/notification-providers/telegram.js @@ -13,6 +13,7 @@ class Telegram extends NotificationProvider { params: { chat_id: notification.telegramChatID, text: msg, + message_thread_id: notification.telegramMessageThreadID, }, }); return okMsg; diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 723bd1be..3f446dc8 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -17,6 +17,11 @@ </button> </div> + + <label for="message_thread_id" class="form-label">{{ $t("Message Thread ID") }}</label> + <input id="message_thread_id" v-model="$parent.notification.telegramMessageThreadID" type="text" class="form-control"> + <p class="form-text">Message Thread ID: Optional Unique identifier for the target message thread (topic) of the forum; for forum supergroups only</p> + <div class="form-text"> {{ $t("supportTelegramChatID") }} From 4323dee7815559ff22ff191ef56639c686015926 Mon Sep 17 00:00:00 2001 From: Haytham Salama <haythamasalama@gmail.com> Date: Sat, 4 Feb 2023 22:54:19 +0200 Subject: [PATCH 28/57] feat: add message thread id to lang --- src/lang/ar-SY.json | 1 + src/lang/bg-BG.json | 1 + src/lang/cs-CZ.json | 1 + src/lang/da-DK.json | 1 + src/lang/de-CH.json | 1 + src/lang/de-DE.json | 1 + src/lang/el-GR.json | 1 + src/lang/en.json | 1 + src/lang/nl-NL.json | 1 + src/lang/pl.json | 1 + src/lang/ru-RU.json | 1 + src/lang/sl-SI.json | 1 + src/lang/th-TH.json | 1 + src/lang/tr-TR.json | 1 + src/lang/uk-UA.json | 1 + src/lang/vi-VN.json | 1 + src/lang/zh-CN.json | 1 + src/lang/zh-HK.json | 1 + src/lang/zh-TW.json | 1 + 19 files changed, 19 insertions(+) diff --git a/src/lang/ar-SY.json b/src/lang/ar-SY.json index d852a690..98dacd5f 100644 --- a/src/lang/ar-SY.json +++ b/src/lang/ar-SY.json @@ -215,6 +215,7 @@ "Bot Token": "رمز الروبوت", "wayToGetTelegramToken": "يمكنك الحصول على رمز من {0}.", "Chat ID": "معرف الدردشة", + "Message Thread ID": "معرف المواضيع", "supportTelegramChatID": "دعم الدردشة المباشرة / معرف الدردشة للقناة", "wayToGetTelegramChatID": "يمكنك الحصول على معرف الدردشة الخاص بك عن طريق إرسال رسالة إلى الروبوت والانتقال إلى عنوان URL هذا لعرض Chat_id", "YOUR BOT TOKEN HERE": "رمز الروبوت الخاص بك هنا", diff --git a/src/lang/bg-BG.json b/src/lang/bg-BG.json index 3a5f532d..db81e21f 100644 --- a/src/lang/bg-BG.json +++ b/src/lang/bg-BG.json @@ -210,6 +210,7 @@ "Bot Token": "Бот токен", "wayToGetTelegramToken": "Можете да получите токен от {0}.", "Chat ID": "Чат ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Поддържа Direct Chat / Group / Channel's Chat ID", "wayToGetTelegramChatID": "Можете да получите вашето чат ID, като изпратите съобщение на бота, след което е нужно да посетите този URL адрес за да го видите:", "YOUR BOT TOKEN HERE": "ВАШИЯТ БОТ ТОКЕН ТУК", diff --git a/src/lang/cs-CZ.json b/src/lang/cs-CZ.json index c6b28312..6a0738da 100644 --- a/src/lang/cs-CZ.json +++ b/src/lang/cs-CZ.json @@ -215,6 +215,7 @@ "Bot Token": "Token robota", "wayToGetTelegramToken": "Token můžete získat od {0}.", "Chat ID": "ID chatu", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Podpora přímého chatu / skupiny / ID chatu kanálu", "wayToGetTelegramChatID": "ID chatu můžete získat tak, že robotovi zašlete zprávu a přejdete na tuto adresu URL, kde zobrazíte chat_id:", "YOUR BOT TOKEN HERE": "SEM ZADEJTE TOKEN VAŠEHO CHATBOTA", diff --git a/src/lang/da-DK.json b/src/lang/da-DK.json index 679431c3..4cfc222c 100644 --- a/src/lang/da-DK.json +++ b/src/lang/da-DK.json @@ -208,6 +208,7 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Du kan få et token fra {0}.", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Support Direct Chat / Group / Channel's Chat ID", "wayToGetTelegramChatID": "Du kan få dit chat-ID ved at sende en besked til bot'en og gå til denne URL for at se chat_id'et:", "YOUR BOT TOKEN HERE": "DIT BOT TOKEN HER", diff --git a/src/lang/de-CH.json b/src/lang/de-CH.json index 85da35e0..42cb3c9e 100644 --- a/src/lang/de-CH.json +++ b/src/lang/de-CH.json @@ -214,6 +214,7 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Hier kannst du einen Token erhalten {0}.", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Unterstützt Direkt Chat / Gruppe / Kanal Chat-ID's", "wayToGetTelegramChatID": "Du kannst die Chat-ID erhalten, indem du eine Nachricht an den Bot sendest und zu dieser URL gehst, um die chat_id: zu sehen.", "YOUR BOT TOKEN HERE": "HIER DEIN BOT TOKEN", diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 45b5ae56..d4a023ec 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -214,6 +214,7 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Hier kannst du einen Token erhalten {0}.", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Unterstützt Direkt Chat / Gruppe / Kanal Chat-ID's", "wayToGetTelegramChatID": "Du kannst die Chat-ID erhalten, indem du eine Nachricht an den Bot sendest und zu dieser URL gehst, um die chat_id: zu sehen.", "YOUR BOT TOKEN HERE": "HIER DEIN BOT TOKEN", diff --git a/src/lang/el-GR.json b/src/lang/el-GR.json index c77d6158..7031290b 100644 --- a/src/lang/el-GR.json +++ b/src/lang/el-GR.json @@ -198,6 +198,7 @@ "Bot Token": "Διακριτικό Bot", "wayToGetTelegramToken": "Μπορείτε να πάρετε ένα διακριτικό από {0}.", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Support Direct Chat / Group / Channel's Chat ID", "wayToGetTelegramChatID": "Μπορείτε να λάβετε το αναγνωριστικό συνομιλίας σας στέλνοντας ένα μήνυμα στο bot και μεταβαίνοντας σε αυτήν τη διεύθυνση URL για να προβάλετε το chat_id:", "YOUR BOT TOKEN HERE": "ΤΟ BOT ΣΑΣ ΔΙΑΚΡΙΤΙΚΌ ΕΔΩ", diff --git a/src/lang/en.json b/src/lang/en.json index 8a195a2a..6e26612d 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -364,6 +364,7 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "You can get a token from {0}.", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "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:", "YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE", diff --git a/src/lang/nl-NL.json b/src/lang/nl-NL.json index 32c79545..e4c1da00 100644 --- a/src/lang/nl-NL.json +++ b/src/lang/nl-NL.json @@ -217,6 +217,7 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Je kunt een token krijgen van {0}.", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Ondersteuning Directe Chat / Groep / Kanaal Chat ID", "wayToGetTelegramChatID": "Je kunt je CHAT ID krijgen door een bericht te sturen naar de bot en naar deze URL te gaan om het chat_id te bekijken:", "YOUR BOT TOKEN HERE": "DE BOT TOKEN HIER", diff --git a/src/lang/pl.json b/src/lang/pl.json index ebc58797..50bb7fbf 100644 --- a/src/lang/pl.json +++ b/src/lang/pl.json @@ -189,6 +189,7 @@ "Bot Token": "Token bota", "wayToGetTelegramToken": "Token można uzyskać z {0}.", "Chat ID": "Identyfikator czatu", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Czat wsparcia technicznego / Bezpośrednia rozmowa / Czat grupowy", "wayToGetTelegramChatID": "Możesz uzyskać swój identyfikator czatu, wysyłając wiadomość do bota i przechodząc pod ten adres URL, aby wyświetlić identyfikator czatu:", "YOUR BOT TOKEN HERE": "TWÓJ TOKEN BOTA", diff --git a/src/lang/ru-RU.json b/src/lang/ru-RU.json index 8395eedb..c38b6808 100644 --- a/src/lang/ru-RU.json +++ b/src/lang/ru-RU.json @@ -216,6 +216,7 @@ "Bot Token": "Токен бота", "wayToGetTelegramToken": "Вы можете взять токен здесь - {0}.", "Chat ID": "ID чата", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Поддерживаются ID чатов, групп и каналов", "wayToGetTelegramChatID": "Вы можете взять ID вашего чата, отправив сообщение боту и перейдя по этому URL для просмотра chat_id:", "YOUR BOT TOKEN HERE": "ВАШ ТОКЕН БОТА ЗДЕСЬ", diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index f4ca81bd..bf32cbed 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -193,6 +193,7 @@ "Bot Token": "Robotkov žetonček", "wayToGetTelegramToken": "Lahko dobiš žeton od {0}.", "Chat ID": "ID pogovora", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Direkten pogovor pomoči / Skupina / ID kanala", "wayToGetTelegramChatID": "Id lahko dobiš, če pošlješ sporočilo robotku in odpreš ta URL, da bi videl chat_id:", "YOUR BOT TOKEN HERE": "ROBOTKOV ŽETON TUKAJ", diff --git a/src/lang/th-TH.json b/src/lang/th-TH.json index 7ad132f5..76c2afb3 100644 --- a/src/lang/th-TH.json +++ b/src/lang/th-TH.json @@ -194,6 +194,7 @@ "Bot Token": "กุญแจของบอท", "wayToGetTelegramToken": "คุณสามารถรับกุญแจได้จาก {0}.", "Chat ID": "ไอดีแชท", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "รองรับ แชทส่วนตัว, แชทกลุ่ม, ไอดีแชท", "wayToGetTelegramChatID": "คุณสามารถรับ ID แชทของคุณได้โดยส่งข้อความไปยังบอทและไปที่ URL นี้เพื่อดู chat_id :", "YOUR BOT TOKEN HERE": "กุญแจของบอทของคุณที่นี่", diff --git a/src/lang/tr-TR.json b/src/lang/tr-TR.json index b9bc8adc..a9070df3 100644 --- a/src/lang/tr-TR.json +++ b/src/lang/tr-TR.json @@ -197,6 +197,7 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "{0} adresinden bir token alabilirsiniz.", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Doğrudan Sohbet / Grup / Kanalın Sohbet Kimliğini Destekleyin", "wayToGetTelegramChatID": "Bot'a bir mesaj göndererek ve chat_id'yi görüntülemek için bu URL'ye giderek sohbet kimliğinizi alabilirsiniz:", "YOUR BOT TOKEN HERE": "BOT TOKENİNİZ BURADA", diff --git a/src/lang/uk-UA.json b/src/lang/uk-UA.json index fcd678a3..9ad37b66 100644 --- a/src/lang/uk-UA.json +++ b/src/lang/uk-UA.json @@ -216,6 +216,7 @@ "Bot Token": "Токен бота", "wayToGetTelegramToken": "Ви можете взяти токен тут - {0}.", "Chat ID": "ID чату", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Підтримуються ID чатів, груп та каналів", "wayToGetTelegramChatID": "Ви можете взяти ID вашого чату, відправивши повідомлення боту і перейшовши по цьому URL для перегляду chat_id:", "YOUR BOT TOKEN HERE": "ВАШ ТОКЕН БОТА ТУТ", diff --git a/src/lang/vi-VN.json b/src/lang/vi-VN.json index 165bf1bb..4446a020 100644 --- a/src/lang/vi-VN.json +++ b/src/lang/vi-VN.json @@ -193,6 +193,7 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Bạn có thể lấy mã token từ", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Hỗ trợ chat trực tiếp / Nhóm / Kênh Chat ID", "wayToGetTelegramChatID": "Bạn có thể lấy chat id của mình bằng cách gửi tin nhắn tới bot và truy cập url này để xem chat_id:", "YOUR BOT TOKEN HERE": "MÃ BOT TOKEN CỦA BẠN", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index a3393bd1..f52fab92 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -213,6 +213,7 @@ "Bot Token": "机器人令牌", "wayToGetTelegramToken": "您可以从 {0} 获取 Token。", "Chat ID": "Chat ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "支持对话/群组/频道的 Chat ID", "wayToGetTelegramChatID": "您可以发送一条消息给您的机器人,然后访问此链接来查看 chat_id:", "YOUR BOT TOKEN HERE": "这里替换成您的 BOT TOKEN", diff --git a/src/lang/zh-HK.json b/src/lang/zh-HK.json index 14f25b5e..3310c995 100644 --- a/src/lang/zh-HK.json +++ b/src/lang/zh-HK.json @@ -211,6 +211,7 @@ "Bot Token": "機器人權杖", "wayToGetTelegramToken": "您可以從 {0} 取得 Token。", "Chat ID": "聊天 ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "支援 對話/群組/頻道的聊天 ID", "wayToGetTelegramChatID": "傳送訊息給機器人,並前往以下網址以取得您的 chat ID:", "YOUR BOT TOKEN HERE": "在此填入您的機器人權杖", diff --git a/src/lang/zh-TW.json b/src/lang/zh-TW.json index 5eb0a699..992a2a0d 100644 --- a/src/lang/zh-TW.json +++ b/src/lang/zh-TW.json @@ -212,6 +212,7 @@ "Bot Token": "機器人權杖", "wayToGetTelegramToken": "您可以從 {0} 取得權杖。", "Chat ID": "聊天 ID", + "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "支援 對話/群組/頻道的聊天 ID", "wayToGetTelegramChatID": "傳送訊息給機器人,並前往以下網址以取得您的 chat ID:", "YOUR BOT TOKEN HERE": "在此填入您的機器人權杖", From c42e5503827b283ca2e76aee43f8029b1d371549 Mon Sep 17 00:00:00 2001 From: Haytham Salama <haythamasalama@gmail.com> Date: Sat, 4 Feb 2023 23:46:19 +0200 Subject: [PATCH 29/57] style: formats --- src/components/notifications/Telegram.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 3f446dc8..a1b74a8a 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -17,7 +17,6 @@ </button> </div> - <label for="message_thread_id" class="form-label">{{ $t("Message Thread ID") }}</label> <input id="message_thread_id" v-model="$parent.notification.telegramMessageThreadID" type="text" class="form-control"> <p class="form-text">Message Thread ID: Optional Unique identifier for the target message thread (topic) of the forum; for forum supergroups only</p> From 727acb32bf8423a5c56cf64776ce33eded9e5aa7 Mon Sep 17 00:00:00 2001 From: Brayan Lozano <brayan@mytide.io> Date: Tue, 7 Feb 2023 21:18:26 -0500 Subject: [PATCH 30/57] Adds name + status + message to slack notification --- server/notification-providers/slack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js index 5a5d40cb..64a58738 100644 --- a/server/notification-providers/slack.js +++ b/server/notification-providers/slack.js @@ -42,7 +42,7 @@ class Slack extends NotificationProvider { const time = heartbeatJSON["time"]; const textMsg = "Uptime Kuma Alert"; let data = { - "text": monitorJSON ? textMsg + `: ${monitorJSON.name}` : textMsg, + "text": monitorJSON ? `${textMsg}\n${msg}` : textMsg, "channel": notification.slackchannel, "username": notification.slackusername, "icon_emoji": notification.slackiconemo, From d45aee450d3e01a9ee7a4a784ff99268e05fff76 Mon Sep 17 00:00:00 2001 From: Brayan Lozano <brayan@mytide.io> Date: Tue, 7 Feb 2023 22:34:10 -0500 Subject: [PATCH 31/57] Removes unecessary ternary operator --- server/notification-providers/slack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js index 64a58738..da89f0f7 100644 --- a/server/notification-providers/slack.js +++ b/server/notification-providers/slack.js @@ -42,7 +42,7 @@ class Slack extends NotificationProvider { const time = heartbeatJSON["time"]; const textMsg = "Uptime Kuma Alert"; let data = { - "text": monitorJSON ? `${textMsg}\n${msg}` : textMsg, + "text": `${textMsg}\n${msg}`, "channel": notification.slackchannel, "username": notification.slackusername, "icon_emoji": notification.slackiconemo, From 36d160ad022706a4d4f29d22af7eb6c00df7c983 Mon Sep 17 00:00:00 2001 From: OidaTiftla <chm.stephan@outlook.com> Date: Thu, 9 Feb 2023 09:04:47 +0100 Subject: [PATCH 32/57] Rename "consequently" to "consecutively" as suggested by @skylarv https://github.com/louislam/uptime-kuma/pull/1212#issuecomment-1423373045 --- src/lang/ar-SY.json | 2 +- src/lang/bg-BG.json | 2 +- src/lang/cs-CZ.json | 2 +- src/lang/de-CH.json | 2 +- src/lang/de-DE.json | 2 +- src/lang/el-GR.json | 2 +- src/lang/en.json | 2 +- src/lang/es-ES.json | 2 +- src/lang/fr-FR.json | 2 +- src/lang/he-IL.json | 2 +- src/lang/hr-HR.json | 2 +- src/lang/id-ID.json | 2 +- src/lang/ko-KR.json | 2 +- src/lang/pl.json | 2 +- src/lang/pt-BR.json | 2 +- src/lang/th-TH.json | 2 +- src/lang/tr-TR.json | 2 +- src/lang/zh-CN.json | 2 +- src/lang/zh-HK.json | 2 +- src/lang/zh-TW.json | 2 +- src/pages/EditMonitor.vue | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/lang/ar-SY.json b/src/lang/ar-SY.json index d852a690..fe2910dd 100644 --- a/src/lang/ar-SY.json +++ b/src/lang/ar-SY.json @@ -90,7 +90,7 @@ "Heartbeat Interval": "فاصل نبضات القلب", "Retries": "يحاول مجدداً", "Heartbeat Retry Interval": "الفاصل الزمني لإعادة محاكمة نبضات القلب", - "Resend Notification if Down X times consequently": "إعادة تقديم الإخطار إذا انخفض x مرات بالتالي", + "Resend Notification if Down X times consecutively": "إعادة تقديم الإخطار إذا انخفض x مرات بالتالي", "Advanced": "متقدم", "Upside Down Mode": "وضع أسفل أسفل", "Max. Redirects": "الأعلى. إعادة التوجيه", diff --git a/src/lang/bg-BG.json b/src/lang/bg-BG.json index 3a5f532d..5bbebf9c 100644 --- a/src/lang/bg-BG.json +++ b/src/lang/bg-BG.json @@ -539,7 +539,7 @@ "wayToGetLineNotifyToken": "Може да получите токен код за достъп от {0}", "resendEveryXTimes": "Изпращай повторно на всеки {0} пъти", "resendDisabled": "Повторното изпращане е изключено", - "Resend Notification if Down X times consequently": "Повторно изпращане на известие, ако е недостъпен X пъти последователно", + "Resend Notification if Down X times consecutively": "Повторно изпращане на известие, ако е недостъпен X пъти последователно", "Bark Group": "Bark група", "Bark Sound": "Bark звук", "HTTP Headers": "HTTP хедъри", diff --git a/src/lang/cs-CZ.json b/src/lang/cs-CZ.json index c6b28312..28ca79ee 100644 --- a/src/lang/cs-CZ.json +++ b/src/lang/cs-CZ.json @@ -90,7 +90,7 @@ "Heartbeat Interval": "Heartbeat interval", "Retries": "Počet pokusů", "Heartbeat Retry Interval": "Interval opakování heartbeatu", - "Resend Notification if Down X times consequently": "Znovu zaslat oznámení, pokud je služba nedostupná Xkrát za sebou", + "Resend Notification if Down X times consecutively": "Znovu zaslat oznámení, pokud je služba nedostupná Xkrát za sebou", "Advanced": "Rozšířené", "Upside Down Mode": "Inverzní režim", "Max. Redirects": "Max. přesměrování", diff --git a/src/lang/de-CH.json b/src/lang/de-CH.json index 85da35e0..d8a46562 100644 --- a/src/lang/de-CH.json +++ b/src/lang/de-CH.json @@ -165,7 +165,7 @@ "Pink": "Pink", "Search...": "Suchen…", "Heartbeat Retry Interval": "Überprüfungsintervall", - "Resend Notification if Down X times consequently": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander", + "Resend Notification if Down X times consecutively": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander", "retryCheckEverySecond": "Alle {0} Sekunden neu versuchen", "resendEveryXTimes": "Erneut versenden alle {0} mal", "resendDisabled": "Erneut versenden deaktiviert", diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 45b5ae56..f6671598 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -165,7 +165,7 @@ "Pink": "Pink", "Search...": "Suchen…", "Heartbeat Retry Interval": "Überprüfungsintervall", - "Resend Notification if Down X times consequently": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander", + "Resend Notification if Down X times consecutively": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander", "retryCheckEverySecond": "Alle {0} Sekunden neu versuchen", "resendEveryXTimes": "Erneut versenden alle {0} mal", "resendDisabled": "Erneut versenden deaktiviert", diff --git a/src/lang/el-GR.json b/src/lang/el-GR.json index c77d6158..fbd8a369 100644 --- a/src/lang/el-GR.json +++ b/src/lang/el-GR.json @@ -74,7 +74,7 @@ "Heartbeat Interval": "Διάστημα καρδιακών παλμών", "Retries": "Επαναλήψεις", "Heartbeat Retry Interval": "Διάστημα επανάληψης παλμών καρδιάς", - "Resend Notification if Down X times consequently": "Αποστολή νέας ειδοποίησης εάν κατω X φορές κατά συνέχεια", + "Resend Notification if Down X times consecutively": "Αποστολή νέας ειδοποίησης εάν κατω X φορές κατά συνέχεια", "Advanced": "Προχωρημένα", "Upside Down Mode": "Ανάποδη λειτουργία", "Max. Redirects": "Μέγιστη. Ανακατευθύνσεις", diff --git a/src/lang/en.json b/src/lang/en.json index d907f4e0..0fed82c0 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -55,7 +55,7 @@ "Heartbeat Interval": "Heartbeat Interval", "Retries": "Retries", "Heartbeat Retry Interval": "Heartbeat Retry Interval", - "Resend Notification if Down X times consequently": "Resend Notification if Down X times consequently", + "Resend Notification if Down X times consecutively": "Resend Notification if Down X times consecutively", "Advanced": "Advanced", "checkEverySecond": "Check every {0} seconds", "retryCheckEverySecond": "Retry every {0} seconds", diff --git a/src/lang/es-ES.json b/src/lang/es-ES.json index 8fa80158..a9c8e34f 100644 --- a/src/lang/es-ES.json +++ b/src/lang/es-ES.json @@ -304,7 +304,7 @@ "General Monitor Type": "Monitor Tipo General", "Specific Monitor Type": "Monitor Tipo Específico", "Monitor": "Monitores", - "Resend Notification if Down X times consequently": "Reenviar Notificación si Caído X veces consecutivas", + "Resend Notification if Down X times consecutively": "Reenviar Notificación si Caído X veces consecutivas", "resendEveryXTimes": "Reenviar cada {0} veces", "resendDisabled": "Reenvío deshabilitado", "needPushEvery": "Debe llamar a esta URL cada {0} segundos.", diff --git a/src/lang/fr-FR.json b/src/lang/fr-FR.json index ae39af3c..3580cca1 100644 --- a/src/lang/fr-FR.json +++ b/src/lang/fr-FR.json @@ -89,7 +89,7 @@ "Heartbeat Interval": "Intervalle de vérification", "Retries": "Essais", "Heartbeat Retry Interval": "Réessayer l'intervalle de vérification", - "Resend Notification if Down X times consequently": "Renvoyer une notification si hors ligne X fois", + "Resend Notification if Down X times consecutively": "Renvoyer une notification si hors ligne X fois", "Advanced": "Avancé", "Upside Down Mode": "Mode inversé", "Max. Redirects": "Nombre maximum de redirections", diff --git a/src/lang/he-IL.json b/src/lang/he-IL.json index c8219ff5..c61ad77c 100644 --- a/src/lang/he-IL.json +++ b/src/lang/he-IL.json @@ -89,7 +89,7 @@ "Heartbeat Interval": "מרווח פעימות", "Retries": "נסיונות חוזרים", "Heartbeat Retry Interval": "מרווח נסיונות חוזר של פעימות", - "Resend Notification if Down X times consequently": "שלח שוב הודעה אם ירד X פעמים כתוצאה מכך", + "Resend Notification if Down X times consecutively": "שלח שוב הודעה אם ירד X פעמים כתוצאה מכך", "Advanced": "מתקדם", "Upside Down Mode": "מצב הפוך", "Max. Redirects": "מקסימום הפניות מחדש", diff --git a/src/lang/hr-HR.json b/src/lang/hr-HR.json index 417b689e..b909ed55 100644 --- a/src/lang/hr-HR.json +++ b/src/lang/hr-HR.json @@ -378,7 +378,7 @@ "resendEveryXTimes": "Ponovno pošalji svakih {0} puta", "resendDisabled": "Ponovno slanje je onemogućeno", "dnsPortDescription": "Port DNS poslužitelja. Zadana vrijednost je 53. Moguće je promijeniti ga u svakom trenutku.", - "Resend Notification if Down X times consequently": "Ponovno pošalji obavijest ako je usluga nedostupna više puta zaredom", + "Resend Notification if Down X times consecutively": "Ponovno pošalji obavijest ako je usluga nedostupna više puta zaredom", "topic": "Tema", "topicExplanation": "MQTT tema koja će se monitorirati", "successMessage": "Poruka o uspjehu", diff --git a/src/lang/id-ID.json b/src/lang/id-ID.json index 59a06521..ecd50672 100644 --- a/src/lang/id-ID.json +++ b/src/lang/id-ID.json @@ -74,7 +74,7 @@ "Heartbeat Interval": "Jarak Waktu Heartbeat ", "Retries": "Coba lagi", "Heartbeat Retry Interval": "Jarak Waktu Heartbeat Mencoba kembali ", - "Resend Notification if Down X times consequently": "Kirim Ulang Notifikasi jika Tidak Aktif X kali", + "Resend Notification if Down X times consecutively": "Kirim Ulang Notifikasi jika Tidak Aktif X kali", "Advanced": "Tingkat Lanjut", "Upside Down Mode": "Mode Terbalik", "Max. Redirects": "Maksimal Pengalihan", diff --git a/src/lang/ko-KR.json b/src/lang/ko-KR.json index 2c2297c6..079c9f58 100644 --- a/src/lang/ko-KR.json +++ b/src/lang/ko-KR.json @@ -680,7 +680,7 @@ "Passive Monitor Type": "수동 모니터링", "Specific Monitor Type": "특정 모니터링", "Monitor": "모니터", - "Resend Notification if Down X times consequently": "X번 중단될 경우 알림 다시 보내기", + "Resend Notification if Down X times consecutively": "X번 중단될 경우 알림 다시 보내기", "Schedule maintenance": "점검 예약하기", "Affected Monitors": "영향을 받는 모니터링", "Pick Affected Monitors...": "영향을 받는 모니터링 선택하기…", diff --git a/src/lang/pl.json b/src/lang/pl.json index ebc58797..27b5d72b 100644 --- a/src/lang/pl.json +++ b/src/lang/pl.json @@ -494,7 +494,7 @@ "atLeastOneMonitor": "Wybierz co najmniej jeden monitor, którego dotyczy problem", "deleteMaintenanceMsg": "Czy na pewno chcesz usunąć tę konserwację?", "dnsPortDescription": "Port serwera DNS. Domyślnie 53. Możesz zmienić port w dowolnym momencie.", - "Resend Notification if Down X times consequently": "Wyślij ponownie powiadomienie, jeśli nie działa X razy pod rząd", + "Resend Notification if Down X times consecutively": "Wyślij ponownie powiadomienie, jeśli nie działa X razy pod rząd", "error": "błąd", "critical": "krytyczny", "wayToGetPagerDutyKey": "Możesz to uzyskać, przechodząc do Service -> Service Directory -> (wybierz usługę) -> Integrations -> Add integration. Tutaj możesz wyszukać \"Events API V2\". Więcej informacji {0}", diff --git a/src/lang/pt-BR.json b/src/lang/pt-BR.json index b7ebdbd4..a0c6d1fd 100644 --- a/src/lang/pt-BR.json +++ b/src/lang/pt-BR.json @@ -249,7 +249,7 @@ "enabled": "Ativado", "setAsDefault": "Definir como padrão", "Primary Base URL": "URL base principal", - "Resend Notification if Down X times consequently": "Reenviar notificação se OFFLINE X vezes consecutivamente", + "Resend Notification if Down X times consecutively": "Reenviar notificação se OFFLINE X vezes consecutivamente", "pushOptionalParams": "Parâmetros opcionais: {0}", "webhookFormDataDesc": "{multipart} é bom para PHP. O JSON precisará ser analisado com {decodeFunction}", "HeadersInvalidFormat": "Os cabeçalhos da solicitação não são um JSON válidos: ", diff --git a/src/lang/th-TH.json b/src/lang/th-TH.json index 7ad132f5..1895a153 100644 --- a/src/lang/th-TH.json +++ b/src/lang/th-TH.json @@ -522,7 +522,7 @@ "resendEveryXTimes": "ส่งซ้ำทุก {0} ครั้ง", "resendDisabled": "การส่งซ้ำถูกปิดใช้งาน", "dnsPortDescription": "พอร์ตของเซิร์ฟเวอร์ DNS, ค่าเริ่มต้นคือ 53, คุณสามารถเปลี่ยนพอร์ตตอนไหนก็ได้", - "Resend Notification if Down X times consequently": "ส่งการแจ้งเตือนซ้ำถ้าออฟไลน์ครบ X ครั้ง", + "Resend Notification if Down X times consecutively": "ส่งการแจ้งเตือนซ้ำถ้าออฟไลน์ครบ X ครั้ง", "error": "เกิดข้อผิดพลาด", "critical": "วิกฤต", "wayToGetPagerDutyKey": "คุณสามารถรับคีย์ได้โดยการไปที่ Service -> Service Directory -> (Select a service) -> Integrations -> Add integration, และค้นหา \"Events API V2\", สำหรับข้อมูลเพิ่มเติม {0}", diff --git a/src/lang/tr-TR.json b/src/lang/tr-TR.json index b9bc8adc..13ddd373 100644 --- a/src/lang/tr-TR.json +++ b/src/lang/tr-TR.json @@ -74,7 +74,7 @@ "Heartbeat Interval": "Servis Test Aralığı", "Retries": "Yeniden deneme", "Heartbeat Retry Interval": "Sağlık Durumları Tekrar Deneme Sıklığı", - "Resend Notification if Down X times consequently": "Sonuç olarak X kez düşerse bildirimi yeniden gönder", + "Resend Notification if Down X times consecutively": "Sonuç olarak X kez düşerse bildirimi yeniden gönder", "Advanced": "Gelişmiş", "Upside Down Mode": "Ters/Düz Modu", "Max. Redirects": "Maksimum Yönlendirme", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index a3393bd1..45529c6d 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -89,7 +89,7 @@ "Heartbeat Interval": "心跳间隔", "Retries": "重试次数", "Heartbeat Retry Interval": "心跳重试间隔", - "Resend Notification if Down X times consequently": "连续失败时重复发送通知的间隔次数", + "Resend Notification if Down X times consecutively": "连续失败时重复发送通知的间隔次数", "Advanced": "高级", "Upside Down Mode": "反转监控", "Max. Redirects": "最大重定向次数", diff --git a/src/lang/zh-HK.json b/src/lang/zh-HK.json index 14f25b5e..024781a3 100644 --- a/src/lang/zh-HK.json +++ b/src/lang/zh-HK.json @@ -397,7 +397,7 @@ "affectedStatusPages": "在已選取的狀態頁中顯示此維護訊息", "Primary Base URL": "主要 Base URL", "Passive Monitor Type": "被動監測器類型", - "Resend Notification if Down X times consequently": "若 X 次心跳皆離線,重新傳送通知", + "Resend Notification if Down X times consecutively": "若 X 次心跳皆離線,重新傳送通知", "Game": "遊戲", "Specific Monitor Type": "特定監測器類型", "Monitor": "監測器 | 監測器", diff --git a/src/lang/zh-TW.json b/src/lang/zh-TW.json index 5eb0a699..3e208215 100644 --- a/src/lang/zh-TW.json +++ b/src/lang/zh-TW.json @@ -89,7 +89,7 @@ "Heartbeat Interval": "心跳間隔", "Retries": "重試次數", "Heartbeat Retry Interval": "心跳重試間隔", - "Resend Notification if Down X times consequently": "若 X 次心跳皆離線,重新傳送通知", + "Resend Notification if Down X times consecutively": "若 X 次心跳皆離線,重新傳送通知", "Advanced": "進階", "Upside Down Mode": "顛倒模式", "Max. Redirects": "最大重新導向次數", diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index e9cbd824..297759c5 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -340,7 +340,7 @@ <div class="my-3"> <label for="resend-interval" class="form-label"> - {{ $t("Resend Notification if Down X times consequently") }} + {{ $t("Resend Notification if Down X times consecutively") }} <span v-if="monitor.resendInterval > 0">({{ $t("resendEveryXTimes", [ monitor.resendInterval ]) }})</span> <span v-else>({{ $t("resendDisabled") }})</span> </label> From 3439074835d1f40dd56ca2b6531dcbbec53071b0 Mon Sep 17 00:00:00 2001 From: Nelson Chan <chakflying@hotmail.com> Date: Thu, 9 Feb 2023 17:42:02 +0800 Subject: [PATCH 33/57] Feat: Use message to improve errror status code --- server/routers/api-router.js | 14 +++++++------- server/routers/status-page-router.js | 18 ++++++------------ server/util-server.js | 24 ++++++++++++++++++------ 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 665163ae..2d5f9661 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -1,5 +1,5 @@ let express = require("express"); -const { allowDevAllOrigin, allowAllOrigin, percentageToColor, filterAndJoin, send403 } = require("../util-server"); +const { allowDevAllOrigin, allowAllOrigin, percentageToColor, filterAndJoin, sendHttpError } = require("../util-server"); const { R } = require("redbean-node"); const apicache = require("../modules/apicache"); const Monitor = require("../model/monitor"); @@ -175,7 +175,7 @@ router.get("/api/badge/:id/status", cache("5 minutes"), async (request, response response.type("image/svg+xml"); response.send(svg); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); @@ -242,7 +242,7 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques response.type("image/svg+xml"); response.send(svg); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); @@ -303,7 +303,7 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request, response.type("image/svg+xml"); response.send(svg); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); @@ -373,7 +373,7 @@ router.get("/api/badge/:id/avg-response/:duration?", cache("5 minutes"), async ( response.type("image/svg+xml"); response.send(svg); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); @@ -464,7 +464,7 @@ router.get("/api/badge/:id/cert-exp", cache("5 minutes"), async (request, respon response.type("image/svg+xml"); response.send(svg); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); @@ -536,7 +536,7 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon response.type("image/svg+xml"); response.send(svg); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); diff --git a/server/routers/status-page-router.js b/server/routers/status-page-router.js index de075db8..28cf5f4c 100644 --- a/server/routers/status-page-router.js +++ b/server/routers/status-page-router.js @@ -2,7 +2,7 @@ let express = require("express"); const apicache = require("../modules/apicache"); const { UptimeKumaServer } = require("../uptime-kuma-server"); const StatusPage = require("../model/status_page"); -const { allowDevAllOrigin, send403 } = require("../util-server"); +const { allowDevAllOrigin, sendHttpError } = require("../util-server"); const { R } = require("redbean-node"); const Monitor = require("../model/monitor"); @@ -44,10 +44,7 @@ router.get("/api/status-page/:slug", cache("5 minutes"), async (request, respons let statusPageData = await StatusPage.getStatusPageData(statusPage); if (!statusPageData) { - response.statusCode = 404; - response.json({ - msg: "Not Found" - }); + sendHttpError(response, "Not Found"); return; } @@ -55,7 +52,7 @@ router.get("/api/status-page/:slug", cache("5 minutes"), async (request, respons response.json(statusPageData); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); @@ -103,7 +100,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques }); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); @@ -119,10 +116,7 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async ]); if (!statusPage) { - response.statusCode = 404; - response.json({ - msg: "Not Found" - }); + sendHttpError(response, "Not Found"); return; } @@ -141,7 +135,7 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async }); } catch (error) { - send403(response, error.message); + sendHttpError(response, error.message); } }); diff --git a/server/util-server.js b/server/util-server.js index edce2890..c83c8cd1 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -730,15 +730,27 @@ exports.filterAndJoin = (parts, connector = "") => { }; /** - * Send a 403 response + * Send an Error response * @param {Object} res Express response object * @param {string} [msg=""] Message to send */ -module.exports.send403 = (res, msg = "") => { - res.status(403).json({ - "status": "fail", - "msg": msg, - }); +module.exports.sendHttpError = (res, msg = "") => { + if (msg.includes("SQLITE_BUSY") || msg.includes("SQLITE_LOCKED")) { + res.status(503).json({ + "status": "fail", + "msg": msg, + }); + } else if (msg.toLowerCase().includes("not found")) { + res.status(404).json({ + "status": "fail", + "msg": msg, + }); + } else { + res.status(403).json({ + "status": "fail", + "msg": msg, + }); + } }; function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) { From dd1d71530fc3eeb435e669b2c31cc6daf7710a38 Mon Sep 17 00:00:00 2001 From: Luke Hamburg <1992842+luckman212@users.noreply.github.com> Date: Wed, 15 Feb 2023 14:06:29 -0500 Subject: [PATCH 34/57] sorted tags on dashboard see https://github.com/louislam/uptime-kuma/issues/2785 --- server/model/monitor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 4cbb56e1..bbeb0da0 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -143,7 +143,7 @@ class Monitor extends BeanModel { * @returns {Promise<LooseObject<any>[]>} */ async getTags() { - return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ?", [ this.id ]); + return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ? ORDER BY tag.name", [ this.id ]); } /** From c9b4a7f53ef502a5ea58faf970102b6098d0b479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Fri, 17 Feb 2023 17:59:43 +0300 Subject: [PATCH 35/57] Change column type --- db/patch-http-body-encoding.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/patch-http-body-encoding.sql b/db/patch-http-body-encoding.sql index de02bede..fa75ae90 100644 --- a/db/patch-http-body-encoding.sql +++ b/db/patch-http-body-encoding.sql @@ -1,6 +1,6 @@ -- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; -ALTER TABLE [monitor] ADD http_body_encoding TEXT; +ALTER TABLE [monitor] ADD http_body_encoding VARCHAR(25); COMMIT; From 9e3a77f4194b43bc617fb22756521f99b05e1aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Sat, 18 Feb 2023 17:02:56 +0300 Subject: [PATCH 36/57] Customize body placeholder for body encoding --- src/pages/EditMonitor.vue | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index d36693bb..2d28195e 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -732,6 +732,15 @@ message HealthCheckResponse { ` ]); }, bodyPlaceholder() { + if (this.monitor && this.monitor.httpBodyEncoding && this.monitor.httpBodyEncoding === "xml") { + return this.$t("Example:", [ ` +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> + <soap:Body> + <Uptime>Kuma</Uptime> + </soap:Body> +</soap:Envelope>` ]); + } return this.$t("Example:", [ ` { "key": "value" From 3ab0faee91d5aae3b0d0dc6a54b8ceeafa64e337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Faruk=20Gen=C3=A7?= <omer@farukgenc.com> Date: Sat, 18 Feb 2023 22:18:48 +0300 Subject: [PATCH 37/57] Add update query for old monitors and save new data correctly --- db/patch-http-body-encoding.sql | 8 +++++++- src/pages/EditMonitor.vue | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/db/patch-http-body-encoding.sql b/db/patch-http-body-encoding.sql index fa75ae90..322c8b89 100644 --- a/db/patch-http-body-encoding.sql +++ b/db/patch-http-body-encoding.sql @@ -1,6 +1,12 @@ -- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; -ALTER TABLE [monitor] ADD http_body_encoding VARCHAR(25); +ALTER TABLE monitor ADD http_body_encoding VARCHAR(25); + +COMMIT; + +BEGIN TRANSACTION; + +UPDATE monitor SET http_body_encoding = 'json' WHERE (type = 'http' or type = 'keyword') AND http_body_encoding IS NULL; COMMIT; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 2d28195e..dbf44d73 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -952,6 +952,7 @@ message HealthCheckResponse { * @returns {void} */ async submit() { + this.processing = true; if (!this.isInputValid()) { @@ -964,6 +965,10 @@ message HealthCheckResponse { this.monitor.body = JSON.stringify(JSON.parse(this.monitor.body), null, 4); } + if (this.monitor.type && this.monitor.type !== "http" && this.monitor.type !== "keyword") { + this.monitor.httpBodyEncoding = null; + } + if (this.monitor.headers) { this.monitor.headers = JSON.stringify(JSON.parse(this.monitor.headers), null, 4); } From cf32b8bc64b866c9d050aa1747a123bc78d81e9e Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Mon, 20 Feb 2023 20:26:53 +0800 Subject: [PATCH 38/57] Read latest version from website and add `Run when system starts` --- extra/exe-builder/.gitignore | 1 + extra/exe-builder/App.config | 26 ++++- extra/exe-builder/DownloadForm.cs | 14 ++- extra/exe-builder/FodyWeavers.xml | 3 + extra/exe-builder/FodyWeavers.xsd | 141 ++++++++++++++++++++++++++++ extra/exe-builder/Program.cs | 28 +++++- extra/exe-builder/UptimeKuma.csproj | 104 +++++++++++++++++++- extra/exe-builder/Version.cs | 9 ++ extra/exe-builder/packages.config | 52 ++++++++++ 9 files changed, 373 insertions(+), 5 deletions(-) create mode 100644 extra/exe-builder/.gitignore create mode 100644 extra/exe-builder/FodyWeavers.xml create mode 100644 extra/exe-builder/FodyWeavers.xsd create mode 100644 extra/exe-builder/Version.cs create mode 100644 extra/exe-builder/packages.config diff --git a/extra/exe-builder/.gitignore b/extra/exe-builder/.gitignore new file mode 100644 index 00000000..d52874b6 --- /dev/null +++ b/extra/exe-builder/.gitignore @@ -0,0 +1 @@ +packages/ diff --git a/extra/exe-builder/App.config b/extra/exe-builder/App.config index 09265d8b..e1ab3695 100644 --- a/extra/exe-builder/App.config +++ b/extra/exe-builder/App.config @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8" ?> +<?xml version="1.0" encoding="utf-8"?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /> @@ -7,4 +7,28 @@ <System.Windows.Forms.ApplicationConfigurationSection> <add key="DpiAwareness" value="PerMonitorV2" /> </System.Windows.Forms.ApplicationConfigurationSection> + <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.0" newVersion="4.1.1.0" /> + </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> + </assemblyBinding> + </runtime> </configuration> diff --git a/extra/exe-builder/DownloadForm.cs b/extra/exe-builder/DownloadForm.cs index f16af422..aed8bd29 100644 --- a/extra/exe-builder/DownloadForm.cs +++ b/extra/exe-builder/DownloadForm.cs @@ -8,6 +8,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; +using Newtonsoft.Json; namespace UptimeKuma { public partial class DownloadForm : Form { @@ -23,9 +24,18 @@ namespace UptimeKuma { webClient.DownloadProgressChanged += DownloadProgressChanged; webClient.DownloadFileCompleted += DownloadFileCompleted; + label.Text = "Reading latest version..."; + + // Read json from https://uptime.kuma.pet/version + var versionObj = JsonConvert.DeserializeObject<Version>(new WebClient().DownloadString("https://uptime.kuma.pet/version")); + + + var nodeVersion = versionObj.nodejs; + var uptimeKumaVersion = versionObj.latest; + if (!Directory.Exists("node")) { downloadQueue.Enqueue(new DownloadItem { - URL = "https://nodejs.org/dist/v16.17.1/node-v16.17.1-win-x64.zip", + URL = $"https://nodejs.org/dist/v{nodeVersion}/node-v{nodeVersion}-win-x64.zip", Filename = "node.zip", TargetFolder = "node" }); @@ -33,7 +43,7 @@ namespace UptimeKuma { if (!Directory.Exists("node")) { downloadQueue.Enqueue(new DownloadItem { - URL = "https://github.com/louislam/uptime-kuma/archive/refs/tags/1.18.3.zip", + URL = $"https://github.com/louislam/uptime-kuma/archive/refs/tags/{uptimeKumaVersion}.zip", Filename = "core.zip", TargetFolder = "core" }); diff --git a/extra/exe-builder/FodyWeavers.xml b/extra/exe-builder/FodyWeavers.xml new file mode 100644 index 00000000..f1dea8fc --- /dev/null +++ b/extra/exe-builder/FodyWeavers.xml @@ -0,0 +1,3 @@ +<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> + <Costura /> +</Weavers> \ No newline at end of file diff --git a/extra/exe-builder/FodyWeavers.xsd b/extra/exe-builder/FodyWeavers.xsd new file mode 100644 index 00000000..ff119f71 --- /dev/null +++ b/extra/exe-builder/FodyWeavers.xsd @@ -0,0 +1,141 @@ +<?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> \ No newline at end of file diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs index 82c76b05..27e345b7 100644 --- a/extra/exe-builder/Program.cs +++ b/extra/exe-builder/Program.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; +using Microsoft.Win32; using UptimeKuma.Properties; namespace UptimeKuma { @@ -25,17 +26,27 @@ namespace UptimeKuma { public class UptimeKumaApplicationContext : ApplicationContext { + const string appName = "Uptime Kuma"; + private NotifyIcon trayIcon; private Process process; + private MenuItem runWhenStarts; + + private RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); + public UptimeKumaApplicationContext() { trayIcon = new NotifyIcon(); + runWhenStarts = new MenuItem("Run when system starts", RunWhenStarts); + runWhenStarts.Checked = registryKey.GetValue(appName) != null; + trayIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); trayIcon.ContextMenu = new ContextMenu(new MenuItem[] { new("Open", Open), //new("Debug Console", DebugConsole), + runWhenStarts, new("Check for Update...", CheckForUpdate), new("Visit GitHub...", VisitGitHub), new("About", About), @@ -59,6 +70,21 @@ namespace UptimeKuma { 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", @@ -103,7 +129,7 @@ namespace UptimeKuma { void About(object sender, EventArgs e) { - MessageBox.Show("Uptime Kuma v1.0.0" + Environment.NewLine + "© 2022 Louis Lam", "Info"); + MessageBox.Show("Uptime Kuma Windows Runtime v1.0.0" + Environment.NewLine + "© 2023 Louis Lam", "Info"); } void Exit(object sender, EventArgs e) diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj index 2ad857b2..3f55649e 100644 --- a/extra/exe-builder/UptimeKuma.csproj +++ b/extra/exe-builder/UptimeKuma.csproj @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -38,18 +39,104 @@ <PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "%UserProfile%\Desktop\uptime-kuma-win64\"</PostBuildEvent> </PropertyGroup> <ItemGroup> + <Reference Include="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath> + </Reference> + <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.ComponentModel.Composition" /> + <Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath> + </Reference> <Reference Include="System.Core" /> + <Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\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.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Net.Http.4.3.0\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.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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath> + </Reference> + <Reference Include="System.Runtime.Extensions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Runtime.Extensions.4.3.0\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.0\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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.0\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.0\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.Net.Http" /> <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.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> <Compile Include="DownloadForm.cs"> @@ -60,6 +147,7 @@ </Compile> <Compile Include="Program.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Version.cs" /> <EmbeddedResource Include="DownloadForm.resx"> <DependentUpon>DownloadForm.cs</DependentUpon> </EmbeddedResource> @@ -75,6 +163,7 @@ <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> @@ -88,5 +177,18 @@ <ItemGroup> <None Include="App.config" /> </ItemGroup> + <ItemGroup> + <Content Include=".gitignore" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="packages\Fody.6.5.5\build\Fody.targets" Condition="Exists('packages\Fody.6.5.5\build\Fody.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\Fody.6.5.5\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.5.5\build\Fody.targets'))" /> + <Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" /> + <Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" /> + </Target> + <Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" /> </Project> \ No newline at end of file diff --git a/extra/exe-builder/Version.cs b/extra/exe-builder/Version.cs new file mode 100644 index 00000000..896c7a24 --- /dev/null +++ b/extra/exe-builder/Version.cs @@ -0,0 +1,9 @@ +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; } + } +} diff --git a/extra/exe-builder/packages.config b/extra/exe-builder/packages.config new file mode 100644 index 00000000..82dd7c3b --- /dev/null +++ b/extra/exe-builder/packages.config @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Costura.Fody" version="5.7.0" targetFramework="net472" developmentDependency="true" /> + <package id="Fody" version="6.5.5" targetFramework="net472" developmentDependency="true" /> + <package id="Microsoft.NETCore.Platforms" version="1.1.0" targetFramework="net472" /> + <package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net472" /> + <package id="NETStandard.Library" version="1.6.1" 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.Collections" version="4.3.0" targetFramework="net472" /> + <package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net472" /> + <package id="System.Console" version="4.3.0" targetFramework="net472" /> + <package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net472" /> + <package id="System.Diagnostics.DiagnosticSource" 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.Http" version="4.3.0" targetFramework="net472" /> + <package id="System.Net.Primitives" version="4.3.0" targetFramework="net472" /> + <package id="System.Net.Sockets" version="4.3.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" version="4.3.0" targetFramework="net472" /> + <package id="System.Runtime.Extensions" version="4.3.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.Algorithms" 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.Security.Cryptography.X509Certificates" 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.Text.RegularExpressions" 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.ReaderWriter" version="4.3.0" targetFramework="net472" /> + <package id="System.Xml.XDocument" version="4.3.0" targetFramework="net472" /> +</packages> \ No newline at end of file From 372c6b90783ec3fdc7ac0ebbd7a58f6a0de2ecdd Mon Sep 17 00:00:00 2001 From: Andreas Brett <andreasbrett@users.noreply.github.com> Date: Mon, 20 Feb 2023 16:09:17 +0100 Subject: [PATCH 39/57] add markdown support for description --- src/pages/StatusPage.vue | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index dcee15e7..f4a6eb76 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -20,6 +20,9 @@ <div class="my-3"> <label for="description" class="form-label">{{ $t("Description") }}</label> <textarea id="description" v-model="config.description" class="form-control"></textarea> + <div class="form-text"> + {{ $t("markdownSupported") }} + </div> </div> <!-- Footer Text --> @@ -258,7 +261,9 @@ <!-- Description --> <strong v-if="editMode">{{ $t("Description") }}:</strong> - <Editable v-model="config.description" :contenteditable="editMode" tag="div" class="mb-4 description" /> + <Editable v-if="enableEditMode" v-model="config.description" :contenteditable="editMode" tag="div" class="mb-4 description" /> + <!-- eslint-disable-next-line vue/no-v-html--> + <div v-if="! enableEditMode" class="alert-heading p-2" v-html="descriptionHTML"></div> <div v-if="editMode" class="mb-4"> <div> @@ -500,6 +505,10 @@ export default { return DOMPurify.sanitize(marked(this.incident.content)); }, + descriptionHTML() { + return DOMPurify.sanitize(marked(this.config.description)); + }, + footerHTML() { return DOMPurify.sanitize(marked(this.config.footerText)); }, From 4642f9be0af92e6e8cde9a67b8c460541b665ffa Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Mon, 20 Feb 2023 23:15:49 +0800 Subject: [PATCH 40/57] Fix download-dist.js do not exit sometimes --- extra/download-dist.js | 1 + 1 file changed, 1 insertion(+) diff --git a/extra/download-dist.js b/extra/download-dist.js index b04beec7..a854ca8b 100644 --- a/extra/download-dist.js +++ b/extra/download-dist.js @@ -47,6 +47,7 @@ function download(url) { }); } console.log("Done"); + process.exit(0); }); tarStream.on("error", () => { From 22902139d2885fea7ee3d985f6755835f5f095a8 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Tue, 21 Feb 2023 02:50:25 +0800 Subject: [PATCH 41/57] Implement update --- extra/exe-builder/DownloadForm.cs | 39 ++++++++++++++++++++++-------- extra/exe-builder/Program.cs | 40 +++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/extra/exe-builder/DownloadForm.cs b/extra/exe-builder/DownloadForm.cs index aed8bd29..28a57c52 100644 --- a/extra/exe-builder/DownloadForm.cs +++ b/extra/exe-builder/DownloadForm.cs @@ -27,11 +27,12 @@ namespace UptimeKuma { label.Text = "Reading latest version..."; // Read json from https://uptime.kuma.pet/version - var versionObj = JsonConvert.DeserializeObject<Version>(new WebClient().DownloadString("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 { @@ -41,12 +42,30 @@ namespace UptimeKuma { }); } - if (!Directory.Exists("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(); @@ -75,9 +94,12 @@ namespace UptimeKuma { 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 = "run setup", + Arguments = $"/k \"{cmd}\"", RedirectStandardOutput = false, RedirectStandardError = false, RedirectStandardInput = true, @@ -89,11 +111,11 @@ namespace UptimeKuma { var process = new Process(); process.StartInfo = startInfo; process.EnableRaisingEvents = true; - process.Exited += (object _, EventArgs e) => { + process.Exited += (_, e) => { progressBar.Value = 100; if (process.ExitCode == 0) { - Task.Delay(2000).ContinueWith((task) => { + Task.Delay(2000).ContinueWith(_ => { Application.Restart(); }); label.Text = "Done"; @@ -105,10 +127,7 @@ namespace UptimeKuma { process.Start(); label.Text = "Installing dependencies and download dist files"; progressBar.Value = 50; - - process.StandardInput.WriteLine("\"../node/npm\" ci --production"); - process.StandardInput.WriteLine("\"../node/npm\" run download-dist"); - process.StandardInput.WriteLine("exit"); + process.WaitForExit(); } void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs index 27e345b7..1385e830 100644 --- a/extra/exe-builder/Program.cs +++ b/extra/exe-builder/Program.cs @@ -4,11 +4,13 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; +using System.Net; using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; using Microsoft.Win32; +using Newtonsoft.Json; using UptimeKuma.Properties; namespace UptimeKuma { @@ -56,7 +58,9 @@ namespace UptimeKuma { trayIcon.MouseDoubleClick += new MouseEventHandler(Open); trayIcon.Visible = true; - if (Directory.Exists("core") && Directory.Exists("node") && Directory.Exists("core/node_modules") && Directory.Exists("core/dist")) { + 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 { @@ -110,6 +114,10 @@ namespace UptimeKuma { } } + void StopProcess() { + process?.Kill(); + } + void Open(object sender, EventArgs e) { Process.Start("http://localhost:3001"); } @@ -119,7 +127,35 @@ namespace UptimeKuma { } void CheckForUpdate(object sender, EventArgs e) { - Process.Start("https://github.com/louislam/uptime-kuma/releases"); + var needUpdate = false; + + // 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) From 0e38391454f012c6f0e87ab0e768b6aa15ab0ee8 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Tue, 21 Feb 2023 03:11:29 +0800 Subject: [PATCH 42/57] Fix dpi issue using app.manifest --- extra/exe-builder/App.config | 5 +- extra/exe-builder/UptimeKuma.csproj | 390 ++++++++++++++-------------- extra/exe-builder/app.manifest | 28 ++ 3 files changed, 226 insertions(+), 197 deletions(-) create mode 100644 extra/exe-builder/app.manifest diff --git a/extra/exe-builder/App.config b/extra/exe-builder/App.config index e1ab3695..2514085c 100644 --- a/extra/exe-builder/App.config +++ b/extra/exe-builder/App.config @@ -1,12 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <configuration> <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> </startup> - <System.Windows.Forms.ApplicationConfigurationSection> - <add key="DpiAwareness" value="PerMonitorV2" /> - </System.Windows.Forms.ApplicationConfigurationSection> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj index 3f55649e..6b7534af 100644 --- a/extra/exe-builder/UptimeKuma.csproj +++ b/extra/exe-builder/UptimeKuma.csproj @@ -1,194 +1,198 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" /> - <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> - <PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "%UserProfile%\Desktop\uptime-kuma-win64\"</PostBuildEvent> - </PropertyGroup> - <ItemGroup> - <Reference Include="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL"> - <HintPath>packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath> - </Reference> - <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.ComponentModel.Composition" /> - <Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath> - </Reference> - <Reference Include="System.Core" /> - <Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> - <HintPath>packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\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.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Net.Http.4.3.0\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.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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath> - </Reference> - <Reference Include="System.Runtime.Extensions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Runtime.Extensions.4.3.0\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.0\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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.0\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.0\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.0\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" /> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <Import Project="packages\Fody.6.5.5\build\Fody.targets" Condition="Exists('packages\Fody.6.5.5\build\Fody.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\Fody.6.5.5\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.5.5\build\Fody.targets'))" /> - <Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" /> - <Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" /> - </Target> - <Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" /> +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" /> + <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="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath> + </Reference> + <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.ComponentModel.Composition" /> + <Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath> + </Reference> + <Reference Include="System.Core" /> + <Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\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.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Net.Http.4.3.0\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.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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath> + </Reference> + <Reference Include="System.Runtime.Extensions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Runtime.Extensions.4.3.0\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.0\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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.0\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.0\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.0\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" /> + <Import Project="packages\Fody.6.5.5\build\Fody.targets" Condition="Exists('packages\Fody.6.5.5\build\Fody.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\Fody.6.5.5\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.5.5\build\Fody.targets'))" /> + <Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" /> + <Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" /> + </Target> + <Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" /> </Project> \ No newline at end of file diff --git a/extra/exe-builder/app.manifest b/extra/exe-builder/app.manifest new file mode 100644 index 00000000..4a48528f --- /dev/null +++ b/extra/exe-builder/app.manifest @@ -0,0 +1,28 @@ +<?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> From 02ddb58686a56146aa3545307067350a45eb2de5 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Tue, 21 Feb 2023 15:16:54 +0800 Subject: [PATCH 43/57] Fix cwd issues --- extra/exe-builder/FS.cs | 65 +++++++++++++++++++++++++++++ extra/exe-builder/UptimeKuma.csproj | 1 + 2 files changed, 66 insertions(+) create mode 100644 extra/exe-builder/FS.cs diff --git a/extra/exe-builder/FS.cs b/extra/exe-builder/FS.cs new file mode 100644 index 00000000..99a63694 --- /dev/null +++ b/extra/exe-builder/FS.cs @@ -0,0 +1,65 @@ +using System.IO; +using System.Reflection; + +namespace UptimeKuma { + + /** + * Current Directory using App location + */ + public class Directory { + private static string baseDir; + + public static string FullPath(string path) { + return Path.Combine(GetBaseDir(), path); + } + + public static string GetBaseDir() { + if (baseDir == null) { + baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + } + return baseDir; + } + + public static bool Exists(string path) { + return System.IO.Directory.Exists(FullPath(path)); + } + + public static void Delete(string path, bool recursive) { + System.IO.Directory.Delete(FullPath(path), recursive); + } + + public static void Move(string src, string dest) { + System.IO.Directory.Move(FullPath(src), FullPath(dest)); + } + + public static string[] GetDirectories(string path) { + return System.IO.Directory.GetDirectories(FullPath(path)); + } + } + + public class File { + + private static string FullPath(string path) { + return Directory.FullPath(path); + } + public static bool Exists(string path) { + return System.IO.File.Exists(FullPath(path)); + } + + public static FileStream Create(string path) { + return System.IO.File.Create(FullPath(path)); + } + + public static string ReadAllText(string path) { + return System.IO.File.ReadAllText(FullPath(path)); + } + + public static void Delete(string path) { + System.IO.File.Delete(FullPath(path)); + } + + public static void WriteAllText(string path, string content) { + System.IO.File.WriteAllText(FullPath(path), content); + } + } +} diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj index 6b7534af..1b484d7a 100644 --- a/extra/exe-builder/UptimeKuma.csproj +++ b/extra/exe-builder/UptimeKuma.csproj @@ -148,6 +148,7 @@ <Compile Include="DownloadForm.Designer.cs"> <DependentUpon>DownloadForm.cs</DependentUpon> </Compile> + <Compile Include="FS.cs" /> <Compile Include="Program.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Version.cs" /> From dad21065cf3e6045bd3a6fcf6a2b5d20f0b9d08b Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Tue, 21 Feb 2023 15:45:18 +0800 Subject: [PATCH 44/57] Update release procedures --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 09c94e71..4c6a5587 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -235,6 +235,7 @@ https://github.com/louislam/uptime-kuma/issues?q=sort%3Aupdated-desc 1. Draft a release note 2. Make sure the repo is cleared +3. If the healthcheck is updated, remember to re-compile it: `npm run build-docker-builder-go` 3. `npm run release-final with env vars: `VERSION` and `GITHUB_TOKEN` 4. Wait until the `Press any key to continue` 5. `git push` From 2c62d197a08462fa7fb044f23395eb1464e9a031 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Tue, 21 Feb 2023 16:03:41 +0800 Subject: [PATCH 45/57] [exe] Update dependencies --- extra/exe-builder/App.config | 6 +++- extra/exe-builder/UptimeKuma.csproj | 48 +++++++++++++++++++---------- extra/exe-builder/packages.config | 30 ++++++++++-------- 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/extra/exe-builder/App.config b/extra/exe-builder/App.config index 2514085c..97eb34af 100644 --- a/extra/exe-builder/App.config +++ b/extra/exe-builder/App.config @@ -20,12 +20,16 @@ </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" /> + <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> diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj index 1b484d7a..bd4e0dea 100644 --- a/extra/exe-builder/UptimeKuma.csproj +++ b/extra/exe-builder/UptimeKuma.csproj @@ -56,13 +56,16 @@ <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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath> + <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=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> - <HintPath>packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath> + <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> @@ -92,21 +95,30 @@ <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.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll</HintPath> + <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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath> + <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.Extensions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll</HintPath> + <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> @@ -115,7 +127,7 @@ <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.0\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath> + <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> @@ -123,11 +135,11 @@ <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.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath> + <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.0\lib\net463\System.Text.RegularExpressions.dll</HintPath> + <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" /> @@ -138,7 +150,7 @@ <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.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath> + <HintPath>packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> @@ -186,14 +198,16 @@ <Content Include="app.manifest" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <Import Project="packages\Fody.6.5.5\build\Fody.targets" Condition="Exists('packages\Fody.6.5.5\build\Fody.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\Fody.6.5.5\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.5.5\build\Fody.targets'))" /> <Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" /> <Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" /> + <Error Condition="!Exists('packages\Fody.6.6.4\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.6.4\build\Fody.targets'))" /> + <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\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" /> + <Import Project="packages\Fody.6.6.4\build\Fody.targets" Condition="Exists('packages\Fody.6.6.4\build\Fody.targets')" /> + <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> \ No newline at end of file diff --git a/extra/exe-builder/packages.config b/extra/exe-builder/packages.config index 82dd7c3b..aca26d67 100644 --- a/extra/exe-builder/packages.config +++ b/extra/exe-builder/packages.config @@ -1,17 +1,27 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="Costura.Fody" version="5.7.0" targetFramework="net472" developmentDependency="true" /> - <package id="Fody" version="6.5.5" targetFramework="net472" developmentDependency="true" /> - <package id="Microsoft.NETCore.Platforms" version="1.1.0" targetFramework="net472" /> + <package id="Fody" version="6.6.4" targetFramework="net472" developmentDependency="true" /> + <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="1.6.1" 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.Console" version="4.3.0" targetFramework="net472" /> <package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net472" /> - <package id="System.Diagnostics.DiagnosticSource" 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" /> @@ -23,30 +33,24 @@ <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.Http" version="4.3.0" targetFramework="net472" /> - <package id="System.Net.Primitives" 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" version="4.3.0" targetFramework="net472" /> - <package id="System.Runtime.Extensions" 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.Algorithms" 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.Security.Cryptography.X509Certificates" 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.Text.RegularExpressions" 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.ReaderWriter" version="4.3.0" targetFramework="net472" /> <package id="System.Xml.XDocument" version="4.3.0" targetFramework="net472" /> </packages> \ No newline at end of file From de7df46aa801c725426489a951d5f777d9ef55c7 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Wed, 22 Feb 2023 04:27:12 +0800 Subject: [PATCH 46/57] Sort the notification list by name and remove translation keys of brand names or product names --- src/components/NotificationDialog.vue | 74 +++++++++++++++++++++++-- src/components/notifications/Gorush.vue | 2 +- src/lang/en.json | 29 ---------- src/lang/zh-CN.json | 2 - 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index 0ca95c22..02ddce80 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -13,7 +13,7 @@ <div class="mb-3"> <label for="notification-type" class="form-label">{{ $t("Notification Type") }}</label> <select id="notification-type" v-model="notification.type" class="form-select"> - <option v-for="type in notificationTypes" :key="type" :value="type">{{ $t(type) }}</option> + <option v-for="(name, type) in notificationNameList" :key="type" :value="type">{{ name }}</option> </select> </div> @@ -67,7 +67,7 @@ </Confirm> </template> -<script lang="ts"> +<script> import { Modal } from "bootstrap"; import Confirm from "./Confirm.vue"; @@ -103,7 +103,71 @@ export default { return null; } return NotificationFormList[this.notification.type]; - } + }, + + notificationNameList() { + let list = { + "alerta": "Alerta", + "AlertNow": "AlertNow", + "AliyunSMS": "AliyunSMS (阿里云短信服务)", + "apprise": this.$t("apprise"), + "Bark": "Bark", + "clicksendsms": "ClickSend SMS", + "DingDing": "DingDing (钉钉自定义机器人)", + "discord": "Discord", + "Feishu": "Feishu (飞书)", + "FreeMobile": "FreeMobile", + "GoogleChat": "Google Chat (Google Workspace)", + "gorush": "Gorush", + "gotify": "Gotify", + "HomeAssistant": "Home Assistant", + "Kook": "Kook", + "line": "LINE Messenger", + "LineNotify": "LINE Notify", + "lunasea": "LunaSea", + "matrix": "Matrix", + "mattermost": "Mattermost", + "ntfy": "Ntfy", + "octopush": "Octopush", + "OneBot": "OneBot", + "PagerDuty": "PagerDuty", + "promosms": "PromoSMS", + "pushbullet": "Pushbullet", + "PushByTechulus": "Push by Techulus", + "PushDeer": "PushDeer", + "pushover": "Pushover", + "pushy": "Pushy", + "rocket.chat": "Rocket.Chat", + "serwersms": "SerwerSMS.pl", + "signal": "Signal", + "SMSManager": "SmsManager (smsmanager.cz)", + "slack": "Slack", + "squadcast": "SquadCast", + "SMSEagle": "SMSEagle", + "smtp": this.$t("smtp"), + "stackfield": "Stackfield", + "teams": "Microsoft Teams", + "telegram": "Telegram", + "Splunk": "Splunk", + "webhook": "Webhook", + "WeCom": "WeCom (企业微信群机器人)", + "GoAlert": "GoAlert", + "ServerChan": "ServerChan (Server酱)", + "ZohoCliq": "ZohoCliq" + }; + + // Sort by notification name + // No idea how, but it works + // https://stackoverflow.com/questions/1069666/sorting-object-property-by-values + const sortable = Object.entries(list) + .sort(([ , a ], [ , b ]) => a - b) + .reduce((r, [ k, v ]) => ({ + ...r, + [k]: v + }), {}); + + return sortable; + }, }, watch: { @@ -203,6 +267,7 @@ export default { * @return {string} */ getUniqueDefaultName(notificationKey) { + /* let index = 1; let name = ""; do { @@ -211,7 +276,8 @@ export default { number: index++ }); } while (this.$root.notificationList.find(it => it.name === name)); - return name; + return name;*/ + return "123"; } }, }; diff --git a/src/components/notifications/Gorush.vue b/src/components/notifications/Gorush.vue index b53be2d2..315ee677 100644 --- a/src/components/notifications/Gorush.vue +++ b/src/components/notifications/Gorush.vue @@ -16,7 +16,7 @@ <div class="mb-3"> <label for="gorush-platform" class="form-label">{{ $t("Platform") }}</label><span style="color: red;"><sup>*</sup></span> <select id="gorush-platform" v-model="$parent.notification.gorushPlatform" class="form-select"> - <option value="ios">{{ $t("iOS") }}</option> + <option value="ios">iOS</option> <option value="android">{{ $t("Android") }}</option> <option value="huawei">{{ $t("Huawei") }}</option> </select> diff --git a/src/lang/en.json b/src/lang/en.json index 1e3242ca..97941a5b 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -186,7 +186,6 @@ "defaultNotificationName": "My {notification} Alert ({number})", "here": "here", "Required": "Required", - "webhook": "Webhook", "Post URL": "Post URL", "Content Type": "Content Type", "webhookJsonDesc": "{0} is good for any modern HTTP servers such as Express.js", @@ -360,7 +359,6 @@ "Workstation": "Workstation", "Packet Size": "Packet Size", "telegram": "Telegram", - "ZohoCliq": "ZohoCliq", "Bot Token": "Bot Token", "wayToGetTelegramToken": "You can get a token from {0}.", "Chat ID": "Chat ID", @@ -388,7 +386,6 @@ "backupOutdatedWarning": "Deprecated: Since a lot of features were added and this backup feature is a bit unmaintained, it cannot generate or restore a complete backup.", "backupRecommend": "Please backup the volume or the data folder (./data/) directly instead.", "Optional": "Optional", - "squadcast": "Squadcast", "or": "or", "recurringInterval": "Interval", "Recurring": "Recurring", @@ -530,28 +527,11 @@ "pushoversounds none": "None (silent)", "pushyAPIKey": "Secret API Key", "pushyToken": "Device token", - "discord": "Discord", - "teams": "Microsoft Teams", - "signal": "Signal", - "gotify": "Gotify", - "slack": "Slack", - "rocket.chat": "Rocket.Chat", - "pushover": "Pushover", - "pushy": "Pushy", - "PushByTechulus": "Push by Techulus", - "octopush": "Octopush", - "promosms": "PromoSMS", - "clicksendsms": "ClickSend SMS", - "lunasea": "LunaSea", "apprise": "Apprise (Support 50+ Notification services)", "GoogleChat": "Google Chat (Google Workspace only)", - "pushbullet": "Pushbullet", - "Kook": "Kook", "wayToGetKookBotToken": "Create application and get your bot token at {0}", "wayToGetKookGuildID": "Switch on 'Developer Mode' in Kook setting, and right click the guild to get its ID", "Guild ID": "Guild ID", - "line": "Line Messenger", - "mattermost": "Mattermost", "User Key": "User Key", "Device": "Device", "Message Title": "Message Title", @@ -586,12 +566,10 @@ "SendKey": "SendKey", "SMSManager API Docs": "SMSManager API Docs ", "Gateway Type": "Gateway Type", - "SMSManager": "SMSManager", "You can divide numbers with": "You can divide numbers with", "Base URL": "Base URL", "goAlertInfo": "GoAlert is a An open source application for on-call scheduling, automated escalations and notifications (like SMS or voice calls). Automatically engage the right person, the right way, and at the right time! {0}", "goAlertIntegrationKeyInfo": "Get generic API integration key for the service in this format \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" usually the value of token parameter of copied URL.", - "goAlert": "GoAlert", "AccessKeyId": "AccessKey ID", "SecretAccessKey": "AccessKey Secret", "PhoneNumbers": "PhoneNumbers", @@ -606,7 +584,6 @@ "For safety, must use secret key": "For safety, must use secret key", "Device Token": "Device Token", "Platform": "Platform", - "iOS": "iOS", "Android": "Android", "Huawei": "Huawei", "High": "High", @@ -617,7 +594,6 @@ "Proxy Protocol": "Proxy Protocol", "Proxy Server": "Proxy Server", "Proxy server has authentication": "Proxy server has authentication", - "matrix": "Matrix", "promosmsTypeEco": "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.", "promosmsTypeFlash": "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.", "promosmsTypeFull": "SMS FULL - Premium tier of SMS, You can use your Sender Name (You need to register name first). Reliable for alerts.", @@ -653,19 +629,15 @@ "do nothing": "do nothing", "auto acknowledged": "auto acknowledged", "auto resolve": "auto resolve", - "gorush": "Gorush", - "alerta": "Alerta", "alertaApiEndpoint": "API Endpoint", "alertaEnvironment": "Environment", "alertaApiKey": "API Key", "alertaAlertState": "Alert State", "alertaRecoverState": "Recover State", - "serwersms": "SerwerSMS.pl", "serwersmsAPIUser": "API Username (incl. webapi_ prefix)", "serwersmsAPIPassword": "API Password", "serwersmsPhoneNumber": "Phone number", "serwersmsSenderName": "SMS Sender Name (registered via customer portal)", - "smseagle": "SMSEagle", "smseagleTo": "Phone number(s)", "smseagleGroup": "Phonebook group name(s)", "smseagleContact": "Phonebook contact name(s)", @@ -675,7 +647,6 @@ "smseagleUrl": "Your SMSEagle device URL", "smseagleEncoding": "Send as Unicode", "smseaglePriority": "Message priority (0-9, default = 0)", - "stackfield": "Stackfield", "Recipient Number": "Recipient Number", "From Name/Number": "From Name/Number", "Leave blank to use a shared sender number.": "Leave blank to use a shared sender number.", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index f3a222dc..a0539593 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -272,7 +272,6 @@ "apprise": "Apprise (支持 50+ 种通知服务)", "GoogleChat": "Google Chat(仅 Google Workspace)", "pushbullet": "Pushbullet", - "AliyunSMS": "阿里云短信服务", "Kook": "Kook", "wayToGetKookBotToken": "在 {0} 创建应用并获取机器人 Token", "wayToGetKookGuildID": "在 Kook 设置中打开“开发者模式”,然后右键点击频道可获取其 ID", @@ -448,7 +447,6 @@ "Bark Endpoint": "Bark 接入点", "Bark Group": "Bark 群组", "Bark Sound": "Bark 铃声", - "DingDing": "钉钉自定义机器人", "WebHookUrl": "钉钉自定义机器人 Webhook 地址", "SecretKey": "钉钉自定义机器人加签密钥", "For safety, must use secret key": "出于安全考虑,必须使用加签密钥", From 7da48b27a57015d83341070bff1aa7cd9376ed47 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Wed, 22 Feb 2023 04:29:43 +0800 Subject: [PATCH 47/57] Fix `getUniqueDefaultName` --- src/components/NotificationDialog.vue | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index 02ddce80..9631538e 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -267,17 +267,16 @@ export default { * @return {string} */ getUniqueDefaultName(notificationKey) { - /* + let index = 1; let name = ""; do { name = this.$t("defaultNotificationName", { - notification: this.$t(notificationKey).replace(/\(.+\)/, "").trim(), + notification: this.notificationNameList[notificationKey].replace(/\(.+\)/, "").trim(), number: index++ }); } while (this.$root.notificationList.find(it => it.name === name)); - return name;*/ - return "123"; + return name; } }, }; From df5da0054e8b12ba44e8a9ec0a5d8ad9d1ee790d Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Wed, 22 Feb 2023 04:40:03 +0800 Subject: [PATCH 48/57] Remove more keys --- src/lang/en.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lang/en.json b/src/lang/en.json index 97941a5b..cfbad0b6 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -358,7 +358,6 @@ "Domain": "Domain", "Workstation": "Workstation", "Packet Size": "Packet Size", - "telegram": "Telegram", "Bot Token": "Bot Token", "wayToGetTelegramToken": "You can get a token from {0}.", "Chat ID": "Chat ID", @@ -653,7 +652,6 @@ "Octopush API Version": "Octopush API Version", "Legacy Octopush-DM": "Legacy Octopush-DM", "ntfy Topic": "ntfy Topic", - "HomeAssistant": "Home Assistant", "onebotHttpAddress": "OneBot HTTP Address", "onebotMessageType": "OneBot Message Type", "onebotGroupMessage": "Group", From 7c8cff7708cef68017875175eaae2d02e15a15af Mon Sep 17 00:00:00 2001 From: Nelson Chan <chakflying@hotmail.com> Date: Thu, 23 Feb 2023 17:02:16 +0800 Subject: [PATCH 49/57] Fix: Add null check for injected HTML --- src/pages/StatusPage.vue | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index f4a6eb76..edf32561 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -502,15 +502,27 @@ export default { }, incidentHTML() { - return DOMPurify.sanitize(marked(this.incident.content)); + if (this.incident.content != null) { + return DOMPurify.sanitize(marked(this.incident.content)); + } else { + return ""; + } }, descriptionHTML() { - return DOMPurify.sanitize(marked(this.config.description)); + if (this.config.description != null) { + return DOMPurify.sanitize(marked(this.config.description)); + } else { + return ""; + } }, footerHTML() { - return DOMPurify.sanitize(marked(this.config.footerText)); + if (this.config.footerText != null) { + return DOMPurify.sanitize(marked(this.config.footerText)); + } else { + return ""; + } }, }, watch: { From fa7f75a930606d4365039395eb2894cb739ec674 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Thu, 23 Feb 2023 18:01:42 +0800 Subject: [PATCH 50/57] Organize notification list --- src/components/NotificationDialog.vue | 63 ++++++++++++++++++--------- src/lang/en.json | 1 + 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index 9631538e..c3851b56 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -13,7 +13,10 @@ <div class="mb-3"> <label for="notification-type" class="form-label">{{ $t("Notification Type") }}</label> <select id="notification-type" v-model="notification.type" class="form-select"> - <option v-for="(name, type) in notificationNameList" :key="type" :value="type">{{ name }}</option> + <option v-for="(name, type) in notificationNameList.regularList" :key="type" :value="type">{{ name }}</option> + <optgroup :label="$t('notificationRegional')"> + <option v-for="(name, type) in notificationNameList.regionalList" :key="type" :value="type">{{ name }}</option> + </optgroup> </select> </div> @@ -106,17 +109,13 @@ export default { }, notificationNameList() { - let list = { + let regularList = { "alerta": "Alerta", "AlertNow": "AlertNow", - "AliyunSMS": "AliyunSMS (阿里云短信服务)", "apprise": this.$t("apprise"), "Bark": "Bark", "clicksendsms": "ClickSend SMS", - "DingDing": "DingDing (钉钉自定义机器人)", "discord": "Discord", - "Feishu": "Feishu (飞书)", - "FreeMobile": "FreeMobile", "GoogleChat": "Google Chat (Google Workspace)", "gorush": "Gorush", "gotify": "Gotify", @@ -131,16 +130,12 @@ export default { "octopush": "Octopush", "OneBot": "OneBot", "PagerDuty": "PagerDuty", - "promosms": "PromoSMS", "pushbullet": "Pushbullet", "PushByTechulus": "Push by Techulus", - "PushDeer": "PushDeer", "pushover": "Pushover", "pushy": "Pushy", "rocket.chat": "Rocket.Chat", - "serwersms": "SerwerSMS.pl", "signal": "Signal", - "SMSManager": "SmsManager (smsmanager.cz)", "slack": "Slack", "squadcast": "SquadCast", "SMSEagle": "SMSEagle", @@ -150,23 +145,51 @@ export default { "telegram": "Telegram", "Splunk": "Splunk", "webhook": "Webhook", - "WeCom": "WeCom (企业微信群机器人)", "GoAlert": "GoAlert", - "ServerChan": "ServerChan (Server酱)", "ZohoCliq": "ZohoCliq" }; + // Put notifications here if it's not supported in most regions or its documentation is not in English + let regionalList = { + "AliyunSMS": "AliyunSMS (阿里云短信服务)", + "DingDing": "DingDing (钉钉自定义机器人)", + "Feishu": "Feishu (飞书)", + "FreeMobile": "FreeMobile (mobile.free.fr)", + "PushDeer": "PushDeer", + "promosms": "PromoSMS", + "serwersms": "SerwerSMS.pl", + "SMSManager": "SmsManager (smsmanager.cz)", + "WeCom": "WeCom (企业微信群机器人)", + "ServerChan": "ServerChan (Server酱)", + }; + // Sort by notification name // No idea how, but it works // https://stackoverflow.com/questions/1069666/sorting-object-property-by-values - const sortable = Object.entries(list) - .sort(([ , a ], [ , b ]) => a - b) - .reduce((r, [ k, v ]) => ({ - ...r, - [k]: v - }), {}); + let sort = (list2) => { + return Object.entries(list2) + .sort(([ , a ], [ , b ]) => a.localeCompare(b)) + .reduce((r, [ k, v ]) => ({ + ...r, + [k]: v + }), {}); + }; - return sortable; + return { + regularList: sort(regularList), + regionalList: sort(regionalList), + }; + }, + + notificationFullNameList() { + let list = {}; + for (let [ key, value ] of Object.entries(this.notificationNameList.regularList)) { + list[key] = value; + } + for (let [ key, value ] of Object.entries(this.notificationNameList.regionalList)) { + list[key] = value; + } + return list; }, }, @@ -272,7 +295,7 @@ export default { let name = ""; do { name = this.$t("defaultNotificationName", { - notification: this.notificationNameList[notificationKey].replace(/\(.+\)/, "").trim(), + notification: this.notificationFullNameList[notificationKey].replace(/\(.+\)/, "").trim(), number: index++ }); } while (this.$root.notificationList.find(it => it.name === name)); diff --git a/src/lang/en.json b/src/lang/en.json index cfbad0b6..de86111a 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -432,6 +432,7 @@ "uninstall": "Uninstall", "uninstalling": "Uninstalling", "confirmUninstallPlugin": "Are you sure want to uninstall this plugin?", + "notificationRegional": "Regional", "smtp": "Email (SMTP)", "secureOptionNone": "None / STARTTLS (25, 587)", "secureOptionTLS": "TLS (465)", From 7e3734af53458f086df0a3daa79425532ea393e5 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Thu, 23 Feb 2023 20:59:24 +0800 Subject: [PATCH 51/57] Better handling --- server/notification-providers/telegram.js | 14 +++++++++----- src/components/notifications/Telegram.vue | 8 ++++---- src/lang/ar-SY.json | 2 +- src/lang/bg-BG.json | 1 - src/lang/cs-CZ.json | 1 - src/lang/da-DK.json | 1 - src/lang/de-CH.json | 1 - src/lang/de-DE.json | 1 - src/lang/el-GR.json | 1 - src/lang/en.json | 3 ++- src/lang/nl-NL.json | 1 - src/lang/pl.json | 1 - src/lang/ru-RU.json | 1 - src/lang/sl-SI.json | 1 - src/lang/th-TH.json | 1 - src/lang/tr-TR.json | 1 - src/lang/uk-UA.json | 1 - src/lang/vi-VN.json | 1 - src/lang/zh-CN.json | 1 - src/lang/zh-HK.json | 1 - src/lang/zh-TW.json | 1 - 21 files changed, 16 insertions(+), 28 deletions(-) diff --git a/server/notification-providers/telegram.js b/server/notification-providers/telegram.js index fb53b971..7f46b3fc 100644 --- a/server/notification-providers/telegram.js +++ b/server/notification-providers/telegram.js @@ -9,12 +9,16 @@ class Telegram extends NotificationProvider { let okMsg = "Sent Successfully."; try { + let params = { + chat_id: notification.telegramChatID, + text: msg, + }; + if (notification.telegramMessageThreadID) { + params.message_thread_id = notification.telegramMessageThreadID; + } + await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, { - params: { - chat_id: notification.telegramChatID, - text: msg, - message_thread_id: notification.telegramMessageThreadID, - }, + params: params, }); return okMsg; diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index a1b74a8a..042774ac 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -17,10 +17,6 @@ </button> </div> - <label for="message_thread_id" class="form-label">{{ $t("Message Thread ID") }}</label> - <input id="message_thread_id" v-model="$parent.notification.telegramMessageThreadID" type="text" class="form-control"> - <p class="form-text">Message Thread ID: Optional Unique identifier for the target message thread (topic) of the forum; for forum supergroups only</p> - <div class="form-text"> {{ $t("supportTelegramChatID") }} @@ -32,6 +28,10 @@ <a :href="telegramGetUpdatesURL('withToken')" target="_blank" style="word-break: break-word;">{{ telegramGetUpdatesURL("masked") }}</a> </p> </div> + + <label for="message_thread_id" class="form-label">{{ $t("telegramMessageThreadID") }}</label> + <input id="message_thread_id" v-model="$parent.notification.telegramMessageThreadID" type="text" class="form-control"> + <p class="form-text">{{ $t("telegramMessageThreadIDDescription") }}</p> </div> </template> diff --git a/src/lang/ar-SY.json b/src/lang/ar-SY.json index b44ed206..3a4cf140 100644 --- a/src/lang/ar-SY.json +++ b/src/lang/ar-SY.json @@ -215,7 +215,7 @@ "Bot Token": "رمز الروبوت", "wayToGetTelegramToken": "يمكنك الحصول على رمز من {0}.", "Chat ID": "معرف الدردشة", - "Message Thread ID": "معرف المواضيع", + "telegramMessageThreadID": "معرف المواضيع", "supportTelegramChatID": "دعم الدردشة المباشرة / معرف الدردشة للقناة", "wayToGetTelegramChatID": "يمكنك الحصول على معرف الدردشة الخاص بك عن طريق إرسال رسالة إلى الروبوت والانتقال إلى عنوان URL هذا لعرض Chat_id", "YOUR BOT TOKEN HERE": "رمز الروبوت الخاص بك هنا", diff --git a/src/lang/bg-BG.json b/src/lang/bg-BG.json index 23e0e549..ae2cdce6 100644 --- a/src/lang/bg-BG.json +++ b/src/lang/bg-BG.json @@ -210,7 +210,6 @@ "Bot Token": "Бот токен", "wayToGetTelegramToken": "Можете да получите токен от {0}.", "Chat ID": "Чат ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Поддържа Direct Chat / Group / Channel's Chat ID", "wayToGetTelegramChatID": "Можете да получите вашето чат ID, като изпратите съобщение на бота, след което е нужно да посетите този URL адрес за да го видите:", "YOUR BOT TOKEN HERE": "ВАШИЯТ БОТ ТОКЕН ТУК", diff --git a/src/lang/cs-CZ.json b/src/lang/cs-CZ.json index 5981971d..dc8e2637 100644 --- a/src/lang/cs-CZ.json +++ b/src/lang/cs-CZ.json @@ -215,7 +215,6 @@ "Bot Token": "Token bota", "wayToGetTelegramToken": "Token můžete získat od {0}.", "Chat ID": "ID chatu", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Podpora přímého chatu / skupiny / ID chatu kanálu", "wayToGetTelegramChatID": "ID chatu můžete získat tak, že robotovi zašlete zprávu a přejdete na tuto adresu URL, kde zobrazíte chat_id:", "YOUR BOT TOKEN HERE": "SEM ZADEJTE TOKEN VAŠEHO CHATBOTA", diff --git a/src/lang/da-DK.json b/src/lang/da-DK.json index 02a63220..1b0fe210 100644 --- a/src/lang/da-DK.json +++ b/src/lang/da-DK.json @@ -208,7 +208,6 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Du kan få et token fra {0}.", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Support Direct Chat / Group / Channel's Chat ID", "wayToGetTelegramChatID": "Du kan få dit chat-ID ved at sende en besked til bot'en og gå til denne URL for at se chat_id'et:", "YOUR BOT TOKEN HERE": "DIT BOT TOKEN HER", diff --git a/src/lang/de-CH.json b/src/lang/de-CH.json index 7e0f0ebd..d8a46562 100644 --- a/src/lang/de-CH.json +++ b/src/lang/de-CH.json @@ -214,7 +214,6 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Hier kannst du einen Token erhalten {0}.", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Unterstützt Direkt Chat / Gruppe / Kanal Chat-ID's", "wayToGetTelegramChatID": "Du kannst die Chat-ID erhalten, indem du eine Nachricht an den Bot sendest und zu dieser URL gehst, um die chat_id: zu sehen.", "YOUR BOT TOKEN HERE": "HIER DEIN BOT TOKEN", diff --git a/src/lang/de-DE.json b/src/lang/de-DE.json index 37d27a6e..2e7bbb5f 100644 --- a/src/lang/de-DE.json +++ b/src/lang/de-DE.json @@ -214,7 +214,6 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Hier kannst du einen Token erhalten {0}.", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Unterstützt Direkt Chat / Gruppe / Kanal Chat-ID's", "wayToGetTelegramChatID": "Du kannst deine Chat-ID erhalten, indem du eine Nachricht an den Bot sendest und zu dieser URL gehst, um die chat_id: zu sehen.", "YOUR BOT TOKEN HERE": "HIER DEIN BOT TOKEN", diff --git a/src/lang/el-GR.json b/src/lang/el-GR.json index 1f8459f1..19a9bd4c 100644 --- a/src/lang/el-GR.json +++ b/src/lang/el-GR.json @@ -198,7 +198,6 @@ "Bot Token": "Διακριτικό Bot", "wayToGetTelegramToken": "Μπορείτε να πάρετε ένα διακριτικό από {0}.", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Support Direct Chat / Group / Channel's Chat ID", "wayToGetTelegramChatID": "Μπορείτε να λάβετε το αναγνωριστικό συνομιλίας σας στέλνοντας ένα μήνυμα στο bot και μεταβαίνοντας σε αυτήν τη διεύθυνση URL για να προβάλετε το chat_id:", "YOUR BOT TOKEN HERE": "ΤΟ BOT ΣΑΣ ΔΙΑΚΡΙΤΙΚΌ ΕΔΩ", diff --git a/src/lang/en.json b/src/lang/en.json index e70dbb38..c1249d31 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -361,7 +361,8 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "You can get a token from {0}.", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", + "telegramMessageThreadID": "(Optional) Message Thread ID", + "telegramMessageThreadIDDescription": "Optional Unique identifier for the target message thread (topic) of the forum; for forum supergroups only", "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:", "YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE", diff --git a/src/lang/nl-NL.json b/src/lang/nl-NL.json index e4c1da00..32c79545 100644 --- a/src/lang/nl-NL.json +++ b/src/lang/nl-NL.json @@ -217,7 +217,6 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Je kunt een token krijgen van {0}.", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Ondersteuning Directe Chat / Groep / Kanaal Chat ID", "wayToGetTelegramChatID": "Je kunt je CHAT ID krijgen door een bericht te sturen naar de bot en naar deze URL te gaan om het chat_id te bekijken:", "YOUR BOT TOKEN HERE": "DE BOT TOKEN HIER", diff --git a/src/lang/pl.json b/src/lang/pl.json index 6996e761..472b595c 100644 --- a/src/lang/pl.json +++ b/src/lang/pl.json @@ -189,7 +189,6 @@ "Bot Token": "Token bota", "wayToGetTelegramToken": "Token można uzyskać z {0}.", "Chat ID": "Identyfikator czatu", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Czat wsparcia technicznego / Bezpośrednia rozmowa / Czat grupowy", "wayToGetTelegramChatID": "Możesz uzyskać swój identyfikator czatu, wysyłając wiadomość do bota i przechodząc pod ten adres URL, aby wyświetlić identyfikator czatu:", "YOUR BOT TOKEN HERE": "TWÓJ TOKEN BOTA", diff --git a/src/lang/ru-RU.json b/src/lang/ru-RU.json index 96ad8661..7ea1f643 100644 --- a/src/lang/ru-RU.json +++ b/src/lang/ru-RU.json @@ -216,7 +216,6 @@ "Bot Token": "Токен бота", "wayToGetTelegramToken": "Вы можете взять токен здесь - {0}.", "Chat ID": "ID чата", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Поддерживаются ID чатов, групп и каналов", "wayToGetTelegramChatID": "Вы можете взять ID вашего чата, отправив сообщение боту и перейдя по этому URL для просмотра chat_id:", "YOUR BOT TOKEN HERE": "ВАШ ТОКЕН БОТА ЗДЕСЬ", diff --git a/src/lang/sl-SI.json b/src/lang/sl-SI.json index bf32cbed..f4ca81bd 100644 --- a/src/lang/sl-SI.json +++ b/src/lang/sl-SI.json @@ -193,7 +193,6 @@ "Bot Token": "Robotkov žetonček", "wayToGetTelegramToken": "Lahko dobiš žeton od {0}.", "Chat ID": "ID pogovora", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Direkten pogovor pomoči / Skupina / ID kanala", "wayToGetTelegramChatID": "Id lahko dobiš, če pošlješ sporočilo robotku in odpreš ta URL, da bi videl chat_id:", "YOUR BOT TOKEN HERE": "ROBOTKOV ŽETON TUKAJ", diff --git a/src/lang/th-TH.json b/src/lang/th-TH.json index 2146c734..9f5c78a1 100644 --- a/src/lang/th-TH.json +++ b/src/lang/th-TH.json @@ -194,7 +194,6 @@ "Bot Token": "กุญแจของบอท", "wayToGetTelegramToken": "คุณสามารถรับกุญแจได้จาก {0}.", "Chat ID": "ไอดีแชท", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "รองรับ แชทส่วนตัว, แชทกลุ่ม, ไอดีแชท", "wayToGetTelegramChatID": "คุณสามารถรับ ID แชทของคุณได้โดยส่งข้อความไปยังบอทและไปที่ URL นี้เพื่อดู chat_id :", "YOUR BOT TOKEN HERE": "กุญแจของบอทของคุณที่นี่", diff --git a/src/lang/tr-TR.json b/src/lang/tr-TR.json index d55f2aab..80d273e1 100644 --- a/src/lang/tr-TR.json +++ b/src/lang/tr-TR.json @@ -197,7 +197,6 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "{0} adresinden bir token alabilirsiniz.", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Doğrudan Sohbet / Grup / Kanalın Sohbet Kimliğini Destekleyin", "wayToGetTelegramChatID": "Bot'a bir mesaj göndererek ve chat_id'yi görüntülemek için bu URL'ye giderek sohbet kimliğinizi alabilirsiniz:", "YOUR BOT TOKEN HERE": "BOT TOKENİNİZ BURADA", diff --git a/src/lang/uk-UA.json b/src/lang/uk-UA.json index 7de6829c..9a63cfe0 100644 --- a/src/lang/uk-UA.json +++ b/src/lang/uk-UA.json @@ -216,7 +216,6 @@ "Bot Token": "Токен бота", "wayToGetTelegramToken": "Ви можете взяти токен тут - {0}.", "Chat ID": "ID чату", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Підтримуються ID чатів, груп та каналів", "wayToGetTelegramChatID": "Ви можете взяти ID вашого чату, відправивши повідомлення боту і перейшовши по цьому URL для перегляду chat_id:", "YOUR BOT TOKEN HERE": "ВАШ ТОКЕН БОТА ТУТ", diff --git a/src/lang/vi-VN.json b/src/lang/vi-VN.json index 4446a020..165bf1bb 100644 --- a/src/lang/vi-VN.json +++ b/src/lang/vi-VN.json @@ -193,7 +193,6 @@ "Bot Token": "Bot Token", "wayToGetTelegramToken": "Bạn có thể lấy mã token từ", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "Hỗ trợ chat trực tiếp / Nhóm / Kênh Chat ID", "wayToGetTelegramChatID": "Bạn có thể lấy chat id của mình bằng cách gửi tin nhắn tới bot và truy cập url này để xem chat_id:", "YOUR BOT TOKEN HERE": "MÃ BOT TOKEN CỦA BẠN", diff --git a/src/lang/zh-CN.json b/src/lang/zh-CN.json index 8bad70ab..a0539593 100644 --- a/src/lang/zh-CN.json +++ b/src/lang/zh-CN.json @@ -213,7 +213,6 @@ "Bot Token": "机器人令牌", "wayToGetTelegramToken": "您可以从 {0} 获取 Token。", "Chat ID": "Chat ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "支持对话/群组/频道的 Chat ID", "wayToGetTelegramChatID": "您可以发送一条消息给您的机器人,然后访问此链接来查看 chat_id:", "YOUR BOT TOKEN HERE": "这里替换成您的 BOT TOKEN", diff --git a/src/lang/zh-HK.json b/src/lang/zh-HK.json index 1d7e0e65..8111b73d 100644 --- a/src/lang/zh-HK.json +++ b/src/lang/zh-HK.json @@ -211,7 +211,6 @@ "Bot Token": "機器人權杖", "wayToGetTelegramToken": "您可以從 {0} 取得 Token。", "Chat ID": "聊天 ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "支援 對話/群組/頻道的聊天 ID", "wayToGetTelegramChatID": "傳送訊息給機器人,並前往以下網址以取得您的 chat ID:", "YOUR BOT TOKEN HERE": "在此填入您的機器人權杖", diff --git a/src/lang/zh-TW.json b/src/lang/zh-TW.json index 5a63ac54..3e208215 100644 --- a/src/lang/zh-TW.json +++ b/src/lang/zh-TW.json @@ -212,7 +212,6 @@ "Bot Token": "機器人權杖", "wayToGetTelegramToken": "您可以從 {0} 取得權杖。", "Chat ID": "聊天 ID", - "Message Thread ID": "Message Thread ID", "supportTelegramChatID": "支援 對話/群組/頻道的聊天 ID", "wayToGetTelegramChatID": "傳送訊息給機器人,並前往以下網址以取得您的 chat ID:", "YOUR BOT TOKEN HERE": "在此填入您的機器人權杖", From 10228874fa41c7afaf4cca8ac72f3edc9ab9f5bd Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Fri, 24 Feb 2023 16:54:58 +0800 Subject: [PATCH 52/57] Merge manually --- server/notification-providers/telegram.js | 1 + src/components/notifications/Telegram.vue | 2 +- src/lang/en.json | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/server/notification-providers/telegram.js b/server/notification-providers/telegram.js index 7f46b3fc..614e487e 100644 --- a/server/notification-providers/telegram.js +++ b/server/notification-providers/telegram.js @@ -12,6 +12,7 @@ class Telegram extends NotificationProvider { let params = { chat_id: notification.telegramChatID, text: msg, + disable_notification: notification.telegramSendSilently ?? false, }; if (notification.telegramMessageThreadID) { params.message_thread_id = notification.telegramMessageThreadID; diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 7816de74..a90ceafc 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -35,7 +35,7 @@ <div class="form-check form-switch"> <input v-model="$parentnotification.telegramSendSilently" class="form-check-input" type="checkbox"> - <label class="form-check-label">{{ $t("Send Silently") }}</label> + <label class="form-check-label">{{ $t("telegramSendSilently") }}</label> </div> <div class="form-text"> diff --git a/src/lang/en.json b/src/lang/en.json index c1249d31..ef6cb688 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -363,6 +363,8 @@ "Chat ID": "Chat ID", "telegramMessageThreadID": "(Optional) Message Thread ID", "telegramMessageThreadIDDescription": "Optional Unique identifier for the target message thread (topic) of the forum; for forum supergroups only", + "telegramSendSilently": "Send Silently", + "telegramSendSilentlyDescription": "Sends the message silently. Users will receive a notification with no sound.", "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:", "YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE", From 06278dc51fb89b3f7e323973fcc982c6b15cbd03 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Fri, 24 Feb 2023 17:03:40 +0800 Subject: [PATCH 53/57] Fix telegram silent issue --- src/components/notifications/Telegram.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index a90ceafc..52a63b8c 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -34,7 +34,7 @@ <p class="form-text">{{ $t("telegramMessageThreadIDDescription") }}</p> <div class="form-check form-switch"> - <input v-model="$parentnotification.telegramSendSilently" class="form-check-input" type="checkbox"> + <input v-model="$parent.notification.telegramSendSilently" class="form-check-input" type="checkbox"> <label class="form-check-label">{{ $t("telegramSendSilently") }}</label> </div> From 2fa233ae7fa76eaf82bf7658c42dd61dc21cd22c Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Fri, 24 Feb 2023 17:12:57 +0800 Subject: [PATCH 54/57] Fix prometheus null issues --- server/model/monitor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 4bb859e9..d6e1896a 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -755,7 +755,7 @@ class Monitor extends BeanModel { await R.store(bean); log.debug("monitor", `[${this.name}] prometheus.update`); - this.prometheus.update(bean, tlsInfo); + this.prometheus?.update(bean, tlsInfo); previousBeat = bean; @@ -840,7 +840,7 @@ class Monitor extends BeanModel { clearTimeout(this.heartbeatInterval); this.isStop = true; - this.prometheus.remove(); + this.prometheus?.remove(); } /** From af82ea742cbe1559b0fbc8d4cf80f7d850d5ae30 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Fri, 24 Feb 2023 17:21:53 +0800 Subject: [PATCH 55/57] Merge manually --- src/components/notifications/Telegram.vue | 27 ++--------------------- src/lang/en.json | 2 ++ 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 46824538..a7e46fde 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -43,37 +43,14 @@ </div> </div> - <div class="mb-3"> - <label for="telegram-chat-thread" class="form-label">{{ $t("Thread ID") }}</label> - - <div class="input-group mb-3"> - <input id="telegram-chat-thread" v-model="$parent.notification.telegramChatThread" type="text" class="form-control"> - </div> - - <div class="form-text"> - {{ $t("Thread ID Description") }} - </div> - </div> - - <div class="mb-3"> - <div class="form-check form-switch"> - <input v-model="$parent.notification.telegramSilentNotification" class="form-check-input" type="checkbox"> - <label class="form-check-label">{{ $t("Silent Notification") }}</label> - </div> - - <div class="form-text"> - {{ $t("Silent Notification Description") }} - </div> - </div> - <div class="mb-3"> <div class="form-check form-switch"> <input v-model="$parent.notification.telegramProtectContent" class="form-check-input" type="checkbox"> - <label class="form-check-label">{{ $t("Protect Forwarding") }}</label> + <label class="form-check-label">{{ $t("telegramProtectContent") }}</label> </div> <div class="form-text"> - {{ $t("Protect Forwarding Description") }} + {{ $t("telegramProtectContentDescription") }} </div> </div> </template> diff --git a/src/lang/en.json b/src/lang/en.json index ef6cb688..478ddddc 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -365,6 +365,8 @@ "telegramMessageThreadIDDescription": "Optional Unique identifier for the target message thread (topic) of the forum; for forum supergroups only", "telegramSendSilently": "Send Silently", "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.", "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:", "YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE", From 7b8ed01f272fc4c6b69ff6299185e936a5e63735 Mon Sep 17 00:00:00 2001 From: Nelson Chan <chakflying@hotmail.com> Date: Fri, 24 Feb 2023 21:06:00 +0800 Subject: [PATCH 56/57] Fix: getGameList returns nothing on first run --- server/socket-handlers/general-socket-handler.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/socket-handlers/general-socket-handler.js b/server/socket-handlers/general-socket-handler.js index 11b47a5b..48412183 100644 --- a/server/socket-handlers/general-socket-handler.js +++ b/server/socket-handlers/general-socket-handler.js @@ -12,7 +12,7 @@ let gameList = null; * @returns {any[]} */ function getGameList() { - if (!gameList) { + if (gameList == null) { gameList = gameResolver._readGames().games.sort((a, b) => { if ( a.pretty < b.pretty ) { return -1; @@ -22,9 +22,8 @@ function getGameList() { } return 0; }); - } else { - return gameList; } + return gameList; } module.exports.generalSocketHandler = (socket, server) => { From c65a920050688afed790a8bc6e400f45ee32f54c Mon Sep 17 00:00:00 2001 From: Nelson Chan <chakflying@hotmail.com> Date: Fri, 24 Feb 2023 21:09:55 +0800 Subject: [PATCH 57/57] Chore: Fix code comment --- server/socket-handlers/general-socket-handler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/socket-handlers/general-socket-handler.js b/server/socket-handlers/general-socket-handler.js index 48412183..bb4a3808 100644 --- a/server/socket-handlers/general-socket-handler.js +++ b/server/socket-handlers/general-socket-handler.js @@ -9,7 +9,7 @@ let gameList = null; /** * Get a game list via GameDig - * @returns {any[]} + * @returns {Object[]} list of games supported by GameDig */ function getGameList() { if (gameList == null) {