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

  • Neues YouTube-Video: Visualisierung im Devices-Adapter
    BluefoxB
    Bluefox
    11
    1
    439

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

  • Verwendung von KI bitte immer deutlich kennzeichnen
    HomoranH
    Homoran
    11
    1
    822

Todoist Script Lösung

Geplant Angeheftet Gesperrt Verschoben JavaScript
11 Beiträge 5 Kommentatoren 291 Aufrufe 5 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.
  • 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 S 2 Antworten 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.7, Nodejs 22.22.2 ,JS Controller 7.0.7 ,Admin 7.8.24

              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.

                S Offline
                S Offline
                Stadtschloss
                schrieb am zuletzt editiert von
                #8

                @mcm1957 sagte:

                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.

                Der Adapter konnte jedoch mehr undzwar zum Beispiel. die Todos in Json ausgeben. Ich wäre an dem Adapter sehr interessiert.

                Samson71S 1 Antwort Letzte Antwort
                0
                • S Stadtschloss

                  @mcm1957 sagte:

                  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.

                  Der Adapter konnte jedoch mehr undzwar zum Beispiel. die Todos in Json ausgeben. Ich wäre an dem Adapter sehr interessiert.

                  Samson71S Offline
                  Samson71S Offline
                  Samson71
                  Global Moderator
                  schrieb am zuletzt editiert von Samson71
                  #9

                  @Stadtschloss
                  Das Cross-Posting hier ist völlig sinnfrei, da es hier nicht um den Adapter selbst geht (der Dir jetzt vermeintlich fehlt), sondern um einen zumindest teilweisen Ersatz. Dein Interesse am eigentlichen Adapter hast Du ja bereits im (abgekündigten) Thread gepostet.

                  Markus

                  Bitte beachten:
                  Hinweise für gute Forenbeiträge
                  Maßnahmen zum Schutz des Forums

                  OliverIOO 1 Antwort Letzte Antwort
                  0
                  • Samson71S Samson71

                    @Stadtschloss
                    Das Cross-Posting hier ist völlig sinnfrei, da es hier nicht um den Adapter selbst geht (der Dir jetzt vermeintlich fehlt), sondern um einen zumindest teilweisen Ersatz. Dein Interesse am eigentlichen Adapter hast Du ja bereits im (abgekündigten) Thread gepostet.

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

                    @Samson71

                    Man könnte natürlich im Script, in der Funktion getTasks die Daten die von der api zurückkommen, optional auch in einen datenpunkt schreiben. Das wäre nicht so sehr komplex.

                    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

                      @Samson71

                      Man könnte natürlich im Script, in der Funktion getTasks die Daten die von der api zurückkommen, optional auch in einen datenpunkt schreiben. Das wäre nicht so sehr komplex.

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

                      Update:

                      Mit diesem Befehl in einer Konsole kann man seine Projekte auflisten lassen (aus der App).
                      Das ist wichtig für die Projekt ID im Skript.

                      curl -i https://api.todoist.com/api/v1/projects
                      -H "Authorization: Bearer XXXXXXXX" (für die XXXX muss euer Token eingesetzt werden)

                      Die Ausgabe sähe als Beispiel so aus:

                      {
                      "results": [
                      {
                      "id": "XXXXXX",
                      "can_assign_tasks": false,
                      "can_comment": true,
                      "child_order": 0,
                      "is_collapsed": false,
                      "color": "grey",
                      "creator_uid": "",
                      "created_at": "",
                      "is_archived": false,
                      "is_deleted": false,
                      "is_favorite": false,
                      "is_frozen": false,
                      "name": "Inbox",
                      "is_shared": false,
                      "updated_at": "",
                      "view_style": "list",
                      "default_order": 0,
                      "description": "",
                      "public_access": false,
                      "public_key": "",
                      "access": {
                      "visibility": "restricted",
                      "configuration": {}
                      },
                      "role": "CREATOR",
                      "goal_ids": [],
                      "parent_id": null,
                      "inbox_project": true
                      },
                      {
                      "id": "XXXXXX",
                      "can_assign_tasks": false,
                      "can_comment": true,
                      "child_order": 1,
                      "is_collapsed": false,
                      "color": "sky_blue",
                      "creator_uid": "",
                      "created_at": "",
                      "is_archived": false,
                      "is_deleted": false,
                      "is_favorite": false,
                      "is_frozen": false,
                      "name": "Alexa-Einkaufsliste",
                      "is_shared": false,
                      "updated_at": "",
                      "view_style": "list",
                      "default_order": 0,
                      "description": "",
                      "public_access": false,
                      "public_key": "",
                      "access": {
                      "visibility": "restricted",
                      "configuration": {}
                      },
                      "role": "CREATOR",
                      "goal_ids": [],
                      "parent_id": null,
                      "inbox_project": false
                      },
                      {
                      "id": "XXXXXX",
                      "can_assign_tasks": false,
                      "can_comment": true,
                      "child_order": 2,
                      "is_collapsed": false,
                      "color": "orange",
                      "creator_uid": "",
                      "created_at": "",
                      "is_archived": false,
                      "is_deleted": false,
                      "is_favorite": false,
                      "is_frozen": false,
                      "name": "Alexa To-Do Liste",
                      "is_shared": false,
                      "updated_at": "",
                      "view_style": "list",
                      "default_order": 0,
                      "description": "",
                      "public_access": false,
                      "public_key": "",
                      "access": {
                      "visibility": "restricted",
                      "configuration": {}
                      },
                      "role": "CREATOR",
                      "goal_ids": [],
                      "parent_id": null,
                      "inbox_project": false
                      }
                      ],
                      "next_cursor": null

                      Nehmen wir den Block , wo Alexa-Einkaufsliste steht. Darüber gibt es das Feld "id".
                      Diese ID nehmt ihr für euer Skript.
                      Das könnt ihr für jedes Projekt , was ihr in der App angelegt habt, machen.
                      Ich habe ne ToDo Liste noch mit Aufgaben, die ich mir zukünftig so vorgenommen habe.
                      Ein HTML Widget und sie werden mir in der VIS angezeigt.
                      Immer wenns mir in den Kopp kommt, trage ich ne Aufgabe oder was für den Einkauf in der ToDoIst App ein und je nach Update Intervall im Skript, erscheint es dann in der VIS.

                      4af9418b-b376-4f21-8e11-192aec03c340-image.jpeg

                      Token und Project ID vervollständigen und die beiden Datenpunkte anlegen

                      0_userdata.0.todoist.aufgaben.html
                      0_userdata.0.todoist.aufgaben.count

                      const TOKEN = "XXXXXX";
                      
                      // 🔴 Kann numerisch sein (muss nicht)
                      const PROJECT_ID = "XXXXXX";
                      
                      const DP_HTML = "0_userdata.0.todoist.aufgaben.html";
                      const DP_COUNT = "0_userdata.0.todoist.aufgaben.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("*/5 * * * *", 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 => {
                                  let text = escapeHtml(t.content || "");
                      
                                  // entfernt führende "-" oder "•" falls sie im Task stehen
                                  text = text.replace(/^(\s*[-•]\s*)+/, "");
                      
                                  return "&#8226; " + text;
                                   }).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, "&amp;")
                              .replace(/</g, "&lt;")
                              .replace(/>/g, "&gt;");
                      }
                      

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

                      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

                      266

                      Online

                      32.9k

                      Benutzer

                      83.0k

                      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