Sync your Alexa/Todoist shopping list to the Home Assistant shopping list!

Can someone help me reviewing mine?

Amazon Echo and Todois work flawlessly (even HA updates when adding from both services) but when I add, delete or update my list from HA i get this error

WARNING (MainThread) [homeassistant.util.async_] Detected blocking call to sleep inside the event loop. This is causing stability issues. Please report issue to the custom integration author for pyscript doing blocking calls at custom_components/pyscript/eval.py, line 1906: return func(*args, **kwargs)

import requests
import sys
import time
from importlib import reload
if "/config/pyscript_modules" not in sys.path:
    sys.path.append("/config/pyscript_modules")

import write_file

write_file = reload(write_file)

TODOIST_TOKEN = "74d00fa66d414292c9cf027c165351b47e8d6fc3"
TODOIST_PROJECT_ID = "2300057472"

def get_tasks():
    get_tasks_url =f"https://api.todoist.com/rest/v2/tasks?project_id={TODOIST_PROJECT_ID}"
    headers = {"Authorization" : f"Bearer {TODOIST_TOKEN}"}

    status_code = 500

    while status_code is not 200:
        response = task.executor(requests.get, get_tasks_url, headers = headers)
        status_code = response.status_code
        time.sleep(1)
    json = response.json()
    return json

def add_task(item):
    url = "https://api.todoist.com/rest/v2/tasks"
    headers = {"Authorization" : f"Bearer {TODOIST_TOKEN}", "Content-Type" : "application/json"}
    body = {"content" : item, "project_id" : TODOIST_PROJECT_ID}
    status_code = 500

    while status_code is not 200:
        response = task.executor(requests.post, url, headers = headers, json=body)
        status_code = response.status_code
        time.sleep(1)
    if status_code == 200:
        return True
    else:
        return False

def update_task(id, content):
    url = f"https://api.todoist.com/rest/v2/tasks/{id}"
    headers = {"Authorization" : f"Bearer {TODOIST_TOKEN}", "Content-Type" : "application/json"}
    body = {"content" : content}
    status_code = 500

    counter = 0
    while status_code is not 204 and counter < 10:
        response = task.executor(requests.post, url, headers = headers, json=body)
        status_code = response.status_code
        time.sleep(1)
        counter += 1
    if status_code == 204:
        return True
    else:
        return False

def complete_task(id):
    url = f"https://api.todoist.com/rest/v2/tasks/{id}/close"
    headers = {"Authorization" : f"Bearer {TODOIST_TOKEN}"}
    status_code = 500

    counter = 0
    while status_code is not 204 and counter < 10:
        response = task.executor(requests.post, url, headers = headers)
        status_code = response.status_code
        time.sleep(1)
        counter += 1
    if status_code == 204:
        return True
    else:
        return False

@service
def sync_shopping_list():
    tasks = []
    json = get_tasks()
    for item in json:
        tasks.append({"name" : item["content"], "id" : str(item["id"]), "complete" : item["is_completed"]})

    task.executor(write_file.write_json, filename = "/config/.shopping_list.json", content=tasks)
    hass.data["shopping_list"].async_load()

@event_trigger('shopping_list_updated')
def update_shopping_list(action=None, item=None):
    if action == "add":
        add_task(item["name"])
        sync_shopping_list()
    if action == "update" and item["complete"] == False:
        update_task(item["id"],item["name"])
        sync_shopping_list()
    if action == "update" and item["complete"] == True:
        complete_task(item["id"])
        sync_shopping_list()```

See earlier in this thread. That error was fixed by @alexismadd - Sync your Alexa/Todoist shopping list to the Home Assistant shopping list! - #73 by alexismadd

You’ll need to check the code differences to yours, or start again and make the above v2 API changes to his version. Although the blocking call error that I used to get didn’t prevent any syncing.

hey @fenty17 everything works for me i.e. I can sync my shopping list from todoist to HA and also from Alexa to todoist. However I cannot sync whatever I have added to my todoist from Alexa onto my HA shopping list.

What am I doing wrong with this, its making me pull my hair :frowning:

But on @alexismadd the code is the old /v1/ on, I thoutgh I had to change that to /v2/

sorry, im not an expert, im following the stepts, but im getting the following error:

Exception in <file.shopping_list_sync.sync_shopping_list> line 26: json = response.json() ^ ContentTypeError: 0, message='Attempt to decode JSON with unexpected mimetype: text/plain; charset=utf-8', url=URL('https://api.todoist.com/rest/v1/tasks?project_id=2303489826')

i can sync alexa with todoist but im still no able to sync todoist with HA.

please help!

There’s been a couple of fixes made during the course of this thread for updated v2 api calls and blocking error.

I’ve popped the latest shopping_list_sync.py code into github. Use this insetead of the one in OP, add your todoist project id and api token. Rest of the instructions as in the OP.

9 Likes

This fixed it for me too! Thanks!

Hopefully someone might answer this. Is it possible to keep the items in the HA shopping list when you sync them with Alexa etc?

I wanted to share that for the last few weeks my HA install has been freezing every few hours and I couldn’t figure out the reason, and the cause was this script. It was blocking the whole system in a never-ending sleep.

For now I’ve disabled it, I’ll try the second version when I have some time.

Just wanted to add, that I had the same problem as cibernox and also searched for days, maybe weeks what caused the problem.
I just tried the new script and it seems like that fixed it. Won’t know for sure until some days without issues passed, but it’s definetly worth the try, @cibernox !

Yeah it’s pretty ugly if you are stuck on the first version. Better just to disable it until you have the time to fix it properly.

is there an advantage to using aiohttp over the built-in task.executor, which takes the functions out of the IO loop:

https://hacs-pyscript.readthedocs.io/en/latest/reference.html?highlight=task.executor#task-executor

e.g.

response = task.executor(requests.get, url, headers=headers)

Any possibility to do this with a connected o365 calendar, where sharing isnt allowed? I could integrate it to alexa. Would be nice to do the same stuff as the todo list

This is really cool, thanks for making it!

I don’t have my HA instance exposed to the Internet and I’m a bit hesitant to punch a hole in my firewall. Would there be any way to have this poll the Todoist APIs rather than using a webhook? I know that’s less clean / efficient, but according to the Todoist v9 APIs the rule is that you shouldn’t hit the partial sync API more than 450 times in 15 minutes so it seems like hitting them once every few minutes should be okay…

Has anyone gotten to the bottom of why a webhook wont work in todoist?
Anything I do on the shopping list in Home assistant is replicated on the todoist website in around 2 seconds.
Any changes made on the todoist site need a manual sync, at which point the lists sync.
So all working fine apart from todoist not getting a message to HA to trigger the sync. The Automation is fine as if I manually fire it the list syncs too.
What am I missing in Todoist?
I can see in the app setup that the webhook status is “active”
The callback url is my https://nabucasa address82.ui.nabu.casa/api/webhook/-FlgBBIganDsMallLetters
I have all the item watched Events selected

If you get creative you can set up a free AWS account and set up a simple relay. I use API gateway to put messages onto an SQS queue from various endpoints (for different purposes, the todoist webhook is one). I then have a docker inside my LAN running a simple python script that reads the queue and passes on the messages to whoever needs to know (in this case it calls the HASS webhook). The call and message rate is so small you easily stay in the free tier. If anyone is interested I can share more details.

When you manually fire the automation is that from inside Hass or using curl? To rule out any issues with the webhook have you tried firing it from curl if you haven’t already:
curl -X POST <the webhook url>

Well i;'m not sure how but the reboot gods seem to have deemed me worthy. After a few restarts for other updates this seems to be working now.
Thank you for responding though guys.

Is this path still working? I tried several months back and it didnt work for me. My HA just hung up sevral times and i had to backup. Maybe ill give it a new try

Since HA 2023.06 I got this error with this script. Someone else with the same issue?

 Logger: custom_components.pyscript.file.shopping_list_sync
Source: custom_components/pyscript/global_ctx.py:341
Integration: Pyscript Python scripting (documentation, issues)
First occurred: 16:00:09 (14 occurrences)
Last logged: 16:27:14

    Exception in </config/pyscript/shopping_list_sync.py> line 10: import write_file ^ UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9e in position 0: invalid start byte
    Exception in </config/pyscript/shopping_list_sync.py> line 12: write_file = reload(write_file) ^ NameError: name 'write_file' is not defined
    Exception in </config/pyscript/shopping_list_sync.py> line 6: import write_file ^ UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9e in position 0: invalid start byte
    Exception in </config/pyscript/shopping_list_sync.py> line 7: import write_file ^ UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9e in position 0: invalid start byte
    Exception in </config/pyscript/shopping_list_sync.py> line 11: import write_file ^ UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9e in position 0: invalid start byte

1 Like