@martin_olw Ich hab es jetzt doch getestet und noch was geändert:
Hier die Beschreibung:
Der Skript überwacht den Datenpunkt alexa2.0.Lists.SHOP.json.
Sobald Alexa z. B. sagt:
„Alexa, setze vier Äpfel auf die Einkaufsliste“
wird das als neuer Eintrag in dieser Liste erkannt.
Zahlwort-Umwandlung:
Aus „vier Äpfel“ wird „4 Äpfel“.
Auch zusammengesetzte Zahlen wie „fünfzehn“ oder „dreiundzwanzig“ werden korrekt erkannt.
Das erste Wort nach der Zahl wird großgeschrieben: z. B. „4 Äpfel“ statt „4 äpfel“.
Todoist-Eintrag:
Der bereinigte und umgewandelte Eintrag wird direkt über die REST-API an Todoist gesendet und dort im definierten Projekt als Aufgabe eingetragen.
Automatisches Entfernen in Alexa:
Nach 60 Sekunden wird der passende Alexa-Listeneintrag automatisch als „abgehakt“ markiert.
Es muss nur die ListID und der Token eingesetzt werden.
const axios = require('axios');
// Todoist API-Konfiguration
const todoistProjectId = 'XXXXXXXX'; // Deine Projekt-ID
const todoistToken = 'XXXXXXXXXXXXXXXXXXXXXXX'; // Dein Token
let previousList = [];
// 1. Alexa-Änderungen überwachen
on({ id: 'alexa2.0.Lists.SHOP.json', change: 'any' }, function (obj) {
try {
const currentList = JSON.parse(obj.state.val);
if (currentList && currentList.length > 0) {
if (previousList.length < currentList.length) {
const newItem = currentList.find(item =>
!previousList.some(prevItem => prevItem.id === item.id)
);
if (newItem) {
const umgewandelt = wordsToNumbersSmart(newItem.value);
const aufgabe = capitalizeFirst(umgewandelt);
addTaskToTodoist(aufgabe);
// Nach 60 Sekunden Alexa-Eintrag auf "completed" setzen
setTimeout(() => {
const alexaList = JSON.parse(getState('alexa2.0.Lists.SHOP.json').val);
const matchingItem = alexaList.find(item => {
const itemText = wordsToNumbersSmart(item.value).trim().toLowerCase();
return itemText === aufgabe.trim().toLowerCase();
});
if (matchingItem) {
const completeState = `alexa2.0.Lists.SHOP.items.${matchingItem.id}.completed`;
setState(completeState, true);
} else {
console.warn(`⚠️ Kein passender Alexa-Eintrag zu "${aufgabe}" gefunden.`);
}
}, 60 * 1000); // 60 Sekunden
}
}
previousList = currentList;
}
} catch (e) {
console.error('Fehler beim Parsen der Alexa-Liste:', e.message || e);
}
});
// 2. Aufgaben an Todoist senden
function addTaskToTodoist(itemValue) {
const todoistData = {
content: itemValue,
project_id: todoistProjectId
};
axios.post('https://api.todoist.com/rest/v2/tasks', todoistData, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${todoistToken}`
}
})
.then(() => {
console.log(`✅ "${itemValue}" zu Todoist hinzugefügt.`);
})
.catch(error => {
console.error('Fehler beim Hinzufügen zu Todoist:', error.message || error);
});
}
// 3. Erstes Wort groß
function capitalizeFirst(text) {
if (!text || typeof text !== 'string') return '';
return text.charAt(0).toUpperCase() + text.slice(1);
}
// 4. Wörter → Zahlen (z. B. „vierzehn“ → 14)
function wordsToNumbersSmart(text) {
const ones = {
'null': 0, 'eins': 1, 'eine': 1, 'einen': 1,
'zwei': 2, 'drei': 3, 'vier': 4, 'fünf': 5,
'sechs': 6, 'sieben': 7, 'acht': 8, 'neun': 9,
'zehn': 10, 'elf': 11, 'zwölf': 12, 'dreizehn': 13,
'vierzehn': 14, 'fünfzehn': 15, 'sechzehn': 16,
'siebzehn': 17, 'achtzehn': 18, 'neunzehn': 19
};
const tens = {
'zwanzig': 20, 'dreißig': 30, 'vierzig': 40,
'fünfzig': 50, 'sechzig': 60, 'siebzig': 70,
'achtzig': 80, 'neunzig': 90
};
const multipliers = {
'hundert': 100,
'tausend': 1000
};
const skipWords = ['und', 'oder', 'mit', 'für', 'pro'];
const words = text.toLowerCase().split(/\s+/);
const finalText = [];
let i = 0;
let capitalizeNext = 0;
while (i < words.length) {
const word = words[i];
if (ones[word] !== undefined) {
if (i + 2 < words.length && words[i + 1] === 'und' && tens[words[i + 2]]) {
const value = ones[word] + tens[words[i + 2]];
finalText.push(value.toString());
capitalizeNext = 2;
i += 3;
continue;
}
if (i + 1 < words.length && multipliers[words[i + 1]]) {
const value = ones[word] * multipliers[words[i + 1]];
finalText.push(value.toString());
capitalizeNext = 2;
i += 2;
continue;
}
finalText.push(ones[word].toString());
capitalizeNext = 2;
i++;
} else if (tens[word] !== undefined) {
finalText.push(tens[word].toString());
capitalizeNext = 2;
i++;
} else if (!isNaN(word)) {
finalText.push(word);
capitalizeNext = 2;
i++;
} else {
if (capitalizeNext > 0 && !skipWords.includes(word)) {
finalText.push(word.charAt(0).toUpperCase() + word.slice(1));
capitalizeNext--;
} else {
finalText.push(word);
}
i++;
}
}
return finalText.join(' ');
}