iobroker.weather-warnings
Version:
833 lines (832 loc) • 31.9 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var notification_exports = {};
__export(notification_exports, {
NotificationClass: () => NotificationClass
});
module.exports = __toCommonJS(notification_exports);
var import_definition = require("./def/definition");
var NotificationType = __toESM(require("./def/notificationService-def"));
var library = __toESM(require("./library"));
var import_messages_def = require("./def/messages-def");
class NotificationClass extends library.BaseClass {
options;
takeThemAll = false;
providerDB;
removeAllSend = true;
//clearAll(): void {}
/**
* Creates a new notification class.
*
* @param adapter The adapter instance.
* @param notifcationOptions The options for the notification service.
*/
constructor(adapter, notifcationOptions) {
super(adapter, notifcationOptions.name);
this.options = notifcationOptions;
this.options = Object.assign(this.options, NotificationType.serciceCapabilities[notifcationOptions.name]);
this.log.info(
`Create notification service ${this.name}${this.options.adapter != void 0 ? this.name == "alexa2" ? ` state: ${this.adapter.config.alexa2_device_ids.map((a) => `${this.options.adapter}.Echo-Devices.${a}.Commands.speak`).join(", ")}` : ` adapter: ${this.options.adapter}` : ""}.`
);
this.log.setLogPrefix(this.options.adapter != void 0 ? this.options.adapter : this.name);
}
/**
* Initialisiere class - create channel, states etc
*/
async init() {
switch (this.name) {
case "history":
case "json":
{
let dp = "";
let def = import_definition.genericStateObjects.history;
const providers = this.adapter.providerController.providers.filter(
(a) => this.options.service.includes(a.service)
);
if (this.adapter.providerController) {
const targets = [...providers, this.adapter.providerController];
for (const a of targets) {
switch (this.options.name) {
case "history":
{
dp = `${a.name}.history`;
def = import_definition.genericStateObjects.history;
}
break;
case "json":
{
dp = `${a.name}.activeWarnings_json`;
def = import_definition.genericStateObjects.activeWarningsJson;
}
break;
}
const state = this.adapter.library.readdp(dp);
if (state == void 0) {
await this.adapter.library.writedp(dp, "[]", def);
}
}
}
}
break;
}
}
/**
* Sends notifications based on the `allowActions` array.
*
* @param providers - The providers to get messages from.
* @param allowActions - The actions that are allowed to be sent.
* @param manual - If true, sends all messages, otherwise only sends messages that have changed.
*/
async sendMessage(providers, allowActions, manual = false) {
if (!manual && !this.allowSending()) {
this.log.debug("Sending the notification is not allowed.");
return;
}
let activeWarnings = 0;
const filter = manual && this.options.filter.manual ? this.options.filter.manual : this.options.filter.auto;
const actions = this.options.actions;
let result = [];
const notifications = this.options.notifications;
for (const a of providers) {
if (this.options.service.indexOf(a.service) == -1) {
continue;
}
for (const message of a.messages) {
if (message && (filter.level === void 0 || filter.level <= message.level) && !(0, import_messages_def.filterWarntype)(a.service, filter.type, message.type)) {
if (message.notDeleted) {
activeWarnings++;
}
for (const c in actions) {
const action = c;
if (manual && NotificationType.manual.indexOf(action) == -1) {
continue;
}
if (action == void 0 || actions[action] == "none" || actions[action] == "") {
continue;
}
if (!allowActions.includes(action)) {
continue;
}
if (!notifications.includes(action)) {
continue;
}
const templateKey = actions[action];
if (!templateKey || templateKey == "none") {
continue;
}
if (action == "removeAll") {
continue;
}
if (manual || // get every message
action == "new" && message.newMessage || // new message
action == "remove" && !message.notDeleted || // remove message
action == "manualAll" || action == "all" && // bei Diensten mit all sollten keine neuen oder entfernten nachrichten bei all durchlaufen.
notifications.includes("all") && !(notifications.includes("new") && message.newMessage) && !(notifications.includes("remove") && !message.notDeleted)) {
const msg = await message.getMessage(templateKey, this);
if (msg.text != "") {
msg.action = action;
msg.provider = a;
msg.message = message;
if (notifications.includes("title") && actions.title !== void 0 && actions.title !== "none") {
const title = await message.getMessage(actions.title, this);
msg.title = title.text;
}
result.push(msg);
}
}
}
}
}
}
if (notifications.includes("all") && notifications.includes("new") && notifications.includes("remove")) {
let sendthem = manual;
if (!sendthem) {
for (const msg of result) {
if (msg.message && (msg.message.newMessage || !msg.message.notDeleted)) {
sendthem = true;
break;
}
}
}
if (!sendthem) {
result = [];
} else {
result.sort((a, b) => {
if (!a.message) {
return 1;
}
if (!b.message) {
return -1;
}
if (a.message.newMessage && b.message.newMessage || !a.message.notDeleted && !b.message.notDeleted) {
return a.startts == b.startts ? 0 : a.startts < b.startts ? -1 : 1;
}
if (a.message.newMessage) {
return -1;
}
if (b.message.newMessage) {
return 1;
}
if (!a.message.notDeleted) {
return -1;
}
if (!b.message.notDeleted) {
return 1;
}
return a.startts == b.startts ? 0 : a.startts < b.startts ? -1 : 1;
});
}
}
if (result.length > 0 && (activeWarnings > 0 || !notifications.includes("removeAll"))) {
await this.sendNotifications(result);
this.removeAllSend = false;
} else {
if (!manual && this.options.notifications.includes("removeAll") && this.options.actions.removeAll != "none" && allowActions.includes("removeAll") && !this.removeAllSend && activeWarnings == 0 || this.options.notifications.includes("removeManualAll") && this.options.actions.removeManualAll && this.options.actions.removeManualAll != "none" && allowActions.includes("removeAll") && manual) {
const templates = this.adapter.config.templateTable;
const tempid = templates.findIndex(
(a) => a.templateKey == this.options.actions[manual ? "removeManualAll" : "removeAll"]
);
if (tempid != -1) {
const result2 = await this.adapter.providerController.noWarning.getMessage(
this.options.actions[manual ? "removeManualAll" : "removeAll"],
this
);
const msg = [
{
uniqueId: result2.uniqueId,
text: result2.text,
// templates[tempid].template.replaceAll('\\}', '}'),
startts: result2.startts,
template: result2.template,
action: manual ? "removeManualAll" : "removeAll"
}
];
const res = this.options.actions.title && this.options.actions.title != "none" && templates.findIndex((a) => a.templateKey == this.options.actions.title) != -1 ? await this.adapter.providerController.noWarning.getMessage(
this.options.actions.title,
this
) : null;
if (res !== null && res.text) {
msg[0].title = res.text;
}
await this.sendNotifications(msg);
}
this.removeAllSend = true;
}
}
}
/**
* Returns true if the given notification service is allowed to send notifications.
*
* For some services like alexa2 and sayit, the result of `isSpeakAllowed` is used.
* For all other services, always true is returned.
*/
allowSending() {
switch (this.options.name) {
case "telegram":
case "gotify":
case "nspanel":
case "pushover":
case "whatsapp":
case "json":
case "history":
case "email":
break;
case "sayit":
case "alexa2": {
return this.adapter.providerController.isSpeakAllowed();
}
}
return true;
}
/**
* Checks if the given notification service is allowed to send manual messages.
*
* A notification service is allowed to send manual messages if its configuration
* includes at least one of the following actions: 'manualAll', 'removeManualAll'.
*
* @returns true if the given notification service is allowed to send manual messages, false otherwise.
*/
canManual() {
if (this.options.notifications.findIndex((a) => NotificationType.manual.indexOf(a) != -1) != -1) {
return true;
}
return false;
}
/**
* Goes through all messages and removes unwanted information from sayit and alexa2 messages.
* This function is used to clean up the messages before sending them to the user.
*
* @param messages The array of messages to clean up.
* @returns The cleaned up messages.
*/
cleanupMessage(messages) {
for (const message of messages) {
if (message === null || message == void 0) {
continue;
}
switch (this.options.name) {
case "telegram":
case "gotify":
case "nspanel":
case "pushover":
case "whatsapp":
case "json":
case "history":
case "email":
break;
case "sayit":
case "alexa2": {
switch (this.library.language) {
case "en":
case "ru":
case "pt":
case "nl":
case "fr":
case "it":
case "es":
case "pl":
case "zh-cn":
case "uk":
case "de":
{
message.text = message.text.replace(/\([0-9]+.m\/s, [0-9]+.kn, Bft.[0-9]+../g, "");
message.text = message.text.replace(/°C/g, this.library.getTranslation("celsius"));
message.text = message.text.replace(/km\/h/g, this.library.getTranslation("kmh"));
message.text = message.text.replace(/l\/m²/g, this.library.getTranslation("lm"));
message.text = message.text.replace(
/ [a-zA-Z][a-zA-Z], \d{1,2}\.\d{1,2}\.\d{4} /g,
(x) => this.library.convertSpeakDate(x, this.options.name, true)
);
message.text = message.text.replace(/\\+n/g, "");
let count = 0;
let pos = 250;
while (pos <= message.text.length && count++ < 50) {
const oldpos = pos;
pos = message.text.lastIndexOf(";", oldpos);
if (pos == -1 || pos == oldpos - 250) {
pos = message.text.lastIndexOf(".", oldpos);
}
if (pos == -1) {
pos = message.text.lastIndexOf(" ", oldpos);
}
if (pos == -1) {
break;
}
message.text = `${message.text.slice(0, pos)};${message.text.slice(pos + 1)}`;
pos += 250;
}
}
break;
}
}
}
}
return messages;
}
/**
* @description Send notifications based on the settings of the adapter
* @param messages - The messages to be sent.
* @returns A promise that resolves to True if the sending was successful, false if not.
* @example
* adapter.sendNotifications([
* {
* text: 'Hello World',
* },
* {
* text: 'Hello Universe',
* },
* ]);
*/
async sendNotifications(messages) {
if (!Array.isArray(messages) || messages.length == 0) {
this.log.debug(`no messages`);
return false;
}
messages = this.cleanupMessage(Object.assign([], messages));
switch (this.options.name) {
case "telegram":
{
for (const msg of messages) {
const opt = { text: msg.text, disable_notification: this.options.withNoSound };
if (this.options.parse_mode != "none") {
opt.parse_mode = this.options.parse_mode;
}
try {
if (this.options.userid.length > 0 || this.options.chatid.length > 0) {
if (this.options.userid.length > 0) {
opt.user = this.options.userid;
}
if (this.options.chatid.length > 0) {
const chatids = this.options.chatid.split(",");
for (const chatid of chatids) {
this.adapter.sendTo(this.options.adapter, "send", {
...opt,
chatId: chatid
});
}
} else {
this.adapter.sendTo(this.options.adapter, "send", opt);
}
} else {
this.adapter.sendTo(this.options.adapter, "send", opt);
}
await library.sleep(20);
this.log.debug(`Send the message: ${msg.text}`);
} catch (error) {
if (error.message == "Timeout exceeded") {
this.log.warn(
`Error sending a notification: ${this.options.adapter} does not react in the given time.`
);
} else {
throw error;
}
}
}
}
break;
case "pushover":
{
for (const msg of messages) {
const opt = {
message: msg.text,
sound: this.options.sound || "none"
};
if (msg.title !== void 0 && msg.title != "") {
opt.title = msg.title;
}
if (this.options.priority) {
opt.priority = msg.message ? msg.message.level - 2 : -1;
}
if (this.options.device.length > 0) {
opt.device = this.options.device;
}
try {
await this.adapter.sendToAsync(this.options.adapter, "send", opt, { timeout: 2e3 });
this.log.debug(`Send the message: ${msg.text}`);
} catch (error) {
if (error.message == "Timeout exceeded") {
this.log.warn(
`Error sending a notification: ${this.options.adapter} does not react in the given time.`
);
} else {
throw error;
}
}
}
}
break;
case "whatsapp":
{
for (const msg of messages) {
if (Array.isArray(msg)) {
return false;
}
const opt = { text: msg.text };
if (this.options.phonenumber) {
opt.phone = this.options.phonenumber;
}
try {
this.adapter.sendTo(this.options.adapter, "send", opt);
this.log.debug(`Send the message: ${msg.text}`);
} catch (error) {
if (error.message == "Timeout exceeded") {
this.log.warn(
`Error sending a notification: ${this.options.adapter} does not react in the given time.`
);
} else {
throw error;
}
}
}
}
break;
case "gotify":
{
for (const msg of messages) {
if (Array.isArray(msg)) {
return false;
}
const opt = { message: msg.text, contentType: this.options.contentType };
if (this.options.priority) {
opt.priority = this.options.priority;
}
if (this.options.actions.title && msg.title) {
opt.title = msg.title;
}
try {
this.adapter.sendTo(this.options.adapter, "send", opt);
this.log.debug(`Send the message: ${msg.text}`);
} catch (error) {
if (error.message == "Timeout exceeded") {
this.log.warn(
`Error sending a notification: ${this.options.adapter} does not react in the given time.`
);
} else {
throw error;
}
}
}
}
break;
case "nspanel":
{
for (const msg of messages) {
if (Array.isArray(msg)) {
return false;
}
if (msg.action === "removeAll" || msg.action === "removeManualAll") {
this.adapter.sendTo(this.options.adapter, "setPopupNotification", {
id: `${this.adapter.namespace}.`,
priority: -100
});
await this.adapter.delay(20);
if (msg.text === "-1") {
continue;
}
} else if (msg.action === "remove") {
this.adapter.sendTo(this.options.adapter, "setPopupNotification", {
id: `${this.adapter.namespace}.${msg.uniqueId}`,
priority: -1
});
await this.adapter.delay(20);
if (msg.text === "-1") {
continue;
}
}
const id = `${this.adapter.namespace}.${msg.uniqueId}`;
const opt = { id, text: msg.text, headline: "Weatherwarning", buttonRight: "Ok" };
opt.type = msg.action === "removeAll" || msg.action === "removeManualAll" || msg.action === "remove" ? "information" : "acknowledge";
if (msg.action === "removeAll" || msg.action === "removeManualAll" || msg.action === "remove") {
opt.colorHeadline = { r: 0, g: 255, b: 0 };
} else if (msg.formatedData && msg.formatedData.warnlevelcolorhex) {
opt.colorHeadline = msg.formatedData.warnlevelcolorhex;
} else {
opt.colorHeadline = { r: 255, g: 0, b: 0 };
}
if (!(msg.action === "removeAll" || msg.action === "removeManualAll" || msg.action === "remove")) {
if (msg.formatedData && "warntypegeneric" in msg.formatedData) {
const key = msg.formatedData.warntypegeneric;
if (import_messages_def.genericWarntyp[key] && import_messages_def.genericWarntyp[key].mdi) {
opt.icon = import_messages_def.genericWarntyp[key].mdi;
opt.iconColor = opt.colorHeadline;
}
}
}
if (this.options.priority) {
opt.priority = this.options.priority;
}
if (this.options.actions.title && msg.title) {
opt.headline = msg.title;
}
try {
this.adapter.sendTo(this.options.adapter, "setPopupNotification", opt);
this.log.debug(`Send the message: ${msg.text}`);
} catch (error) {
if (error.message == "Timeout exceeded") {
this.log.warn(
`Error sending a notification: ${this.options.adapter} does not react in the given time.`
);
} else {
throw error;
}
}
}
}
break;
case "alexa2":
{
const devices = this.adapter.config.alexa2_device_ids;
if (devices.length == 0) {
break;
}
let opt = "";
if (this.options.sounds_enabled) {
const prefix = `${this.options.volumen}`;
for (const device of devices) {
for (const msg of messages) {
if (Array.isArray(msg)) {
continue;
}
let index = -1;
if (msg.message !== void 0 && msg.message.notDeleted) {
index = this.options.sounds.findIndex(
(a) => a.warntypenumber == Number(msg.message.genericType)
);
} else {
index = this.options.sounds.findIndex((a) => a.warntypenumber == 0);
}
const sound = index !== -1 ? this.options.sounds[index].sound : "";
if (sound) {
opt += `;${sound};${msg.text}`;
} else {
opt += `;${msg.text}`;
}
}
this.log.debug(`Send to alexa2: ${prefix + opt}`);
if (opt != "") {
await this.adapter.setForeignStateAsync(
`${this.options.adapter}.Echo-Devices.${device}.Commands.speak`,
prefix + opt
);
}
}
} else {
const prefix = `${this.options.volumen}${this.options.audio ? `;${this.options.audio}` : ""}`;
for (const device of devices) {
for (const msg of messages) {
if (Array.isArray(msg)) {
continue;
}
opt += `;${msg.text}`;
}
this.log.debug(`Send to alexa2: ${prefix + opt}`);
if (opt != "") {
await this.adapter.setForeignStateAsync(
`${this.options.adapter}.Echo-Devices.${device}.Commands.speak`,
prefix + opt
);
}
}
}
}
break;
case "sayit":
{
let d = "";
const prefix = `${this.options.volumen};`;
for (const msg of messages) {
if (Array.isArray(msg)) {
continue;
}
if (msg.text != "") {
await this.adapter.setForeignStateAsync(
`${this.options.adapter}.tts.text`,
prefix + msg.text
);
d += prefix + msg.text;
}
}
this.log.debug(`Send to sayit: ${d}`);
}
break;
case "history":
{
for (const msg of messages) {
if (Array.isArray(msg)) {
return false;
}
if (!msg || !msg.provider || !this.adapter.config.history_Enabled || !msg.message) {
return false;
}
let newMsg = { message: msg.text };
if (this.adapter.config.history_allinOne) {
newMsg = { ...msg.message.formatedData, ts: Date.now() };
} else {
try {
const temp = JSON.parse(newMsg.message);
newMsg.message = temp;
} catch {
this.log.debug(` write message: ${newMsg.message}`);
}
}
const targets = [msg.provider.name, msg.provider.providerController.name];
for (const a of targets) {
try {
const dp = `${a}.history`;
const state = this.adapter.library.readdp(dp);
let json = [];
if (state && state.val && typeof state.val == "string" && state.val != "") {
json = JSON.parse(state.val);
}
json.unshift(newMsg);
json.splice(100);
await this.adapter.library.writedp(
dp,
JSON.stringify(json),
import_definition.genericStateObjects.history
);
} catch {
this.log.error(
`${this.name} template has wrong formate. ${this.name} deactivated! template: ${msg.action ? this.options.actions[msg.action] : "unknown"}, message: ${JSON.stringify(msg)}`
);
this.adapter.config.history_Enabled = false;
return false;
}
}
}
}
break;
case "json":
{
let result = [];
let providers = [];
for (const msg of messages) {
try {
try {
const temp = this.adapter.config.json_parse ? JSON.parse(msg.text) : msg.text;
result.push({
startts: msg.startts,
message: temp,
provider: msg.provider
});
} catch {
const temp = this.adapter.config.json_parse ? JSON.parse(msg.text.replace("\u201E", '"').replace("\u201C", '"')) : msg.text;
result.push({
startts: msg.startts,
message: temp,
provider: msg.provider
});
}
providers.push(msg.provider !== void 0 ? msg.provider.name : "");
} catch {
this.log.error(
`Json template has wrong formate. Conversion deactivated! template: ${msg.template}, message: ${msg.text}`
);
this.adapter.config.json_parse = false;
continue;
}
}
providers = providers.filter((i, p) => {
if (i != "") {
if (providers.indexOf(i) == p) {
return true;
}
}
return false;
});
result = result.filter((i, p) => {
if (i.message != "" && i.provider) {
if (result.findIndex(
(i2) => i2.provider.name == i.provider.name && i2.message == i.message
) == p) {
return true;
}
}
return false;
});
result.sort((a, b) => {
if (a.provider > b.provider) {
return 1;
} else if (a.provider < b.provider) {
return -1;
}
return a.startts - b.startts;
});
for (const p of providers) {
const dp = `${p}.activeWarnings_json`;
const data = result.filter((a) => a.provider && a.provider.name == p).map((a) => a.message);
await this.adapter.library.writedp(
dp,
JSON.stringify(data),
import_definition.genericStateObjects.activeWarningsJson
);
}
result = result.map((a) => a.message);
result = result.filter((i, p) => {
if (i != "") {
if (result.findIndex((i2) => i2 == i) == p) {
return true;
}
}
return false;
}) || [];
if (this.adapter.providerController) {
const dp = `${this.adapter.providerController.name}.activeWarnings_json`;
await this.adapter.library.writedp(
dp,
JSON.stringify(result),
import_definition.genericStateObjects.activeWarningsJson
);
}
}
break;
case "email":
{
const result = messages.filter((i, p) => {
if (i.text != "") {
if (messages.findIndex((i2) => i2.text == i.text) == p) {
return true;
}
}
return false;
});
const opt = {};
if (result.length > 0 && messages.length > 0 && messages[0].title) {
opt.subject = messages[0].title;
}
opt.html = result.map((a) => a.text).join(this.adapter.config.email_line_break);
if (this.options.recipients && this.options.recipients.trim().length > 0) {
opt.to = this.options.recipients.split(",").map((email) => email.trim()).filter((email) => email.length > 0).join(",");
}
const templates = this.adapter.config.templateTable;
let token = "message.status.new";
if (messages[0].action == "removeAll") {
token = "message.status.clear";
}
if (this.adapter.config.email_Header !== "none") {
const tempid = templates.findIndex((a) => a.templateKey == this.adapter.config.email_Header);
if (tempid != -1) {
const temp = templates[tempid].template.replace(
"${emailheader}",
this.adapter.library.getTranslation(token)
);
opt.html = temp + opt.html;
}
}
if (this.adapter.config.email_Footer !== "none") {
const tempid = templates.findIndex((a) => a.templateKey == this.adapter.config.email_Footer);
if (tempid != -1) {
opt.html = opt.html + templates[tempid].template;
}
}
this.log.debug(`start email sending! Messagecount: ${result.length}`);
try {
this.adapter.sendTo(this.options.adapter, "send", opt);
this.log.debug(`Send the message: ${JSON.stringify(opt)}`);
await library.sleep(200);
} catch (error) {
if (error.message == "Timeout exceeded") {
this.log.warn(
`Error sending a notification: ${this.options.adapter} does not react in the given time.`
);
} else {
throw error;
}
}
}
break;
}
return true;
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
NotificationClass
});
//# sourceMappingURL=notification.js.map