Not a zope post. Spent a few hours of my long leave to code a simplistic todoist api python wrapper.
Todoist.com is a web 2.0 todo site where users can register and set their to do lists. Todoist.com supports groupings, labels, tasks and subtasks and more. I have not yet used it to the max to really review it. However, limited use has shown its usefulness.
The python wrapper is just a straight copy of the todoist api. I hope to try and build a simple python app for s60, and maybe a desktop one or an interface to basket, too. I hope this is not just piped dreams :P.
A few problems:
- can't indent, therefore can't do subtask via api
- can't display all items; have to getCompletedItems and getUncompletedItems and total 'em up
- can't add items to *, or groups. So, prepare our groupings via the web and add projects/items under groupings.
Have a look at the wrapper and comment, please.
import simplejson as json
import urllib
class todois(object):
def __init__(self, token):
self.token = token
self.baseurl = 'http://todoist.com/API/'
def getProjects(self):
"""retrun list of projects
http://todoist.com/API/getProjects?token=fb5f22601ec566e48083213f7573e908a7a272e5
"""
xtra = 'getProjects?token='
tapi = urllib.urlopen(self.baseurl+xtra+self.token)
return json.load(tapi)
def getProject(self, project_id):
"""return items
http://todoist.com/API/getProject?project_id=22073&token=fb5f22601ec566e48083213f7573e908a7a272e5
"""
xtra = 'getProject?token=%s&project_id=%s' % (self.token, project_id)
tapi = urllib.urlopen(self.baseurl+xtra)
return json.load(tapi)
def getallLabels(self):
"""return all labels
http://todoist.com/API/getLabels?token=fb5f22601ec566e48083213f7573e908a7a272e5
"""
xtra = 'getLabels?token=%s' % self.token
tapi = urllib.urlopen(self.baseurl + xtra)
return json.load(tapi)
def getUncompletedItems(self, project_id):
"""return list of all uncompeted
http://todoist.com/API/getUncompletedItems?project_id=22073&token=fb5f22601ec566e48083213f7573e908a7a272e5
"""
xtra = 'getUncompletedItems?project_id=%s&token=%s' % (project_id, self.token)
tapi = urllib.urlopen(self.baseurl+xtra)
return json.load(tapi)
def getCompletedItems(self, project_id, offset=0):
"""return completed items
http://todoist.com/API/getCompletedItems?project_id=22073&offset=0&token=fb5f22601ec566e48083213f7573e908a7a272e5
"""
pass
def addItems(self, project_id, content, date_string='',priority=1):
"""add item
http://todoist.com/API/addItem?content=Test&project_id=22073&priority=1&token=fb5f22601ec566e48083213f7573e908a7a272e5
"""
xtra='addItem?content=%s&project_id=%s&priority=%s&token=%s' % (urllib.quote(content), project_id, priority, self.token)
tapi = urllib.urlopen(self.baseurl + xtra)
return json.load(tapi)
def updateItem(self, project_id, content, date_string='',priority=1):
"""update item
http://todoist.com/API/updateItem?id=210873&content=TestHello&token=fb5f22601ec566e48083213f7573e908a7a272e
"""
xtra = 'updateItem?id=%s&content=%s&token=%s' % (project_id, content,
date_string, priority)
tapi = urllib.urlopen(self.baseurl + xtra)
return json.load(tapi)
def deleteItem(self, project_id, ids):
"""delete"""
xtra = 'deleteItems?project_id=%s&ids=%s&token=%s' % (project_id,
ids, self.token)
tapi = urllib.urlopen(self.baseurl + xtra)
#return json.load(tapi)
def query(self, qlist):
"""http://todoist.com/API/query?queries=["2007-4-29T10:13","overdue","p1","p2"]&token=fb5f22601ec566e48083213f7573e908a7a272e5
"""
xtra = 'query?queries=%s&token=%s' % (qlist, self.token)
tapi = urllib.urlopen(self.baseurl+xtra)
try:
res = json.load(tapi)
except ValueError, e:
res = {}
return res
Here's a screen shot of my
And here's what the wrapper does:
In [1]: import todoist
In [2]: x=todoist.todois(token='yourtokenhere')
In [3]: projects=x.getProjects()
In [4]: projects
Out[4]:
[{'cache_count': 0,
'collapsed': 0,
'color': '#ff8581',
'id': 510635,
'indent': 1,
'item_order': 1,
'name': '* personal',
'user_id': 97366},
{'cache_count': 2,
'collapsed': 0,
'color': '#ff8581',
'id': 510671,
'indent': 2,
'item_order': 2,
'name': 'proj 2',
'user_id': 97366},
{'cache_count': 0,
'collapsed': 0,
'color': '#ff8581',
'id': 510670,
'indent': 2,
'item_order': 3,
'name': 'proj 1',
'user_id': 97366},
{'cache_count': 1,
'collapsed': 0,
'color': '#ff8581',
'id': 510636,
'indent': 1,
'item_order': 4,
'name': '* work',
'user_id': 97366},
{'cache_count': 1,
'collapsed': 0,
'color': '#ff8581',
'id': 510637,
'indent': 1,
'item_order': 5,
'name': 'others',
'user_id': 97366}]
In [5]: todo = x.getUncompletedItems(project_id='510637')
In [6]: todo
Out[6]:
[{'chains': None,
'checked': 0,
'children': None,
'collapsed': 0,
'content': 'send kids to school',
'date_string': '',
'due_date': None,
'has_notifications': 0,
'id': 4025800,
'in_history': 0,
'indent': 1,
'is_dst': 0,
'item_order': 1,
'labels': [59094],
'mm_offset': 480,
'priority': 4,
'project_id': 510637,
'user_id': 97366}]
In [7]: x.getallLabels()
Out[7]:
{'label1': {'color': 0,
'count': 2,
'id': 59094,
'name': 'label1',
'uid': 97366},
'label2': {'color': 0,
'count': 0,
'id': 59095,
'name': 'label2',
'uid': 97366}}
In [8]: x.query('["viewall"]')
Out[8]:
[{'data': [{'cache_count': 2,
'completed_count': 4,
'history_max_order': 4,
'project_id': 510671,
'uncompleted': [{'chains': None,
'checked': 0,
'children': None,
'collapsed': 0,
'content': 'task 1 proj 1',
'date_string': '',
'due_date': None,
'has_notifications': 0,
'id': 3980454,
'in_history': 0,
'indent': 1,
'is_dst': 0,
'item_order': 1,
'labels': [59094],
'mm_offset': 480,
'priority': 1,
'project_id': 510671,
'user_id': 97366},
{'chains': None,
'checked': 0,
'children': None,
'collapsed': 0,
'content': 'task 2 proj 1',
'date_string': '30. Jan 2009',
'due_date': 'Fri Jan 30 23:59:59 2009',
'has_notifications': 0,
'id': 3980455,
'in_history': 0,
'indent': 1,
'is_dst': 0,
'item_order': 2,
'labels': [],
'mm_offset': 480,
'priority': 1,
'project_id': 510671,
'user_id': 97366}]},
{'cache_count': 1,
'completed_count': 0,
'history_max_order': None,
'project_id': 510636,
'uncompleted': [{'chains': None,
'checked': 0,
'children': None,
'collapsed': 0,
'content': 'this is a test',
'date_string': '',
'due_date': None,
'has_notifications': 0,
'id': 4026204,
'in_history': 0,
'indent': 1,
'is_dst': 0,
'item_order': 1,
'labels': [],
'mm_offset': 480,
'priority': 4,
'project_id': 510636,
'user_id': 97366}]},
{'cache_count': 1,
'completed_count': 2,
'history_max_order': 3,
'project_id': 510637,
'uncompleted': [{'chains': None,
'checked': 0,
'children': None,
'collapsed': 0,
'content': 'send kids to school',
'date_string': '',
'due_date': None,
'has_notifications': 0,
'id': 4025800,
'in_history': 0,
'indent': 1,
'is_dst': 0,
'item_order': 1,
'labels': [59094],
'mm_offset': 480,
'priority': 4,
'project_id': 510637,
'user_id': 97366}]}],
'type': 'viewall'}]
In [9]: x.query('["@label1"]')
Out[9]:
[{'data': [{'chains': None,
'checked': 0,
'children': None,
'collapsed': 0,
'content': 'send kids to school',
'date_string': '',
'due_date': None,
'has_notifications': 0,
'id': 4025800,
'in_history': 0,
'indent': 1,
'is_dst': 0,
'item_id': 4025800,
'item_label.id': 820970,
'item_order': 1,
'l_order': 1,
'label_id': '59094',
'labels': [59094],
'mm_offset': 480,
'priority': 4,
'project_id': 510637,
'uid': 97366,
'user_id': 97366},
{'chains': None,
'checked': 0,
'children': None,
'collapsed': 0,
'content': 'task 1 proj 1',
'date_string': '',
'due_date': None,
'has_notifications': 0,
'id': 3980454,
'in_history': 0,
'indent': 1,
'is_dst': 0,
'item_id': 3980454,
'item_label.id': 820966,
'item_order': 1,
'l_order': 1,
'label_id': '59094',
'labels': [59094],
'mm_offset': 480,
'priority': 1,
'project_id': 510671,
'uid': 97366,
'user_id': 97366}],
'type': 'label'}]
Now, the hard part is coming up with how to display these. I'll probably come up with a simple interface initially; list all uncompleted items in all projects, and an add item, search button.
I welcome ideas and suggestions.
Trackback is http://myzope.kedai.com.my/blogs/kedai/227/tbping
nice, was just looking into creating something like this...amazing that you just posted this...I will try it out and let you know how it goes
great! see if it's at all useful and share your apps too :)
