Weiter zum Inhalt
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. Todoist Script Lösung

NEWS

  • Neuer ioBroker-Blog online: Monatsrückblick März/April 2026
    BluefoxB
    Bluefox
    8
    1
    750

  • Verwendung von KI bitte immer deutlich kennzeichnen
    HomoranH
    Homoran
    10
    1
    575

  • Monatsrückblick Januar/Februar 2026 ist online!
    BluefoxB
    Bluefox
    18
    1
    1.1k

Todoist Script Lösung

Geplant Angeheftet Gesperrt Verschoben JavaScript
7 Beiträge 3 Kommentatoren 125 Aufrufe 3 Beobachtet
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • haselchenH Offline
    haselchenH Offline
    haselchen
    Most Active
    schrieb am zuletzt editiert von haselchen
    #1

    Moin Moin,

    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.
    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.
    Ich benutze Todoist schon seit Ewigkeiten und möchte auf die Vielfalt nicht verzichten.
    In der App eingetragen erscheint es fast in Echtzeit in der VIS. Oder Alexa liest die Liste vor.
    Next Step wäre , dass Alexa die Liste durch Zuruf befüllt.
    Aber erstmal das Skript (meine Einkaufsliste). Token und Projektnummer gibs in der App.

    const TOKEN = "XXXXXX";
    const PROJECT_ID = "XXXXXXX";
    const DP_HTML = "0_userdata.0.todoist.einkaufsliste.html";
    const DP_COUNT = "0_userdata.0.todoist.einkaufsliste.count";
    // Cache
    let lastHTML = "Keine Daten";
    let lastCount = 0;
    // =====================
    // LOG INFO TEIL (SEPARAT & CLEAN)
    // =====================
    function logInfo(msg) {
    log("[TODOIST] " + msg, "info");
    }
    function logError(msg) {
    log("[TODOIST ERROR] " + msg, "info"); // kein warn/error → keine Stacktraces
    }
    // =====================
    // START
    // =====================
    schedule("*/4 * * * ", loadTasks);
    loadTasks();
    // =====================
    // MAIN
    // =====================
    function loadTasks() {
    logInfo("Lade Tasks...");
    httpPost("https://api.todoist.com/api/v1/sync",
    "sync_token=
    &resource_types=" + encodeURIComponent('["items"]'),
    {
    headers: {
    "Authorization": "Bearer " + TOKEN,
    "Content-Type": "application/x-www-form-urlencoded"
    },
    timeout: 10000
    },
    (err, res) => {
    if (err) {
    logError("HTTP Fehler");
    setState(DP_HTML, lastHTML, true);
    setState(DP_COUNT, lastCount, true);
    return;
    }
    let data;
    try {
    data = JSON.parse(res.data);
    } catch (e) {
    logError("JSON Fehler");
    return;
    }
    const items = data.items || [];
    if (!Array.isArray(items)) return;
    const filtered = items.filter(t =>
    t.project_id == PROJECT_ID
    );
    const html = filtered.length
    ? filtered.map(t => "• " + escapeHtml(t.content || "")).join("<br>")
    : "Keine Einträge vorhanden";
    setState(DP_HTML, html, true);
    setState(DP_COUNT, filtered.length, true);
    lastHTML = html;
    lastCount = filtered.length;
    logInfo("OK: " + filtered.length + " Items");
    }
    );
    }

    // =====================
    // HTML SAFE
    // =====================
    function escapeHtml(str) {
    return (str || "")
    .replace(/&/g, "&")
    .replace(/</g, "<")
    .replace(/>/g, ">");
    }

    VIS Beispielbild
    c791c301-7729-4395-8a8a-968295c68a2b-image.jpeg

    Synology DS218+ & 2 x Fujitsu Esprimo (VM/Container) + FritzBox7590 + 2 AVM 3000 Repeater & Homematic & HUE & Osram & Xiaomi, NPM 10.9.4, Nodejs 22.21.0 ,JS Controller 7.0.7 ,Admin 7.7.19

    1 Antwort Letzte Antwort
    1
    • mcm1957M Online
      mcm1957M Online
      mcm1957
      schrieb am zuletzt editiert von mcm1957
      #2

      DANKE füs Teilen.

      Bisher hat kein User an einem Versuch der Migration des Adapter interesse gezeigt:
      https://forum.iobroker.net/topic/84408/deprecated-adapter-todoist2

      Entwicklung u Betreuung: envertech-pv, hoymiles-ms, ns-client, pid, snmp Adapter;
      Support Repositoryverwaltung.

      Wer 'nen Kaffee spendieren will: https://paypal.me

      LESEN - gute Forenbeitrage

      1 Antwort Letzte Antwort
      0
      • mcm1957M Online
        mcm1957M Online
        mcm1957
        schrieb am zuletzt editiert von
        #3

        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.

        Entwicklung u Betreuung: envertech-pv, hoymiles-ms, ns-client, pid, snmp Adapter;
        Support Repositoryverwaltung.

        Wer 'nen Kaffee spendieren will: https://paypal.me

        LESEN - gute Forenbeitrage

        OliverIOO 1 Antwort Letzte Antwort
        0
        • mcm1957M mcm1957

          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.

          OliverIOO Offline
          OliverIOO Offline
          OliverIO
          schrieb am zuletzt editiert von OliverIO
          #4

          @mcm1957

          Der github user stroell hat gestern mit copilot was am fork gemacht
          https://github.com/Stroell/ioBroker.todoist2/commits/master/

          ist wohl der user @stroell (forum/github gleiches Bild)
          war aber seit der Anmeldung 2023 nicht mehr im Forum

          Meine Adapter und Widgets
          TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
          Links im Profil

          1 Antwort Letzte Antwort
          0
          • mcm1957M Online
            mcm1957M Online
            mcm1957
            schrieb am zuletzt editiert von mcm1957
            #5

            Das wird ihm nur privat was nutzen, da das Paket unter dem Namen nicht veröffentlicht werden kann.

            Entwicklung u Betreuung: envertech-pv, hoymiles-ms, ns-client, pid, snmp Adapter;
            Support Repositoryverwaltung.

            Wer 'nen Kaffee spendieren will: https://paypal.me

            LESEN - gute Forenbeitrage

            OliverIOO 1 Antwort Letzte Antwort
            0
            • mcm1957M mcm1957

              Das wird ihm nur privat was nutzen, da das Paket unter dem Namen nicht veröffentlicht werden kann.

              OliverIOO Offline
              OliverIOO Offline
              OliverIO
              schrieb am zuletzt editiert von
              #6

              @mcm1957

              ja dann, ist das natürlich ganz schön kompliziert

              Meine Adapter und Widgets
              TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
              Links im Profil

              haselchenH 1 Antwort Letzte Antwort
              0
              • OliverIOO OliverIO

                @mcm1957

                ja dann, ist das natürlich ganz schön kompliziert

                haselchenH Offline
                haselchenH Offline
                haselchen
                Most Active
                schrieb am zuletzt editiert von haselchen
                #7

                Fortsetzung:

                Ansage von Alexa, was auf der Einkaufsliste steht.
                Eine Routine anlegen mit , wenn gesagt wird einkaufsliste, dann soll Alexa benutzerdefiniert anworten (was, könnt ihr euch aussuchen).
                Hat den Hintergrund, dass Alexa auf das Wort "einkaufsliste" reagiert und nicht eine Fehlermeldung raushaut.
                Dann ein Blockly anlegen:

                443abf28-f488-40d4-9014-268512c05ed6-image.jpeg

                Damit triggern wir auf das Wort einkaufsliste (Kleinschreibung beachten)
                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.
                Der DP wird vom Skript angelegt.
                Korrektur.
                Den müsst ihr selber anlegen.
                09a736ff-cd17-44aa-9462-8ff5a4a044aa-image.jpeg

                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) => {
                
                    if (obj.state.val !== true) return;
                    if (isRunning) return;
                
                    isRunning = true;
                
                    loadTasks();
                
                    // Trigger sofort zurücksetzen (kein Loop!)
                    setTimeout(() => {
                        setState(TRIGGER_DP, false, true);
                        isRunning = false;
                    }, 1500);
                });
                
                // =====================
                // MAIN
                // =====================
                function loadTasks() {
                
                    httpPost(
                        "https://api.todoist.com/api/v1/sync",
                        "sync_token=*&resource_types=" + encodeURIComponent('["items"]'),
                        {
                            headers: {
                                "Authorization": "Bearer " + TOKEN,
                                "Content-Type": "application/x-www-form-urlencoded"
                            },
                            timeout: 10000
                        },
                        (err, res) => {
                
                            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 =>
                                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 <= 5) {
                                text = "Auf deiner Einkaufsliste stehen: " +
                                    list.map(t => t.content).join(", ");
                            }
                            else {
                                text = "Du hast " + list.length + " Artikel. Zum Beispiel: " +
                                    list.slice(0, 5).map(t => 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(() => {
                        setState(dp, text + " ");
                    }, 1000);
                }
                

                Token und Project ID findet ihr in eurem Todoist Account.
                Natürlich solltest ihr vorher eine Einkaufsliste angelegt haben (Projekt).
                Den Echo bzw. die Seriennummer bekommt ihr aus dem Alexa2 Adapter.

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

                Im Skript selber, ich bin da Laie, steht wohl, dass der DP nachdem er auf true gegangen ist, gleich wieder auf false gesetzt wird.
                Bei mir hat es nun so, wie ich es hier aufgeschrieben habe funktioniert.
                Ihr könnt ja ein wenig rumprobieren.

                Was aktuell nicht so einfach funktioniert, ist, Sachen per Sprache auf die Einkaufsliste zu setzen.
                Da habe ich mir bis jetzt die Zähne ausgebissen.

                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.
                Also nach dem Wort einkaufsliste nach der Uhrzeit fragen , damit sich der DP wieder ändert 😊

                Edit 2: Es funktioniert wohl auch, wenn man beim Trigger aktualisiert nimmt. Da kann man so oft einkaufsliste sagen , wie man will.

                Synology DS218+ & 2 x Fujitsu Esprimo (VM/Container) + FritzBox7590 + 2 AVM 3000 Repeater & Homematic & HUE & Osram & Xiaomi, NPM 10.9.4, Nodejs 22.21.0 ,JS Controller 7.0.7 ,Admin 7.7.19

                1 Antwort Letzte Antwort
                0

                Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

                Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

                Mit deinem Input könnte dieser Beitrag noch besser werden 💗

                Registrieren Anmelden
                Antworten
                • In einem neuen Thema antworten
                Anmelden zum Antworten
                • Älteste zuerst
                • Neuste zuerst
                • Meiste Stimmen


                Support us

                ioBroker
                Community Adapters
                Donate

                626

                Online

                32.8k

                Benutzer

                82.9k

                Themen

                1.3m

                Beiträge
                Community
                Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                ioBroker Community 2014-2025
                logo
                • Anmelden

                • Du hast noch kein Konto? Registrieren

                • Anmelden oder registrieren, um zu suchen
                • Erster Beitrag
                  Letzter Beitrag
                0
                • Home
                • Aktuell
                • Tags
                • Ungelesen 0
                • Kategorien
                • Unreplied
                • Beliebt
                • GitHub
                • Docu
                • Hilfe