def test_add_indox_task():
    g.db.close()
    content = 'Это новая задача!'

    debug_processing('{"type": "message_new", '
                     '"object": {"id": 43, "date": 1492522323, "out": 0, '
                     '"user_id": 481116745, "read_state": 0, '
                     '"body": "' + content + '"}}')

    acc = Subscription.get(Subscription.messenger_user_id == 481116745).account

    service = TodoistService()
    api = TodoistAPI(AccessToken.get(account=acc.id).token)
    api.sync()

    found_content = [
        item['content'] for item in api.items.all()
        if item['content'] == content and item['project_id'] ==
        service.project_name_to_id(api=api, proj_name='Inbox')
    ][0]

    assertEqual(funcname=test_add_indox_task.__name__,
                a=found_content,
                b=content)
    # assertEqual(vkapi.sended_message, 'Я не понял команды. Попробуйте еще раз.', __name__)

    service.delete_task(task=content, proj='Inbox', user_id=481116745)
 def connect_to_todoist(self, api_token=None):
     if connected_to_internet():
         if api_token is None:
             from dev.old.resources import default_token_path
             api_token = default_token_path
         if os.path.exists(api_token):
             from pyutils import get_token
             api_token = get_token(api_token)
         if True:
             print("WARNING - using mock to generate mock.")
             prototype = TodoistAPI(api_token)
             engine = 'pkl'  # 'json' or 'pkl'
             from secrets import lib_root
             mock_path = os.path.join(lib_root, 'app_data', 'mock_TodoistAPI_py{}.{}'.format('3' if is_python_3() else '2', engine))
             from pyutils import Mock
             self._api = Mock(prototype, dump_path=mock_path, dump_engine=engine)
         else:
             self._api = TodoistAPI(api_token)
     else:
         prototype = TodoistAPI()
         engine = 'pkl'  # 'json' or 'pkl'
         from secrets import lib_root
         mock_path = os.path.join(lib_root, 'app_data', 'mock_TodoistAPI_py{}.{}'.format('3' if is_python_3() else '2', engine))
         from pyutils import Mock
         self._api = Mock(prototype, dump_path=mock_path, dump_engine=engine)
class TaskManager:
    def __init__(self, settings):
        self.todoist = TodoistAPI(settings['API_KEY'])
        self.todoist.sync()
        self.user = self.todoist.state['user']['id']
        self.labels = convert_labels(self.todoist.state['labels'])

    def _sync(func):
        def synced(self, *args, **kwargs):
            self.todoist.sync()
            return func(self, *args, **kwargs)
        return synced

    @_sync
    def avg_spoons(self):
        completed_spoonsy_tasks = [ task for task in self.get_tasks() if is_spoonsy_task(task, self.labels) and task['date_completed'] ]
        return mean([ calculate_values(task['labels']) for task in completed_spoonsy_tasks ])

    @_sync
    def get_projects(self):
        return [ project for project in self.todoist.state['projects'] if project_owned_by_user(project, self.user) ]

    @_sync
    def get_tasks(self, project_name='all'):
        all_tasks = self.todoist.state['items']
        if project_name == 'all':
            return all_tasks
        else:
            project = get_project_or_none(all_tasks, project_name)
            return [ item for item in all_tasks if item['project_id'] == project['id'] ]
Beispiel #4
0
class Todoist:
    def __init__(self):
        self.token = token
        self.api = TodoistAPI(self.token)
        self.api.sync()

    def sync(self):
        self.api.sync()

    def get_obj(self, obj):
        if obj == 'state':
            return self.api.state
        elif obj == 'projects':
            return self.api.state['projects']
        elif obj == 'labels':
            return self.api.state['labels']
        elif obj == 'items':
            return self.api.state['items']
        elif obj == 'sections':
            return self.api.state['sections']
        else:
            return 'Object Not Found'

    def get_items(self, p_id=False):
        all_items = self.get_obj('items')
        if p_id:
            select_items = []
            for item in all_items:
                if item['project_id'] == p_id:
                    select_items.append(item)
            all_items = select_items
        return all_items
Beispiel #5
0
def initiate_api(access_token):
    """Initiate and sync Todoist API"""
    api = TodoistAPI(access_token)
    api.sync()
    if bool(api['user']):
        return api
    else:
        return None
def add_task(task,
             project='',
             date_string='',
             accuracy='day',
             due_datetime=''):
    g.db.close()

    import time
    time.sleep(1)
    body = '{0}{1}{2}.'.format(task, ' в ' + project if project != '' else '',
                               '. ' + date_string if datetime != '' else '')
    debug_processing('{"type": "message_new", '
                     '"object": {"id": 43, "date": 1492522323, "out": 0, '
                     '"user_id": 481116745, "read_state": 0, '
                     '"body": "' + body + '"}}')

    time.sleep(1)

    if 'Все верно?' in vkapi.sended_message:  # bad
        debug_processing('{"type": "message_new", '
                         '"object": {"id": 43, "date": 1492522323, "out": 0, '
                         '"user_id": 481116745, "read_state": 0, '
                         '"body": "Ага!"}}')

    time.sleep(1)
    acc = Subscription.get(Subscription.messenger_user_id == 481116745).account

    service = TodoistService()
    api = TodoistAPI(AccessToken.get(account=acc.id).token)
    api.sync()

    project = 'Inbox' if project == '' else project
    try:
        found_content = [
            item for item in api.items.all()
            if item['content'] == task + '.' and item['project_id'] ==
            service.project_name_to_id(api=api, proj_name=project)
        ][0]
    except Exception as e:
        print(api.items.all())

        found_content = [
            item for item in api.items.all()
            if item['content'] == task + '.' and item['project_id'] ==
            service.project_name_to_id(api=api, proj_name=project)
        ][0]

    assertEqual(funcname=add_task.__name__,
                a=found_content.data['content'],
                b=task + '.')

    # import datetime as dt
    # timedelts = {'day': dt.timedelta(days=1), 'hour': dt.timedelta(hours=1)}
    # assertTrue(due_datetime < found_content['due_date_utc'] + timedelts[accuracy]
    #            and due_datetime > found_content['due_date_utc'] - timedelts[accuracy], funcname=add_task.__name__)

    service.delete_task(task=task + '.', proj=project, user_id=481116745)
Beispiel #7
0
def openTodoist():
    f = open('config.json',) 
    config = json.load(f)
    f.close()

    if config['api-token']=='':
        print('Please add an API token to config.json')
        exit()

    api = TodoistAPI(token=config['api-token'])
    api.sync()
    return api
Beispiel #8
0
 def __init__(self, token=None, **kwargs):
     super(ServiceTodoist, self).__init__(token, **kwargs)
     self.AUTH_URL = 'https://todoist.com/oauth/authorize'
     self.ACC_TOKEN = 'https://todoist.com/oauth/access_token'
     self.REQ_TOKEN = 'https://todoist.com/oauth/access_token'
     self.consumer_key = settings.TH_TODOIST['client_id']
     self.consumer_secret = settings.TH_TODOIST['client_secret']
     self.scope = 'task:add,data:read,data:read_write'
     self.service = 'ServiceTodoist'
     self.oauth = 'oauth2'
     if token:
         self.token = token
         self.todoist = TodoistAPI(token)
Beispiel #9
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()
Beispiel #10
0
 def __init__(self):
     token, fromfile = self._load_token()
     if not fromfile:
         # if prompting for token, already interactive, so
         # show confirmation if the task is added.
         self.verbose = True
     self._api = TodoistAPI(token)
Beispiel #11
0
 def init_api(self):
     if not self.is_authorized():
         return
     try:
         with app.app_context():
             self.api = TodoistAPI(self.auth,
                                   cache=app.config['TODOIST']['CACHE'])
         result = self.api.sync()
         if 'error' in result:
             raise SyncError
         if 'user' in result and not self.todoist_id:
             self.todoist_id = result['user']['id']
     except SyncError:
         self.auth = ''
         self.todoist_id = None
         self.api = None
def api_init():
    """
    Initialises the API and retrieves the projects.

    :return: a dictionary of projects.
    :rtype: dict
    """
    global __api
    __api = TodoistAPI(secret())
Beispiel #13
0
 def __init__(self, apiToken: str):
     """
     Initialize common protected properties
     Args:
         apiToken: The login token for the todoist API
     """
     self._todoist: TodoistAPI = TodoistAPI(apiToken)
     self._preferences: Preferences = Preferences()
     self._devTasks: Tasks = Tasks([])
Beispiel #14
0
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tg_id = db.Column(db.BigInteger, unique=True)
    first_name = db.Column(db.String(255))
    last_name = db.Column(db.String(255))
    username = db.Column(db.String(100))
    todoist_id = db.Column(db.BigInteger, nullable=True, index=True)
    state = db.Column(db.String(36), default='', index=True)
    auth = db.Column(db.String(255), default='')
    is_active = db.Column(db.Boolean, default=True)
    created_at = db.Column(db.DateTime, nullable=False)
    last_active_at = db.Column(db.DateTime, nullable=True)

    # noinspection PyTypeChecker
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.update = None  # type: Update
        self.message = None  # type: Message
        self.api = None  # type: TodoistAPI
        self.now = None  # type: datetime

    def is_authorized(self):
        return bool(self.auth)

    def first_init_api(self):
        self.init_api()
        if not self.is_authorized():
            return
        from app.telegram.handlers import bot
        bot().base_welcome(self)

    def init_api(self):
        if not self.is_authorized():
            return
        try:
            with app.app_context():
                self.api = TodoistAPI(self.auth,
                                      cache=app.config['TODOIST']['CACHE'])
            result = self.api.sync()
            if 'error' in result:
                raise SyncError
            if 'user' in result and not self.todoist_id:
                self.todoist_id = result['user']['id']
        except SyncError:
            self.auth = ''
            self.todoist_id = None
            self.api = None

    def send_message(self, text, **kwargs):
        from app.telegram.handlers import bot
        try:
            return bot().send_message(self.tg_id, text, **kwargs)
        except Unauthorized:
            self.is_active = False
            db.session.add(self)
            db.session.commit()
        return False
Beispiel #15
0
class TodoistItems:
    def __init__(self, token):
        self.api_token = token
        self.api = TodoistAPI(self.api_token)
        self.api.sync()

    def key_check(self, item, key):
        try:
            result = item[key]
            return result
        except:
            return False

    def date_check(self, item, date):
        if self.key_check(item, 'due'):
            if item['due']['lang'] == 'ja':
                if date.replace('/', '-') in item['due']['date']:
                    return True
                elif '毎日' in item['due']['string']:
                    return True
            else:
                try:
                    if date == parse(item['due']['date']).strftime('%Y/%m/%d'):
                        return True
                except ValueError:
                    pass
        return False

    def get_project_name(self, item):
        if self.key_check(item, 'project_id'):
            project_id = item['project_id']
        else:
            project_id = item['parent_id']
        project = self.api.projects.get_by_id(project_id)
        return project['name']

    def find_by_date(self, date):
        return [
            item for item in self.api['items'] if self.date_check(item, date)
        ]
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 subscribe(self, chat_id: int, todoist_key: str):
        subscribed = any(sub.chat_id == chat_id for sub in self._subscriptions)
        if subscribed:
            return

        with self._lock:
            self._subscriptions.append(
                Subscription(chat_id, TodoistAPI(token=todoist_key,
                                                 cache=None)))
            self._redis.lpush(
                redis_keys.subscription,
                dumps({
                    'chat_id': chat_id,
                    'todoist_key': todoist_key
                }))

        logging.info(f'User with telegram id {chat_id} subcribed')
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 #19
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()
def load_subscriptions_store(redis: Redis):
    try:
        subscription_jsons = redis.lrange(redis_keys.subscription, 0, -1)

        subscription_dicts = [loads(sjs) for sjs in subscription_jsons]

        subscriptions = [
            Subscription(chat_id=sdict['chat_id'],
                         todoist_api=TodoistAPI(
                             token=sdict['todoist_key'],
                             cache=None,
                             api_endpoint='https://api.todoist.com'))
            for sdict in subscription_dicts
        ]

        logging.info('Successfully loaded notifications from redis.')
        return SubscriptionsStore(redis=redis,
                                  initial_subscriptions=subscriptions)
    except JSONDecodeError as ex:
        logging.error(ex)
        logging.error(
            'Could not load subscriptions from redis. Initializing with empty list instead'
        )
        return SubscriptionsStore(redis=redis)
Beispiel #21
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 #22
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 #23
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 #24
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 #25
0
 def __init__(self, api_token: str) -> None:
     super().__init__()
     self.api = TodoistAPI(api_token)
     self.data: JsonDict = {}
     self.projects: DictProjectId = {}
     self._allow_creation = False
Beispiel #26
0
class ServiceTodoist(ServicesMgr):

    def __init__(self, token=None, **kwargs):
        super(ServiceTodoist, self).__init__(token, **kwargs)
        self.AUTH_URL = 'https://todoist.com/oauth/authorize'
        self.ACC_TOKEN = 'https://todoist.com/oauth/access_token'
        self.REQ_TOKEN = 'https://todoist.com/oauth/access_token'
        self.consumer_key = settings.TH_TODOIST['client_id']
        self.consumer_secret = settings.TH_TODOIST['client_secret']
        self.scope = 'task:add,data:read,data:read_write'
        self.service = 'ServiceTodoist'
        self.oauth = 'oauth2'
        if token:
            self.token = token
            self.todoist = TodoistAPI(token)

    def read_data(self, **kwargs):
        """
            get the data from the service
            as the pocket service does not have any date
            in its API linked to the note,
            add the triggered date to the dict data
            thus the service will be triggered when data will be found

            :param kwargs: contain keyword args : trigger_id at least
            :type kwargs: dict

            :rtype: list
        """
        trigger_id = kwargs['trigger_id']
        data = list()
        cache.set('th_todoist_' + str(trigger_id), data)

    def save_data(self, trigger_id, **data):
        """
            let's save the data
            :param trigger_id: trigger ID from which to save data
            :param data: the data to check to be used and save
            :type trigger_id: int
            :type data:  dict
            :return: the status of the save statement
            :rtype: boolean
        """
        kwargs = {}

        title, content = super(ServiceTodoist, self).save_data(trigger_id,
                                                               data, **kwargs)

        if self.token:
            if title or content or \
                            (data.get('link') and len(data.get('link'))) > 0:
                content = title + ' ' + content + ' ' + data.get('link')

                self.todoist.add_item(content)

                sentence = str('todoist {} created').format(data.get('link'))
                logger.debug(sentence)
                status = True
            else:
                status = False
        else:
            logger.critical("no token or link provided for "
                            "trigger ID {} ".format(trigger_id))
            status = False
        return status
Beispiel #27
0
class Todoist(SingletonMixin):
    """A wrapper for the Todoist API."""

    def __init__(self, api_token: str) -> None:
        super().__init__()
        self.api = TodoistAPI(api_token)
        self.data: JsonDict = {}
        self.projects: DictProjectId = {}
        self._allow_creation = False

    def smart_sync(self):
        """Only perform a full resync if needed."""
        if not self.data.get("projects", {}):
            # If internal data has no projects, reset the state and a full (slow) sync will be performed.
            self.api.reset_state()

        partial_data = {}
        for attempt in range(3):
            # For some reason, sometimes this sync() method returns an empty string instead of a dict.
            # In this case, let's try again for a few times until we get a dictionary.
            partial_data = self.api.sync()
            if isinstance(partial_data, dict):
                break
            LOGGER.warning(f"Retrying, attempt {attempt + 1}: partial_data is not a dict(): {partial_data!r}")

        self._merge_new_data(partial_data)

        self.projects = dict(PROJECTS_NAME_ID_JMEX.search(self.data))

    def _merge_new_data(self, partial_data: JsonDict):
        if not self.data:
            self.data = partial_data
            return

        for key, value in partial_data.items():
            if isinstance(value, list):
                if key not in self.data:
                    self.data[key] = []
                self.data[key].extend(value)
            elif isinstance(value, dict):
                if key not in self.data:
                    self.data[key] = {}
                self.data[key].update(value)
            else:
                self.data[key] = value

    def keys(self):
        """Keys of the data."""
        return sorted(self.data.keys())

    @deprecated(reason="use find* functions instead")
    def fetch(
        self,
        element_name: str,
        return_field: str = None,
        filters: JsonDict = None,
        index: int = None,
        matching_function=all,
    ) -> List[Any]:
        """Fetch elements matching items that satisfy the desired parameters.

        :param element_name: Name of the element to search. E.g. 'projects', 'items'.
        :param return_field: Name of the return field. If None, return the whole element.
        :param filters: Parameters for the search.
        :param index: Desired index to be returned. If nothing was found, return None.
        :param matching_function: ``all`` items by default, but ``any`` can be used as well.
        """
        if not filters:
            values_to_list: JsonDict = {}
        else:
            values_to_list = {key: [value] if not isinstance(value, list) else value for key, value in filters.items()}
        found_elements = [
            element[return_field] if return_field else element
            for element in self.data[element_name]
            if not filters or matching_function(element[key] in value for key, value in values_to_list.items())
        ]
        if index is not None:
            return found_elements[index] if found_elements else None
        return found_elements

    @deprecated(reason="use find* functions instead")
    def fetch_first(self, element_name: str, return_field: str = None, filters: JsonDict = None) -> Optional[Any]:
        """Fetch only the first result from the fetched list, or None if the list is empty."""
        return self.fetch(element_name, return_field, filters, 0)

    def find_project_id(self, exact_name: str) -> Optional[int]:
        """Find a project ID by its exact name.

        :param exact_name: Exact name of a project.
        """
        return self.projects.get(exact_name, None)

    def find_projects(self, partial_name: str = "") -> DictProjectId:
        """Find projects by partial name.

        :param partial_name: Partial name of a project.
        """
        return {
            name: project_id for name, project_id in self.projects.items() if partial_name.casefold() in name.casefold()
        }

    def find_project_items(self, exact_project_name: str, extra_jmes_expression: str = "") -> List[JsonDict]:
        """Fetch all project items by the exact project name.

        :param exact_project_name: Exact name of a project.
        :param extra_jmes_expression: Extra JMESPath expression to filter fields, for instance.
        """
        project_id = self.find_project_id(exact_project_name)
        if not project_id:
            return []
        return jmespath.search(f"items[?project_id==`{project_id}`]{extra_jmes_expression}", self.data)

    def find_items_by_content(self, exact_project_name: str, partial_content: str) -> List[JsonDict]:
        """Return items of a project by partial content.

        :param exact_project_name: Exact name of a project.
        :param partial_content: Partial content of an item.
        """
        clean_content = partial_content.casefold()
        return [
            item
            for item in self.find_project_items(exact_project_name)
            if clean_content in item.get("content", "").casefold()
        ]
Beispiel #28
0
 def __init__(self, settings):
     self.todoist = TodoistAPI(settings['API_KEY'])
     self.todoist.sync()
     self.user = self.todoist.state['user']['id']
     self.labels = convert_labels(self.todoist.state['labels'])
Beispiel #29
0
def get_todoist_client():
    """
    The Todoist client isn't thread safe, so we need to create it each time we want to use it
    """
    return TodoistAPI(TODOIST_TOKEN)
Beispiel #30
0
 def __init__(self, conf):
     self.todoist = TodoistAPI(conf['secret'])
     self.conf = conf
     self.todoist.sync()
Beispiel #31
0
import config
import urwid
from todoist import TodoistAPI
import pprint

token = config.todoist_api_key
api = TodoistAPI(token)
api.sync()
items = api.state['items']

pprint.pprint(len(items))

for item in items:
    # pprint.pprint(item, indent=4)
    # print('++++++++++++++++++++++++++++++++++')
    pprint.pprint('Content: ' + item['content'], indent=4)
    pprint.pprint('Date Completed: ' + str(item['date_completed']), indent=4)
    pprint.pprint('Checked: ' + str(item['checked']), indent=4)
    # pprint.pprint('Due Date: ' + item['due']['date'], indent=4)
    print(
        '////////////////////////////////////////////////////////////////////////////////////\n'
    )


def exit_on_q(key):
    if key in ('q', 'Q'):
        raise urwid.ExitMainLoop()


palette1 = [('tl_txt_pal', 'light magenta', 'black'),
            ('tr_txt_pal', 'light blue', 'black'),
Beispiel #32
0
 def _api_for_user(self, user_id):
     acc = Subscription.get(
         Subscription.messenger_user_id == user_id).account
     api = TodoistAPI(AccessToken.get(AccessToken.account == acc).token)
     api.sync()
     return api
Beispiel #33
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()