2 Wrapper for Remember The Milk API
10 return "/".join(rturl.split(r"\/"))
13 class RtMilkManager(object):
15 Interface with rememberthemilk.com
17 API_KEY = '71f471f7c6ecdda6def341967686fe05'
18 SECRET = '7d3248b085f7efbe'
20 def __init__(self, username, password, token):
21 self._username = username
22 self._password = password
25 self._rtm = rtmapi.RTMapi(self._username, self.API_KEY, self.SECRET, token)
27 resp = self._rtm.timelines.create()
28 self._timeline = resp.timeline
31 def get_projects(self):
32 if len(self._lists) == 0:
33 self._populate_projects()
35 for list in self._lists:
38 def get_project(self, projId):
39 proj = [proj for proj in self.get_projects() if projId == proj["id"]]
40 assert len(proj) == 1, "%r / %r" % (proj, self._lists)
43 def get_project_names(self):
44 return (list["name"] for list in self.get_projects)
46 def lookup_project(self, projName):
48 From a project's name, returns the project's details
50 todoList = [list for list in self.get_projects() if list["name"] == projName]
51 assert len(todoList) == 1, "Wrong number of lists found for %s, in %r" % (projName, todoList)
54 def get_locations(self):
55 rsp = self._rtm.locations.getList()
56 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
61 ("longitude", t.longitude),
62 ("latitude", t.latitude),
63 ("address", t.address),
65 for t in rsp.locations
69 def get_tasks_with_details(self, projId):
70 for taskSeries in self._get_taskseries(projId):
71 for task in self._get_tasks(taskSeries):
72 taskId = self._pack_ids(projId, taskSeries.id, task.id)
73 priority = task.priority if task.priority != "N" else ""
77 "name": taskSeries.name,
78 "url": fix_url(taskSeries.url),
79 "locationId": taskSeries.location_id,
81 "isCompleted": len(task.completed) != 0,
82 "completedDate": task.completed,
84 "estimate": task.estimate,
85 "notes": list(self._get_notes(taskSeries.notes)),
88 def get_task_details(self, taskId):
89 projId, seriesId, taskId = self._unpack_ids(taskId)
90 for taskSeries in self._get_taskseries(projId):
91 curSeriesId = taskSeries.id
92 if seriesId != curSeriesId:
94 for task in self._get_tasks(taskSeries):
96 if task.id != curTaskId:
101 "name": taskSeries.name,
102 "url": fix_url(taskSeries.url),
103 "locationId": taskSeries.location_id,
105 "isCompleted": task.completed,
106 "completedDate": task.completed,
107 "priority": task.priority,
108 "estimate": task.estimate,
109 "notes": list(self._get_notes(taskSeries.notes)),
113 def add_task(self, projId, taskName):
114 rsp = self._rtm.tasks.add(
115 timeline=self._timeline,
119 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
120 seriesId = rsp.list.taskseries.id
121 taskId = rsp.list.taskseries.task.id
122 name = rsp.list.taskseries.name
124 return self._pack_ids(projId, seriesId, taskId)
126 def set_project(self, taskId, newProjId):
127 projId, seriesId, taskId = self._unpack_ids(taskId)
128 rsp = self._rtm.tasks.moveTo(
129 timeline=self._timeline,
131 to_list_id=newProjId,
132 taskseries_id=seriesId,
135 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
137 def set_name(self, taskId, name):
138 projId, seriesId, taskId = self._unpack_ids(taskId)
139 rsp = self._rtm.tasks.setName(
140 timeline=self._timeline,
142 taskseries_id=seriesId,
146 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
148 def set_duedate(self, taskId, dueDate):
149 projId, seriesId, taskId = self._unpack_ids(taskId)
150 rsp = self._rtm.tasks.setDueDate(
151 timeline=self._timeline,
153 taskseries_id=seriesId,
158 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
160 def set_priority(self, taskId, priority):
164 priority = str(priority)
165 projId, seriesId, taskId = self._unpack_ids(taskId)
167 rsp = self._rtm.tasks.setPriority(
168 timeline=self._timeline,
170 taskseries_id=seriesId,
174 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
176 def complete_task(self, taskId):
177 projId, seriesId, taskId = self._unpack_ids(taskId)
179 rsp = self._rtm.tasks.complete(
180 timeline=self._timeline,
182 taskseries_id=seriesId,
185 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
190 >>> RtMilkManager._pack_ids(123, 456)
193 return "-".join((str(id) for id in ids))
196 def _unpack_ids(ids):
198 >>> RtMilkManager._unpack_ids("123-456")
201 return ids.split("-")
203 def _get_taskseries(self, projId):
204 rsp = self._rtm.tasks.getList(
207 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
208 # @note Meta-projects return lists for each project (I think)
209 rspTasksList = rsp.tasks.list
211 if not isinstance(rspTasksList, list):
212 rspTasksList = (rspTasksList, )
214 for something in rspTasksList:
217 except AttributeError:
220 if isinstance(something.taskseries, list):
221 somethingsTaskseries = something.taskseries
223 somethingsTaskseries = (something.taskseries, )
225 for taskSeries in somethingsTaskseries:
228 def _get_tasks(self, taskSeries):
229 if isinstance(taskSeries.task, list):
230 tasks = taskSeries.task
232 tasks = (taskSeries.task, )
236 def _get_notes(self, notes):
239 elif isinstance(notes.note, list):
242 notes = (notes.note, )
247 body = getattr(note, "$t")
254 def _populate_projects(self):
255 rsp = self._rtm.lists.getList()
256 assert rsp.stat == "ok", "Bad response: %r" % (rsp, )
262 ("isVisible", not int(t.archived)),
263 ("isMeta", not not int(t.smart)),
265 for t in rsp.lists.list