def add_tasks_todoist(project_name: str, tasks: List[Task]): # Authenticate with the todoist API api_token = open("todoist_token.txt").read() api = TodoistAPI(api_token) api.sync() # Find the uni project or create it projects = api.state["projects"] projects = list(filter(lambda p: p["name"] == project_name, projects)) if len(projects) != 0: project_id = projects[0]["id"] else: procject = api.projects.add(project_name) api.commit() project_id = procject["id"] # Add the tasks for task in tasks: api.items.add( task.text, project_id=project_id, due={"date": task.duedate.strftime("%Y-%m-%d")}, ) print(task) api.commit()
def todoist_reading_list(handler=None): todoist = TodoistAPI(get_credential('todoist_token')) todoist.sync() reading_list = t_utils.get_project_by_name(todoist, 'reading list') categories = t_utils.get_child_projects(todoist, reading_list) for task in todoist.state['items']: for project in categories: if task['project_id'] == project['id']: content = task['content'] logging.info(content) m = re.search(r'\[([^\[]+)\]\((.*)\)', content) # The todoist app stores links as either a markdown formatted link or "title - url" # if markdown links fail, try to parse the "title - url" format. if m: logging.info("markdown group") title = m.group(1) url = m.group(2) logging.info(title) logging.info(url) else: logging.info("hyphen group") content_components = content.split(" - ") if len(content_components) > 1: title = ''.join(content_components[:-1]) url = content_components[-1].strip() logging.info(title) logging.info(url) else: task.update(content="FAILED TO PARSE: " + content) task.move(parent_id=reading_list['id']) comments = t_utils.get_comments_for_task(todoist, task) article = article_parser.parse_url(url) data = { 'url': url, 'title': title, 'summary': article.summary, 'keywords': article.keywords, 'text': article.text, 'published_date': article.publish_date, 'notes': comments, 'category': project['name'] } handler.publish('archive_article', url, data) task.complete() todoist.commit()
def add_issue_to_todoist(event=None, handler=None): todoist = TodoistAPI(get_credential('todoist_token')) todoist.sync() issue_project = t_utils.get_project_by_name(todoist, 'issues') r = event.data todoist.items.add( '{} [#{}]({})'.format(r['title'], r['number'], r['html_url']), project_id=issue_project['id'], ) # todo close todos for prs/issues that are no longer active todoist.commit()
def add_mention_to_todoist(event=None, handler=None): todoist = TodoistAPI(get_credential('todoist_token')) todoist.sync() mention_project = t_utils.get_project_by_name(todoist, 'GH Mentions') r = event.data todoist.items.add( 'GH Mention - {} [#{}]({})'.format(r['title'], r['number'], r['url']), # project_id=mention_project['id'], # auto_reminder=True, # due={"string": "next workday at 9am"}, priority=4) # todo close todos for prs/issues that are no longer active todoist.commit()
def add_issue_to_todoist(event=None, handler=None): todoist = TodoistAPI(get_credential('todoist_token')) todoist.sync() issue_project = None for p in todoist.state['projects']: if p['name'].lower() == 'issues': issue_project = p break r = event.data todoist.items.add( '{} [#{}]({})'.format(r.title, r.number , r.html_url), project_id=issue_project['id'], ) # todo close todos for prs/issues that are no longer active todoist.commit()
def add_pr_to_todoist(event=None, handler=None): todoist = TodoistAPI(get_credential('todoist_token')) todoist.sync() review_project = None for p in todoist.state['projects']: if p['name'].lower() == 'review requests': review_project = p break r = event.data todoist.items.add('{} [{} #{}]({})'.format(r.title, r.base.repo.full_name, r.number, r.html_url), project_id=review_project['id'], auto_reminder=True, due={"string": "next workday at 9am"}, priority=4) # todo close todos for prs/issues that are no longer active todoist.commit()
def main(args=None): """Console script for greminders2todoist.""" flow = MyInstalledAppFlow.from_client_secrets_file('client.json', SCOPES) creds: Credentials = flow.run_local_server(port=3423) api = TodoistAPI(creds.token) api.sync() tree: _ElementTree = etree.parse(open('./Reminders.html'), etree.HTMLParser()) pprint(scan_fields(tree)) rows = [ dict(type='task', content=task.title, priority=4, indent=None, author=None, responsible=None, date=proc_date(task), date_lang='en', timezone=None) for task in gen_tasks(tree) if task.state != 'archived' and ( task.recurrence or task.due and task.due > datetime.now()) ] with open('out.csv', 'w') as outfile: writer = csv.DictWriter(outfile, [ 'type', 'content', 'priority', 'indent', 'author', 'responsible', 'date', 'date_lang', 'timezone' ]) writer.writeheader() writer.writerows(rows) [inbox] = [p for p in api.state['projects'] if p['name'] == 'Inbox'] for task in rows: api.items.add(task['content'], inbox['id'], date_string=task['date']) api.commit() return 0
def add_pr_to_todoist(event=None, handler=None): todoist = TodoistAPI(get_credential('todoist_token')) todoist.sync() # review_project = t_utils.get_project_by_name(todoist, 'review requests') r = event.data title = 'PR' if r['base']['repo']['full_name'] == 'pulp/pulp_ansible': title = 'Pulp Ansible PR' todoist.items.add( '{} - {} [{} #{}]({})'.format(title, r['title'], r['base']['repo']['full_name'], r['number'], r['html_url']), # project_id=review_project['id'], # auto_reminder=True, # due={"string": "next workday at 9am"}, # priority=4 ) # todo close todos for prs/issues that are no longer active todoist.commit()
class TodoistWrapper: def __init__(self, conf): self.todoist = TodoistAPI(conf['secret']) self.conf = conf self.todoist.sync() def get_projects(self): projs = [Project(self, p['id']) for p in self.todoist['projects']] if not self.conf['show_inbox']: return [proj for proj in projs if proj.name != 'Inbox'] else: return projs def project_data(self, project_id): return self.todoist.projects.get_data(project_id) def task_data(self, task_id): return self.todoist.items.get(task_id) def create_task(self, name, project_id): self.todoist.items.add(name, project_id) self.todoist.commit() def create_project(self, project_name): self.todoist.projects.add(project_name) self.todoist.commit() def complete_task(self, task_id): try: self.todoist.items.complete([int(task_id)]) self.todoist.commit() except ValueError: raise CmdError("Argument must be a task id.") def _get_project_task_ids(self, project_id): try: project = Project(self, int(project_id)) task_ids = [task.obj_id for task in project] return task_ids except ValueError: raise CmdError("Argument must be a project id.") def complete_project(self, project_id): self.todoist.items.complete(self._get_project_task_ids(project_id)) self.todoist.commit() def clear_project(self, project_id): self.todoist.items.delete(self._get_project_task_ids(project_id)) self.todoist.commit() def delete_project(self, project_id): self.todoist.projects.delete([project_id]) self.todoist.commit()
def main(): with token() as t: todo = TodoistAPI(t) todo.sync() yield todo todo.commit()
class TodoistLibrary: api: TodoistAPI ### Test Setup ### def todoist_api_client_is_connected(self): self.api = TodoistAPI('313f6bf203b35e7ac56e39561a80633e459c9c54') self.api.sync() ### Test Teardown ### def test_clean_up(self): self.delete_project() self.api.commit() def commit_and_sync(self): self.api.commit() self.api.sync() def delete_project(self): for project in self.api.projects.all(): self.api.projects.delete(project["id"]) self.api.items.all().clear() def create_project_with_name(self, name: str = None): self.api.projects.add(name) def create_project_with_name_and_parent_id(self, name: str, parent_id: int = None): self.api.projects.add(name=name, parent_id=parent_id) def create_task_with_name(self, name_project: str, name_task: str): project = self.api.projects.add(name_project) self.api.items.add(name_task, project_id=project['id']) def create_task_with_name_and_due_date(self, name_project: str, name_task: str, due_date: str): project = self.api.projects.add(name_project) self.api.items.add(name_task, project_id=project['id'], due={'date': due_date}) def create_task_and_subtask_with_name(self, name_project: str, name_task: str, name_subtask: str): project = self.api.projects.add(name_project) task_id = self.api.items.add(name_task, project_id=project['id'], due={'date': '2020-07-18T07:00:00Z'}) subtask = self.api.items.add(name_subtask, project_id=project['id'], due={'date': '2020-07-18T05:00:00Z'}) subtask.move(parent_id=task_id['id']) def create_project_and_add_comment(self, name_project, name_task): project = self.api.projects.add(name_project) task_id = self.api.items.add(name_task, project_id=project['id'], due={'date': '2020-07-18T07:00:00Z'}) self.api.notes.add(task_id['id'], 'Comment3') def create_parent_project_and_child_project(self, parent: str, child: str): parent_project = self.api.projects.add(parent) self.api.projects.add(child, parent_id=parent_project["id"]) def create_task_with_name_and_priority(self, name_project, task_name, priority: int): self.api.projects.add(name_project) self.api.items.add(task_name, priority=priority) def assert_project_with_name_exists(self, name_project): projects = self.api.projects.all(filt=lambda project: project['name'] == name_project) assert len(projects) > 0, "Project could not be found" project = projects[0] assert project['name'] == name_project, "Project is not created" def assert_task_exists(self, name_task): name_tasks = self.api.items.all(filt=lambda task: task['content'] == name_task) assert len(name_tasks) > 0, "Parent task could not be found" task = name_tasks[0] assert task['content'] == name_task, "Task is not created" def assert_task_has_due_date(self, task_name, due_date): tasks = self.api.items.all(filt=lambda task: task["content"] == task_name) assert len(tasks) > 0, "Parent task could not be found" task = tasks[0] assert task['due']['date'] == due_date, "Task due date is wrong" def assert_task_with_subtask_exists(self, parent_task, child_task): parent_tasks = self.api.items.all(filt=lambda task: task["content"] == parent_task) assert len(parent_tasks) > 0, "Parent task could not be found" parent = parent_tasks[0] child_tasks = self.api.items.all(filt=lambda project: project["content"] == child_task) assert len( child_tasks) > 0, "Child task could not be found" child = child_tasks[0] assert child["parent_id"] == parent['id'], "Task is not parent of another project" def assert_project_is_parent_of_another_project(self, parent, child): projects = self.api.projects.all(filt=lambda project: project["name"] == parent) assert len(projects) > 0, "Parent project could not be found" parent_project = projects[0] projects = self.api.projects.all(filt=lambda project: project["name"] == child) assert len(projects) > 0, "Child project could not be found" child_project = projects[0] assert child_project["parent_id"] == parent_project['id'], "Project is not parent of another project" def commit_and_sync_expect_error(self, error: str, error_code: int = None): try: self.api.commit() self.api.sync() assert False, "Server did not throw any error" except AssertionError as ae: raise ae except SyncError as ex: assert ex.args[1]['error'] == error, "Wrong error message" if error_code is not None and ex.args[1]['error_code'] != error_code: assert False, "Wrong error code" def task_has_priority(self, task_name, priority: int): tasks = self.api.items.all(filt=lambda task: task["content"] == task_name) assert len(tasks) > 0, "Task could not be found" task = tasks[0] assert task['priority'] == priority, "Task priority is wrong"
for task in old_tasks: message_html += "<li>{}</li><br>".format(task.data['content']) message_plain += "{} \r\n".format(task.data['content']) message_html += "</ul>" msg = MIMEMultipart('alternative') msg['From'] = my_addr msg['To'] = my_addr msg['Subject'] = "Old tasks for {}".format(str(datetime.today())) msg.attach(MIMEText(message_plain, 'plain')) msg.attach(MIMEText(message_html, 'html')) text = msg.as_string() server = SMTP('smtp.gmail.com', '587') server.starttls() server.login(my_addr, mail_pw) server.sendmail(my_addr, my_addr, text) server.quit() if __name__ == '__main__': api = TodoistAPI(os.getenv('API_KEY')) old_tasks = TaskFetcher(api) MailSender(old_tasks) for task in old_tasks: task.delete() api.commit() print("break")