<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Todoist Script Lösung]]></title><description><![CDATA[<p dir="auto">Moin Moin,</p>
<p dir="auto">der Adapter war unschlagbar. Ich hab nicht weiter geguckt, ob sich jemand dem aktuell angenommen hat, da zur Zeit Warn-und Errormeldungen kommen , wenn ich den Adapter starte.<br />
Eine Suche ergab, dass Todoist mal wieder die API geändert hat. In den Adapter Dateien fummeln hat nichts gebracht. Also Old School per Skript und KI Hilfe.<br />
Ich benutze Todoist schon seit Ewigkeiten und möchte auf die Vielfalt nicht verzichten.<br />
In der App eingetragen erscheint es fast in Echtzeit in der VIS. Oder Alexa liest die Liste vor.<br />
Next Step wäre , dass Alexa die Liste durch Zuruf befüllt.<br />
Aber erstmal das Skript (meine Einkaufsliste). Token und Projektnummer gibs in der App.</p>
<p dir="auto">const TOKEN = "XXXXXX";<br />
const PROJECT_ID = "XXXXXXX";<br />
const DP_HTML = "0_userdata.0.todoist.einkaufsliste.html";<br />
const DP_COUNT = "0_userdata.0.todoist.einkaufsliste.count";<br />
// Cache<br />
let lastHTML = "Keine Daten";<br />
let lastCount = 0;<br />
// =====================<br />
// LOG INFO TEIL (SEPARAT &amp; CLEAN)<br />
// =====================<br />
function logInfo(msg) {<br />
log("[TODOIST] " + msg, "info");<br />
}<br />
function logError(msg) {<br />
log("[TODOIST ERROR] " + msg, "info"); // kein warn/error → keine Stacktraces<br />
}<br />
// =====================<br />
// START<br />
// =====================<br />
schedule("*/4 * * * <em>", loadTasks);<br />
loadTasks();<br />
// =====================<br />
// MAIN<br />
// =====================<br />
function loadTasks() {<br />
logInfo("Lade Tasks...");<br />
httpPost("<a href="https://api.todoist.com/api/v1/sync" rel="nofollow ugc">https://api.todoist.com/api/v1/sync</a>",<br />
"sync_token=</em>&amp;resource_types=" + encodeURIComponent('["items"]'),<br />
{<br />
headers: {<br />
"Authorization": "Bearer " + TOKEN,<br />
"Content-Type": "application/x-www-form-urlencoded"<br />
},<br />
timeout: 10000<br />
},<br />
(err, res) =&gt; {<br />
if (err) {<br />
logError("HTTP Fehler");<br />
setState(DP_HTML, lastHTML, true);<br />
setState(DP_COUNT, lastCount, true);<br />
return;<br />
}<br />
let data;<br />
try {<br />
data = JSON.parse(res.data);<br />
} catch (e) {<br />
logError("JSON Fehler");<br />
return;<br />
}<br />
const items = data.items || [];<br />
if (!Array.isArray(items)) return;<br />
const filtered = items.filter(t =&gt;<br />
t.project_id == PROJECT_ID<br />
);<br />
const html = filtered.length<br />
? filtered.map(t =&gt; "• " + escapeHtml(t.content || "")).join("&lt;br&gt;")<br />
: "Keine Einträge vorhanden";<br />
setState(DP_HTML, html, true);<br />
setState(DP_COUNT, filtered.length, true);<br />
lastHTML = html;<br />
lastCount = filtered.length;<br />
logInfo("OK: " + filtered.length + " Items");<br />
}<br />
);<br />
}</p>
<p dir="auto">// =====================<br />
// HTML SAFE<br />
// =====================<br />
function escapeHtml(str) {<br />
return (str || "")<br />
.replace(/&amp;/g, "&amp;")<br />
.replace(/&lt;/g, "&lt;")<br />
.replace(/&gt;/g, "&gt;");<br />
}</p>
<p dir="auto">VIS Beispielbild<br />
<img src="/assets/uploads/files/1777816657163-c791c301-7729-4395-8a8a-968295c68a2b-image.jpeg" alt="c791c301-7729-4395-8a8a-968295c68a2b-image.jpeg" class=" img-fluid img-markdown" /></p>
]]></description><link>https://forum.iobroker.net/topic/84467/todoist-script-lösung</link><generator>RSS for Node</generator><lastBuildDate>Wed, 06 May 2026 15:10:04 GMT</lastBuildDate><atom:link href="https://forum.iobroker.net/topic/84467.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 03 May 2026 13:56:26 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Todoist Script Lösung on Mon, 04 May 2026 21:12:58 GMT]]></title><description><![CDATA[<p dir="auto">Fortsetzung:</p>
<p dir="auto">Ansage von Alexa, was auf der Einkaufsliste steht.<br />
Eine Routine anlegen mit , wenn gesagt wird einkaufsliste, dann soll Alexa benutzerdefiniert anworten (was, könnt ihr euch aussuchen).<br />
Hat den Hintergrund, dass Alexa auf das Wort "einkaufsliste" reagiert und nicht eine Fehlermeldung raushaut.<br />
Dann ein Blockly anlegen:</p>
<p dir="auto"><img src="/assets/uploads/files/1777925756428-443abf28-f488-40d4-9014-268512c05ed6-image.jpeg" alt="443abf28-f488-40d4-9014-268512c05ed6-image.jpeg" class=" img-fluid img-markdown" /></p>
<p dir="auto">Damit triggern wir auf das Wort einkaufsliste (Kleinschreibung beachten)<br />
Den DP setzen wir , wenn das Wort erkannt wird, kurz auf true (dadurch wird das Script ausgelöst) und 2 sek später wieder auf false.<br />
<s>Der DP wird vom Skript angelegt.</s><br />
Korrektur.<br />
Den müsst ihr selber anlegen.<br />
<img src="/assets/uploads/files/1777926332516-09a736ff-cd17-44aa-9462-8ff5a4a044aa-image.jpeg" alt="09a736ff-cd17-44aa-9462-8ff5a4a044aa-image.jpeg" class=" img-fluid img-markdown" /></p>
<pre><code>const TOKEN = "XXXXXXXXXXXX";

// 🔴 numerische Projekt-ID
const PROJECT_ID = "XXXXXXXX";

// 🔵 TRIGGER
const TRIGGER_DP = "0_userdata.0.todoist.readList";

let isRunning = false;

// =====================
// TRIGGER
// =====================
on({ id: TRIGGER_DP, change: "ne" }, (obj) =&gt; {

    if (obj.state.val !== true) return;
    if (isRunning) return;

    isRunning = true;

    loadTasks();

    // Trigger sofort zurücksetzen (kein Loop!)
    setTimeout(() =&gt; {
        setState(TRIGGER_DP, false, true);
        isRunning = false;
    }, 1500);
});

// =====================
// MAIN
// =====================
function loadTasks() {

    httpPost(
        "https://api.todoist.com/api/v1/sync",
        "sync_token=*&amp;resource_types=" + encodeURIComponent('["items"]'),
        {
            headers: {
                "Authorization": "Bearer " + TOKEN,
                "Content-Type": "application/x-www-form-urlencoded"
            },
            timeout: 10000
        },
        (err, res) =&gt; {

            if (err) {
                speak("Ich konnte deine Einkaufsliste nicht laden.");
                return;
            }

            let data;

            try {
                data = JSON.parse(res.data);
            } catch (e) {
                speak("Fehler beim Verarbeiten der Daten.");
                return;
            }

            const items = data.items || [];

            const list = items.filter(t =&gt;
                t.project_id == PROJECT_ID
            );

            if (!list.length) {
                speak("Deine Einkaufsliste ist leer.");
                return;
            }

            let text;

            if (list.length === 1) {
                text = "Du hast nur " + list[0].content + " auf deiner Einkaufsliste.";
            }
            else if (list.length &lt;= 5) {
                text = "Auf deiner Einkaufsliste stehen: " +
                    list.map(t =&gt; t.content).join(", ");
            }
            else {
                text = "Du hast " + list.length + " Artikel. Zum Beispiel: " +
                    list.slice(0, 5).map(t =&gt; t.content).join(", ");
            }

            speak(text);
        }
    );
}

// =====================
// 🔊 SPEAK (DEIN FIX BEIBEHALTEN)
// =====================
function speak(text) {

    if (!text) return;

    const dp =
        "alexa2.0.Echo-Devices.XXXXXXXXXXXXX.Commands.speak";

    if (!existsState(dp)) {
        log("Alexa speak DP nicht gefunden!", "error");
        return;
    }

    log("ALEXA SPEAK: " + text, "info");

    setState(dp, "");

    setTimeout(() =&gt; {
        setState(dp, text + " ");
    }, 1000);
}
</code></pre>
<p dir="auto">Token und Project ID findet ihr in eurem Todoist Account.<br />
Natürlich solltest ihr vorher eine Einkaufsliste angelegt haben (Projekt).<br />
Den Echo bzw. die Seriennummer bekommt ihr aus dem Alexa2 Adapter.</p>
<p dir="auto">const dp =<br />
"alexa2.0.Echo-Devices.XXXXXXXXXXXXX.Commands.speak"</p>
<p dir="auto">Im Skript selber, ich bin da Laie, steht wohl, dass der DP nachdem er auf true gegangen ist, gleich wieder auf false gesetzt wird.<br />
Bei mir hat es nun so, wie ich es hier aufgeschrieben habe funktioniert.<br />
Ihr könnt ja ein wenig rumprobieren.</p>
<p dir="auto">Was aktuell nicht so einfach funktioniert, ist, Sachen per Sprache auf die Einkaufsliste zu setzen.<br />
Da habe ich mir bis jetzt die Zähne ausgebissen.</p>
<p dir="auto">Edit: kleiner Hinweis zur summary. Das Wort muss ich sich ja ändern in dem DP. Also 2 mal hintereinander einkaufsliste sagen, löst nur 1 mal das Skript aus.<br />
Also nach dem Wort einkaufsliste nach der Uhrzeit fragen , damit sich der DP wieder ändert <img src="https://forum.iobroker.net/assets/plugins/nodebb-plugin-emoji/emoji/android/1f60a.png?v=ba16ebd4856" class="not-responsive emoji emoji-android emoji--blush" style="height:23px;width:auto;vertical-align:middle" title=":blush:" alt="😊" /></p>
<p dir="auto">Edit 2: Es funktioniert wohl auch, wenn man beim Trigger aktualisiert nimmt. Da kann man so oft einkaufsliste sagen , wie man will.</p>
]]></description><link>https://forum.iobroker.net/post/1337938</link><guid isPermaLink="true">https://forum.iobroker.net/post/1337938</guid><dc:creator><![CDATA[haselchen]]></dc:creator><pubDate>Mon, 04 May 2026 21:12:58 GMT</pubDate></item><item><title><![CDATA[Reply to Todoist Script Lösung on Sun, 03 May 2026 14:49:25 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mcm1957" aria-label="Profile: mcm1957">@<bdi>mcm1957</bdi></a></p>
<p dir="auto">ja dann, ist das natürlich ganz schön kompliziert</p>
]]></description><link>https://forum.iobroker.net/post/1337690</link><guid isPermaLink="true">https://forum.iobroker.net/post/1337690</guid><dc:creator><![CDATA[OliverIO]]></dc:creator><pubDate>Sun, 03 May 2026 14:49:25 GMT</pubDate></item><item><title><![CDATA[Reply to Todoist Script Lösung on Sun, 03 May 2026 14:48:40 GMT]]></title><description><![CDATA[<p dir="auto">Das wird ihm nur privat was  nutzen, da das Paket unter dem Namen nicht veröffentlicht werden kann.</p>
]]></description><link>https://forum.iobroker.net/post/1337689</link><guid isPermaLink="true">https://forum.iobroker.net/post/1337689</guid><dc:creator><![CDATA[mcm1957]]></dc:creator><pubDate>Sun, 03 May 2026 14:48:40 GMT</pubDate></item><item><title><![CDATA[Reply to Todoist Script Lösung on Sun, 03 May 2026 14:48:07 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mcm1957" aria-label="Profile: mcm1957">@<bdi>mcm1957</bdi></a></p>
<p dir="auto">Der github user stroell hat gestern mit copilot was am fork gemacht<br />
<a href="https://github.com/Stroell/ioBroker.todoist2/commits/master/" rel="nofollow ugc">https://github.com/Stroell/ioBroker.todoist2/commits/master/</a></p>
<p dir="auto">ist wohl der user <a class="plugin-mentions-user plugin-mentions-a" href="/user/stroell" aria-label="Profile: stroell">@<bdi>stroell</bdi></a> (forum/github gleiches Bild)<br />
war aber seit der Anmeldung 2023 nicht mehr im Forum</p>
]]></description><link>https://forum.iobroker.net/post/1337688</link><guid isPermaLink="true">https://forum.iobroker.net/post/1337688</guid><dc:creator><![CDATA[OliverIO]]></dc:creator><pubDate>Sun, 03 May 2026 14:48:07 GMT</pubDate></item><item><title><![CDATA[Reply to Todoist Script Lösung on Sun, 03 May 2026 14:35:23 GMT]]></title><description><![CDATA[<p dir="auto">Aber wenn das eh per Script geht stellt sich die Frage ob irgendein Aufwand für den Adapter sinnvoll wäre. Vor allem wenn es kaum Interesse gibt.</p>
]]></description><link>https://forum.iobroker.net/post/1337686</link><guid isPermaLink="true">https://forum.iobroker.net/post/1337686</guid><dc:creator><![CDATA[mcm1957]]></dc:creator><pubDate>Sun, 03 May 2026 14:35:23 GMT</pubDate></item><item><title><![CDATA[Reply to Todoist Script Lösung on Sun, 03 May 2026 14:35:57 GMT]]></title><description><![CDATA[<p dir="auto"><strong>DANKE füs Teilen.</strong></p>
<p dir="auto">Bisher hat kein User an einem Versuch der Migration des Adapter interesse gezeigt:<br />
<a href="https://forum.iobroker.net/topic/84408/deprecated-adapter-todoist2">https://forum.iobroker.net/topic/84408/deprecated-adapter-todoist2</a></p>
]]></description><link>https://forum.iobroker.net/post/1337685</link><guid isPermaLink="true">https://forum.iobroker.net/post/1337685</guid><dc:creator><![CDATA[mcm1957]]></dc:creator><pubDate>Sun, 03 May 2026 14:35:57 GMT</pubDate></item></channel></rss>