Ich habs hinbekommen :)
Laut der Github-Doku des Adapters kann man Regeln auch per Script verarbeiten:
https://github.com/ioBroker/ioBroker.text2command#external-rules-with-javascript
Das Script reagiert immer auf Telegram-Eingaben, wird aber tatsächlich nur dann aktiv, wenn es das wirklich soll. Und so sieht es dann aus:
[image: 1660131406334-project-name.gif]
(sorry für die schlechte Qualität, das Original war viel zu groß für einen Upload hier)
Der initiale Aufruf erfolgt über den text2command-Adapter:
[image: 1660129164155-bildschirmfoto-2022-08-10-um-12.59.08-resized.png]
Damit bei einem Neustart das Script nicht in einen undefinierten Zustand fährt, wird intern nochmal abgefragt, ob wirklich der Befehl gesendet wurde. Man kennt das ja, die ganzen Tastaturscripte werden ausgeführt, sobald man den Javascript-Adapter neustartet, wenn man keine Vorkehrungen trifft.
Der Rest erklärt sich glaube ich von selbst. Was jetzt natürlich noch geschehen muss ist, dass das eingegebene Datum weiterverarbeitet werden muss, aber das ist ja ein ganz anderes Thema.
Das Script benötigt diese Datenpunkte (bitte manuell anlegen):
0_userdata.0.Telegram.text2command.datePicker_Datum -> String
0_userdata.0.Telegram.text2command.datePicker_Jahr -> Number
0_userdata.0.Telegram.text2command.datePicker_Monat -> Number
0_userdata.0.Telegram.text2command.datePicker_Tag -> Number
0_userdata.0.Telegram.text2command.textProcessor -> String oder mixed
Letzterer muss auch in den Einstellungen des text2command-Adapters hinterlegt werden.
var today = new Date();
var currentYear = today.getYear() + 1900;
var currentMonth = today.getMonth();
var currentDay = today.getDate();
var currentWeekday = today.getDay();
const months = ['Jan','Feb','Mrz','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'];
var year = 0;
var month = 0;
var day = 0;
function go() {
// Bei Auslösung Status schreiben damit klar ist, dass reagiert werden muss
setState("0_userdata.0.Telegram.text2command.datePicker_Datum", 'running');
// Mit Jahreseingabe beginnen
keyboardYear();
};
function keyboardYear () {
// Tastatur für die Jahresauswahl zusammenbauen
var yearKeys =
[
[currentYear.toString(), (currentYear + 1).toString()],
[(currentYear + 2).toString(), (currentYear + 3).toString()],
["Abbrechen", ""]
]
// Tastatur senden
sendTo('telegram.0', {
text: 'Jahr wählen',
reply_markup: {
keyboard: yearKeys,
resize_keyboard: true,
one_time_keyboard: false
}
});
};
function keyboardMonth () {
// Tastatur für die Monatsauswahl zusammenbauen
var avMonths = new Array(11);
var monthKeys = new Array(4);
year = getState("0_userdata.0.Telegram.text2command.datePicker_Jahr").val;
for (let i = 0; i < 12; i++) {
if (year == currentYear) {
if (i < currentMonth) {
avMonths[i] = " ";
} else {
avMonths[i] = months[i];
}
} else {
avMonths = months;
}
}
monthKeys[0] = avMonths.slice(0,4);
monthKeys[1] = avMonths.slice(4,8);
monthKeys[2] = avMonths.slice(8);
monthKeys[3] = ["Abbrechen",""];
// Tastatur senden
sendTo('telegram.0', {
text: 'Monat wählen',
reply_markup: {
keyboard: monthKeys,
resize_keyboard: true,
one_time_keyboard: false
}
});
};
function keyboardDay () {
// Tastatur für die Tagesauswahl zusammenbauen
var days = new Array();
var dayKeys = new Array(8);
year = getState("0_userdata.0.Telegram.text2command.datePicker_Jahr").val;
month = getState("0_userdata.0.Telegram.text2command.datePicker_Monat").val;
let firstDay = new Date(year, month, 1).getDay();
let daysInMonth = new Date(year, month + 1, 0).getDate()
// Tages-Array mit " " füllen, falls erster Tag nicht Montag
if (firstDay == 0) {
for (let i = 0; i < 6; i++) {
days.push(" ");
}
} else if (firstDay > 1) {
for (let i = 1; i < firstDay; i++) {
days.push(" ");
}
}
// Tage zum Array hinzufügen
for (let i = 1; i <= daysInMonth; i++) {
if (getState("0_userdata.0.Telegram.text2command.datePicker_Jahr").val == currentYear && getState("0_userdata.0.Telegram.text2command.datePicker_Monat").val == currentMonth) {
if (i < currentDay) {
days.push(" ");
} else {
days.push(i.toString());
}
} else {
days.push(i.toString());
}
}
// Rest mit " " füllen
for (let i = days.length; i < 42; i++) {
days.push(" ");
}
dayKeys[0] = ['M','D','M','D','F','S','S'];
dayKeys[1] = days.slice(0,7);
dayKeys[2] = days.slice(7,14);
dayKeys[3] = days.slice(14,21);
dayKeys[4] = days.slice(21,28);
dayKeys[5] = days.slice(28,35);
dayKeys[6] = days.slice(35);
dayKeys[7] = ["Abbrechen"];
// Tastatur senden
sendTo('telegram.0', {
text: 'Tag wählen',
reply_markup: {
keyboard: dayKeys,
resize_keyboard: true,
one_time_keyboard: false
}
});
};
// Auf Eingabe reagieren
on({id: "0_userdata.0.Telegram.text2command.textProcessor", change: "ne"}, async function (obj) {
try {
var task = JSON.parse(obj.state.val);
// Start
if (isNaN(task.command) && task.command == "Abwesenheit planen") {
go();
}
// Jahr eingegeben
else if (!isNaN(task.command) && task.command >= currentYear &&
getState("0_userdata.0.Telegram.text2command.textProcessor").val != "" &&
getState("0_userdata.0.Telegram.text2command.datePicker_Datum").val == 'running' &&
getState("0_userdata.0.Telegram.text2command.datePicker_Jahr").val == 0 &&
getState("0_userdata.0.Telegram.text2command.datePicker_Monat").val == 0 &&
getState("0_userdata.0.Telegram.text2command.datePicker_Tag").val == 0) {
// Jahr abspeichern
setState("0_userdata.0.Telegram.text2command.datePicker_Jahr", Number(task.command), true);
//Bestätigung an textProcessor
setState("0_userdata.0.Telegram.text2command.textProcessor", 'Jahr gespeichert', true);
// Monat aufrufen
keyboardMonth();
}
// Monat eingegeben
else if (isNaN(task.command) &&
getState("0_userdata.0.Telegram.text2command.textProcessor").val != "" &&
getState("0_userdata.0.Telegram.text2command.datePicker_Datum").val == 'running' &&
getState("0_userdata.0.Telegram.text2command.datePicker_Jahr").val > 0 &&
getState("0_userdata.0.Telegram.text2command.datePicker_Monat").val == 0 &&
getState("0_userdata.0.Telegram.text2command.datePicker_Tag").val == 0) {
// Monat abspeichern
setState("0_userdata.0.Telegram.text2command.datePicker_Monat", months.indexOf(task.command), true);
//Bestätigung an textProcessor
setState("0_userdata.0.Telegram.text2command.textProcessor", 'Monat gespeichert', true);
// Tag aufrufen
keyboardDay();
}
// Tag eingegeben
else if (!isNaN(task.command) &&
getState("0_userdata.0.Telegram.text2command.textProcessor").val != "" &&
getState("0_userdata.0.Telegram.text2command.datePicker_Datum").val == 'running' &&
getState("0_userdata.0.Telegram.text2command.datePicker_Jahr").val > 0 &&
getState("0_userdata.0.Telegram.text2command.datePicker_Monat").val > 0 &&
getState("0_userdata.0.Telegram.text2command.datePicker_Tag").val == 0) {
//Tag abspeichern
setState("0_userdata.0.Telegram.text2command.datePicker_Tag", Number(task.command), true);
//Bestätigung an textProcessor
setState("0_userdata.0.Telegram.text2command.textProcessor", 'Tag gespeichert', true);
//Datum zusammenbauen und in Datenpunkt schreiben
setState("0_userdata.0.Telegram.text2command.datePicker_Datum",
getState("0_userdata.0.Telegram.text2command.datePicker_Jahr").val
+ "-"
+ (getState("0_userdata.0.Telegram.text2command.datePicker_Monat").val + 1)
+ "-"
+ getState("0_userdata.0.Telegram.text2command.datePicker_Tag").val
, true);
//Einzel-DP für Datum zurücksetzen
setState("0_userdata.0.Telegram.text2command.datePicker_Jahr", 0, true);
setState("0_userdata.0.Telegram.text2command.datePicker_Monat", 0, true);
setState("0_userdata.0.Telegram.text2command.datePicker_Tag", 0, true);
//Bestätigung senden
sendTo("telegram", "send", {
text: 'Datum gespeichert'
});
//zurück ins Hauptmenü
setState("javascript.0.scriptEnabled.Telegram-Menu.000_menu", true);
}
//Abbrechen
else if (isNaN(task.command) && task.command == "Abbrechen") {
//Einzel-DP für Datum zurücksetzen
setState("0_userdata.0.Telegram.text2command.datePicker_Jahr", 0, true);
setState("0_userdata.0.Telegram.text2command.datePicker_Monat", 0, true);
setState("0_userdata.0.Telegram.text2command.datePicker_Tag", 0, true);
//Datum zurücksetzen
setState("0_userdata.0.Telegram.text2command.datePicker_Datum", "", true);
//Bestätigung an textProcessor
setState("0_userdata.0.Telegram.text2command.textProcessor", 'Abbruch', true);
//zurück ins Hauptmenü
setState("javascript.0.scriptEnabled.Telegram-Menu.000_menu", true);
}
// Rückmeldung geben, dass das Script nicht reagieren wird
else {
setState("0_userdata.0.Telegram.text2command.textProcessor", '', true);
}
} catch {
// do nothing
}
});
Was mich derzeit noch stört ist, dass im Log immer eine Warnung auftaucht, wenn ein Befehl gesendet wurde, auf den das Script nicht reagieren wird. Das halte ich aber für einen Bug, da die Rückmeldung, dass das Script nichts tun wird, ja korrekt ausgeführt wird.
text2command.0 2022-08-10 13:27:06.692 warn Timeout for external processor: 0_userdata.0.Telegram.text2command.textProcessor
Was mich außerdem stört ist, dass die Aufforderung zur nächsten Eingabe eher kommt, als die Bestätigung der letzten Eingabe. Das sieht im Chat-Verlauf echt komisch aus, aber ich habe noch keine Idee, woran das liegt und wie man das lösen könnte.
Vielleicht kann das Ganze ja jemand gebrauchen - viel Spaß damit :)
Für Verbessungsvorschläge bin ich offen, falls jemand welche hat.