Jump to content

Introducing AlfreDo, a Workflow for Todoist ✅


Recommended Posts

AlfreDo

An Alfred Workflow for Todoist

Download

image.thumb.png.f202bdb64203b562f651e6ff34ba2795.png

Motivation

- Quickly list, search, and act on your Todoist tasks 
- Add new tasks to Todoist through Alfred

 

Setting up ⚙️

 

Needed
- Alfred 5 with Powerpack license
- A Todoist account
- Python3
 

 

Default settings 
- In Alfred, open the 'Configure Workflow' menu in AlfreDo preferences
     - set the Todoist API token (login into your account, then generate it here)
- Optional:    
    - set the keyword (or hotkey) to show: 
        1. Tasks due today (default: !1)
        2. Overdue (default: !2)
        3. All tasks (default: !3)
    - set the keyword (or hotkey) to force-refresh (default: todoist::refresh)
    - set the keyword (or hotkey) to create a new task (default: !!!)
    - set refresh rate (in days). Default: 1
        - Recommended 0 (refresh every time, slower) or 1 if you use Todoist often from browser, mobile etc. 
        - Database is automatically refreshed when a task is created, completed, or rescheduled.
        - Refresh can be forced using a keyword (default: todoist::refresh) or hotkey.
    - show Karma daily and weekly goals? Default: yes


Basic Usage 📖

 

Searching your tasks 🔍
- launch with keyword or custom hotkey. You can start from 1) tasks due today, 2) tasks overdue, or 3) all tasks
- Use multiple strings, or label/projects to refine search. Use @ to enter one or more labels, # to enter a project. 
- Once a task is selected, you can do one of three things: 
    - enter ↩️ will open the task on Todoist
    - shift-enter↩️ will complete the task
    - ctrl-enter ^↩️ will open a menu to reschedule the task. Choose one of the options, or enter a number of days. You can also use `w` or `m` after the number to enter weeks and months, respectively (e.g. `10w` will reschedule in 10 weeks)
    

Creating new tasks
- launch with keyword (default: !!!) or hotkey. Use `@` to enter one or more labels, `#` to enter a project (Inbox will be used if none entered), due: to enter a due date. As in reschedule, choose one of the options, or enter a number of days. You can also use `w` or `m` after the number to enter weeks and months, respectively (e.g. `10w` will set a due date in 10 weeks)  
- Universal Action: new highlights can be created by selecting text in any app, then launching Universal Actions and selecting Create a new Todoist task


Database refresh 🔄
- will occur according to the rate in days set in AlfreDo preferences, after a task is created, completed, or rescheduled, or...
    - todoist::refresh to force database refresh


Limitations & known issues ⚠️

- None for now, but I have not done extensive testing, let me know if you see anything!

 

Acknowledgments 😀

- Thanks to the Alfred forum community!
- Icons from Flaticon
    - https://www.flaticon.com/free-icon/overdue_6534474
    - https://www.flaticon.com/free-icon/calendar_6816638
    - https://www.flaticon.com/free-icon/project-management_4844342
    - https://www.flaticon.com/free-icon/task_2098402
    
Changelog 🧰

- 05-03-2023: version 0.1


Feedback 🧐

Feedback welcome! If you notice a bug, or have ideas for new features, please feel free to get in touch either here, or on Github.
 

Link to comment
  • 4 weeks later...

glad you find it helpful @Werner Dijkerman, I only implemented the features I used, but I am happy to add new ones! 

On 5/28/2023 at 8:48 AM, Werner Dijkerman said:

How do I set the due time

if you are ok with entering the number of days and then an hour in 24-h format (like due:10-1025), that is straightforward. If you want to enter a full date, plus the time (i.e. 2023-06-10-10:25, that is also possible but it will take me more time because I currently take either the number of days, or one the preset intervals, so I would need to take a standard format date.

 

On 5/28/2023 at 8:48 AM, Werner Dijkerman said:

can I also put the task in a section

if I understand correctly, sections behave like project-specific tags? If so, I can use the same function to get tags, but restrict to the ones in that project. 

 

I am happy to add these features, I might need some help with troubleshooting as I am not too familiar with them.

Edited by giovanni
Link to comment
On 6/1/2023 at 1:37 AM, giovanni said:

glad you find it helpful @Werner Dijkerman, I only implemented the features I used, but I am happy to add new ones! 

if you are ok with entering the number of days and then an hour in 24-h format (like due:10-1025), that is straightforward. If you want to enter a full date, plus the time (i.e. 2023-06-10-10:25, that is also possible but it will take me more time because I currently take either the number of days, or one the preset intervals, so I would need to take a standard format date.

 

if I understand correctly, sections behave like project-specific tags? If so, I can use the same function to get tags, but restrict to the ones in that project. 

 

I am happy to add these features, I might need some help with troubleshooting as I am not too familiar with them.

Thank you for your reply, hugely appreciated!

 

I personally like the 'due:2023-06-10-10:25' pretty much, i like those kind of dates :). I have Todoist linked to my Gmail calender, meaning that when I create a task and only select a date (like tomorrow, or ..) it will be an 'all day' schedule in my calender. The first one is also possible (due:10-1025), but - maybe that is me personally - not that mind friendly (calculating/math).

 

In my "Private" project, I have what Todoist calls "Sections". I have a few, like "Research", "Reviews" & "Books". When I create a new todo for a book that I need to read, I create one in the "Private" project and place it in the "Books" section. This allows me to see that at the moment, I have to buy 6 books atm. From a usage p.o.v. it is indeed something like project-specific tags, or maybe groups.

 

I can always help where needed.

Link to comment

@Werner Dijkerman could you try this version?
- Sections are now supported, both in task search and creation (trigger: ^). Because they are project-specific, it is sufficient to enter the section (i.e. project name not needed when entering a section). If the user enters both a section and then the wrong project, the task will be assigned to the right project (i.e. the project indicated by the user will be ignored).
- Date format: Both in rescheduling and task creation dates can now be in international format, either with (2023-08-15T15:15) or without (2023-08-15) time. 

 

Give it a try and if you don't see problems I will create a new release. 

Edited by giovanni
Link to comment

Thank you! I do see the Sections now. So `!!! ^` and it provides (some, not all) of the sections. That is already helping a lot.

 

Issues that I see so far with Sections:

* I have a section `Reviews` and `Research` in the same project, but only `Research` shows up. (Solved with: `todoist::refresh`)

* I have a section `Schedules` in 2 projects, only 1 shows up when doing `!!! ^`. Even when I rename 1 "Schedules" into something else (like "something), I can not select it.

 

But when I want to add the date: `!!! ^Books 📚 Read something due:2023-08-15T15:15` It won't show up in todoist.

 

While writing this, I noticed that no tasks are added at all. Even a simple one with `!!! #Private blablabla` or `!!! blablabla`.

I checked, my api key is correct, i did the `todoist::refresh` twice and closed todoist as well.

Link to comment

thanks for checking @Werner Dijkerman. Not sure why it is not saving, it seems to be working fine for me, do you see any relevant messages in the debugger? 

Re sections, I checked the browser/desktop UI and they list the sections in the project list (like this: #Project/Section), maybe it is easier to have that (i.e. list #Project and then #Project/Section using the # trigger) instead of 2 separate triggers for project and sections? This should help with sections with the same name across multiple projects

Edited by giovanni
Link to comment

OK @Werner Dijkerman you could not see all the sections because the ones without tasks were hidden. That's because in search mode the app only shows the labels, sections etc that are present in the subset of tasks currently filtered, and I was using the same logic when creating a new task. 

 

So, I have split the logic:

- in search it works like before (only shows projects/sections from the current subset of tasks);

- for new tasks it will show all the projects/sections (including those with 0 tasks) using the # trigger. This should also solve the problem of sections with the same name across projects. 

revised workflow here. Let me know what you think and thanks for your help troubleshooting! 

 

Link to comment

Thank you so far! That overview looks awesome and I do see everything! 🥳

Yes, I now see all sections which is awesome. I added a task in my inbox, that went fine. But now when I want to add it into my section, like this:

 

#Private 🏡/Research 🔎 pizza eten

My "private" project, has "Research" as section and "eating pizza" as a task.

 

I get the error:

[21:07:56.782] AlfreDo[Script Filter] Passing output '🏡/Research 🔎 pizza eten #Private 🏡/Research 🔎 ' to Run Script
[21:07:57.027] ERROR: AlfreDo[Run Script] Traceback (most recent call last):
  File "/Users/wdijkerman/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.2C7310D3-44BF-479B-9EC1-FBD823EF246B/alfredo_ops.py", line 981, in <module>
    main ()
  File "/Users/wdijkerman/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.2C7310D3-44BF-479B-9EC1-FBD823EF246B/alfredo_ops.py", line 973, in main
    createNewTask (taskText,taskLabels,taskProjectID, taskSectionID, myDueDate)
  File "/Users/wdijkerman/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.2C7310D3-44BF-479B-9EC1-FBD823EF246B/alfredo_ops.py", line 293, in createNewTask
    taskLabels = taskLabels.split(',')
AttributeError: 'NoneType' object has no attribute 'split'

I did a test, because I had a lot of "split" with Python myself 😉 is that I now created a project and section without any icons. There I was able to create the task in my new section without any problems:

 

[21:12:30.478] STDERR: AlfreDo[Run Script] b'{"full_sync":true,"sync_status":{"231797cb-9aac-4202-9d6d-pizzae0efd":"ok"},"sync_token":"SomeTokenwhichmihghtbesecret","temp_id_mapping":{"f428d44d-2cb8-4e5f-a143-f5df782b8ea5":"6950082140"}}'

 

Then the 2nd task, was creating a task in this new project/section, with a due date:

 

[21:17:07.504] AlfreDo[Script Filter] Passing output '#Work/Testing due:2023-06-09T10:00 eating pizza' to Run Script
[21:17:08.603] STDERR: AlfreDo[Run Script] b'{"full_sync":true,"sync_status":{"e6d5f6d7-3039-484e-b7a8-0c396c86206a":"ok"},"sync_token":"SomeTokenwhichmihghtbesecret","temp_id_mapping":{"2ed4a983-9890-4ebc-a72d-7eba2bd3ae0f":"6950093094"}}'

 

And that works as well! Nice! Only noticed the STDERR instead of an OK, but it doesn't provide an error and it worked, so - in a way - i don't care 😃 (probably something very minor...)

 

The pleasure is all mine!  

Edited by Werner Dijkerman
Link to comment
2 hours ago, Werner Dijkerman said:

now created a project and section without any icons.

I think the issue is with the space, not the icon. It should work with emojis and without spaces. I don't have project names with spaces so I didn't catch this. I will think of a way to fix it. 

Have you tested the due date format with time? you mentioned it didn't work last time. 

STDERR is just the output channel, it is not necessarily an error, and in fact the response from the Todoist server is clean. 

Edited by giovanni
Link to comment
  • 4 months later...
  • 2 weeks later...
  • 1 month later...

Hi! Brand new user here. I seem to have it all set up correctly — but nothing happens when I hit shift + return once in the create a new task menu. Any idea why this would happen?

 

And I have up to date python, I have the API code, aI have the powerpack

 

Edited by Ben DW
Link to comment
  • 3 weeks later...

Hey @giovanni this is great! I'm a long time Alfred user dipping my toes in todoist and this workflow will be very helpful. 

I'm not sure why but upon initial installation Todoist did not detect any of my today and / or late tasks. However, after I moved a few tasks around by changing due dates, it started llisting my today tasks and overdue tasks.

However, it won't list all tasks (!3 will just revert to default search for the string "!3")

 

Here is the debug log from Alfred: 


 

[08:03:21.791] Logging Started...
[08:03:27.802] AlfreDo[Script Filter] Queuing argument '(null)'
[08:03:27.986] AlfreDo[Script Filter] Script with argv '(null)' finished
[08:03:27.992] ERROR: AlfreDo[Script Filter] Code 1: 0 days from last update
[]
[]
[]
Traceback (most recent call last):
  File "/Users/paul/Dropbox/Alfred.alfredpreferences/workflows/user.workflow.3922CD67-5DB7-48BC-ACE9-AB1517287EF6/alfredo-query.py", line 421, in <module>
    main ()
  File "/Users/paul/Dropbox/Alfred.alfredpreferences/workflows/user.workflow.3922CD67-5DB7-48BC-ACE9-AB1517287EF6/alfredo-query.py", line 331, in main
    dueDate = datetime.strptime(task ['due']['date'], "%Y-%m-%dT%H:%M:%S")
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/_strptime.py", line 568, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/_strptime.py", line 352, in _strptime
    raise ValueError("unconverted data remains: %s" %
ValueError: unconverted data remains: Z

 

I'm not sure what's going on with the Code 1 : 0 days from last update?

Thanks for your help!

 

Edited by seishonagon
bug still present - added debug log from Alfred
Link to comment
  • 1 month later...

Hi, I was excited to find this workflow but I can't get it to work. I installed Python 3 from here: https://www.python.org/downloads/ and added my Todoist token. 

 

Below is what I see in the debugger. Thanks for any help you can provide. 

 

[06:37:20.899] AlfreDo[Script Filter] Queuing argument 'T'

[06:37:21.000] AlfreDo[Script Filter] Queuing argument 'Te'

[06:37:21.088] AlfreDo[Script Filter] Script with argv 'T' finished

[06:37:21.089] ERROR: AlfreDo[Script Filter] Code 1: Traceback (most recent call last):

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 1147, in <module>

    main ()

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 1143, in main

    parseNewTask (MY_INPUT)

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 394, in parseNewTask

    allTasks, mySections, myProjects, myStats, myUser = readTodoistData()

                                                        ^^^^^^^^^^^^^^^^^

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 279, in readTodoistData

    with open(MY_DATABASE,'r') as myFile:

         ^^^^^^^^^^^^^^^^^^^^^

FileNotFoundError: [Errno 2] No such file or directory: '/Users/work/Library/Application Support/Alfred/Workflow Data/giovanni-alfreDo/allData.json'

[06:37:21.192] AlfreDo[Script Filter] Queuing argument 'Tes'

[06:37:21.231] AlfreDo[Script Filter] Script with argv 'Te' finished

[06:37:21.231] ERROR: AlfreDo[Script Filter] Code 1: Traceback (most recent call last):

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 1147, in <module>

    main ()

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 1143, in main

    parseNewTask (MY_INPUT)

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 394, in parseNewTask

    allTasks, mySections, myProjects, myStats, myUser = readTodoistData()

                                                        ^^^^^^^^^^^^^^^^^

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 279, in readTodoistData

    with open(MY_DATABASE,'r') as myFile:

         ^^^^^^^^^^^^^^^^^^^^^

FileNotFoundError: [Errno 2] No such file or directory: '/Users/work/Library/Application Support/Alfred/Workflow Data/giovanni-alfreDo/allData.json'

[06:37:21.368] AlfreDo[Script Filter] Script with argv 'Tes' finished

[06:37:21.369] ERROR: AlfreDo[Script Filter] Code 1: Traceback (most recent call last):

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 1147, in <module>

    main ()

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 1143, in main

    parseNewTask (MY_INPUT)

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 394, in parseNewTask

    allTasks, mySections, myProjects, myStats, myUser = readTodoistData()

                                                        ^^^^^^^^^^^^^^^^^

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 279, in readTodoistData

    with open(MY_DATABASE,'r') as myFile:

         ^^^^^^^^^^^^^^^^^^^^^

FileNotFoundError: [Errno 2] No such file or directory: '/Users/work/Library/Application Support/Alfred/Workflow Data/giovanni-alfreDo/allData.json'

[06:37:21.389] AlfreDo[Script Filter] Queuing argument 'Test'

[06:37:21.538] AlfreDo[Script Filter] Script with argv 'Test' finished

[06:37:21.538] ERROR: AlfreDo[Script Filter] Code 1: Traceback (most recent call last):

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 1147, in <module>

    main ()

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 1143, in main

    parseNewTask (MY_INPUT)

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 394, in parseNewTask

    allTasks, mySections, myProjects, myStats, myUser = readTodoistData()

                                                        ^^^^^^^^^^^^^^^^^

  File "/Users/work/Dropbox (Maestral)/Alfred/Alfred.alfredpreferences/workflows/user.workflow.139248B8-5266-4B56-94D2-46591E199731/alfredo_ops.py", line 279, in readTodoistData

    with open(MY_DATABASE,'r') as myFile:

         ^^^^^^^^^^^^^^^^^^^^^

FileNotFoundError: [Errno 2] No such file or directory: '/Users/work/Library/Application Support/Alfred/Workflow Data/giovanni-alfreDo/allData.json'

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...