munin/source/conf.ts
2025-06-28 04:27:46 +00:00

1167 lines
21 KiB
TypeScript

/*
This file is part of »munin«.
Copyright 2025 'Fenris Wolf' <fenris@folksprak.org>
»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 <http://www.gnu.org/licenses/>.
*/
/**
* @todo versioning
*/
namespace _munin.conf
{
/**
*/
type type_reminder_raw = {
frequency : (
"hourly"
|
"daily"
|
"weekly"
|
"monthly"
);
offset : int;
from : int;
to : int;
};
/**
*/
type type_conf_v1 = {
sources : Array<
(
{
kind : "kalender_digital";
data : {
path : string;
filtration : {
category_blacklist : Array<string>;
title_blacklist : Array<string>;
};
};
}
)
>;
targets : Array<
(
{
kind : "telegram_bot";
data : {
bot_token : string;
chat_id : int;
/**
* in hours
*/
interval : Array<int>;
}
}
)
>;
frequency : float;
labels : {
head : string;
title : string;
time : string;
location : string;
};
};
/**
*/
type type_conf_v2 = {
sources : Array<
(
{
kind : "ical_feed";
data : {
url : string;
filtration : {
category_blacklist : Array<string>;
title_blacklist : Array<string>;
}
}
}
)
>;
targets : Array<
(
{
kind : "telegram_bot";
data : {
bot_token : string;
chat_id : int;
/**
* in hours
*/
reminders : Array<int>;
}
}
)
>;
settings : {
interval : float;
};
labels : {
head : string;
title : string;
time : string;
location : string;
};
};
/**
*/
type type_conf_v3 = {
sources : Array<
(
{
kind : "ical_feed";
data : {
url : string;
filtration : {
category_blacklist : Array<string>;
title_blacklist : Array<string>;
}
}
}
)
>;
targets : Array<
(
{
kind : "email";
data : {
smtp_host : string;
smtp_port : int;
smtp_username : string;
smtp_password : string;
sender : string;
receivers : Array<string>;
/**
* in hours
*/
reminders : Array<int>;
}
}
|
{
kind : "telegram_bot";
data : {
bot_token : string;
chat_id : int;
/**
* in hours
*/
reminders : Array<int>;
}
}
)
>;
settings : {
interval : float;
};
labels : {
head : string;
title : string;
time : string;
location : string;
};
};
/**
*/
type type_conf_v4 = {
sources : Array<
(
{
kind : "ical_feed";
data : {
url : string;
filtration : {
category_whitelist : (null | Array<string>);
category_blacklist : (null | Array<string>);
title_whitelist : (null | Array<string>);
title_blacklist : (null | Array<string>);
}
}
}
)
>;
targets : Array<
(
{
kind : "email";
data : {
smtp_host : string;
smtp_port : int;
smtp_username : string;
smtp_password : string;
sender : string;
receivers : Array<string>;
hide_tags : boolean;
/**
* in hours
*/
reminders : Array<int>;
}
}
|
{
kind : "telegram_bot";
data : {
bot_token : string;
chat_id : int;
hide_tags : boolean;
/**
* in hours
*/
reminders : Array<int>;
}
}
)
>;
settings : {
interval : float;
};
labels : {
head : string;
title : string;
time : string;
location : string;
};
};
/**
*/
type type_conf_v5 = {
sources : Array<
(
{
kind : "ical_feed";
data : {
url : string;
filtration : {
category_whitelist : (null | Array<string>);
category_blacklist : (null | Array<string>);
title_whitelist : (null | Array<string>);
title_blacklist : (null | Array<string>);
}
}
}
)
>;
targets : Array<
(
{
kind : "email";
data : {
smtp_host : string;
smtp_port : int;
smtp_username : string;
smtp_password : string;
sender : string;
receivers : Array<string>;
hide_tags : boolean;
/**
* in hours
*/
reminders : Array<type_reminder_raw>;
}
}
|
{
kind : "telegram_bot";
data : {
bot_token : string;
chat_id : int;
hide_tags : boolean;
/**
* in hours
*/
reminders : Array<type_reminder_raw>;
}
}
)
>;
settings : {
interval : float;
};
labels : {
head : string;
title : string;
time : string;
location : string;
};
};
/**
*/
export type type_conf = type_conf_v5;
/**
*/
function convert_from_v1(
conf_v1 : type_conf_v1
) : type_conf_v2
{
return {
"sources": conf_v1.sources.map(
source => {
switch (source.kind) {
case "kalender_digital": {
return {
"kind": "ical_feed",
"data": {
"url": lib_plankton.url.encode(
{
"scheme": "https",
"host": "export.kalender.digital",
"username": null,
"password": null,
"port": null,
"path": ("/ics/" + source.data.path + ".ics"),
"query": "past_months=0&future_months=1",
"hash": null,
}
),
"filtration": source.data.filtration,
}
};
break;
}
default: {
// return source;
throw (new Error("unhandled source kind: " + source.kind));
break;
}
}
}
),
"targets": conf_v1.targets.map(
target => {
switch (target.kind) {
case "telegram_bot": {
return {
"kind": "telegram_bot",
"data": {
"bot_token": target.data.bot_token,
"chat_id": target.data.chat_id,
"reminders": target.data.interval,
},
};
break;
}
default: {
// return target;
throw (new Error("unhandled target kind: " + target.kind));
break;
}
}
}
),
"settings": {
"interval": conf_v1.frequency,
},
"labels": conf_v1.labels,
};
}
/**
*/
function convert_from_v2(
conf_v2 : type_conf_v2
) : type_conf_v3
{
return conf_v2;
}
/**
*/
function convert_from_v3(
conf_v3 : type_conf_v3
) : type_conf_v4
{
return {
"sources": conf_v3.sources.map(
source => {
switch (source.kind) {
case "ical_feed": {
return {
"kind": "ical_feed",
"data": {
"url": source.data.url,
"filtration": {
"category_whitelist": null,
"category_blacklist": source.data.filtration.category_blacklist,
"title_whitelist": null,
"title_blacklist": source.data.filtration.category_blacklist,
},
}
};
break;
}
default: {
// return source;
throw (new Error("unhandled source kind: " + source.kind));
break;
}
}
}
),
"targets": conf_v3.targets.map(
target => {
switch (target.kind) {
case "email": {
return {
"kind": "email",
"data": {
"smtp_host": target.data.smtp_host,
"smtp_port": target.data.smtp_port,
"smtp_username": target.data.smtp_username,
"smtp_password": target.data.smtp_password,
"sender": target.data.sender,
"receivers": target.data.receivers,
"hide_tags": false,
"reminders": target.data.reminders,
},
};
break;
}
case "telegram_bot": {
return {
"kind": "telegram_bot",
"data": {
"bot_token": target.data.bot_token,
"chat_id": target.data.chat_id,
"hide_tags": false,
"reminders": target.data.reminders,
},
};
break;
}
default: {
// return target;
throw (new Error("unhandled target kind: " + String(target)));
break;
}
}
}
),
"settings": conf_v3.settings,
"labels": conf_v3.labels,
};
}
/**
*/
function convert_from_v4(
conf_v4 : type_conf_v4
) : type_conf_v5
{
const map_reminder = hours => ({
"frequency": "hourly",
"offset": 0,
"from": hours,
"to": (hours + 1),
} as type_reminder_raw);
return {
"sources": conf_v4.sources,
"targets": conf_v4.targets.map(
target => {
switch (target.kind) {
case "email": {
return {
"kind": "email",
"data": {
"smtp_host": target.data.smtp_host,
"smtp_port": target.data.smtp_port,
"smtp_username": target.data.smtp_username,
"smtp_password": target.data.smtp_password,
"sender": target.data.sender,
"receivers": target.data.receivers,
"hide_tags": target.data.hide_tags,
"reminders": target.data.reminders.map(map_reminder),
},
};
break;
}
case "telegram_bot": {
return {
"kind": "telegram_bot",
"data": {
"bot_token": target.data.bot_token,
"chat_id": target.data.chat_id,
"hide_tags": target.data.hide_tags,
"reminders": target.data.reminders.map(map_reminder),
},
};
break;
}
default: {
// return target;
throw (new Error("unhandled target kind: " + String(target)));
break;
}
}
}
),
"settings": conf_v4.settings,
"labels": conf_v4.labels,
};
}
/**
*/
function schema_source_kalender_digital(
version : string
) : lib_plankton.conf.type_schema
{
return {
"type": "object",
"properties": {
"kind": {
"nullable": false,
"type": "string",
"enum": ["kalender_digital"]
},
"data": {
"nullable": false,
"type": "object",
"properties": {
"path": {
"nullable": false,
"type": "string"
},
"filtration": {
"nullable": false,
"type": "object",
"properties": {
"category_blacklist": {
"nullable": true,
"type": "array",
"items": {
"nullable": false,
"type": "string",
},
"default": [],
},
"title_blacklist": {
"nullable": true,
"type": "array",
"items": {
"nullable": false,
"type": "string",
},
"default": [],
},
},
"additionalProperties": false,
"required": [
],
"default": {}
},
},
"additionalProperties": false,
"required": [
"path",
]
}
},
"additionalProperties": false,
"required": [
"kind",
"data",
]
};
}
/**
*/
function schema_source_ical_feed(
version : string
) : lib_plankton.conf.type_schema
{
return {
"type": "object",
"properties": {
"kind": {
"nullable": false,
"type": "string",
"enum": ["ical_feed"]
},
"data": {
"nullable": false,
"type": "object",
"properties": {
"url": {
"nullable": false,
"type": "string"
},
"filtration": {
"nullable": false,
"type": "object",
"properties": {
"category_whitelist": {
"nullable": true,
"type": "array",
"items": {
"nullable": false,
"type": "string",
},
"default": null,
},
"category_blacklist": {
"nullable": true,
"type": "array",
"items": {
"nullable": false,
"type": "string",
},
"default": null,
},
"title_whitelist": {
"nullable": true,
"type": "array",
"items": {
"nullable": false,
"type": "string",
},
"default": null,
},
"title_blacklist": {
"nullable": true,
"type": "array",
"items": {
"nullable": false,
"type": "string",
},
"default": null,
},
},
"additionalProperties": false,
"required": [
],
"default": {}
},
},
"additionalProperties": false,
"required": [
"url",
]
}
},
"additionalProperties": false,
"required": [
"kind",
"data",
]
};
}
/**
*/
function schema_sources(
version : string
) : lib_plankton.conf.type_schema
{
switch (version) {
case "1": {
return {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"anyOf": [
schema_source_kalender_digital(version),
],
}
};
break;
}
default:
case "2": {
return {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"anyOf": [
schema_source_ical_feed(version),
],
}
};
break;
}
}
}
/**
*/
function schema_reminder(
version : string
) : lib_plankton.conf.type_schema
{
switch (version)
{
case "1":
case "2":
case "3":
case "4":
{
return {
"type": "integer",
};
}
case "5":
default:
{
return {
"nullable": false,
"type": "object",
"properties": {
"frequency": {
"nullable": false,
"type": "string",
"enum": [
"hourly",
"daily",
"weekly",
"monthly",
]
},
"offset": {
"nullable": false,
"type": "integer",
"default": 0
},
"from": {
"nullable": false,
"type": "integer"
},
"to": {
"nullable": false,
"type": "integer"
},
},
"additionalProperties": false,
"required": [
"frequency",
"from",
"to",
]
};
break;
}
}
}
/**
*/
function default_reminder(
version : string
) : any
{
switch (version)
{
case "1":
case "2":
case "3":
case "4":
{
return [24];
}
case "5":
default:
{
return [
{
"frequency": "hourly",
"from": 24,
"to": 25
}
];
break;
}
}
}
/**
*/
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",
}
},
"hide_tags": {
"nullable": false,
"type": "boolean",
"default": false,
},
"reminders": {
"nullable": false,
"type": "array",
"items": schema_reminder(version),
"default": default_reminder(version),
},
},
"additionalProperties": false,
"required": [
"smtp_host",
"smtp_port",
"smtp_username",
"smtp_password",
"receivers",
]
}
},
"additionalProperties": false,
"required": [
"kind",
"data",
]
};
}
/**
*/
function schema_target_telegram_bot(
version : string
) : lib_plankton.conf.type_schema
{
return {
"nullable": false,
"type": "object",
"properties": {
"kind": {
"nullable": false,
"type": "string",
"enum": ["telegram_bot"]
},
"data": {
"nullable": false,
"type": "object",
"properties": {
"bot_token": {
"nullable": false,
"type": "string",
},
"chat_id": {
"nullable": false,
"type": "integer",
},
"hide_tags": {
"nullable": false,
"type": "boolean",
"default": false,
},
"reminders": {
"nullable": false,
"type": "array",
"items": schema_reminder(version),
"default": default_reminder(version),
},
},
"additionalProperties": false,
"required": [
"bot_token",
"chat_id",
]
}
},
"additionalProperties": false,
"required": [
"kind",
"data",
]
};
}
/**
*/
function schema_targets(
version : string
) : lib_plankton.conf.type_schema
{
return {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"anyOf": (() => {
switch (version) {
case "1":
case "2":
{
return [
schema_target_telegram_bot(version),
];
break;
}
case "4":
case "5":
default:
{
return [
schema_target_email(version),
schema_target_telegram_bot(version),
];
break;
}
}
}) (),
}
};
}
/**
*/
function schema_settings(
version : string
) : lib_plankton.conf.type_schema
{
return {
"nullable": false,
"type": "object",
"properties": {
"interval": {
"nullable": false,
"type": "number",
"default": 1.0
}
},
"additionalProperties": false,
"required": [
],
"default": {
}
};
}
/**
*/
function schema_labels(
version : string
) : lib_plankton.conf.type_schema
{
return {
"nullable": false,
"type": "object",
"properties": {
"head": {
"nullable": false,
"type": "string",
"default": "Termin-Erinnerung"
},
"title": {
"nullable": false,
"type": "string",
"default": "was"
},
"time": {
"nullable": false,
"type": "string",
"default": "wann"
},
"location": {
"nullable": false,
"type": "string",
"default": "wo"
},
},
"additionalProperties": false,
"required": [
],
"default": {}
};
}
/**
*/
export function schema(
version : string = "5"
) : lib_plankton.conf.type_schema
{
switch (version) {
case "1": {
return {
"nullable": false,
"type": "object",
"properties": {
"sources": schema_sources(version),
"targets": schema_targets(version),
"frequency": {
"nullable": false,
"type": "number",
"default": 1.0,
},
"labels": schema_labels(version),
},
"additionalProperties": false,
"required": [
"sources",
"targets",
],
};
break;
}
case "2":
case "3":
case "4":
case "5":
{
return {
"nullable": false,
"type": "object",
"properties": {
"sources": schema_sources(version),
"targets": schema_targets(version),
"settings": schema_settings(version),
"labels": schema_labels(version),
},
"additionalProperties": false,
"required": [
"sources",
"targets",
],
};
break;
}
}
}
/**
*/
export async function load(
path : string
) : Promise<type_conf>
{
const conf_raw : {version : string; content : any} = await lib_plankton.conf.load_versioned(
path,
schema,
{
"1": {"target": "2", "function": convert_from_v1},
"2": {"target": "3", "function": convert_from_v2},
"3": {"target": "4", "function": convert_from_v3},
"4": {"target": "5", "function": convert_from_v4},
"5": null,
}
);
/*
switch (conf_raw.version) {
case "1": {
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);
const conf_v4 : type_conf_v4 = convert_from_v3(conf_v3);
return conf_v4;
break;
}
case "2": {
const conf_v2 : type_conf_v2 = (conf_raw.content as type_conf_v2);
const conf_v3 : type_conf_v3 = convert_from_v2(conf_v2);
const conf_v4 : type_conf_v4 = convert_from_v3(conf_v3);
return conf_v4;
break;
}
case "3": {
const conf_v3 : type_conf_v3 = (conf_raw.content as type_conf_v3);
const conf_v4 : type_conf_v4 = convert_from_v3(conf_v3);
return conf_v4;
break;
}
case "4": {
const conf_v4 : type_conf_v4 = (conf_raw.content as type_conf_v4);
return conf_v4;
break;
}
default: {
throw (new Error("invalid version: " + conf_raw.version));
break;
}
}
*/
return (conf_raw.content as type_conf_v5);
}
}