Todo list: Check if an item exists

I’ve just started using the todo list. It would be great if we could check if an item is already added.

+1. Inability to check means that using todo.remove_item potentially throws an error, and also appears as though todo.remove_item doesn’t handle the continue_on_error: true modifier either. Found I can work around this by executing in parallel, but should either have the ability to check or otherwise gracefully handle the error.

2 Likes

I think to go along with this I would like the ability to check the status of an item. For example, to know if an automation should tell me if should do a specific item on the list (and OP could allow me to verify if it exists or not)

Todo API is a bit strange.

Take update_item, for example. It uses “item” attribute to locate the item.
But you can have two items with the same “item” value. In this case, it will just pick random one.

You also may not have an item with specific “item” attribute. In this case you will get an exception ValueError: Unable to find To-do item ‘NEW ITEM’ logged in system log, not return value “doesn’t exist”, for example.

Apart from having a “find” method, maybe a todo list should have an option for items to be unique? I know I don’t want “BUY MILK” 10 x on my list.
Plus, update_item, the way it is constructed, would make sense.

In this case, add_item will throw an error when adding existing item. Which is fine. Or better yet, return “already exist”, so system log does not get polluted with exceptions. Also, this gives you a chance to call update_item, if needed.

I haven’t updated HA to the latest version yet and I’m wondering if maybe this problem no longer occurs?
It would be nice if each task was an attribute. Then it would be easy to determine whether a given task already exists.

I’m using a small helper script to check if an item with the specified title exists. it returns a boolean and if the item exists, the item itself.

alias: "Todo: Item exists"
sequence:
  - service: todo.get_items
    target:
      entity_id: "{{ list }}"
    response_variable: todo
  - variables:
      result: >
        {% set x = (item in todo[list]['items'] | map(attribute='summary')) %}
        {% set item = todo[list]['items'] | selectattr('summary', 'eq', item) |
        list | first | default([]) %} {{ {'exists': x, 'item': item} }}
  - stop: Finished
    response_variable: result
mode: single
icon: mdi:checkbox-marked-circle-auto-outline
fields:
  item:
    selector:
      text: null
    name: Item
    description: The todo item to check
    required: true
  list:
    selector:
      entity:
        filter:
          - integration: todo
    name: List
    required: true
    description: The todo list entity

Response

exists: true
item:
  summary: Clean the coffee machine
  uid: e1f8ded2-9d7c-11ee-925c-e45f018f63e6
  status: needs_action
  due: "2024-01-11"
  description: Clean the coffee machine internals, the drip trays and the exterior
{% set t = 'Medication' %}
{% set j = {
  "todo.andy_s_tasks": {
    "items": [
      {
        "summary": "take stomach protector",
        "uid": "WWg3a01sQ3Y0OUwzZ01saw",
        "status": "needs_action",
        "due": "2024-01-08"
      },
      {
        "summary": "Check Medication",
        "uid": "cnYxcktOSFc0djVheTV5Zg",
        "status": "needs_action",
        "due": "2024-01-08"
      },
      {
        "summary": "Make Vitamin C Drink",
        "uid": "RE9rUFZfR0JHc3FXS1E4Sw",
        "status": "needs_action",
        "due": "2024-01-08"
      },
      {
        "summary": "Wash Feet",
        "uid": "Wm53V3hJQzRrU196OEhscg",
        "status": "needs_action",
        "due": "2024-01-07"
      },
      {
        "summary": "Empty Bins",
        "uid": "Tm5PS1hpT3Ffd2VCYWdrNg",
        "status": "needs_action",
        "due": "2024-01-04"
      },
      {
        "summary": "Hoover a room",
        "uid": "SzB2R0IwTWZfdkdodlZrVg",
        "status": "needs_action",
        "due": "2024-01-04"
      }
    ]
  }
}
 %}
{% set j = j['todo.andy_s_tasks']['items'] %}
{{ j|selectattr('summary','search','Medication')|list }}

returns:

[{'summary': 'Check Medication', 'uid': 'cnYxcktOSFc0djVheTV5Zg', 'status': 'needs_action', 'due': '2024-01-08'}]

and if it doesn’t exist - it returns [] (a list of count 0)

Just to be clear - it only needs one line:

{% set found =  todo['todo.my_todo_list']['items']|selectattr('summary','search','my search text')|list %}

found|list|count will either be 0 if the item is not found, or a count over 0 if one or more entries matching the search were found.
If you need to update the item - you have all it’s data:

{% set todo_name, todo_due_date = found[0]['summary'], found[0]['due'] %}
1 Like

can you please add the automation that sending the data to the script please?

We really need something to iteract better throught the items of a todo-list.
I need a script to DELETE REPEATED ENTRIES in a todo-list; maybe something that got the source list, then created a new list, and then add one by one checking if there are duplicates, and then replacing the old list with the new one (just a suggestion / thought). I also need to remove similar items, like for instance, "Coffee " and “coffee” or “Coffeé”, standarizing the list in some way (maybe capitalize the first letter of all items).
Can someone PLEASE help me with this??? Can this be done? It is something I need really bad… lol

PS: I cannot use the command_line solution, because my list is not a .json file, it is created by the google_keep_sync integration. I can’t even locate this list in my files, including .storage…

Thanks, in advance!