ts6-botflow/flow-schedule.mjs
Bxio 1be8a45dde
All checks were successful
Testar e publicar imagem Docker / publish (push) Successful in 44s
Expand flow editor with TeamSpeak events, permissions and execution controls
2026-10-10 20:38:31 +01:00

65 lines
2.0 KiB
JavaScript

function parseField(source, min, max) {
const values = new Set();
for (const part of source.split(",")) {
const match = /^(\*|\d+(?:-\d+)?)(?:\/(\d+))?$/.exec(part);
if (!match) throw new Error("Campo cron inválido.");
const step = Number(match[2] || 1);
if (step < 1) throw new Error("Passo cron inválido.");
const base = match[1],
range =
base === "*"
? [min, max]
: base.includes("-")
? base.split("-").map(Number)
: [Number(base), match[2] ? max : Number(base)];
if (range[0] < min || range[1] > max || range[0] > range[1])
throw new Error("Valor cron fora do intervalo.");
for (let i = range[0]; i <= range[1]; i += step) values.add(i);
}
return values;
}
export function compileCron(expression, timezone = "Europe/Lisbon") {
const fields = String(expression).trim().split(/\s+/);
if (fields.length === 5) fields.unshift("0");
if (fields.length !== 6) throw new Error("O cron precisa de 5 ou 6 campos.");
const limits = [
[0, 59],
[0, 59],
[0, 23],
[1, 31],
[1, 12],
[0, 7],
],
sets = fields.map((v, i) => parseField(v, ...limits[i]));
if (sets[5].has(7)) sets[5].add(0);
const formatter = new Intl.DateTimeFormat("en-GB", {
timeZone: timezone,
second: "2-digit",
minute: "2-digit",
hour: "2-digit",
day: "2-digit",
month: "2-digit",
weekday: "short",
hourCycle: "h23",
});
return (date) => {
const p = Object.fromEntries(
formatter.formatToParts(date).map((p) => [p.type, p.value]),
),
values = [
+p.second,
+p.minute,
+p.hour,
+p.day,
+p.month,
["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].indexOf(p.weekday),
];
const day = sets[3].has(values[3]),
week = sets[5].has(values[5]);
return (
[0, 1, 2, 4].every((i) => sets[i].has(values[i])) &&
(fields[3] !== "*" && fields[5] !== "*" ? day || week : day && week)
);
};
}