You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
360 lines
9.9 KiB
360 lines
9.9 KiB
from __future__ import annotations
|
|
|
|
from typing import List, Literal
|
|
|
|
import attr
|
|
|
|
from ..todoist_api_python.utils import get_url_for_task
|
|
|
|
VIEW_STYLE = Literal["list", "board"]
|
|
|
|
|
|
@attr.s
|
|
class Project(object):
|
|
color: str = attr.ib()
|
|
comment_count: int = attr.ib()
|
|
id: str = attr.ib()
|
|
is_favorite: bool = attr.ib()
|
|
is_inbox_project: bool = attr.ib()
|
|
is_shared: bool = attr.ib()
|
|
is_team_inbox: bool = attr.ib()
|
|
name: str = attr.ib()
|
|
order: int = attr.ib()
|
|
parent_id: str | None = attr.ib()
|
|
url: str = attr.ib()
|
|
view_style: VIEW_STYLE = attr.ib()
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
return cls(
|
|
color=obj["color"],
|
|
comment_count=obj["comment_count"],
|
|
id=obj["id"],
|
|
is_favorite=obj["is_favorite"],
|
|
is_inbox_project=obj.get("is_inbox_project"),
|
|
is_shared=obj["is_shared"],
|
|
is_team_inbox=obj.get("is_team_inbox"),
|
|
name=obj["name"],
|
|
order=obj.get("order"),
|
|
parent_id=obj.get("parent_id"),
|
|
url=obj["url"],
|
|
view_style=obj["view_style"],
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class Section(object):
|
|
id: str = attr.ib()
|
|
name: str = attr.ib()
|
|
order: int = attr.ib()
|
|
project_id: str = attr.ib()
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
return cls(
|
|
id=obj["id"],
|
|
name=obj["name"],
|
|
order=obj["order"],
|
|
project_id=obj["project_id"],
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class Due(object):
|
|
date: str = attr.ib()
|
|
is_recurring: bool = attr.ib()
|
|
string: str = attr.ib()
|
|
|
|
datetime: str | None = attr.ib(default=None)
|
|
timezone: str | None = attr.ib(default=None)
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
return cls(
|
|
date=obj["date"],
|
|
is_recurring=obj["is_recurring"],
|
|
string=obj["string"],
|
|
datetime=obj.get("datetime"),
|
|
timezone=obj.get("timezone"),
|
|
)
|
|
|
|
def to_dict(self):
|
|
return {
|
|
"date": self.date,
|
|
"is_recurring": self.is_recurring,
|
|
"string": self.string,
|
|
"datetime": self.datetime,
|
|
"timezone": self.timezone,
|
|
}
|
|
|
|
@classmethod
|
|
def from_quick_add_response(cls, obj):
|
|
due = obj.get("due")
|
|
|
|
if not due:
|
|
return None
|
|
|
|
timezone = due.get("timezone")
|
|
|
|
datetime: str | None = None
|
|
|
|
if timezone:
|
|
datetime = due["date"]
|
|
|
|
return cls(
|
|
date=due["date"],
|
|
is_recurring=due["is_recurring"],
|
|
string=due["string"],
|
|
datetime=datetime,
|
|
timezone=timezone,
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class Task(object):
|
|
assignee_id: str | None = attr.ib()
|
|
assigner_id: str | None = attr.ib()
|
|
comment_count: int = attr.ib()
|
|
is_completed: bool = attr.ib()
|
|
content: str = attr.ib()
|
|
created_at: str = attr.ib()
|
|
creator_id: str = attr.ib()
|
|
description: str = attr.ib()
|
|
due: Due | None = attr.ib()
|
|
id: str = attr.ib()
|
|
labels: List[str] = attr.ib()
|
|
order: int = attr.ib()
|
|
parent_id: str | None = attr.ib()
|
|
priority: int = attr.ib()
|
|
project_id: str = attr.ib()
|
|
section_id: str | None = attr.ib()
|
|
url: str = attr.ib()
|
|
|
|
sync_id: str | None = attr.ib(default=None)
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
due: Due | None = None
|
|
|
|
if obj.get("due"):
|
|
due = Due.from_dict(obj["due"])
|
|
|
|
return cls(
|
|
assignee_id=obj.get("assignee_id"),
|
|
assigner_id=obj.get("assigner_id"),
|
|
comment_count=obj["comment_count"],
|
|
is_completed=obj["is_completed"],
|
|
content=obj["content"],
|
|
created_at=obj["created_at"],
|
|
creator_id=obj["creator_id"],
|
|
description=obj["description"],
|
|
due=due,
|
|
id=obj["id"],
|
|
labels=obj.get("labels"),
|
|
order=obj.get("order"),
|
|
parent_id=obj.get("parent_id"),
|
|
priority=obj["priority"],
|
|
project_id=obj["project_id"],
|
|
section_id=obj["section_id"],
|
|
url=obj["url"],
|
|
)
|
|
|
|
def to_dict(self):
|
|
due: dict | None = None
|
|
|
|
if self.due:
|
|
due = self.due.to_dict()
|
|
|
|
return {
|
|
"assignee_id": self.assignee_id,
|
|
"assigner_id": self.assigner_id,
|
|
"comment_count": self.comment_count,
|
|
"is_completed": self.is_completed,
|
|
"content": self.content,
|
|
"created_at": self.created_at,
|
|
"creator_id": self.creator_id,
|
|
"description": self.description,
|
|
"due": due,
|
|
"id": self.id,
|
|
"labels": self.labels,
|
|
"order": self.order,
|
|
"parent_id": self.parent_id,
|
|
"priority": self.priority,
|
|
"project_id": self.project_id,
|
|
"section_id": self.section_id,
|
|
"sync_id": self.sync_id,
|
|
"url": self.url,
|
|
}
|
|
|
|
@classmethod
|
|
def from_quick_add_response(cls, obj):
|
|
due: Due | None = None
|
|
|
|
if obj.get("due"):
|
|
due = Due.from_quick_add_response(obj)
|
|
|
|
return cls(
|
|
assignee_id=obj.get("responsible_uid"),
|
|
assigner_id=obj.get("assigned_by_uid"),
|
|
comment_count=0,
|
|
is_completed=False,
|
|
content=obj["content"],
|
|
created_at=obj["added_at"],
|
|
creator_id=obj["added_by_uid"],
|
|
description=obj["description"],
|
|
due=due,
|
|
id=obj["id"],
|
|
labels=obj["labels"],
|
|
order=obj["child_order"],
|
|
parent_id=obj["parent_id"] or None,
|
|
priority=obj["priority"],
|
|
project_id=obj["project_id"],
|
|
section_id=obj["section_id"] or None,
|
|
sync_id=obj["sync_id"],
|
|
url=get_url_for_task(obj["id"], obj["sync_id"]),
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class QuickAddResult:
|
|
task: Task = attr.ib()
|
|
|
|
resolved_project_name: str | None = attr.ib(default=None)
|
|
resolved_assignee_name: str | None = attr.ib(default=None)
|
|
resolved_label_names: List[str] | None = attr.ib(default=None)
|
|
resolved_section_name: str | None = attr.ib(default=None)
|
|
|
|
@classmethod
|
|
def from_quick_add_response(cls, obj):
|
|
project_data = obj["meta"].get("project", {})
|
|
assignee_data = obj["meta"].get("assignee", {})
|
|
section_data = obj["meta"].get("section", {})
|
|
|
|
resolved_project_name = None
|
|
resolved_assignee_name = None
|
|
resolved_section_name = None
|
|
|
|
if project_data and len(project_data) == 2:
|
|
resolved_project_name = obj["meta"]["project"][1]
|
|
|
|
if assignee_data and len(assignee_data) == 2:
|
|
resolved_assignee_name = obj["meta"]["assignee"][1]
|
|
|
|
if section_data and len(section_data) == 2:
|
|
resolved_section_name = obj["meta"]["section"][1]
|
|
|
|
return cls(
|
|
task=Task.from_quick_add_response(obj),
|
|
resolved_project_name=resolved_project_name,
|
|
resolved_assignee_name=resolved_assignee_name,
|
|
resolved_label_names=list(obj["meta"]["labels"].values()),
|
|
resolved_section_name=resolved_section_name,
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class Collaborator(object):
|
|
id: str = attr.ib()
|
|
email: str = attr.ib()
|
|
name: str = attr.ib()
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
return cls(
|
|
id=obj["id"],
|
|
email=obj["email"],
|
|
name=obj["name"],
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class Attachment(object):
|
|
resource_type: str | None = attr.ib(default=None)
|
|
|
|
file_name: str | None = attr.ib(default=None)
|
|
file_size: int | None = attr.ib(default=None)
|
|
file_type: str | None = attr.ib(default=None)
|
|
file_url: str | None = attr.ib(default=None)
|
|
file_duration: int | None = attr.ib(default=None)
|
|
upload_state: str | None = attr.ib(default=None)
|
|
|
|
image: str | None = attr.ib(default=None)
|
|
image_width: int | None = attr.ib(default=None)
|
|
image_height: int | None = attr.ib(default=None)
|
|
|
|
url: str | None = attr.ib(default=None)
|
|
title: str | None = attr.ib(default=None)
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
return cls(
|
|
resource_type=obj.get("resource_type"),
|
|
file_name=obj.get("file_name"),
|
|
file_size=obj.get("file_size"),
|
|
file_type=obj.get("file_type"),
|
|
file_url=obj.get("file_url"),
|
|
upload_state=obj.get("upload_state"),
|
|
image=obj.get("image"),
|
|
image_width=obj.get("image_width"),
|
|
image_height=obj.get("image_height"),
|
|
url=obj.get("url"),
|
|
title=obj.get("title"),
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class Comment(object):
|
|
attachment: Attachment | None = attr.ib()
|
|
content: str = attr.ib()
|
|
id: str = attr.ib()
|
|
posted_at: str = attr.ib()
|
|
project_id: str | None = attr.ib()
|
|
task_id: str | None = attr.ib()
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
attachment: Attachment | None = None
|
|
|
|
if "attachment" in obj and obj["attachment"] is not None:
|
|
attachment = Attachment.from_dict(obj["attachment"])
|
|
|
|
return cls(
|
|
attachment=attachment,
|
|
content=obj["content"],
|
|
id=obj["id"],
|
|
posted_at=obj["posted_at"],
|
|
project_id=obj.get("project_id"),
|
|
task_id=obj.get("task_id"),
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class Label:
|
|
id: str = attr.ib()
|
|
name: str = attr.ib()
|
|
color: str = attr.ib()
|
|
order: int = attr.ib()
|
|
is_favorite: bool = attr.ib()
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
return cls(
|
|
id=obj["id"],
|
|
name=obj["name"],
|
|
color=obj["color"],
|
|
order=obj["order"],
|
|
is_favorite=obj["is_favorite"],
|
|
)
|
|
|
|
|
|
@attr.s
|
|
class AuthResult:
|
|
access_token: str = attr.ib()
|
|
state: str = attr.ib()
|
|
|
|
@classmethod
|
|
def from_dict(cls, obj):
|
|
return cls(
|
|
access_token=obj["access_token"],
|
|
state=obj["state"],
|
|
)
|
|
|