Beispiel #1
0
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()
Beispiel #4
0
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()
Beispiel #5
0
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()
Beispiel #6
0
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()
Beispiel #7
0
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
Beispiel #8
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()
Beispiel #9
0
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()
Beispiel #10
0
def main():
    with token() as t:
        todo = TodoistAPI(t)
    todo.sync()
    yield todo
    todo.commit()
Beispiel #11
0
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"
Beispiel #12
0
    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")