2019-12-25 20:32:54 +01:00
|
|
|
import time
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
import todoist
|
2023-11-18 10:16:14 +01:00
|
|
|
import todoist.managers.items # type: ignore
|
|
|
|
import websocket
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
from platypush.plugins import Plugin, action
|
2023-11-18 10:16:14 +01:00
|
|
|
from platypush.schemas.todoist import (
|
|
|
|
TodoistCollaboratorSchema,
|
|
|
|
TodoistFilterSchema,
|
|
|
|
TodoistItemSchema,
|
|
|
|
TodoistLiveNotificationSchema,
|
|
|
|
TodoistNoteSchema,
|
|
|
|
TodoistProjectNoteSchema,
|
|
|
|
TodoistProjectSchema,
|
|
|
|
TodoistUserSchema,
|
2023-09-24 16:54:43 +02:00
|
|
|
)
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
|
|
|
|
class TodoistPlugin(Plugin):
|
|
|
|
"""
|
|
|
|
Todoist integration.
|
|
|
|
|
2023-11-18 10:16:14 +01:00
|
|
|
You'll also need a Todoist token. You can get it `here
|
2023-11-19 00:10:10 +01:00
|
|
|
<https://todoist.com/prefs/integrations>`_.
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
_sync_timeout = 60.0
|
|
|
|
|
|
|
|
def __init__(self, api_token: str, **kwargs):
|
|
|
|
"""
|
2024-01-18 00:26:05 +01:00
|
|
|
:param api_token: Todoist API token.
|
|
|
|
You can get it `here <https://todoist.com/prefs/integrations>`_.
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
self.api_token = api_token
|
|
|
|
self._api = None
|
|
|
|
self._last_sync_time = None
|
|
|
|
|
2023-11-18 10:16:14 +01:00
|
|
|
self._ws_url: Optional[str] = None
|
|
|
|
self._ws: Optional[websocket.WebSocketApp] = None
|
|
|
|
self._connected = False
|
|
|
|
self._todoist_initialized = False
|
|
|
|
|
|
|
|
self._items = {}
|
|
|
|
self._event_handled = False
|
|
|
|
|
|
|
|
def _get_api(self) -> todoist.TodoistAPI: # type: ignore
|
2019-12-25 20:32:54 +01:00
|
|
|
if not self._api:
|
2023-11-18 10:16:14 +01:00
|
|
|
self._api = todoist.TodoistAPI(self.api_token) # type: ignore
|
2019-12-25 20:32:54 +01:00
|
|
|
|
2023-09-24 16:54:43 +02:00
|
|
|
if (
|
|
|
|
not self._last_sync_time
|
|
|
|
or time.time() - self._last_sync_time > self._sync_timeout
|
|
|
|
):
|
2019-12-25 20:32:54 +01:00
|
|
|
self._api.sync()
|
|
|
|
|
|
|
|
return self._api
|
|
|
|
|
|
|
|
@action
|
2023-11-18 10:16:14 +01:00
|
|
|
def get_user(self):
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
Get logged user info.
|
2023-11-18 10:16:14 +01:00
|
|
|
|
|
|
|
:return: .. schema:: todoist.TodoistUserSchema
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
2023-11-18 10:16:14 +01:00
|
|
|
return TodoistUserSchema().dump(self._get_api().state['user'])
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
@action
|
2023-11-18 10:16:14 +01:00
|
|
|
def get_projects(self):
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
Get list of Todoist projects.
|
2023-11-18 10:16:14 +01:00
|
|
|
|
|
|
|
:return: .. schema:: todoist.TodoistProjectSchema(many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
2023-11-18 10:16:14 +01:00
|
|
|
return TodoistProjectSchema().dump(self._get_api().state['projects'], many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
@action
|
2023-11-18 10:16:14 +01:00
|
|
|
def get_items(self):
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
Get list of Todoist projects.
|
2023-11-18 10:16:14 +01:00
|
|
|
|
|
|
|
:return .. schema:: todoist.TodoistItemSchema(many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
2023-11-18 10:16:14 +01:00
|
|
|
return TodoistItemSchema().dump(self._get_api().state['items'], many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
@action
|
2023-11-18 10:16:14 +01:00
|
|
|
def get_filters(self):
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
Get list of Todoist filters.
|
2023-11-18 10:16:14 +01:00
|
|
|
|
|
|
|
:return: .. schema:: todoist.TodoistFilterSchema(many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
2023-11-18 10:16:14 +01:00
|
|
|
return TodoistFilterSchema().dump(self._get_api().state['filters'], many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
@action
|
2023-11-18 10:16:14 +01:00
|
|
|
def get_live_notifications(self):
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
Get list of Todoist live notifications.
|
2023-11-18 10:16:14 +01:00
|
|
|
|
|
|
|
:return: .. schema:: todoist.TodoistLiveNotificationSchema(many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
2023-11-18 10:16:14 +01:00
|
|
|
return TodoistLiveNotificationSchema().dump(
|
|
|
|
self._get_api().state['live_notifications'], many=True
|
|
|
|
)
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
@action
|
2023-11-18 10:16:14 +01:00
|
|
|
def get_collaborators(self):
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
Get list of collaborators.
|
2023-11-18 10:16:14 +01:00
|
|
|
|
|
|
|
:return: .. schema:: todoist.TodoistCollaboratorSchema(many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
2023-11-18 10:16:14 +01:00
|
|
|
return TodoistCollaboratorSchema().dump(
|
|
|
|
self._get_api().state['collaborators'], many=True
|
|
|
|
)
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
@action
|
2023-11-18 10:16:14 +01:00
|
|
|
def get_notes(self):
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
Get list of Todoist notes.
|
2023-11-18 10:16:14 +01:00
|
|
|
|
|
|
|
:return: .. schema:: todoist.TodoistNoteSchema(many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
2023-11-18 10:16:14 +01:00
|
|
|
return TodoistNoteSchema().dump(self._get_api().state['notes'], many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
@action
|
2023-11-18 10:16:14 +01:00
|
|
|
def get_project_notes(self):
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
|
|
|
Get list of Todoist project notes.
|
2023-11-18 10:16:14 +01:00
|
|
|
|
|
|
|
:return: .. schema:: todoist.TodoistProjectNoteSchema(many=True)
|
2019-12-25 20:32:54 +01:00
|
|
|
"""
|
2023-11-18 10:16:14 +01:00
|
|
|
return TodoistProjectNoteSchema().dump(
|
|
|
|
self._get_api().state['project_notes'], many=True
|
|
|
|
)
|
2019-12-25 20:32:54 +01:00
|
|
|
|
|
|
|
@action
|
|
|
|
def add_item(self, content: str, project_id: Optional[int] = None, **kwargs):
|
|
|
|
"""
|
|
|
|
Add a new item.
|
|
|
|
"""
|
|
|
|
api = self._get_api()
|
|
|
|
manager = todoist.managers.items.ItemsManager(api=api)
|
|
|
|
item = manager.add(content, project_id=project_id, **kwargs)
|
|
|
|
api.commit()
|
|
|
|
return item.data
|
|
|
|
|
|
|
|
@action
|
|
|
|
def delete_item(self, item_id: int):
|
|
|
|
"""
|
|
|
|
Delete an item by id.
|
|
|
|
"""
|
|
|
|
api = self._get_api()
|
|
|
|
manager = todoist.managers.items.ItemsManager(api=api)
|
|
|
|
manager.delete(item_id)
|
|
|
|
api.commit()
|
|
|
|
|
|
|
|
@action
|
|
|
|
def update_item(self, item_id: int, **kwargs):
|
|
|
|
"""
|
|
|
|
Update an item by id.
|
|
|
|
"""
|
|
|
|
api = self._get_api()
|
|
|
|
manager = todoist.managers.items.ItemsManager(api=api)
|
|
|
|
manager.update(item_id, **kwargs)
|
|
|
|
api.commit()
|
|
|
|
|
|
|
|
@action
|
|
|
|
def complete_item(self, item_id: int):
|
|
|
|
"""
|
|
|
|
Mark an item as done.
|
|
|
|
"""
|
|
|
|
api = self._get_api()
|
|
|
|
manager = todoist.managers.items.ItemsManager(api=api)
|
|
|
|
manager.complete(item_id)
|
|
|
|
api.commit()
|
|
|
|
|
|
|
|
@action
|
|
|
|
def uncomplete_item(self, item_id: int):
|
|
|
|
"""
|
|
|
|
Mark an item as not done.
|
|
|
|
"""
|
|
|
|
api = self._get_api()
|
|
|
|
manager = todoist.managers.items.ItemsManager(api=api)
|
|
|
|
manager.uncomplete(item_id)
|
|
|
|
api.commit()
|
|
|
|
|
|
|
|
@action
|
|
|
|
def archive(self, item_id: int):
|
|
|
|
"""
|
|
|
|
Archive an item by id.
|
|
|
|
"""
|
|
|
|
api = self._get_api()
|
|
|
|
manager = todoist.managers.items.ItemsManager(api=api)
|
|
|
|
manager.archive(item_id)
|
|
|
|
api.commit()
|
|
|
|
|
|
|
|
@action
|
|
|
|
def unarchive(self, item_id: int):
|
|
|
|
"""
|
|
|
|
Un-archive an item by id.
|
|
|
|
"""
|
|
|
|
api = self._get_api()
|
|
|
|
manager = todoist.managers.items.ItemsManager(api=api)
|
|
|
|
manager.unarchive(item_id)
|
|
|
|
api.commit()
|
|
|
|
|
|
|
|
@action
|
|
|
|
def sync(self):
|
|
|
|
"""
|
|
|
|
Sync/update info with the remote server.
|
|
|
|
"""
|
|
|
|
api = self._get_api()
|
|
|
|
api.sync()
|
|
|
|
|
|
|
|
|
|
|
|
# vim:sw=4:ts=4:et:
|