From 4edab45412f1282fcb311bc792c12f72efe6f23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Tue, 6 May 2025 19:07:38 +0000 Subject: [PATCH] [add] target:email --- ivaldi.json | 2 + libs/plankton/plankton.d.ts | 6 +- libs/plankton/plankton.js | 2 +- source/conf.ts | 200 ++++++++++++++++++++++++++++++++--- source/targets/_functions.ts | 8 +- source/targets/email.ts | 111 +++++++++++++++++++ tools/build | 2 +- 7 files changed, 310 insertions(+), 21 deletions(-) create mode 100644 source/targets/email.ts diff --git a/ivaldi.json b/ivaldi.json index 75d4741..bcedb2f 100644 --- a/ivaldi.json +++ b/ivaldi.json @@ -9,6 +9,7 @@ "http", "ical", "string", + "email", "telegram", "url", "conf", @@ -23,6 +24,7 @@ "sources/ical_feed.ts", "sources/_functions.ts", "targets/telegram_bot.ts", + "targets/email.ts", "targets/_functions.ts", "conf.ts", "main.ts" diff --git a/libs/plankton/plankton.d.ts b/libs/plankton/plankton.d.ts index 085b52d..8dfef7a 100644 --- a/libs/plankton/plankton.d.ts +++ b/libs/plankton/plankton.d.ts @@ -1,11 +1,11 @@ /** * @author fenris */ -declare type int = number; +type int = number; /** * @author fenris */ -declare type float = number; +type float = number; declare var process: any; declare var require: any; declare class Buffer { @@ -22,7 +22,7 @@ declare namespace lib_plankton.base { /** * @author fenris */ -declare type type_pseudopointer = { +type type_pseudopointer = { value: type_value; }; /** diff --git a/libs/plankton/plankton.js b/libs/plankton/plankton.js index 95d0d95..0788b11 100644 --- a/libs/plankton/plankton.js +++ b/libs/plankton/plankton.js @@ -1486,7 +1486,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) { function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); - while (_) try { + while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { diff --git a/source/conf.ts b/source/conf.ts index 7506b0b..8a7e1af 100644 --- a/source/conf.ts +++ b/source/conf.ts @@ -30,7 +30,7 @@ namespace _munin.conf sources : Array< ( { - kind : "kalender_digital", + kind : "kalender_digital"; data : { path : string; filtration : { @@ -44,7 +44,7 @@ namespace _munin.conf targets : Array< ( { - kind : "telegram_bot", + kind : "telegram_bot"; data : { bot_token : string; chat_id : int; @@ -72,21 +72,21 @@ namespace _munin.conf sources : Array< ( { - kind : "ical_feed", + kind : "ical_feed"; data : { url : string; filtration : { category_blacklist : Array; title_blacklist : Array; - }; - }; + } + } } ) >; targets : Array< ( { - kind : "telegram_bot", + kind : "telegram_bot"; data : { bot_token : string; chat_id : int; @@ -112,7 +112,66 @@ namespace _munin.conf /** */ - export type type_conf = type_conf_v2; + type type_conf_v3 = { + sources : Array< + ( + { + kind : "ical_feed"; + data : { + url : string; + filtration : { + category_blacklist : Array; + title_blacklist : Array; + } + } + } + ) + >; + targets : Array< + ( + { + kind : "email"; + data : { + smtp_host : string; + smtp_port : int; + smtp_username : string; + smtp_password : string; + receivers : Array; + /** + * in hours + */ + reminders : Array; + } + } + | + { + kind : "telegram_bot"; + data : { + bot_token : string; + chat_id : int; + /** + * in hours + */ + reminders : Array; + } + } + ) + >; + settings : { + interval : float; + }; + labels : { + head : string; + title : string; + time : string; + location : string; + }; + }; + + + /** + */ + export type type_conf = type_conf_v3; /** @@ -184,6 +243,16 @@ namespace _munin.conf } + /** + */ + function convert_from_v2( + conf_v2 : type_conf_v2 + ) : type_conf_v3 + { + return conf_v2; + } + + /** */ function schema_source_kalender_digital( @@ -316,6 +385,83 @@ namespace _munin.conf } + /** + */ + function schema_target_email( + version : string + ) : lib_plankton.conf.type_schema + { + return { + "nullable": false, + "type": "object", + "properties": { + "kind": { + "nullable": false, + "type": "string", + "enum": ["email"] + }, + "data": { + "nullable": false, + "type": "object", + "properties": { + "smtp_host": { + "nullable": false, + "type": "string", + }, + "smtp_port": { + "nullable": false, + "type": "integer", + }, + "smtp_username": { + "nullable": false, + "type": "string", + }, + "smtp_password": { + "nullable": false, + "type": "string", + }, + "sender": { + "nullable": false, + "type": "string", + "default": "munin" + }, + "receivers": { + "nullable": false, + "type": "array", + "items": { + "nullable": false, + "type": "string", + } + }, + "reminders": { + "nullable": false, + "type": "array", + "items": { + "nullable": false, + "type": "integer" + }, + "default": [24.0], + }, + }, + "additionalProperties": false, + "required": [ + "smtp_host", + "smtp_port", + "smtp_username", + "smtp_password", + "receivers", + ] + } + }, + "additionalProperties": false, + "required": [ + "kind", + "data", + ] + }; + } + + /** */ function schema_sources( @@ -418,9 +564,23 @@ namespace _munin.conf "type": "array", "items": { "nullable": false, - "anyOf": [ - schema_target_telegram_bot(version), - ], + "anyOf": (() => { + switch (version) { + default: { + return [ + schema_target_telegram_bot(version), + ]; + break; + } + case "3": { + return [ + schema_target_email(version), + schema_target_telegram_bot(version), + ]; + break; + } + } + }) (), } }; } @@ -520,7 +680,8 @@ namespace _munin.conf break; } default: - case "2": { + case "2": + case "3": { return { "nullable": false, "type": "object", @@ -553,19 +714,28 @@ namespace _munin.conf schema, { "1": {"target": "2", "function": convert_from_v1}, - "2": null, + "2": {"target": "3", "function": convert_from_v2}, + "3": null, } ); switch (conf_raw.version) { case "1": { - const conf_v2 : type_conf_v2 = convert_from_v1(conf_raw.content); - return conf_v2; + const conf_v1 : type_conf_v1 = (conf_raw.content as type_conf_v1); + const conf_v2 : type_conf_v2 = convert_from_v1(conf_v1); + const conf_v3 : type_conf_v3 = convert_from_v2(conf_v2); + return conf_v3; break; } case "2": { const conf_v2 : type_conf_v2 = (conf_raw.content as type_conf_v2); - return conf_v2; + const conf_v3 : type_conf_v3 = convert_from_v2(conf_v2); + return conf_v3; + break; + } + case "3": { + const conf_v3 : type_conf_v3 = (conf_raw.content as type_conf_v3); + return conf_v3; break; } default: { diff --git a/source/targets/_functions.ts b/source/targets/_functions.ts index b6d0e34..352e5bd 100644 --- a/source/targets/_functions.ts +++ b/source/targets/_functions.ts @@ -35,11 +35,17 @@ namespace _munin.targets throw (new Error("unhandled target kind: " + description.kind)); break; } + case "email": { + return _munin.targets.email.implementation_target( + description.data as _munin.targets.email.type_parameters + ); + break; + } case "telegram_bot": { return _munin.targets.telegram_bot.implementation_target( description.data as _munin.targets.telegram_bot.type_parameters ); - return + break; } } } diff --git a/source/targets/email.ts b/source/targets/email.ts new file mode 100644 index 0000000..1b96ee3 --- /dev/null +++ b/source/targets/email.ts @@ -0,0 +1,111 @@ +/* +This file is part of »munin«. + +Copyright 2025 'Fenris Wolf' + +»munin« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»munin« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »munin«. If not, see . + */ + + +namespace _munin.targets.email +{ + + /** + */ + export type type_parameters = { + smtp_host : string; + smtp_port : int; + smtp_username : string; + smtp_password : string; + sender : string; + receivers : Array; + /** + * in hours + */ + reminders : Array; + }; + + + /** + */ + async function send( + parameters : type_parameters, + labels : _munin.type_labels, + event : _munin.type_event + ) : Promise + { + await lib_plankton.email.send( + { + "host": parameters.smtp_host, + "port": parameters.smtp_port, + "username": parameters.smtp_username, + "password": parameters.smtp_password, + }, + parameters.sender, + parameters.receivers, + lib_plankton.string.coin( + "[{{head}}] {{date}} : {{title}}", + { + "head": labels.head, + "date": lib_plankton.pit.date_format(event.begin.date), + "title": event.title, + } + ), + lib_plankton.string.coin( + "*{{head}}*\n\n\{{title_label}} | {{title_value}}\n{{time_label}} | {{time_value}}{{macro_location}}", + { + "head": labels.head, + "title_label": labels.title.toUpperCase(), + "title_value": event.title, + "time_label": labels.time.toUpperCase(), + "time_value": lib_plankton.pit.timespan_format(event.begin, event.end), + "macro_location": ( + (event.location === null) + ? + "" + : + lib_plankton.string.coin( + "\n{{location_label}} | {{location_value}}", + { + "location_label": labels.location.toUpperCase(), + "location_value": event.location, + } + ) + ), + } + ) + ); + } + + + /** + */ + export function implementation_target( + parameters : type_parameters + ) : _munin.type_target + { + return { + "reminders": parameters.reminders, + "show": () => lib_plankton.string.coin( + "email:{{receivers}}", + { + "receivers": parameters.receivers.join(","), + } + ), + "send": (labels, event) => send(parameters, labels, event), + }; + } + +} + diff --git a/tools/build b/tools/build index fabb724..155b24a 100755 --- a/tools/build +++ b/tools/build @@ -1,4 +1,4 @@ #!/usr/bin/env sh tools/ivaldi build - +cd build && npm install nodemailer ; cd -