This commit is contained in:
fenris 2025-04-25 12:50:13 +02:00
parent 556da302fa
commit e19be3ae43
13 changed files with 636 additions and 166 deletions

View file

@ -10,6 +10,7 @@
"ical",
"telegram",
"conf",
"log",
"args"
]
}
@ -19,6 +20,8 @@
"types.ts",
"sources/kalender_digital.ts",
"sources/_functions.ts",
"targets/telegram_bot.ts",
"targets/_functions.ts",
"conf.ts",
"main.ts"
]

View file

@ -2258,7 +2258,9 @@ declare namespace lib_plankton.telegram {
/**
* @see https://core.telegram.org/bots/api#sendmessage
*/
function bot_call_send_message(token: string, chat_id: (int | string), text: string): Promise<void>;
function bot_call_send_message(token: string, chat_id: (int | string), text: string, { "parse_mode": parse_mode, }?: {
parse_mode?: (null | string);
}): Promise<void>;
}
declare namespace lib_plankton.file {
/**

View file

@ -6243,10 +6243,11 @@ var lib_plankton;
/**
* @see https://core.telegram.org/bots/api#sendmessage
*/
async function bot_call_send_message(token, chat_id, text) {
async function bot_call_send_message(token, chat_id, text, { "parse_mode": parse_mode = null, } = {}) {
const output = await bot_call_generic(token, "sendMessage", {
"chat_id": chat_id,
"text": text,
"parse_mode": (parse_mode ?? undefined),
});
}
telegram.bot_call_send_message = bot_call_send_message;

View file

@ -2,3 +2,29 @@
Sendet Erinnerungen an Termine
## Erstellung
### Erfordernisse
- GNU Make
- Typescript Compiler
### Anweisungen
- `tools/build`
## Verwendung
### Erfordernisse
- NodeJS
### Anweisungen
siehe `munin -h`

View file

@ -1,16 +1,38 @@
namespace _lixer_event_reminder.conf
/*
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
{
/**
*/
export type type_conf = {
bot_token : string;
sources : Array<
(
{
kind : "kalender_digital",
data : {
id : string;
path : string;
filtration : {
category_blacklist : Array<string>;
title_blacklist : Array<string>;
@ -20,11 +42,30 @@ namespace _lixer_event_reminder.conf
)
>;
targets : Array<
{
chat_id : int;
interval : Array<int>;
}
(
{
kind : "telegram_bot",
data : {
bot_token : string;
chat_id : int;
/**
* in hours
*/
interval : Array<int>;
}
}
)
>;
/**
* in hours
*/
frequency : float;
labels : {
head : string;
title : string;
time : string;
location : string;
};
};
@ -38,10 +79,6 @@ namespace _lixer_event_reminder.conf
"nullable": false,
"type": "string",
},
"bot_token": {
"nullable": false,
"type": "string",
},
"sources": {
"nullable": false,
"type": "array",
@ -60,7 +97,7 @@ namespace _lixer_event_reminder.conf
"nullable": false,
"type": "object",
"properties": {
"id": {
"path": {
"nullable": false,
"type": "string"
},
@ -74,7 +111,8 @@ namespace _lixer_event_reminder.conf
"items": {
"nullable": false,
"type": "string",
}
},
"default": [],
},
"title_blacklist": {
"nullable": false,
@ -82,20 +120,19 @@ namespace _lixer_event_reminder.conf
"items": {
"nullable": false,
"type": "string",
}
},
"default": [],
},
},
"additionalProperties": false,
"required": [
"category_blacklist",
"title_blacklist",
]
],
"default": {}
},
},
"additionalProperties": false,
"required": [
"id",
"filtration",
]
}
},
@ -113,35 +150,95 @@ namespace _lixer_event_reminder.conf
"type": "array",
"items": {
"nullable": false,
"type": "object",
"properties": {
"chat_id": {
"anyOf": [
{
"nullable": false,
"type": "integer",
},
"interval": {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"type": "integer"
}
},
},
"additionalProperties": false,
"required": [
"chat_id",
"interval",
]
"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",
},
"interval": {
"nullable": false,
"type": "array",
"items": {
"nullable": false,
"type": "integer"
},
"default": [24.0],
},
},
"additionalProperties": false,
"required": [
"bot_token",
"chat_id",
]
}
},
"additionalProperties": false,
"required": [
"kind",
"data",
]
}
],
}
},
"frequency": {
"nullable": false,
"type": "number",
"default": 1.0,
},
"labels": {
"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": {}
},
},
"additionalProperties": false,
"required": [
"version",
"bot_token",
"chat_id",
"intval",
"sources",
"targets",
],
};

View file

@ -1,6 +1,143 @@
namespace _lixer_event_reminder
/*
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/>.
*/
namespace _munin
{
/**
*/
async function run_iteration(
conf : _munin.conf.type_conf,
sources : Array<_munin.type_source>,
targets : Array<_munin.type_target>,
{
"dry_run": dry_run = false,
} : {
dry_run ?: boolean;
} = {
}
) : Promise<void>
{
const now : lib_plankton.pit.type_pit = lib_plankton.pit.now();
const events : Array<_munin.type_event> = (
(await Promise.all(sources.map(source => source.fetch())))
.reduce((x, y) => x.concat(y), [])
);
for (const target of targets) {
lib_plankton.log._info(
"munin.run.iteration",
{
"details": {
"target": target,
}
}
);
for (const hours of target.interval) {
const window_from : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
now,
hours + 0
);
const window_to : lib_plankton.pit.type_pit = lib_plankton.pit.shift_hour(
now,
hours + (conf.frequency / 2)
);
for (const event of events) {
const event_begin : lib_plankton.pit.type_pit = lib_plankton.pit.from_datetime(event.begin);
lib_plankton.log._debug(
"munin.run.check_dueness",
{
"details": {
"event_begin": lib_plankton.pit.datetime_format(lib_plankton.pit.to_datetime(event_begin)),
"window_from": lib_plankton.pit.datetime_format(lib_plankton.pit.to_datetime(window_from)),
"window_to": lib_plankton.pit.datetime_format(lib_plankton.pit.to_datetime(window_to)),
}
}
);
const remind : boolean = lib_plankton.pit.is_between(
event_begin,
window_from,
window_to
);
if (! remind) {
// do nothing
}
else {
lib_plankton.log._info(
"munin.remind",
{
"details": {
"event": event,
"target": target,
}
}
);
if (dry_run) {
// do nothing
}
else {
await target.send(conf.labels, event);
}
}
}
}
}
}
/**
*/
function run(
conf : _munin.conf.type_conf,
{
"dry_run": dry_run = false,
} : {
dry_run ?: boolean;
} = {
}
) : void
{
const sources : Array<_munin.type_source> = conf.sources.map(
source_raw => _munin.sources.factory(source_raw)
);
const targets : Array<_munin.type_target> = conf.targets.map(
target_raw => _munin.targets.factory(target_raw)
);
lib_plankton.log._info(
"munin.run.start",
{
"details": {
}
}
);
run_iteration(conf, sources, targets, {"dry_run": dry_run});
/**
* outsource setInterval logic
*/
setInterval(
() => {run_iteration(conf, sources, targets, {"dry_run": dry_run});},
(conf.frequency * 60 * 60 * 1000)
);
}
/**
*/
export async function main(
@ -27,14 +164,32 @@ namespace _lixer_event_reminder
"info": "path to configuration file",
"name": "conf-path",
}),
"message": lib_plankton.args.class_argument.volatile({
"indicators_long": ["message"],
"indicators_short": ["m"],
"conf_expose": lib_plankton.args.class_argument.volatile({
"indicators_long": ["conf-expose"],
"indicators_short": ["e"],
"type": lib_plankton.args.enum_type.boolean,
"mode": lib_plankton.args.enum_mode.replace,
"default": false,
"info": "whether to expose the full configuration",
"name": "conf-expose",
}),
"verbosity": lib_plankton.args.class_argument.volatile({
"indicators_long": ["verbosity"],
"indicators_short": ["v"],
"type": lib_plankton.args.enum_type.string,
"mode": lib_plankton.args.enum_mode.replace,
"default": "test",
"info": "message to send",
"name": "message",
"default": "notice",
"info": "error | warning | notice | info | debug",
"name": "verbosity",
}),
"dry_run": lib_plankton.args.class_argument.volatile({
"indicators_long": ["dry-run"],
"indicators_short": ["q"],
"type": lib_plankton.args.enum_type.boolean,
"mode": lib_plankton.args.enum_mode.replace,
"default": false,
"info": "whether to not skip the sending of reminders (logs will be written)",
"name": "dry-run",
}),
"help": lib_plankton.args.class_argument.volatile({
"indicators_long": ["help"],
@ -52,13 +207,6 @@ namespace _lixer_event_reminder
args_raw.join(" ")
);
// init
const conf : _lixer_event_reminder.conf.type_conf = await lib_plankton.conf.load<_lixer_event_reminder.conf.type_conf>(
_lixer_event_reminder.conf.schema,
args.conf_path
);
// exec
if (args.help || (args.action === "help")) {
process.stdout.write(
arg_handler.generate_help(
@ -71,83 +219,69 @@ namespace _lixer_event_reminder
);
}
else {
// init
const conf : _munin.conf.type_conf = await lib_plankton.conf.load<_munin.conf.type_conf>(
_munin.conf.schema,
args.conf_path
);
lib_plankton.log.set_main_logger(
[
{
"kind": "filtered",
"data": {
"core": {
"kind": "std",
"data": {
"target": "stdout",
"format": {
"kind": "human_readable",
"data": {
}
}
}
},
"predicate": [
[
{
"item": {
"kind": "level",
"data": {
"threshold": args.verbosity,
}
},
}
]
],
}
},
]
);
// exec
if (args.conf_expose) {
process.stdout.write(
lib_plankton.json.encode(
conf,
{
"formatted": true,
}
)
+
"\n"
);
}
switch (args.action) {
default: {
throw (new Error("unhandled action: " + args.action));
break;
}
case "fetch": {
const updates : Array<any> = await lib_plankton.telegram.bot_call_get_updates(
conf.bot_token
);
process.stdout.write(JSON.stringify(updates, undefined, "\t") + "\n");
break;
}
case "send": {
for (const target of conf.targets) {
const message = await lib_plankton.telegram.bot_call_send_message(
conf.bot_token,
target.chat_id,
args.message
);
}
break;
}
case "run": {
const sources : Array<_lixer_event_reminder.type_source> = conf.sources.map(
source_raw => _lixer_event_reminder.sources.factory(source_raw)
);
const targets : Array<_lixer_event_reminder.type_target> = conf.targets.map(
target_raw => target_raw
);
const now : lib_plankton.pit.type_pit = lib_plankton.pit.now();
const events : Array<_lixer_event_reminder.type_event> = (
(await Promise.all(sources.map(source => source.fetch())))
.reduce((x, y) => x.concat(y), [])
);
for (const event of events) {
const begin : lib_plankton.pit.type_pit = lib_plankton.pit.from_datetime(event.begin);
for (const target of targets) {
for (const hours of target.interval) {
const remind : boolean = lib_plankton.pit.is_between(
lib_plankton.pit.shift_hour(begin, hours),
now,
/**
* @todo parametrize window
*/
lib_plankton.pit.shift_hour(now, +24)
);
if (remind) {
lib_plankton.log._info(
"remind",
{
"details": {
"event": event,
"target": target,
}
}
);
/**
* @todo activate
* @todo format better
*/
const message = await lib_plankton.telegram.bot_call_send_message(
conf.bot_token,
target.chat_id,
lib_plankton.string.coin(
"{{title}} | {{begin}}",
{
"title": event.title,
"begin": lib_plankton.pit.datetime_format(event.begin),
}
)
);
}
}
run(
conf,
{
"dry_run": args.dry_run,
}
}
);
break;
}
}
@ -157,7 +291,7 @@ namespace _lixer_event_reminder
}
}
_lixer_event_reminder.main(process.argv.slice(2))
_munin.main(process.argv.slice(2))
.then(() => {})
.catch((reason) => {process.stderr.write(String(reason) + "\n");})
;

View file

@ -1,4 +1,24 @@
namespace _lixer_event_reminder.sources
/*
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/>.
*/
namespace _munin.sources
{
/**
@ -8,7 +28,7 @@ namespace _lixer_event_reminder.sources
kind : string,
data : any
}
) : type_source
) : _munin.type_source
{
switch (description.kind) {
default: {
@ -16,8 +36,8 @@ namespace _lixer_event_reminder.sources
break;
}
case "kalender_digital": {
return _lixer_event_reminder.sources.kalender_digital.implementation_source(
description.data as _lixer_event_reminder.sources.kalender_digital.type_parameters
return _munin.sources.kalender_digital.implementation_source(
description.data as _munin.sources.kalender_digital.type_parameters
);
return
}

View file

@ -1,10 +1,10 @@
namespace _lixer_event_reminder.sources.kalender_digital
namespace _munin.sources.kalender_digital
{
/**
*/
export type type_parameters = {
id : string;
path : string;
filtration : {
category_blacklist : Array<string>;
title_blacklist : Array<string>;
@ -16,15 +16,15 @@ namespace _lixer_event_reminder.sources.kalender_digital
*/
async function fetch(
parameters : type_parameters
) : Promise<Array<_lixer_event_reminder.type_event>>
) : Promise<Array<_munin.type_event>>
{
const http_request : lib_plankton.http.type_request = {
"scheme": "https",
"host": "export.kalender.digital",
"path": lib_plankton.string.coin(
"/ics/0/{{id}}/gesamterkalender.ics",
"/ics/{{path}}.ics",
{
"id": parameters.id,
"path": parameters.path,
}
),
"version": "HTTP/2",
@ -33,7 +33,10 @@ namespace _lixer_event_reminder.sources.kalender_digital
"?past_months={{past_months}}&future_months={{future_months}}",
{
"past_months": (0).toFixed(0),
"future_months": (2).toFixed(0),
/**
* anpassen an frequency?
*/
"future_months": (1).toFixed(0),
}
),
"headers": {},
@ -42,13 +45,34 @@ namespace _lixer_event_reminder.sources.kalender_digital
const http_response : lib_plankton.http.type_response = await lib_plankton.http.call(http_request);
const ics : string = http_response.body.toString();
const vcalendar : lib_plankton.ical.type_vcalendar = lib_plankton.ical.ics_decode(ics);
const events : Array<_lixer_event_reminder.type_event> = (
const events : Array<_munin.type_event> = (
vcalendar.vevents
.filter(
vevent => (
vevent.categories.every(category => ! parameters.filtration.category_blacklist.includes(category))
// category
(
vevent.categories.every(
category => (
! (
parameters.filtration.category_blacklist
.map(category_ => category_.toLowerCase())
.includes(category.toLowerCase())
)
)
)
)
&&
parameters.filtration.title_blacklist.every(title => ! vevent.summary.toLowerCase().includes(title.toLowerCase()))
// title
(
parameters.filtration.title_blacklist.every(
title => (
! (
vevent.summary.toLowerCase()
.includes(title.toLowerCase())
)
)
)
)
)
)
.map(
@ -63,11 +87,11 @@ namespace _lixer_event_reminder.sources.kalender_digital
"date": vevent.dtend.value.date,
"time": vevent.dtend.value.time,
};
const event : _lixer_event_reminder.type_event = {
const event : _munin.type_event = {
"title": vevent.summary,
"begin": begin,
"end": end,
"location": vevent.location,
"location": (vevent.location ?? null),
};
return event;
}
@ -81,7 +105,7 @@ namespace _lixer_event_reminder.sources.kalender_digital
*/
export function implementation_source(
parameters : type_parameters
) : _lixer_event_reminder.type_source
) : _munin.type_source
{
return {
"fetch": () => fetch(parameters),

View file

@ -0,0 +1,48 @@
/*
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/>.
*/
namespace _munin.targets
{
/**
*/
export function factory(
description : {
kind : string,
data : any
}
) : _munin.type_target
{
switch (description.kind) {
default: {
throw (new Error("unhandled target kind: " + description.kind));
break;
}
case "telegram_bot": {
return _munin.targets.telegram_bot.implementation_target(
description.data as _munin.targets.telegram_bot.type_parameters
);
return
}
}
}
}

View file

@ -0,0 +1,87 @@
/*
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/>.
*/
namespace _munin.targets.telegram_bot
{
/**
*/
export type type_parameters = {
bot_token : string;
chat_id : int;
interval : Array<int>;
};
/**
*/
async function send(
parameters : type_parameters,
labels : _munin.type_labels,
event : _munin.type_event
) : Promise<void>
{
await lib_plankton.telegram.bot_call_send_message(
parameters.bot_token,
parameters.chat_id,
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,
}
)
),
}
),
{
"parse_mode": "markdown",
}
);
}
/**
*/
export function implementation_target(
parameters : type_parameters
) : _munin.type_target
{
return {
"interval": parameters.interval,
"send": (labels, event) => send(parameters, labels, event),
};
}
}

View file

@ -1,6 +1,16 @@
namespace _lixer_event_reminder
namespace _munin
{
/**
*/
export type type_labels = {
head : string;
title : string;
time : string;
location : string;
};
/**
*/
export type type_event = {
@ -9,20 +19,32 @@ namespace _lixer_event_reminder
end : (null | lib_plankton.pit.type_datetime),
location : (null | string);
};
/**
*/
export type type_source = {
fetch : (() => Promise<Array<type_event>>);
fetch : (
(
)
=>
Promise<Array<type_event>>
);
};
/**
*/
export type type_target = {
chat_id : int;
interval : Array<int>;
send : (
(
labels : type_labels,
event : type_event
)
=>
Promise<void>
);
};
}

0
tools/clear Normal file → Executable file
View file

View file

@ -5076,43 +5076,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
/*
This file is part of »munin«.
This file is part of »ivaldi«.
Copyright 2025 'Fenris Wolf' <fenris@folksprak.org>
»munin« is free software: you can redistribute it and/or modify
»ivaldi« 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,
»ivaldi« 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/>.
along with »ivaldi«. If not, see <http://www.gnu.org/licenses/>.
*/
/*
This file is part of »munin«.
This file is part of »ivaldi«.
Copyright 2025 'Fenris Wolf' <fenris@folksprak.org>
»munin« is free software: you can redistribute it and/or modify
»ivaldi« 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,
»ivaldi« 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/>.
along with »ivaldi«. If not, see <http://www.gnu.org/licenses/>.
*/
var _munin;
(function (_munin) {
var _ivaldi;
(function (_ivaldi) {
/**
* @todo outsource
*/
@ -5252,9 +5252,9 @@ var _munin;
"libs": "libs",
"temp": "temp",
"build": "build",
"makefile": "/tmp",
},
"command_tsc": "tsc",
"makefile_path": "/tmp/ivaldi-makefile",
};
switch (args.action) {
default: {
@ -5432,11 +5432,17 @@ var _munin;
"break_dependencies": true,
"silent_actions": true,
});
yield lib_plankton.file.write(conf.makefile_path, makefile);
const command = lib_plankton.string.coin("make -f {{path}}", {
"path": conf.makefile_path,
const makefile_path = lib_plankton.string.coin("{{directory}}/ivaldi-makefile-{{name}}", {
"directory": conf.directories.makefile,
"name": data.name,
});
yield execute(command);
yield lib_plankton.file.write(makefile_path, makefile);
const command = lib_plankton.string.coin("make -f {{path}}", {
"path": makefile_path,
});
const result = yield execute(command);
process.stdout.write(result.stdout + "\n");
process.stderr.write(result.stderr + "\n");
return Promise.resolve(undefined);
break;
}
@ -5448,8 +5454,8 @@ var _munin;
}
});
}
_munin.main = main;
})(_munin || (_munin = {}));
_munin.main(process.argv.slice(2))
_ivaldi.main = main;
})(_ivaldi || (_ivaldi = {}));
_ivaldi.main(process.argv.slice(2))
.then(() => { })
.catch((reason) => { process.stderr.write(String(reason) + "\n"); });