Part 2 - Todo Lists!

Lets build our second skill, this time something more useful - todo lists


In this part we will create our first proper, useful skill.

This skill will allow us to:

  • create a todo list that we can add items to
  • ask our AI to tell us whats on our list
  • remove items from the list

Table of Contents

Video on YouTube

I created a popular video series on YouTube, which goes over each of the steps below. The second video part is featured below.

Todo lists

Lets break down the task of creating our new skill into the following parts. This process is call decomposition, because we are de-composing the parts that make up the code:

  • Create an Todo-item class - to model a single todo item
  • Create a Todo-class - to model a list of todo items
  • Add items
  • List items
  • Remove items
  • Iterate items - make the list iterable using generators
  • Add a metaclass: Len - to return number of items in the list

Example Conversational flow

It helps to start with the end in mind, below is what we want a typical conversation to look like:

Conversation flow


Grab a copy of version 2 of our code here:

Our skill is made up of the following classes:

  • Status - this is used to define a number of states our item can be in
  • Priority - this is used to define a number of priorities our item can have
  • Item - represents a todo item
  • Todo - contains a list of our todo items, and has the functions for adding, removing and retrieving items

from datetime import date
from enum import Enum
from uuid import uuid4

class Status(Enum):
    """ The Todo Statuses """
    IN_PROGRESS =  1

class Priority(Enum):
    LOW = 0
    MEDIUM = 1
    HIGH = 2

class Item():
    __creation_date =
    __title = "empty"
    __status = Status.NOT_STARTED
    __priority = Priority.LOW
    __flag = False 
    __url = ""
    __due_date = date
    __icon = ""
    __state = False
    __notes = ""

    def __init__(self, title:str=None):
        if title is not None:
            self.__title = title
        self.__id = str(uuid4())

    def title(self):
        return self.__title

    def title(self, value:str):
        self.__title = value

    def priority(self):
    def priority(self, value:Priority):
        self.__priority = value

    def creation_date(self):
        return self.__creation_date

    def creation_date(self, value):
        self.__creation_date = value

    def age(self):
        return self.__creation_date -
    def status(self):
    def status(self, value:Status):
        self.__status = value

    def id(self):
        return self.__id
    def flag(self):
        return self.__flag

    def flag(self, value:bool):
        self.__flag = value

    def url(self):
        return self.__url

    def url(self, value:str):
        self.__url = value
    def due_date(self):
        return self.__due_date

    def due_date(self, value:date):
        self.__due_date = value
    def icon(self):
        return self.__icon

    def icon(self, value:str):
        self.__icon = value

    def state(self):
        return self.__state

    def state(self, value:bool):
        self.__state = value

    def notes(self):
        return self.__notes

    def notes(self, value:str):
        self.__value = value

class Todo():
    __todos = []

    def __init__(self):
        print("new todo list created")
        self._current = -1

    def __iter__(self):
        return self

    def __next__(self):
        if self._current < len(self.__todos) -1 :
            self._current += 1
            return self.__todos[self._current]
            self._current = -1
        raise StopIteration

    def __len__(self):
        """ Returns the number of items in the Todo List """
        return len(self.__todos)

    def new_item(self, item:Item):
    def items(self)->list:
        return self.__todos

    def show(self):
        for item in self.__todos:
            print(item.title, item.status, item.priority, item.age)
    def show(cls):
        print("Todo Items")
        count = 1
        if len(cls.__todos) == 0:
            print("No items in list!")
            for item in cls.__todos:
                print(count, item.title, item.status, item.priority, item.age,
                count += 1 

    def remove_item(self, uuid:str=None, title:str=None)->bool:
        if title is None and uuid is None:
            print("You need to provide some details for me to remote it, either UUID or title")
        if uuid is None and title:
            for item in self.__todos:
                if item.title == title:
                    # del self.__todos[item
                    return True
            print("Item with title", title, 'not found')
            return False
        if uuid:
            return True

Lets update our to include the new skill and some commands for using it.

import pyjokes
from ai import AI
from todo import Todo, Item

alf = AI()
todo = Todo()
# item = Item(title="get shopping")
# item2 = Item("potatoes")
# todo.new_item(item)
# todo.new_item(item2)

def joke():
    funny = pyjokes.get_joke()

def add_todo()->bool:
    item = Item()
    alf.say("Tell me what to add to the list")
        item.title = alf.listen()
        message = "Added" + item.title
        return True
        print("oops there was an error")
        return False
def list_todos():
    if len(todo) > 0:
        alf.say("Here are your to do's")
        for item in todo:
        alf.say("The list is empty!")

def remove_todo()->bool:
    alf.say("Tell me which item to remove")
        item_title = alf.listen()
        message = "Removed" + item_title
        return True
        print("opps there was an error")
        return False
command = ""
while True and command != "goodbye":
        command = alf.listen()
        command = command.lower()
        print("oops there was an error")
        command = ""
    print("command was:", command)

    if command == "tell me a joke":
        command = ""
    if command in ["add to-do","add to do", "add item"]:
        command = ""
    if command in ["list todos", "list todo", "list to do", "list to-do", "list to do's",'list items']:
        command = ""
    if command in ["remove todo", "remove item", "mark done", "remove todos", "remove to-do", "remove to do's"]:

alf.say("Goodbye, I'm going to sleep now")

Did you find this content useful?

If you found this high quality content useful please consider supporting my work, so I can continue to create more content for you.

I give away all my content for free: Weekly video content on YouTube, 3d Printable designs, Programs and Code, Reviews and Project write-ups, but 98% of visitors don't give back, they simply read/watch, download and go. If everyone who reads or watches my content, who likes it, helps fund it just a little, my future would be more secure for years to come. A price of a cup of coffee is all I ask.

There are a couple of ways you can support my work financially:

If you can't afford to provide any financial support, you can also help me grow my influence by doing the following:

Thank you again for your support and helping me grow my hobby into a business I can sustain.
- Kevin McAleer