mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-09 23:28:07 -05:00
feat(block) : Todoist rest api blocks (#9369)
- Resolves - #9303 and #9304 - Depends on - https://github.com/Significant-Gravitas/AutoGPT/pull/9319 ### Blocks list Block Name | What It Does | Manually Tested -- | -- | -- Todoist Create Label | Creates a new label in Todoist | ✅ Todoist List Labels | Retrieves all personal labels from Todoist | ✅ Todoist Get Label | Retrieves a specific label by ID | ✅ Todoist Create Task | Creates a new task in Todoist | ✅ Todoist Get Tasks | Retrieves active tasks from Todoist | ✅ Todoist Update Task | Updates an existing task | ✅ Todoist Close Task | Completes/closes a task | ✅ Todoist Reopen Task | Reopens a completed task | ✅ Todoist Delete Task | Permanently deletes a task | ✅ Todoist List Projects | Retrieves all projects from Todoist | ✅ Todoist Create Project | Creates a new project in Todoist | ✅ Todoist Get Project | Retrieves details for a specific project | ✅ Todoist Update Project | Updates an existing project | ✅ Todoist Delete Project | Deletes a project and its contents | ✅ Todoist List Collaborators | Retrieves collaborators on a project | ✅ Todoist List Sections | Retrieves sections from Todoist | ✅ Todoist Get Section | Retrieves details for a specific section | ✅ Todoist Delete Section | Deletes a section and its tasks | ✅ Todoist Create Comment | Creates a new comment on a task or project | ✅ Todoist Get Comments | Retrieves all comments for a task or project | ✅ Todoist Get Comment | Retrieves a specific comment by ID | ✅ Todoist Update Comment | Updates an existing comment | ✅ Todoist Delete Comment | Deletes a comment | ✅ > I’ve only created action blocks in Todoist because webhooks can only be manually created [we can't do it programatically right now]. I’ve already emailed Todoist for help, but they haven’t replied yet. Once I receive a reply, I’ll create a pull request for webhook triggers in Todoist.
This commit is contained in:
@@ -82,6 +82,14 @@ TWITTER_CLIENT_SECRET=
|
||||
LINEAR_CLIENT_ID=
|
||||
LINEAR_CLIENT_SECRET=
|
||||
|
||||
# To obtain Todoist API credentials:
|
||||
# 1. Create a Todoist account at todoist.com
|
||||
# 2. Visit the Developer Console: https://developer.todoist.com/appconsole.html
|
||||
# 3. Click "Create new app"
|
||||
# 4. Once created, copy your Client ID and Client Secret below
|
||||
TODOIST_CLIENT_ID=
|
||||
TODOIST_CLIENT_SECRET=
|
||||
|
||||
## ===== OPTIONAL API KEYS ===== ##
|
||||
|
||||
# LLM
|
||||
|
||||
61
autogpt_platform/backend/backend/blocks/todoist/_auth.py
Normal file
61
autogpt_platform/backend/backend/blocks/todoist/_auth.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import SecretStr
|
||||
|
||||
from backend.data.model import (
|
||||
CredentialsField,
|
||||
CredentialsMetaInput,
|
||||
OAuth2Credentials,
|
||||
ProviderName,
|
||||
)
|
||||
from backend.integrations.oauth.todoist import TodoistOAuthHandler
|
||||
from backend.util.settings import Secrets
|
||||
|
||||
secrets = Secrets()
|
||||
TODOIST_OAUTH_IS_CONFIGURED = bool(
|
||||
secrets.todoist_client_id and secrets.todoist_client_secret
|
||||
)
|
||||
|
||||
TodoistCredentials = OAuth2Credentials
|
||||
TodoistCredentialsInput = CredentialsMetaInput[
|
||||
Literal[ProviderName.TODOIST], Literal["oauth2"]
|
||||
]
|
||||
|
||||
|
||||
def TodoistCredentialsField(scopes: list[str]) -> TodoistCredentialsInput:
|
||||
"""
|
||||
Creates a Todoist credentials input on a block.
|
||||
|
||||
Params:
|
||||
scopes: The authorization scopes needed for the block to work.
|
||||
"""
|
||||
return CredentialsField(
|
||||
required_scopes=set(TodoistOAuthHandler.DEFAULT_SCOPES + scopes),
|
||||
description="The Todoist integration requires OAuth2 authentication.",
|
||||
)
|
||||
|
||||
|
||||
TEST_CREDENTIALS = OAuth2Credentials(
|
||||
id="01234567-89ab-cdef-0123-456789abcdef",
|
||||
provider="todoist",
|
||||
access_token=SecretStr("mock-todoist-access-token"),
|
||||
refresh_token=None,
|
||||
access_token_expires_at=None,
|
||||
scopes=[
|
||||
"task:add",
|
||||
"data:read",
|
||||
"data:read_write",
|
||||
"data:delete",
|
||||
"project:delete",
|
||||
],
|
||||
title="Mock Todoist OAuth2 Credentials",
|
||||
username="mock-todoist-username",
|
||||
refresh_token_expires_at=None,
|
||||
)
|
||||
|
||||
TEST_CREDENTIALS_INPUT = {
|
||||
"provider": TEST_CREDENTIALS.provider,
|
||||
"id": TEST_CREDENTIALS.id,
|
||||
"type": TEST_CREDENTIALS.type,
|
||||
"title": TEST_CREDENTIALS.title,
|
||||
}
|
||||
24
autogpt_platform/backend/backend/blocks/todoist/_types.py
Normal file
24
autogpt_platform/backend/backend/blocks/todoist/_types.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Colors(Enum):
|
||||
berry_red = "berry_red"
|
||||
red = "red"
|
||||
orange = "orange"
|
||||
yellow = "yellow"
|
||||
olive_green = "olive_green"
|
||||
lime_green = "lime_green"
|
||||
green = "green"
|
||||
mint_green = "mint_green"
|
||||
teal = "teal"
|
||||
sky_blue = "sky_blue"
|
||||
light_blue = "light_blue"
|
||||
blue = "blue"
|
||||
grape = "grape"
|
||||
violet = "violet"
|
||||
lavender = "lavender"
|
||||
magenta = "magenta"
|
||||
salmon = "salmon"
|
||||
charcoal = "charcoal"
|
||||
grey = "grey"
|
||||
taupe = "taupe"
|
||||
439
autogpt_platform/backend/backend/blocks/todoist/comments.py
Normal file
439
autogpt_platform/backend/backend/blocks/todoist/comments.py
Normal file
@@ -0,0 +1,439 @@
|
||||
from typing import Literal, Union
|
||||
|
||||
from pydantic import BaseModel
|
||||
from todoist_api_python.api import TodoistAPI
|
||||
from typing_extensions import Optional
|
||||
|
||||
from backend.blocks.todoist._auth import (
|
||||
TEST_CREDENTIALS,
|
||||
TEST_CREDENTIALS_INPUT,
|
||||
TodoistCredentials,
|
||||
TodoistCredentialsField,
|
||||
TodoistCredentialsInput,
|
||||
)
|
||||
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
|
||||
from backend.data.model import SchemaField
|
||||
|
||||
|
||||
class TaskId(BaseModel):
|
||||
discriminator: Literal["task"]
|
||||
task_id: str
|
||||
|
||||
|
||||
class ProjectId(BaseModel):
|
||||
discriminator: Literal["project"]
|
||||
project_id: str
|
||||
|
||||
|
||||
class TodoistCreateCommentBlock(Block):
|
||||
"""Creates a new comment on a Todoist task or project"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
content: str = SchemaField(description="Comment content")
|
||||
id_type: Union[TaskId, ProjectId] = SchemaField(
|
||||
discriminator="discriminator",
|
||||
description="Specify either task_id or project_id to comment on",
|
||||
default=TaskId(discriminator="task", task_id=""),
|
||||
advanced=False,
|
||||
)
|
||||
attachment: Optional[dict] = SchemaField(
|
||||
description="Optional file attachment", default=None
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
id: str = SchemaField(description="ID of created comment")
|
||||
content: str = SchemaField(description="Comment content")
|
||||
posted_at: str = SchemaField(description="Comment timestamp")
|
||||
task_id: Optional[str] = SchemaField(
|
||||
description="Associated task ID", default=None
|
||||
)
|
||||
project_id: Optional[str] = SchemaField(
|
||||
description="Associated project ID", default=None
|
||||
)
|
||||
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="1bba7e54-2310-4a31-8e6f-54d5f9ab7459",
|
||||
description="Creates a new comment on a Todoist task or project",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistCreateCommentBlock.Input,
|
||||
output_schema=TodoistCreateCommentBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"content": "Test comment",
|
||||
"id_type": {"discriminator": "task", "task_id": "2995104339"},
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("id", "2992679862"),
|
||||
("content", "Test comment"),
|
||||
("posted_at", "2016-09-22T07:00:00.000000Z"),
|
||||
("task_id", "2995104339"),
|
||||
("project_id", None),
|
||||
],
|
||||
test_mock={
|
||||
"create_comment": lambda content, credentials, task_id=None, project_id=None, attachment=None: {
|
||||
"id": "2992679862",
|
||||
"content": "Test comment",
|
||||
"posted_at": "2016-09-22T07:00:00.000000Z",
|
||||
"task_id": "2995104339",
|
||||
"project_id": None,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def create_comment(
|
||||
credentials: TodoistCredentials,
|
||||
content: str,
|
||||
task_id: Optional[str] = None,
|
||||
project_id: Optional[str] = None,
|
||||
attachment: Optional[dict] = None,
|
||||
):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
comment = api.add_comment(
|
||||
content=content,
|
||||
task_id=task_id,
|
||||
project_id=project_id,
|
||||
attachment=attachment,
|
||||
)
|
||||
return comment.__dict__
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
task_id = None
|
||||
project_id = None
|
||||
|
||||
if isinstance(input_data.id_type, TaskId):
|
||||
task_id = input_data.id_type.task_id
|
||||
else:
|
||||
project_id = input_data.id_type.project_id
|
||||
|
||||
comment_data = self.create_comment(
|
||||
credentials,
|
||||
input_data.content,
|
||||
task_id=task_id,
|
||||
project_id=project_id,
|
||||
attachment=input_data.attachment,
|
||||
)
|
||||
|
||||
if comment_data:
|
||||
yield "id", comment_data["id"]
|
||||
yield "content", comment_data["content"]
|
||||
yield "posted_at", comment_data["posted_at"]
|
||||
yield "task_id", comment_data["task_id"]
|
||||
yield "project_id", comment_data["project_id"]
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistGetCommentsBlock(Block):
|
||||
"""Get all comments for a Todoist task or project"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
id_type: Union[TaskId, ProjectId] = SchemaField(
|
||||
discriminator="discriminator",
|
||||
description="Specify either task_id or project_id to get comments for",
|
||||
default=TaskId(discriminator="task", task_id=""),
|
||||
advanced=False,
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
comments: list = SchemaField(description="List of comments")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="9972d8ae-ddf2-11ef-a9b8-32d3674e8b7e",
|
||||
description="Get all comments for a Todoist task or project",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistGetCommentsBlock.Input,
|
||||
output_schema=TodoistGetCommentsBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"id_type": {"discriminator": "task", "task_id": "2995104339"},
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
(
|
||||
"comments",
|
||||
[
|
||||
{
|
||||
"id": "2992679862",
|
||||
"content": "Test comment",
|
||||
"posted_at": "2016-09-22T07:00:00.000000Z",
|
||||
"task_id": "2995104339",
|
||||
"project_id": None,
|
||||
"attachment": None,
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
test_mock={
|
||||
"get_comments": lambda credentials, task_id=None, project_id=None: [
|
||||
{
|
||||
"id": "2992679862",
|
||||
"content": "Test comment",
|
||||
"posted_at": "2016-09-22T07:00:00.000000Z",
|
||||
"task_id": "2995104339",
|
||||
"project_id": None,
|
||||
"attachment": None,
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_comments(
|
||||
credentials: TodoistCredentials,
|
||||
task_id: Optional[str] = None,
|
||||
project_id: Optional[str] = None,
|
||||
):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
comments = api.get_comments(task_id=task_id, project_id=project_id)
|
||||
return [comment.__dict__ for comment in comments]
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
task_id = None
|
||||
project_id = None
|
||||
|
||||
if isinstance(input_data.id_type, TaskId):
|
||||
task_id = input_data.id_type.task_id
|
||||
else:
|
||||
project_id = input_data.id_type.project_id
|
||||
|
||||
comments = self.get_comments(
|
||||
credentials, task_id=task_id, project_id=project_id
|
||||
)
|
||||
|
||||
yield "comments", comments
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistGetCommentBlock(Block):
|
||||
"""Get a single comment from Todoist using comment ID"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
comment_id: str = SchemaField(description="Comment ID to retrieve")
|
||||
|
||||
class Output(BlockSchema):
|
||||
content: str = SchemaField(description="Comment content")
|
||||
id: str = SchemaField(description="Comment ID")
|
||||
posted_at: str = SchemaField(description="Comment timestamp")
|
||||
project_id: Optional[str] = SchemaField(
|
||||
description="Associated project ID", default=None
|
||||
)
|
||||
task_id: Optional[str] = SchemaField(
|
||||
description="Associated task ID", default=None
|
||||
)
|
||||
attachment: Optional[dict] = SchemaField(
|
||||
description="Optional file attachment", default=None
|
||||
)
|
||||
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="a809d264-ddf2-11ef-9764-32d3674e8b7e",
|
||||
description="Get a single comment from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistGetCommentBlock.Input,
|
||||
output_schema=TodoistGetCommentBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"comment_id": "2992679862",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("content", "Test comment"),
|
||||
("id", "2992679862"),
|
||||
("posted_at", "2016-09-22T07:00:00.000000Z"),
|
||||
("project_id", None),
|
||||
("task_id", "2995104339"),
|
||||
("attachment", None),
|
||||
],
|
||||
test_mock={
|
||||
"get_comment": lambda credentials, comment_id: {
|
||||
"content": "Test comment",
|
||||
"id": "2992679862",
|
||||
"posted_at": "2016-09-22T07:00:00.000000Z",
|
||||
"project_id": None,
|
||||
"task_id": "2995104339",
|
||||
"attachment": None,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_comment(credentials: TodoistCredentials, comment_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
comment = api.get_comment(comment_id=comment_id)
|
||||
return comment.__dict__
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
comment_data = self.get_comment(
|
||||
credentials, comment_id=input_data.comment_id
|
||||
)
|
||||
|
||||
if comment_data:
|
||||
yield "content", comment_data["content"]
|
||||
yield "id", comment_data["id"]
|
||||
yield "posted_at", comment_data["posted_at"]
|
||||
yield "project_id", comment_data["project_id"]
|
||||
yield "task_id", comment_data["task_id"]
|
||||
yield "attachment", comment_data["attachment"]
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistUpdateCommentBlock(Block):
|
||||
"""Updates a Todoist comment"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
comment_id: str = SchemaField(description="Comment ID to update")
|
||||
content: str = SchemaField(description="New content for the comment")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the update was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="b773c520-ddf2-11ef-9f34-32d3674e8b7e",
|
||||
description="Updates a Todoist comment",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistUpdateCommentBlock.Input,
|
||||
output_schema=TodoistUpdateCommentBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"comment_id": "2992679862",
|
||||
"content": "Need one bottle of milk",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"update_comment": lambda credentials, comment_id, content: True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def update_comment(credentials: TodoistCredentials, comment_id: str, content: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
api.update_comment(comment_id=comment_id, content=content)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.update_comment(
|
||||
credentials,
|
||||
comment_id=input_data.comment_id,
|
||||
content=input_data.content,
|
||||
)
|
||||
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistDeleteCommentBlock(Block):
|
||||
"""Deletes a Todoist comment"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
comment_id: str = SchemaField(description="Comment ID to delete")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the deletion was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="bda4c020-ddf2-11ef-b114-32d3674e8b7e",
|
||||
description="Deletes a Todoist comment",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistDeleteCommentBlock.Input,
|
||||
output_schema=TodoistDeleteCommentBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"comment_id": "2992679862",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"delete_comment": lambda credentials, comment_id: True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_comment(credentials: TodoistCredentials, comment_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
success = api.delete_comment(comment_id=comment_id)
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.delete_comment(credentials, comment_id=input_data.comment_id)
|
||||
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
557
autogpt_platform/backend/backend/blocks/todoist/labels.py
Normal file
557
autogpt_platform/backend/backend/blocks/todoist/labels.py
Normal file
@@ -0,0 +1,557 @@
|
||||
from todoist_api_python.api import TodoistAPI
|
||||
from typing_extensions import Optional
|
||||
|
||||
from backend.blocks.todoist._auth import (
|
||||
TEST_CREDENTIALS,
|
||||
TEST_CREDENTIALS_INPUT,
|
||||
TodoistCredentials,
|
||||
TodoistCredentialsField,
|
||||
TodoistCredentialsInput,
|
||||
)
|
||||
from backend.blocks.todoist._types import Colors
|
||||
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
|
||||
from backend.data.model import SchemaField
|
||||
|
||||
|
||||
class TodoistCreateLabelBlock(Block):
|
||||
"""Creates a new label in Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
name: str = SchemaField(description="Name of the label")
|
||||
order: Optional[int] = SchemaField(description="Label order", default=None)
|
||||
color: Optional[Colors] = SchemaField(
|
||||
description="The color of the label icon", default=Colors.charcoal
|
||||
)
|
||||
is_favorite: bool = SchemaField(
|
||||
description="Whether the label is a favorite", default=False
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
id: str = SchemaField(description="ID of the created label")
|
||||
name: str = SchemaField(description="Name of the label")
|
||||
color: str = SchemaField(description="Color of the label")
|
||||
order: int = SchemaField(description="Label order")
|
||||
is_favorite: bool = SchemaField(description="Favorite status")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="7288a968-de14-11ef-8997-32d3674e8b7e",
|
||||
description="Creates a new label in Todoist, It will not work if same name already exists",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistCreateLabelBlock.Input,
|
||||
output_schema=TodoistCreateLabelBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"name": "Test Label",
|
||||
"color": Colors.charcoal.value,
|
||||
"order": 1,
|
||||
"is_favorite": False,
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("id", "2156154810"),
|
||||
("name", "Test Label"),
|
||||
("color", "charcoal"),
|
||||
("order", 1),
|
||||
("is_favorite", False),
|
||||
],
|
||||
test_mock={
|
||||
"create_label": lambda *args, **kwargs: {
|
||||
"id": "2156154810",
|
||||
"name": "Test Label",
|
||||
"color": "charcoal",
|
||||
"order": 1,
|
||||
"is_favorite": False,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def create_label(credentials: TodoistCredentials, name: str, **kwargs):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
label = api.add_label(name=name, **kwargs)
|
||||
return label.__dict__
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
label_args = {
|
||||
"order": input_data.order,
|
||||
"color": (
|
||||
input_data.color.value if input_data.color is not None else None
|
||||
),
|
||||
"is_favorite": input_data.is_favorite,
|
||||
}
|
||||
|
||||
label_data = self.create_label(
|
||||
credentials,
|
||||
input_data.name,
|
||||
**{k: v for k, v in label_args.items() if v is not None},
|
||||
)
|
||||
|
||||
if label_data:
|
||||
yield "id", label_data["id"]
|
||||
yield "name", label_data["name"]
|
||||
yield "color", label_data["color"]
|
||||
yield "order", label_data["order"]
|
||||
yield "is_favorite", label_data["is_favorite"]
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistListLabelsBlock(Block):
|
||||
"""Gets all personal labels from Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
|
||||
class Output(BlockSchema):
|
||||
labels: list = SchemaField(description="List of complete label data")
|
||||
label_ids: list = SchemaField(description="List of label IDs")
|
||||
label_names: list = SchemaField(description="List of label names")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="776dd750-de14-11ef-b927-32d3674e8b7e",
|
||||
description="Gets all personal labels from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistListLabelsBlock.Input,
|
||||
output_schema=TodoistListLabelsBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
(
|
||||
"labels",
|
||||
[
|
||||
{
|
||||
"id": "2156154810",
|
||||
"name": "Test Label",
|
||||
"color": "charcoal",
|
||||
"order": 1,
|
||||
"is_favorite": False,
|
||||
}
|
||||
],
|
||||
),
|
||||
("label_ids", ["2156154810"]),
|
||||
("label_names", ["Test Label"]),
|
||||
],
|
||||
test_mock={
|
||||
"get_labels": lambda *args, **kwargs: [
|
||||
{
|
||||
"id": "2156154810",
|
||||
"name": "Test Label",
|
||||
"color": "charcoal",
|
||||
"order": 1,
|
||||
"is_favorite": False,
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_labels(credentials: TodoistCredentials):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
labels = api.get_labels()
|
||||
return [label.__dict__ for label in labels]
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
labels = self.get_labels(credentials)
|
||||
yield "labels", labels
|
||||
yield "label_ids", [label["id"] for label in labels]
|
||||
yield "label_names", [label["name"] for label in labels]
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistGetLabelBlock(Block):
|
||||
"""Gets a personal label from Todoist by ID"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
label_id: str = SchemaField(description="ID of the label to retrieve")
|
||||
|
||||
class Output(BlockSchema):
|
||||
id: str = SchemaField(description="ID of the label")
|
||||
name: str = SchemaField(description="Name of the label")
|
||||
color: str = SchemaField(description="Color of the label")
|
||||
order: int = SchemaField(description="Label order")
|
||||
is_favorite: bool = SchemaField(description="Favorite status")
|
||||
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="7f236514-de14-11ef-bd7a-32d3674e8b7e",
|
||||
description="Gets a personal label from Todoist by ID",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistGetLabelBlock.Input,
|
||||
output_schema=TodoistGetLabelBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"label_id": "2156154810",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("id", "2156154810"),
|
||||
("name", "Test Label"),
|
||||
("color", "charcoal"),
|
||||
("order", 1),
|
||||
("is_favorite", False),
|
||||
],
|
||||
test_mock={
|
||||
"get_label": lambda *args, **kwargs: {
|
||||
"id": "2156154810",
|
||||
"name": "Test Label",
|
||||
"color": "charcoal",
|
||||
"order": 1,
|
||||
"is_favorite": False,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_label(credentials: TodoistCredentials, label_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
label = api.get_label(label_id=label_id)
|
||||
return label.__dict__
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
label_data = self.get_label(credentials, input_data.label_id)
|
||||
|
||||
if label_data:
|
||||
yield "id", label_data["id"]
|
||||
yield "name", label_data["name"]
|
||||
yield "color", label_data["color"]
|
||||
yield "order", label_data["order"]
|
||||
yield "is_favorite", label_data["is_favorite"]
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistUpdateLabelBlock(Block):
|
||||
"""Updates a personal label in Todoist using ID"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
label_id: str = SchemaField(description="ID of the label to update")
|
||||
name: Optional[str] = SchemaField(
|
||||
description="New name of the label", default=None
|
||||
)
|
||||
order: Optional[int] = SchemaField(description="Label order", default=None)
|
||||
color: Optional[Colors] = SchemaField(
|
||||
description="The color of the label icon", default=None
|
||||
)
|
||||
is_favorite: bool = SchemaField(
|
||||
description="Whether the label is a favorite (true/false)", default=False
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the update was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="8755614c-de14-11ef-9b56-32d3674e8b7e",
|
||||
description="Updates a personal label in Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistUpdateLabelBlock.Input,
|
||||
output_schema=TodoistUpdateLabelBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"label_id": "2156154810",
|
||||
"name": "Updated Label",
|
||||
"color": Colors.charcoal.value,
|
||||
"order": 2,
|
||||
"is_favorite": True,
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"update_label": lambda *args, **kwargs: True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def update_label(credentials: TodoistCredentials, label_id: str, **kwargs):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
api.update_label(label_id=label_id, **kwargs)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
label_args = {}
|
||||
if input_data.name is not None:
|
||||
label_args["name"] = input_data.name
|
||||
if input_data.order is not None:
|
||||
label_args["order"] = input_data.order
|
||||
if input_data.color is not None:
|
||||
label_args["color"] = input_data.color.value
|
||||
if input_data.is_favorite is not None:
|
||||
label_args["is_favorite"] = input_data.is_favorite
|
||||
|
||||
success = self.update_label(
|
||||
credentials,
|
||||
input_data.label_id,
|
||||
**{k: v for k, v in label_args.items() if v is not None},
|
||||
)
|
||||
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistDeleteLabelBlock(Block):
|
||||
"""Deletes a personal label in Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
label_id: str = SchemaField(description="ID of the label to delete")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the deletion was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="901b8f86-de14-11ef-98b8-32d3674e8b7e",
|
||||
description="Deletes a personal label in Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistDeleteLabelBlock.Input,
|
||||
output_schema=TodoistDeleteLabelBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"label_id": "2156154810",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"delete_label": lambda *args, **kwargs: True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_label(credentials: TodoistCredentials, label_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
success = api.delete_label(label_id=label_id)
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.delete_label(credentials, input_data.label_id)
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistGetSharedLabelsBlock(Block):
|
||||
"""Gets all shared labels from Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
|
||||
class Output(BlockSchema):
|
||||
labels: list = SchemaField(description="List of shared label names")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="55fba510-de15-11ef-aed2-32d3674e8b7e",
|
||||
description="Gets all shared labels from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistGetSharedLabelsBlock.Input,
|
||||
output_schema=TodoistGetSharedLabelsBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("labels", ["Label1", "Label2", "Label3"])],
|
||||
test_mock={
|
||||
"get_shared_labels": lambda *args, **kwargs: [
|
||||
"Label1",
|
||||
"Label2",
|
||||
"Label3",
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_shared_labels(credentials: TodoistCredentials):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
labels = api.get_shared_labels()
|
||||
return labels
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
labels = self.get_shared_labels(credentials)
|
||||
yield "labels", labels
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistRenameSharedLabelsBlock(Block):
|
||||
"""Renames all instances of a shared label"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
name: str = SchemaField(description="The name of the existing label to rename")
|
||||
new_name: str = SchemaField(description="The new name for the label")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the rename was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="9d63ad9a-de14-11ef-ab3f-32d3674e8b7e",
|
||||
description="Renames all instances of a shared label",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistRenameSharedLabelsBlock.Input,
|
||||
output_schema=TodoistRenameSharedLabelsBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"name": "OldLabel",
|
||||
"new_name": "NewLabel",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"rename_shared_labels": lambda *args, **kwargs: True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def rename_shared_labels(credentials: TodoistCredentials, name: str, new_name: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
success = api.rename_shared_label(name=name, new_name=new_name)
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.rename_shared_labels(
|
||||
credentials, input_data.name, input_data.new_name
|
||||
)
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistRemoveSharedLabelsBlock(Block):
|
||||
"""Removes all instances of a shared label"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
name: str = SchemaField(description="The name of the label to remove")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the removal was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="a6c5cbde-de14-11ef-8863-32d3674e8b7e",
|
||||
description="Removes all instances of a shared label",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistRemoveSharedLabelsBlock.Input,
|
||||
output_schema=TodoistRemoveSharedLabelsBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT, "name": "LabelToRemove"},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"remove_shared_label": lambda *args, **kwargs: True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def remove_shared_label(credentials: TodoistCredentials, name: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
success = api.remove_shared_label(name=name)
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.remove_shared_label(credentials, input_data.name)
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
566
autogpt_platform/backend/backend/blocks/todoist/projects.py
Normal file
566
autogpt_platform/backend/backend/blocks/todoist/projects.py
Normal file
@@ -0,0 +1,566 @@
|
||||
from todoist_api_python.api import TodoistAPI
|
||||
from typing_extensions import Optional
|
||||
|
||||
from backend.blocks.todoist._auth import (
|
||||
TEST_CREDENTIALS,
|
||||
TEST_CREDENTIALS_INPUT,
|
||||
TodoistCredentials,
|
||||
TodoistCredentialsField,
|
||||
TodoistCredentialsInput,
|
||||
)
|
||||
from backend.blocks.todoist._types import Colors
|
||||
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
|
||||
from backend.data.model import SchemaField
|
||||
|
||||
|
||||
class TodoistListProjectsBlock(Block):
|
||||
"""Gets all projects for a Todoist user"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
|
||||
class Output(BlockSchema):
|
||||
names_list: list[str] = SchemaField(description="List of project names")
|
||||
ids_list: list[str] = SchemaField(description="List of project IDs")
|
||||
url_list: list[str] = SchemaField(description="List of project URLs")
|
||||
complete_data: list[dict] = SchemaField(
|
||||
description="Complete project data including all fields"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="5f3e1d5b-6bc5-40e3-97ee-1318b3f38813",
|
||||
description="Gets all projects and their details from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistListProjectsBlock.Input,
|
||||
output_schema=TodoistListProjectsBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("names_list", ["Inbox"]),
|
||||
("ids_list", ["220474322"]),
|
||||
("url_list", ["https://todoist.com/showProject?id=220474322"]),
|
||||
(
|
||||
"complete_data",
|
||||
[
|
||||
{
|
||||
"id": "220474322",
|
||||
"name": "Inbox",
|
||||
"url": "https://todoist.com/showProject?id=220474322",
|
||||
}
|
||||
],
|
||||
),
|
||||
],
|
||||
test_mock={
|
||||
"get_project_lists": lambda *args, **kwargs: (
|
||||
["Inbox"],
|
||||
["220474322"],
|
||||
["https://todoist.com/showProject?id=220474322"],
|
||||
[
|
||||
{
|
||||
"id": "220474322",
|
||||
"name": "Inbox",
|
||||
"url": "https://todoist.com/showProject?id=220474322",
|
||||
}
|
||||
],
|
||||
None,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_project_lists(credentials: TodoistCredentials):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
projects = api.get_projects()
|
||||
|
||||
names = []
|
||||
ids = []
|
||||
urls = []
|
||||
complete_data = []
|
||||
|
||||
for project in projects:
|
||||
names.append(project.name)
|
||||
ids.append(project.id)
|
||||
urls.append(project.url)
|
||||
complete_data.append(project.__dict__)
|
||||
|
||||
return names, ids, urls, complete_data, None
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
names, ids, urls, data, error = self.get_project_lists(credentials)
|
||||
|
||||
if names:
|
||||
yield "names_list", names
|
||||
if ids:
|
||||
yield "ids_list", ids
|
||||
if urls:
|
||||
yield "url_list", urls
|
||||
if data:
|
||||
yield "complete_data", data
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistCreateProjectBlock(Block):
|
||||
"""Creates a new project in Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
name: str = SchemaField(description="Name of the project", advanced=False)
|
||||
parent_id: Optional[str] = SchemaField(
|
||||
description="Parent project ID", default=None, advanced=True
|
||||
)
|
||||
color: Optional[Colors] = SchemaField(
|
||||
description="Color of the project icon",
|
||||
default=Colors.charcoal,
|
||||
advanced=True,
|
||||
)
|
||||
is_favorite: bool = SchemaField(
|
||||
description="Whether the project is a favorite",
|
||||
default=False,
|
||||
advanced=True,
|
||||
)
|
||||
view_style: Optional[str] = SchemaField(
|
||||
description="Display style (list or board)", default=None, advanced=True
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the creation was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="ade60136-de14-11ef-b5e5-32d3674e8b7e",
|
||||
description="Creates a new project in Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistCreateProjectBlock.Input,
|
||||
output_schema=TodoistCreateProjectBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT, "name": "Test Project"},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"create_project": lambda *args, **kwargs: (True)},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def create_project(
|
||||
credentials: TodoistCredentials,
|
||||
name: str,
|
||||
parent_id: Optional[str],
|
||||
color: Optional[Colors],
|
||||
is_favorite: bool,
|
||||
view_style: Optional[str],
|
||||
):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
params = {"name": name, "is_favorite": is_favorite}
|
||||
|
||||
if parent_id is not None:
|
||||
params["parent_id"] = parent_id
|
||||
if color is not None:
|
||||
params["color"] = color.value
|
||||
if view_style is not None:
|
||||
params["view_style"] = view_style
|
||||
|
||||
api.add_project(**params)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.create_project(
|
||||
credentials=credentials,
|
||||
name=input_data.name,
|
||||
parent_id=input_data.parent_id,
|
||||
color=input_data.color,
|
||||
is_favorite=input_data.is_favorite,
|
||||
view_style=input_data.view_style,
|
||||
)
|
||||
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistGetProjectBlock(Block):
|
||||
"""Gets details for a specific Todoist project"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
project_id: str = SchemaField(
|
||||
description="ID of the project to get details for", advanced=False
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
project_id: str = SchemaField(description="ID of project")
|
||||
project_name: str = SchemaField(description="Name of project")
|
||||
project_url: str = SchemaField(description="URL of project")
|
||||
complete_data: dict = SchemaField(
|
||||
description="Complete project data including all fields"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="b435b5ea-de14-11ef-8b51-32d3674e8b7e",
|
||||
description="Gets details for a specific Todoist project",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistGetProjectBlock.Input,
|
||||
output_schema=TodoistGetProjectBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"project_id": "2203306141",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("project_id", "2203306141"),
|
||||
("project_name", "Shopping List"),
|
||||
("project_url", "https://todoist.com/showProject?id=2203306141"),
|
||||
(
|
||||
"complete_data",
|
||||
{
|
||||
"id": "2203306141",
|
||||
"name": "Shopping List",
|
||||
"url": "https://todoist.com/showProject?id=2203306141",
|
||||
},
|
||||
),
|
||||
],
|
||||
test_mock={
|
||||
"get_project": lambda *args, **kwargs: (
|
||||
"2203306141",
|
||||
"Shopping List",
|
||||
"https://todoist.com/showProject?id=2203306141",
|
||||
{
|
||||
"id": "2203306141",
|
||||
"name": "Shopping List",
|
||||
"url": "https://todoist.com/showProject?id=2203306141",
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_project(credentials: TodoistCredentials, project_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
project = api.get_project(project_id=project_id)
|
||||
|
||||
return project.id, project.name, project.url, project.__dict__
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
project_id, project_name, project_url, data = self.get_project(
|
||||
credentials=credentials, project_id=input_data.project_id
|
||||
)
|
||||
|
||||
if project_id:
|
||||
yield "project_id", project_id
|
||||
if project_name:
|
||||
yield "project_name", project_name
|
||||
if project_url:
|
||||
yield "project_url", project_url
|
||||
if data:
|
||||
yield "complete_data", data
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistUpdateProjectBlock(Block):
|
||||
"""Updates an existing project in Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
project_id: str = SchemaField(
|
||||
description="ID of project to update", advanced=False
|
||||
)
|
||||
name: Optional[str] = SchemaField(
|
||||
description="New name for the project", default=None, advanced=False
|
||||
)
|
||||
color: Optional[Colors] = SchemaField(
|
||||
description="New color for the project icon", default=None, advanced=True
|
||||
)
|
||||
is_favorite: Optional[bool] = SchemaField(
|
||||
description="Whether the project should be a favorite",
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
view_style: Optional[str] = SchemaField(
|
||||
description="Display style (list or board)", default=None, advanced=True
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the update was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="ba41a20a-de14-11ef-91d7-32d3674e8b7e",
|
||||
description="Updates an existing project in Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistUpdateProjectBlock.Input,
|
||||
output_schema=TodoistUpdateProjectBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"project_id": "2203306141",
|
||||
"name": "Things To Buy",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"update_project": lambda *args, **kwargs: (True)},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def update_project(
|
||||
credentials: TodoistCredentials,
|
||||
project_id: str,
|
||||
name: Optional[str],
|
||||
color: Optional[Colors],
|
||||
is_favorite: Optional[bool],
|
||||
view_style: Optional[str],
|
||||
):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
params = {}
|
||||
|
||||
if name is not None:
|
||||
params["name"] = name
|
||||
if color is not None:
|
||||
params["color"] = color.value
|
||||
if is_favorite is not None:
|
||||
params["is_favorite"] = is_favorite
|
||||
if view_style is not None:
|
||||
params["view_style"] = view_style
|
||||
|
||||
api.update_project(project_id=project_id, **params)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.update_project(
|
||||
credentials=credentials,
|
||||
project_id=input_data.project_id,
|
||||
name=input_data.name,
|
||||
color=input_data.color,
|
||||
is_favorite=input_data.is_favorite,
|
||||
view_style=input_data.view_style,
|
||||
)
|
||||
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistDeleteProjectBlock(Block):
|
||||
"""Deletes a project and all of its sections and tasks"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
project_id: str = SchemaField(
|
||||
description="ID of project to delete", advanced=False
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the deletion was successful")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="c2893acc-de14-11ef-a113-32d3674e8b7e",
|
||||
description="Deletes a Todoist project and all its contents",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistDeleteProjectBlock.Input,
|
||||
output_schema=TodoistDeleteProjectBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"project_id": "2203306141",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"delete_project": lambda *args, **kwargs: (True)},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_project(credentials: TodoistCredentials, project_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
success = api.delete_project(project_id=project_id)
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.delete_project(
|
||||
credentials=credentials, project_id=input_data.project_id
|
||||
)
|
||||
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistListCollaboratorsBlock(Block):
|
||||
"""Gets all collaborators for a Todoist project"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
project_id: str = SchemaField(
|
||||
description="ID of the project to get collaborators for", advanced=False
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
collaborator_ids: list[str] = SchemaField(
|
||||
description="List of collaborator IDs"
|
||||
)
|
||||
collaborator_names: list[str] = SchemaField(
|
||||
description="List of collaborator names"
|
||||
)
|
||||
collaborator_emails: list[str] = SchemaField(
|
||||
description="List of collaborator email addresses"
|
||||
)
|
||||
complete_data: list[dict] = SchemaField(
|
||||
description="Complete collaborator data including all fields"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="c99c804e-de14-11ef-9f47-32d3674e8b7e",
|
||||
description="Gets all collaborators for a specific Todoist project",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistListCollaboratorsBlock.Input,
|
||||
output_schema=TodoistListCollaboratorsBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"project_id": "2203306141",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("collaborator_ids", ["2671362", "2671366"]),
|
||||
("collaborator_names", ["Alice", "Bob"]),
|
||||
("collaborator_emails", ["alice@example.com", "bob@example.com"]),
|
||||
(
|
||||
"complete_data",
|
||||
[
|
||||
{
|
||||
"id": "2671362",
|
||||
"name": "Alice",
|
||||
"email": "alice@example.com",
|
||||
},
|
||||
{"id": "2671366", "name": "Bob", "email": "bob@example.com"},
|
||||
],
|
||||
),
|
||||
],
|
||||
test_mock={
|
||||
"get_collaborators": lambda *args, **kwargs: (
|
||||
["2671362", "2671366"],
|
||||
["Alice", "Bob"],
|
||||
["alice@example.com", "bob@example.com"],
|
||||
[
|
||||
{
|
||||
"id": "2671362",
|
||||
"name": "Alice",
|
||||
"email": "alice@example.com",
|
||||
},
|
||||
{"id": "2671366", "name": "Bob", "email": "bob@example.com"},
|
||||
],
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_collaborators(credentials: TodoistCredentials, project_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
collaborators = api.get_collaborators(project_id=project_id)
|
||||
|
||||
ids = []
|
||||
names = []
|
||||
emails = []
|
||||
complete_data = []
|
||||
|
||||
for collaborator in collaborators:
|
||||
ids.append(collaborator.id)
|
||||
names.append(collaborator.name)
|
||||
emails.append(collaborator.email)
|
||||
complete_data.append(collaborator.__dict__)
|
||||
|
||||
return ids, names, emails, complete_data
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
ids, names, emails, data = self.get_collaborators(
|
||||
credentials=credentials, project_id=input_data.project_id
|
||||
)
|
||||
|
||||
if ids:
|
||||
yield "collaborator_ids", ids
|
||||
if names:
|
||||
yield "collaborator_names", names
|
||||
if emails:
|
||||
yield "collaborator_emails", emails
|
||||
if data:
|
||||
yield "complete_data", data
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
306
autogpt_platform/backend/backend/blocks/todoist/sections.py
Normal file
306
autogpt_platform/backend/backend/blocks/todoist/sections.py
Normal file
@@ -0,0 +1,306 @@
|
||||
from todoist_api_python.api import TodoistAPI
|
||||
from typing_extensions import Optional
|
||||
|
||||
from backend.blocks.todoist._auth import (
|
||||
TEST_CREDENTIALS,
|
||||
TEST_CREDENTIALS_INPUT,
|
||||
TodoistCredentials,
|
||||
TodoistCredentialsField,
|
||||
TodoistCredentialsInput,
|
||||
)
|
||||
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
|
||||
from backend.data.model import SchemaField
|
||||
|
||||
|
||||
class TodoistListSectionsBlock(Block):
|
||||
"""Gets all sections for a Todoist project"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
project_id: Optional[str] = SchemaField(
|
||||
description="Optional project ID to filter sections"
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
names_list: list[str] = SchemaField(description="List of section names")
|
||||
ids_list: list[str] = SchemaField(description="List of section IDs")
|
||||
complete_data: list[dict] = SchemaField(
|
||||
description="Complete section data including all fields"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="d6a116d8-de14-11ef-a94c-32d3674e8b7e",
|
||||
description="Gets all sections and their details from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistListSectionsBlock.Input,
|
||||
output_schema=TodoistListSectionsBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"project_id": "2203306141",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("names_list", ["Groceries"]),
|
||||
("ids_list", ["7025"]),
|
||||
(
|
||||
"complete_data",
|
||||
[
|
||||
{
|
||||
"id": "7025",
|
||||
"project_id": "2203306141",
|
||||
"order": 1,
|
||||
"name": "Groceries",
|
||||
}
|
||||
],
|
||||
),
|
||||
],
|
||||
test_mock={
|
||||
"get_section_lists": lambda *args, **kwargs: (
|
||||
["Groceries"],
|
||||
["7025"],
|
||||
[
|
||||
{
|
||||
"id": "7025",
|
||||
"project_id": "2203306141",
|
||||
"order": 1,
|
||||
"name": "Groceries",
|
||||
}
|
||||
],
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_section_lists(
|
||||
credentials: TodoistCredentials, project_id: Optional[str] = None
|
||||
):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
sections = api.get_sections(project_id=project_id)
|
||||
|
||||
names = []
|
||||
ids = []
|
||||
complete_data = []
|
||||
|
||||
for section in sections:
|
||||
names.append(section.name)
|
||||
ids.append(section.id)
|
||||
complete_data.append(section.__dict__)
|
||||
|
||||
return names, ids, complete_data
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
names, ids, data = self.get_section_lists(
|
||||
credentials, input_data.project_id
|
||||
)
|
||||
|
||||
if names:
|
||||
yield "names_list", names
|
||||
if ids:
|
||||
yield "ids_list", ids
|
||||
if data:
|
||||
yield "complete_data", data
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
# Error in official todoist SDK. Will add this block using sync_api
|
||||
# class TodoistCreateSectionBlock(Block):
|
||||
# """Creates a new section in a Todoist project"""
|
||||
|
||||
# class Input(BlockSchema):
|
||||
# credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
# name: str = SchemaField(description="Section name")
|
||||
# project_id: str = SchemaField(description="Project ID this section should belong to")
|
||||
# order: Optional[int] = SchemaField(description="Optional order among other sections", default=None)
|
||||
|
||||
# class Output(BlockSchema):
|
||||
# success: bool = SchemaField(description="Whether section was successfully created")
|
||||
# error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
# def __init__(self):
|
||||
# super().__init__(
|
||||
# id="e3025cfc-de14-11ef-b9f2-32d3674e8b7e",
|
||||
# description="Creates a new section in a Todoist project",
|
||||
# categories={BlockCategory.PRODUCTIVITY},
|
||||
# input_schema=TodoistCreateSectionBlock.Input,
|
||||
# output_schema=TodoistCreateSectionBlock.Output,
|
||||
# test_input={
|
||||
# "credentials": TEST_CREDENTIALS_INPUT,
|
||||
# "name": "Groceries",
|
||||
# "project_id": "2203306141"
|
||||
# },
|
||||
# test_credentials=TEST_CREDENTIALS,
|
||||
# test_output=[
|
||||
# ("success", True)
|
||||
# ],
|
||||
# test_mock={
|
||||
# "create_section": lambda *args, **kwargs: (
|
||||
# {"id": "7025", "project_id": "2203306141", "order": 1, "name": "Groceries"},
|
||||
# )
|
||||
# },
|
||||
# )
|
||||
|
||||
# @staticmethod
|
||||
# def create_section(credentials: TodoistCredentials, name: str, project_id: str, order: Optional[int] = None):
|
||||
# try:
|
||||
# api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
# section = api.add_section(name=name, project_id=project_id, order=order)
|
||||
# return section.__dict__
|
||||
|
||||
# except Exception as e:
|
||||
# raise e
|
||||
|
||||
# def run(
|
||||
# self,
|
||||
# input_data: Input,
|
||||
# *,
|
||||
# credentials: TodoistCredentials,
|
||||
# **kwargs,
|
||||
# ) -> BlockOutput:
|
||||
# try:
|
||||
# section_data = self.create_section(
|
||||
# credentials,
|
||||
# input_data.name,
|
||||
# input_data.project_id,
|
||||
# input_data.order
|
||||
# )
|
||||
|
||||
# if section_data:
|
||||
# yield "success", True
|
||||
|
||||
# except Exception as e:
|
||||
# yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistGetSectionBlock(Block):
|
||||
"""Gets a single section from Todoist by ID"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
section_id: str = SchemaField(description="ID of section to fetch")
|
||||
|
||||
class Output(BlockSchema):
|
||||
id: str = SchemaField(description="ID of section")
|
||||
project_id: str = SchemaField(description="Project ID the section belongs to")
|
||||
order: int = SchemaField(description="Order of the section")
|
||||
name: str = SchemaField(description="Name of the section")
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="ea5580e2-de14-11ef-a5d3-32d3674e8b7e",
|
||||
description="Gets a single section by ID from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistGetSectionBlock.Input,
|
||||
output_schema=TodoistGetSectionBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT, "section_id": "7025"},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("id", "7025"),
|
||||
("project_id", "2203306141"),
|
||||
("order", 1),
|
||||
("name", "Groceries"),
|
||||
],
|
||||
test_mock={
|
||||
"get_section": lambda *args, **kwargs: {
|
||||
"id": "7025",
|
||||
"project_id": "2203306141",
|
||||
"order": 1,
|
||||
"name": "Groceries",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_section(credentials: TodoistCredentials, section_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
section = api.get_section(section_id=section_id)
|
||||
return section.__dict__
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
section_data = self.get_section(credentials, input_data.section_id)
|
||||
|
||||
if section_data:
|
||||
yield "id", section_data["id"]
|
||||
yield "project_id", section_data["project_id"]
|
||||
yield "order", section_data["order"]
|
||||
yield "name", section_data["name"]
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistDeleteSectionBlock(Block):
|
||||
"""Deletes a section and all its tasks from Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
section_id: str = SchemaField(description="ID of section to delete")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(
|
||||
description="Whether section was successfully deleted"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if the request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="f0e52eee-de14-11ef-9b12-32d3674e8b7e",
|
||||
description="Deletes a section and all its tasks from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistDeleteSectionBlock.Input,
|
||||
output_schema=TodoistDeleteSectionBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT, "section_id": "7025"},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"delete_section": lambda *args, **kwargs: (True)},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_section(credentials: TodoistCredentials, section_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
success = api.delete_section(section_id=section_id)
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
success = self.delete_section(credentials, input_data.section_id)
|
||||
yield "success", success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
660
autogpt_platform/backend/backend/blocks/todoist/tasks.py
Normal file
660
autogpt_platform/backend/backend/blocks/todoist/tasks.py
Normal file
@@ -0,0 +1,660 @@
|
||||
from datetime import datetime
|
||||
|
||||
from todoist_api_python.api import TodoistAPI
|
||||
from todoist_api_python.models import Task
|
||||
from typing_extensions import Optional
|
||||
|
||||
from backend.blocks.todoist._auth import (
|
||||
TEST_CREDENTIALS,
|
||||
TEST_CREDENTIALS_INPUT,
|
||||
TodoistCredentials,
|
||||
TodoistCredentialsField,
|
||||
TodoistCredentialsInput,
|
||||
)
|
||||
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
|
||||
from backend.data.model import SchemaField
|
||||
|
||||
|
||||
class TodoistCreateTaskBlock(Block):
|
||||
"""Creates a new task in a Todoist project"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
content: str = SchemaField(description="Task content", advanced=False)
|
||||
description: Optional[str] = SchemaField(
|
||||
description="Task description", default=None, advanced=False
|
||||
)
|
||||
project_id: Optional[str] = SchemaField(
|
||||
description="Project ID this task should belong to",
|
||||
default=None,
|
||||
advanced=False,
|
||||
)
|
||||
section_id: Optional[str] = SchemaField(
|
||||
description="Section ID this task should belong to",
|
||||
default=None,
|
||||
advanced=False,
|
||||
)
|
||||
parent_id: Optional[str] = SchemaField(
|
||||
description="Parent task ID", default=None, advanced=True
|
||||
)
|
||||
order: Optional[int] = SchemaField(
|
||||
description="Optional order among other tasks,[Non-zero integer value used by clients to sort tasks under the same parent]",
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
labels: Optional[list[str]] = SchemaField(
|
||||
description="Task labels", default=None, advanced=True
|
||||
)
|
||||
priority: Optional[int] = SchemaField(
|
||||
description="Task priority from 1 (normal) to 4 (urgent)",
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
due_date: Optional[datetime] = SchemaField(
|
||||
description="Due date in YYYY-MM-DD format", advanced=True, default=None
|
||||
)
|
||||
deadline_date: Optional[datetime] = SchemaField(
|
||||
description="Specific date in YYYY-MM-DD format relative to user's timezone",
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
assignee_id: Optional[str] = SchemaField(
|
||||
description="Responsible user ID", default=None, advanced=True
|
||||
)
|
||||
duration_unit: Optional[str] = SchemaField(
|
||||
description="Task duration unit (minute/day)", default=None, advanced=True
|
||||
)
|
||||
duration: Optional[int] = SchemaField(
|
||||
description="Task duration amount, You need to selecct the duration unit first",
|
||||
depends_on=["duration_unit"],
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
id: str = SchemaField(description="Task ID")
|
||||
url: str = SchemaField(description="Task URL")
|
||||
complete_data: dict = SchemaField(
|
||||
description="Complete task data as dictionary"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="fde4f458-de14-11ef-bf0c-32d3674e8b7e",
|
||||
description="Creates a new task in a Todoist project",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistCreateTaskBlock.Input,
|
||||
output_schema=TodoistCreateTaskBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"content": "Buy groceries",
|
||||
"project_id": "2203306141",
|
||||
"priority": 4,
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("id", "2995104339"),
|
||||
("url", "https://todoist.com/showTask?id=2995104339"),
|
||||
(
|
||||
"complete_data",
|
||||
{
|
||||
"id": "2995104339",
|
||||
"project_id": "2203306141",
|
||||
"url": "https://todoist.com/showTask?id=2995104339",
|
||||
},
|
||||
),
|
||||
],
|
||||
test_mock={
|
||||
"create_task": lambda *args, **kwargs: (
|
||||
"2995104339",
|
||||
"https://todoist.com/showTask?id=2995104339",
|
||||
{
|
||||
"id": "2995104339",
|
||||
"project_id": "2203306141",
|
||||
"url": "https://todoist.com/showTask?id=2995104339",
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def create_task(credentials: TodoistCredentials, content: str, **kwargs):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
task = api.add_task(content=content, **kwargs)
|
||||
task_dict = Task.to_dict(task)
|
||||
return task.id, task.url, task_dict
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
due_date = (
|
||||
input_data.due_date.strftime("%Y-%m-%d")
|
||||
if input_data.due_date
|
||||
else None
|
||||
)
|
||||
deadline_date = (
|
||||
input_data.deadline_date.strftime("%Y-%m-%d")
|
||||
if input_data.deadline_date
|
||||
else None
|
||||
)
|
||||
|
||||
task_args = {
|
||||
"description": input_data.description,
|
||||
"project_id": input_data.project_id,
|
||||
"section_id": input_data.section_id,
|
||||
"parent_id": input_data.parent_id,
|
||||
"order": input_data.order,
|
||||
"labels": input_data.labels,
|
||||
"priority": input_data.priority,
|
||||
"due_date": due_date,
|
||||
"deadline_date": deadline_date,
|
||||
"assignee_id": input_data.assignee_id,
|
||||
"duration": input_data.duration,
|
||||
"duration_unit": input_data.duration_unit,
|
||||
}
|
||||
|
||||
id, url, complete_data = self.create_task(
|
||||
credentials,
|
||||
input_data.content,
|
||||
**{k: v for k, v in task_args.items() if v is not None},
|
||||
)
|
||||
|
||||
yield "id", id
|
||||
yield "url", url
|
||||
yield "complete_data", complete_data
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistGetTasksBlock(Block):
|
||||
"""Get active tasks from Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
project_id: Optional[str] = SchemaField(
|
||||
description="Filter tasks by project ID", default=None, advanced=False
|
||||
)
|
||||
section_id: Optional[str] = SchemaField(
|
||||
description="Filter tasks by section ID", default=None, advanced=True
|
||||
)
|
||||
label: Optional[str] = SchemaField(
|
||||
description="Filter tasks by label name", default=None, advanced=True
|
||||
)
|
||||
filter: Optional[str] = SchemaField(
|
||||
description="Filter by any supported filter, You can see How to use filters or create one of your one here - https://todoist.com/help/articles/introduction-to-filters-V98wIH",
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
lang: Optional[str] = SchemaField(
|
||||
description="IETF language tag for filter language", default=None
|
||||
)
|
||||
ids: Optional[list[str]] = SchemaField(
|
||||
description="List of task IDs to retrieve", default=None, advanced=False
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
ids: list[str] = SchemaField(description="Task IDs")
|
||||
urls: list[str] = SchemaField(description="Task URLs")
|
||||
complete_data: list[dict] = SchemaField(
|
||||
description="Complete task data as dictionary"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="0b706e86-de15-11ef-a113-32d3674e8b7e",
|
||||
description="Get active tasks from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistGetTasksBlock.Input,
|
||||
output_schema=TodoistGetTasksBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"project_id": "2203306141",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("ids", ["2995104339"]),
|
||||
("urls", ["https://todoist.com/showTask?id=2995104339"]),
|
||||
(
|
||||
"complete_data",
|
||||
[
|
||||
{
|
||||
"id": "2995104339",
|
||||
"project_id": "2203306141",
|
||||
"url": "https://todoist.com/showTask?id=2995104339",
|
||||
"is_completed": False,
|
||||
}
|
||||
],
|
||||
),
|
||||
],
|
||||
test_mock={
|
||||
"get_tasks": lambda *args, **kwargs: [
|
||||
{
|
||||
"id": "2995104339",
|
||||
"project_id": "2203306141",
|
||||
"url": "https://todoist.com/showTask?id=2995104339",
|
||||
"is_completed": False,
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_tasks(credentials: TodoistCredentials, **kwargs):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
tasks = api.get_tasks(**kwargs)
|
||||
return [Task.to_dict(task) for task in tasks]
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
task_filters = {
|
||||
"project_id": input_data.project_id,
|
||||
"section_id": input_data.section_id,
|
||||
"label": input_data.label,
|
||||
"filter": input_data.filter,
|
||||
"lang": input_data.lang,
|
||||
"ids": input_data.ids,
|
||||
}
|
||||
|
||||
tasks = self.get_tasks(
|
||||
credentials, **{k: v for k, v in task_filters.items() if v is not None}
|
||||
)
|
||||
|
||||
yield "ids", [task["id"] for task in tasks]
|
||||
yield "urls", [task["url"] for task in tasks]
|
||||
yield "complete_data", tasks
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistGetTaskBlock(Block):
|
||||
"""Get an active task from Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
task_id: str = SchemaField(description="Task ID to retrieve")
|
||||
|
||||
class Output(BlockSchema):
|
||||
project_id: str = SchemaField(description="Project ID containing the task")
|
||||
url: str = SchemaField(description="Task URL")
|
||||
complete_data: dict = SchemaField(
|
||||
description="Complete task data as dictionary"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="16d7dc8c-de15-11ef-8ace-32d3674e8b7e",
|
||||
description="Get an active task from Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistGetTaskBlock.Input,
|
||||
output_schema=TodoistGetTaskBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT, "task_id": "2995104339"},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("project_id", "2203306141"),
|
||||
("url", "https://todoist.com/showTask?id=2995104339"),
|
||||
(
|
||||
"complete_data",
|
||||
{
|
||||
"id": "2995104339",
|
||||
"project_id": "2203306141",
|
||||
"url": "https://todoist.com/showTask?id=2995104339",
|
||||
},
|
||||
),
|
||||
],
|
||||
test_mock={
|
||||
"get_task": lambda *args, **kwargs: {
|
||||
"project_id": "2203306141",
|
||||
"id": "2995104339",
|
||||
"url": "https://todoist.com/showTask?id=2995104339",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_task(credentials: TodoistCredentials, task_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
task = api.get_task(task_id=task_id)
|
||||
return Task.to_dict(task)
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
task_data = self.get_task(credentials, input_data.task_id)
|
||||
|
||||
if task_data:
|
||||
yield "project_id", task_data["project_id"]
|
||||
yield "url", task_data["url"]
|
||||
yield "complete_data", task_data
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistUpdateTaskBlock(Block):
|
||||
"""Updates an existing task in Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
task_id: str = SchemaField(description="Task ID to update")
|
||||
content: str = SchemaField(description="Task content", advanced=False)
|
||||
description: Optional[str] = SchemaField(
|
||||
description="Task description", default=None, advanced=False
|
||||
)
|
||||
project_id: Optional[str] = SchemaField(
|
||||
description="Project ID this task should belong to",
|
||||
default=None,
|
||||
advanced=False,
|
||||
)
|
||||
section_id: Optional[str] = SchemaField(
|
||||
description="Section ID this task should belong to",
|
||||
default=None,
|
||||
advanced=False,
|
||||
)
|
||||
parent_id: Optional[str] = SchemaField(
|
||||
description="Parent task ID", default=None, advanced=True
|
||||
)
|
||||
order: Optional[int] = SchemaField(
|
||||
description="Optional order among other tasks,[Non-zero integer value used by clients to sort tasks under the same parent]",
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
labels: Optional[list[str]] = SchemaField(
|
||||
description="Task labels", default=None, advanced=True
|
||||
)
|
||||
priority: Optional[int] = SchemaField(
|
||||
description="Task priority from 1 (normal) to 4 (urgent)",
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
due_date: Optional[datetime] = SchemaField(
|
||||
description="Due date in YYYY-MM-DD format", advanced=True, default=None
|
||||
)
|
||||
deadline_date: Optional[datetime] = SchemaField(
|
||||
description="Specific date in YYYY-MM-DD format relative to user's timezone",
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
assignee_id: Optional[str] = SchemaField(
|
||||
description="Responsible user ID", default=None, advanced=True
|
||||
)
|
||||
duration_unit: Optional[str] = SchemaField(
|
||||
description="Task duration unit (minute/day)", default=None, advanced=True
|
||||
)
|
||||
duration: Optional[int] = SchemaField(
|
||||
description="Task duration amount, You need to selecct the duration unit first",
|
||||
depends_on=["duration_unit"],
|
||||
default=None,
|
||||
advanced=True,
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(description="Whether the update was successful")
|
||||
error: str = SchemaField(description="Error message if request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="1eee6d32-de15-11ef-a2ff-32d3674e8b7e",
|
||||
description="Updates an existing task in Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistUpdateTaskBlock.Input,
|
||||
output_schema=TodoistUpdateTaskBlock.Output,
|
||||
test_input={
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
"task_id": "2995104339",
|
||||
"content": "Buy Coffee",
|
||||
},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"update_task": lambda *args, **kwargs: True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def update_task(credentials: TodoistCredentials, task_id: str, **kwargs):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
is_success = api.update_task(task_id=task_id, **kwargs)
|
||||
return is_success
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
due_date = (
|
||||
input_data.due_date.strftime("%Y-%m-%d")
|
||||
if input_data.due_date
|
||||
else None
|
||||
)
|
||||
deadline_date = (
|
||||
input_data.deadline_date.strftime("%Y-%m-%d")
|
||||
if input_data.deadline_date
|
||||
else None
|
||||
)
|
||||
|
||||
task_updates = {}
|
||||
if input_data.content is not None:
|
||||
task_updates["content"] = input_data.content
|
||||
if input_data.description is not None:
|
||||
task_updates["description"] = input_data.description
|
||||
if input_data.project_id is not None:
|
||||
task_updates["project_id"] = input_data.project_id
|
||||
if input_data.section_id is not None:
|
||||
task_updates["section_id"] = input_data.section_id
|
||||
if input_data.parent_id is not None:
|
||||
task_updates["parent_id"] = input_data.parent_id
|
||||
if input_data.order is not None:
|
||||
task_updates["order"] = input_data.order
|
||||
if input_data.labels is not None:
|
||||
task_updates["labels"] = input_data.labels
|
||||
if input_data.priority is not None:
|
||||
task_updates["priority"] = input_data.priority
|
||||
if due_date is not None:
|
||||
task_updates["due_date"] = due_date
|
||||
if deadline_date is not None:
|
||||
task_updates["deadline_date"] = deadline_date
|
||||
if input_data.assignee_id is not None:
|
||||
task_updates["assignee_id"] = input_data.assignee_id
|
||||
if input_data.duration is not None:
|
||||
task_updates["duration"] = input_data.duration
|
||||
if input_data.duration_unit is not None:
|
||||
task_updates["duration_unit"] = input_data.duration_unit
|
||||
|
||||
self.update_task(
|
||||
credentials,
|
||||
input_data.task_id,
|
||||
**{k: v for k, v in task_updates.items() if v is not None},
|
||||
)
|
||||
|
||||
yield "success", True
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistCloseTaskBlock(Block):
|
||||
"""Closes a task in Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
task_id: str = SchemaField(description="Task ID to close")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(
|
||||
description="Whether the task was successfully closed"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="29fac798-de15-11ef-b839-32d3674e8b7e",
|
||||
description="Closes a task in Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistCloseTaskBlock.Input,
|
||||
output_schema=TodoistCloseTaskBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT, "task_id": "2995104339"},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[("success", True)],
|
||||
test_mock={"close_task": lambda *args, **kwargs: True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def close_task(credentials: TodoistCredentials, task_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
is_success = api.close_task(task_id=task_id)
|
||||
return is_success
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
is_success = self.close_task(credentials, input_data.task_id)
|
||||
yield "success", is_success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistReopenTaskBlock(Block):
|
||||
"""Reopens a task in Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
task_id: str = SchemaField(description="Task ID to reopen")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(
|
||||
description="Whether the task was successfully reopened"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="2e6bf6f8-de15-11ef-ae7c-32d3674e8b7e",
|
||||
description="Reopens a task in Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistReopenTaskBlock.Input,
|
||||
output_schema=TodoistReopenTaskBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT, "task_id": "2995104339"},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("success", True),
|
||||
],
|
||||
test_mock={"reopen_task": lambda *args, **kwargs: (True)},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def reopen_task(credentials: TodoistCredentials, task_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
is_success = api.reopen_task(task_id=task_id)
|
||||
return is_success
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
is_success = self.reopen_task(credentials, input_data.task_id)
|
||||
yield "success", is_success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
|
||||
|
||||
class TodoistDeleteTaskBlock(Block):
|
||||
"""Deletes a task in Todoist"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
credentials: TodoistCredentialsInput = TodoistCredentialsField([])
|
||||
task_id: str = SchemaField(description="Task ID to delete")
|
||||
|
||||
class Output(BlockSchema):
|
||||
success: bool = SchemaField(
|
||||
description="Whether the task was successfully deleted"
|
||||
)
|
||||
error: str = SchemaField(description="Error message if request failed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="33c29ada-de15-11ef-bcbb-32d3674e8b7e",
|
||||
description="Deletes a task in Todoist",
|
||||
categories={BlockCategory.PRODUCTIVITY},
|
||||
input_schema=TodoistDeleteTaskBlock.Input,
|
||||
output_schema=TodoistDeleteTaskBlock.Output,
|
||||
test_input={"credentials": TEST_CREDENTIALS_INPUT, "task_id": "2995104339"},
|
||||
test_credentials=TEST_CREDENTIALS,
|
||||
test_output=[
|
||||
("success", True),
|
||||
],
|
||||
test_mock={"delete_task": lambda *args, **kwargs: (True)},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_task(credentials: TodoistCredentials, task_id: str):
|
||||
try:
|
||||
api = TodoistAPI(credentials.access_token.get_secret_value())
|
||||
is_success = api.delete_task(task_id=task_id)
|
||||
return is_success
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def run(
|
||||
self,
|
||||
input_data: Input,
|
||||
*,
|
||||
credentials: TodoistCredentials,
|
||||
**kwargs,
|
||||
) -> BlockOutput:
|
||||
try:
|
||||
is_success = self.delete_task(credentials, input_data.task_id)
|
||||
yield "success", is_success
|
||||
|
||||
except Exception as e:
|
||||
yield "error", str(e)
|
||||
@@ -92,7 +92,8 @@ class TwitterPostTweetBlock(Block):
|
||||
attachment: Union[Media, DeepLink, Poll, Place, Quote] | None = SchemaField(
|
||||
discriminator="discriminator",
|
||||
description="Additional tweet data (media, deep link, poll, place or quote)",
|
||||
advanced=True,
|
||||
advanced=False,
|
||||
default=Media(discriminator="media"),
|
||||
)
|
||||
|
||||
exclude_reply_user_ids: Optional[List[str]] = SchemaField(
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from backend.integrations.oauth.todoist import TodoistOAuthHandler
|
||||
|
||||
from .github import GitHubOAuthHandler
|
||||
from .google import GoogleOAuthHandler
|
||||
from .linear import LinearOAuthHandler
|
||||
@@ -19,6 +21,7 @@ HANDLERS_BY_NAME: dict["ProviderName", type["BaseOAuthHandler"]] = {
|
||||
NotionOAuthHandler,
|
||||
TwitterOAuthHandler,
|
||||
LinearOAuthHandler,
|
||||
TodoistOAuthHandler,
|
||||
]
|
||||
}
|
||||
# --8<-- [end:HANDLERS_BY_NAMEExample]
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import urllib.parse
|
||||
from typing import ClassVar, Optional
|
||||
|
||||
import requests
|
||||
|
||||
from backend.data.model import OAuth2Credentials, ProviderName
|
||||
from backend.integrations.oauth.base import BaseOAuthHandler
|
||||
|
||||
|
||||
class TodoistOAuthHandler(BaseOAuthHandler):
|
||||
PROVIDER_NAME = ProviderName.TODOIST
|
||||
DEFAULT_SCOPES: ClassVar[list[str]] = [
|
||||
"task:add",
|
||||
"data:read",
|
||||
"data:read_write",
|
||||
"data:delete",
|
||||
"project:delete",
|
||||
]
|
||||
|
||||
AUTHORIZE_URL = "https://todoist.com/oauth/authorize"
|
||||
TOKEN_URL = "https://todoist.com/oauth/access_token"
|
||||
|
||||
def __init__(self, client_id: str, client_secret: str, redirect_uri: str):
|
||||
self.client_id = client_id
|
||||
self.client_secret = client_secret
|
||||
self.redirect_uri = redirect_uri
|
||||
|
||||
def get_login_url(
|
||||
self, scopes: list[str], state: str, code_challenge: Optional[str]
|
||||
) -> str:
|
||||
params = {
|
||||
"client_id": self.client_id,
|
||||
"scope": ",".join(self.DEFAULT_SCOPES),
|
||||
"state": state,
|
||||
}
|
||||
|
||||
return f"{self.AUTHORIZE_URL}?{urllib.parse.urlencode(params)}"
|
||||
|
||||
def exchange_code_for_tokens(
|
||||
self, code: str, scopes: list[str], code_verifier: Optional[str]
|
||||
) -> OAuth2Credentials:
|
||||
"""Exchange authorization code for access tokens"""
|
||||
|
||||
data = {
|
||||
"client_id": self.client_id,
|
||||
"client_secret": self.client_secret,
|
||||
"code": code,
|
||||
"redirect_uri": self.redirect_uri,
|
||||
}
|
||||
|
||||
response = requests.post(self.TOKEN_URL, data=data)
|
||||
response.raise_for_status()
|
||||
|
||||
tokens = response.json()
|
||||
|
||||
response = requests.post(
|
||||
"https://api.todoist.com/sync/v9/sync",
|
||||
headers={"Authorization": f"Bearer {tokens['access_token']}"},
|
||||
data={"sync_token": "*", "resource_types": '["user"]'},
|
||||
)
|
||||
response.raise_for_status()
|
||||
user_info = response.json()
|
||||
user_email = user_info["user"].get("email")
|
||||
|
||||
return OAuth2Credentials(
|
||||
provider=self.PROVIDER_NAME,
|
||||
title=None,
|
||||
username=user_email,
|
||||
access_token=tokens["access_token"],
|
||||
refresh_token=None,
|
||||
access_token_expires_at=None,
|
||||
refresh_token_expires_at=None,
|
||||
scopes=scopes,
|
||||
)
|
||||
|
||||
def _refresh_tokens(self, credentials: OAuth2Credentials) -> OAuth2Credentials:
|
||||
# Todoist does not support token refresh
|
||||
return credentials
|
||||
|
||||
def revoke_tokens(self, credentials: OAuth2Credentials) -> bool:
|
||||
return False
|
||||
@@ -33,5 +33,6 @@ class ProviderName(str, Enum):
|
||||
SLANT3D = "slant3d"
|
||||
SMTP = "smtp"
|
||||
TWITTER = "twitter"
|
||||
TODOIST = "todoist"
|
||||
UNREAL_SPEECH = "unreal_speech"
|
||||
# --8<-- [end:ProviderName]
|
||||
|
||||
@@ -320,6 +320,9 @@ class Secrets(UpdateTrackingModel["Secrets"], BaseSettings):
|
||||
linear_client_id: str = Field(default="", description="Linear client ID")
|
||||
linear_client_secret: str = Field(default="", description="Linear client secret")
|
||||
|
||||
todoist_client_id: str = Field(default="", description="Todoist client ID")
|
||||
todoist_client_secret: str = Field(default="", description="Todoist client secret")
|
||||
|
||||
stripe_api_key: str = Field(default="", description="Stripe API Key")
|
||||
stripe_webhook_secret: str = Field(default="", description="Stripe Webhook Secret")
|
||||
|
||||
|
||||
19
autogpt_platform/backend/poetry.lock
generated
19
autogpt_platform/backend/poetry.lock
generated
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aio-pika"
|
||||
@@ -4296,6 +4296,21 @@ files = [
|
||||
doc = ["reno", "sphinx"]
|
||||
test = ["pytest", "tornado (>=4.5)", "typeguard"]
|
||||
|
||||
[[package]]
|
||||
name = "todoist-api-python"
|
||||
version = "2.1.7"
|
||||
description = "Official Python SDK for the Todoist REST API."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "todoist_api_python-2.1.7-py3-none-any.whl", hash = "sha256:278bfe851b9bd19bde5ff5de09d813d671ef7310ba55e1962131fca5b59bb735"},
|
||||
{file = "todoist_api_python-2.1.7.tar.gz", hash = "sha256:84934a19ccd83fb61010a8126362a5d7d6486c92454c111307ba55bc74903f5c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
requests = ">=2.32.3,<3.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.2.1"
|
||||
@@ -5035,4 +5050,4 @@ type = ["pytest-mypy"]
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10,<3.13"
|
||||
content-hash = "7d37edf4fd4e1935811629fef29d463fa61f904d520aa497de2969fadeba92ec"
|
||||
content-hash = "9a40ee57d7440f352b0ac0a138fa26d05cd8eadb0cf7d3a0f995fb3c36a2fa7c"
|
||||
|
||||
@@ -55,7 +55,8 @@ sqlalchemy = "^2.0.36"
|
||||
psycopg2-binary = "^2.9.10"
|
||||
google-cloud-storage = "^2.18.2"
|
||||
launchdarkly-server-sdk = "^9.8.0"
|
||||
mem0ai = "^0.1.48"
|
||||
mem0ai = "^0.1.44"
|
||||
todoist-api-python = "^2.1.7"
|
||||
moviepy = "^2.1.2"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
|
||||
@@ -85,6 +85,7 @@ export const providerIcons: Record<
|
||||
unreal_speech: fallbackIcon,
|
||||
exa: fallbackIcon,
|
||||
hubspot: FaHubspot,
|
||||
todoist: fallbackIcon,
|
||||
};
|
||||
// --8<-- [end:ProviderIconsEmbed]
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ const providerDisplayNames: Record<CredentialsProviderName, string> = {
|
||||
replicate: "Replicate",
|
||||
revid: "Rev.ID",
|
||||
twitter: "Twitter",
|
||||
todoist: "Todoist",
|
||||
unreal_speech: "Unreal Speech",
|
||||
} as const;
|
||||
// --8<-- [end:CredentialsProviderNames]
|
||||
|
||||
@@ -141,6 +141,7 @@ export const PROVIDER_NAMES = {
|
||||
REDDIT: "reddit",
|
||||
REVID: "revid",
|
||||
UNREAL_SPEECH: "unreal_speech",
|
||||
TODOIST: "todoist",
|
||||
} as const;
|
||||
// --8<-- [end:BlockIOCredentialsSubSchema]
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ Below is a comprehensive list of all available blocks, categorized by their prim
|
||||
|------------|-------------|
|
||||
| [Twitter Post Tweet](twitter/twitter.md#twitter-post-tweet-block) | Creates a tweet on Twitter with text content and optional attachments including media, polls, quotes, or deep links |
|
||||
| [Twitter Delete Tweet](twitter/twitter.md#twitter-delete-tweet-block) | Deletes a specified tweet using its tweet ID |
|
||||
| [Twitter Search Recent](twitter/twitter.md#twitter-search-recent-block) | Searches for tweets matching specified criteria with options for filtering and pagination |
|
||||
| [Twitter Search Recent Tweets](twitter/twitter.md#twitter-search-recent-tweets-block) | Searches for tweets matching specified criteria with options for filtering and pagination |
|
||||
| [Twitter Get Quote Tweets](twitter/twitter.md#twitter-get-quote-tweets-block) | Gets tweets that quote a specified tweet ID with options for pagination and filtering |
|
||||
| [Twitter Retweet](twitter/twitter.md#twitter-retweet-block) | Creates a retweet of a specified tweet using its tweet ID |
|
||||
| [Twitter Remove Retweet](twitter/twitter.md#twitter-remove-retweet-block) | Removes an existing retweet of a specified tweet |
|
||||
@@ -167,4 +167,31 @@ Below is a comprehensive list of all available blocks, categorized by their prim
|
||||
| Twitter Send Direct Message | Working... Sends a direct message to a specified user |
|
||||
| Twitter Create DM Conversation | Working... Creates a new direct message conversation |
|
||||
|
||||
## Todoist Integration
|
||||
| Block Name | Description |
|
||||
|------------|-------------|
|
||||
| [Todoist Create Label](todoist.md#todoist-create-label) | Creates a new label in Todoist |
|
||||
| [Todoist List Labels](todoist.md#todoist-list-labels) | Retrieves all personal labels from Todoist |
|
||||
| [Todoist Get Label](todoist.md#todoist-get-label) | Retrieves a specific label by ID |
|
||||
| [Todoist Create Task](todoist.md#todoist-create-task) | Creates a new task in Todoist |
|
||||
| [Todoist Get Tasks](todoist.md#todoist-get-tasks) | Retrieves active tasks from Todoist |
|
||||
| [Todoist Update Task](todoist.md#todoist-update-task) | Updates an existing task |
|
||||
| [Todoist Close Task](todoist.md#todoist-close-task) | Completes/closes a task |
|
||||
| [Todoist Reopen Task](todoist.md#todoist-reopen-task) | Reopens a completed task |
|
||||
| [Todoist Delete Task](todoist.md#todoist-delete-task) | Permanently deletes a task |
|
||||
| [Todoist List Projects](todoist.md#todoist-list-projects) | Retrieves all projects from Todoist |
|
||||
| [Todoist Create Project](todoist.md#todoist-create-project) | Creates a new project in Todoist |
|
||||
| [Todoist Get Project](todoist.md#todoist-get-project) | Retrieves details for a specific project |
|
||||
| [Todoist Update Project](todoist.md#todoist-update-project) | Updates an existing project |
|
||||
| [Todoist Delete Project](todoist.md#todoist-delete-project) | Deletes a project and its contents |
|
||||
| [Todoist List Collaborators](todoist.md#todoist-list-collaborators) | Retrieves collaborators on a project |
|
||||
| [Todoist List Sections](todoist.md#todoist-list-sections) | Retrieves sections from Todoist |
|
||||
| [Todoist Get Section](todoist.md#todoist-get-section) | Retrieves details for a specific section |
|
||||
| [Todoist Delete Section](todoist.md#todoist-delete-section) | Deletes a section and its tasks |
|
||||
| [Todoist Create Comment](todoist.md#todoist-create-comment) | Creates a new comment on a task or project |
|
||||
| [Todoist Get Comments](todoist.md#todoist-get-comments) | Retrieves all comments for a task or project |
|
||||
| [Todoist Get Comment](todoist.md#todoist-get-comment) | Retrieves a specific comment by ID |
|
||||
| [Todoist Update Comment](todoist.md#todoist-update-comment) | Updates an existing comment |
|
||||
| [Todoist Delete Comment](todoist.md#todoist-delete-comment) | Deletes a comment |
|
||||
|
||||
This comprehensive list covers all the blocks available in AutoGPT. Each block is designed to perform a specific task, and they can be combined to create powerful, automated workflows. For more detailed information on each block, click on its name to view the full documentation.
|
||||
|
||||
722
docs/content/platform/blocks/todoist.md
Normal file
722
docs/content/platform/blocks/todoist.md
Normal file
@@ -0,0 +1,722 @@
|
||||
# Todoist Blocks
|
||||
|
||||
## Todoist Create Label
|
||||
|
||||
### What it is
|
||||
A block that creates a new label in Todoist.
|
||||
|
||||
### What it does
|
||||
Creates a new label in Todoist with specified name, order, color and favorite status.
|
||||
|
||||
### How it works
|
||||
It takes label details as input, connects to Todoist API, creates the label and returns the created label's details.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Name | Name of the label |
|
||||
| Order | Optional label order |
|
||||
| Color | Optional color of the label icon |
|
||||
| Is Favorite | Whether label is marked as favorite |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| ID | ID of the created label |
|
||||
| Name | Name of the label |
|
||||
| Color | Color of the label |
|
||||
| Order | Label order |
|
||||
| Is Favorite | Favorite status |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Creating new labels to organize and categorize tasks in Todoist.
|
||||
|
||||
---
|
||||
|
||||
## Todoist List Labels
|
||||
|
||||
### What it is
|
||||
A block that retrieves all personal labels from Todoist.
|
||||
|
||||
### What it does
|
||||
Fetches all personal labels from the user's Todoist account.
|
||||
|
||||
### How it works
|
||||
Connects to Todoist API using provided credentials and retrieves all labels.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Labels | List of complete label data |
|
||||
| Label IDs | List of label IDs |
|
||||
| Label Names | List of label names |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Getting an overview of all labels to organize tasks or find specific labels.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Get Label
|
||||
|
||||
### What it is
|
||||
A block that retrieves a specific label by ID.
|
||||
|
||||
### What it does
|
||||
Fetches details of a specific label using its ID.
|
||||
|
||||
### How it works
|
||||
Uses the label ID to retrieve label details from Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Label ID | ID of label to retrieve |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| ID | Label ID |
|
||||
| Name | Label name |
|
||||
| Color | Label color |
|
||||
| Order | Label order |
|
||||
| Is Favorite | Favorite status |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Looking up details of a specific label for editing or verification.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Create Task
|
||||
|
||||
### What it is
|
||||
A block that creates a new task in Todoist.
|
||||
|
||||
### What it does
|
||||
Creates a new task with specified content, description, project assignment and other optional parameters.
|
||||
|
||||
### How it works
|
||||
Takes task details and creates a new task via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Content | Task content |
|
||||
| Description | Optional task description |
|
||||
| Project ID | Optional project to add task to |
|
||||
| Section ID | Optional section to add task to |
|
||||
| Parent ID | Optional parent task ID |
|
||||
| Order | Optional task order |
|
||||
| Labels | Optional task labels |
|
||||
| Priority | Optional priority (1-4) |
|
||||
| Due Date | Optional due date |
|
||||
| Deadline Date | Optional deadline date |
|
||||
| Assignee ID | Optional assignee |
|
||||
| Duration Unit | Optional duration unit |
|
||||
| Duration | Optional duration amount |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| ID | Created task ID |
|
||||
| URL | Task URL |
|
||||
| Complete Data | Complete task data |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Creating new tasks with full customization of parameters.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Get Tasks
|
||||
|
||||
### What it is
|
||||
A block that retrieves active tasks from Todoist.
|
||||
|
||||
### What it does
|
||||
Fetches tasks based on optional filters like project, section, label etc.
|
||||
|
||||
### How it works
|
||||
Queries Todoist API with provided filters to get matching tasks.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Project ID | Optional filter by project |
|
||||
| Section ID | Optional filter by section |
|
||||
| Label | Optional filter by label |
|
||||
| Filter | Optional custom filter string |
|
||||
| Lang | Optional filter language |
|
||||
| IDs | Optional specific task IDs |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| IDs | List of task IDs |
|
||||
| URLs | List of task URLs |
|
||||
| Complete Data | Complete task data |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Retrieving tasks matching specific criteria for review or processing.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Update Task
|
||||
|
||||
### What it is
|
||||
A block that updates an existing task.
|
||||
|
||||
### What it does
|
||||
Updates specified fields of an existing task.
|
||||
|
||||
### How it works
|
||||
Takes task ID and updated fields, applies changes via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Task ID | ID of task to update |
|
||||
| Content | New task content |
|
||||
| Description | New description |
|
||||
| Project ID | New project ID |
|
||||
| Section ID | New section ID |
|
||||
| Parent ID | New parent task ID |
|
||||
| Order | New order |
|
||||
| Labels | New labels |
|
||||
| Priority | New priority |
|
||||
| Due Date | New due date |
|
||||
| Deadline Date | New deadline date |
|
||||
| Assignee ID | New assignee |
|
||||
| Duration Unit | New duration unit |
|
||||
| Duration | New duration |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether update succeeded |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Modifying task details like due dates, priority etc.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Close Task
|
||||
|
||||
### What it is
|
||||
A block that completes/closes a task.
|
||||
|
||||
### What it does
|
||||
Marks a task as complete in Todoist.
|
||||
|
||||
### How it works
|
||||
Uses task ID to mark it complete via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Task ID | ID of task to close |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether task was closed |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Marking tasks as done in automated workflows.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Reopen Task
|
||||
|
||||
### What it is
|
||||
A block that reopens a completed task.
|
||||
|
||||
### What it does
|
||||
Marks a completed task as active again.
|
||||
|
||||
### How it works
|
||||
Uses task ID to reactivate via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Task ID | ID of task to reopen |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether task was reopened |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Reactivating tasks that were closed accidentally or need to be repeated.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Delete Task
|
||||
|
||||
### What it is
|
||||
A block that permanently deletes a task.
|
||||
|
||||
### What it does
|
||||
Removes a task completely from Todoist.
|
||||
|
||||
### How it works
|
||||
Uses task ID to delete via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Task ID | ID of task to delete |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether deletion succeeded |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Removing unwanted or obsolete tasks from the system.
|
||||
|
||||
---
|
||||
|
||||
## Todoist List Projects
|
||||
|
||||
### What it is
|
||||
A block that retrieves all projects from Todoist.
|
||||
|
||||
### What it does
|
||||
Fetches all projects and their details from a user's Todoist account.
|
||||
|
||||
### How it works
|
||||
Connects to Todoist API using provided credentials and retrieves all projects.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Names List | List of project names |
|
||||
| IDs List | List of project IDs |
|
||||
| URL List | List of project URLs |
|
||||
| Complete Data | Complete project data |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Getting an overview of all projects for organization or automation.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Create Project
|
||||
|
||||
### What it is
|
||||
A block that creates a new project in Todoist.
|
||||
|
||||
### What it does
|
||||
Creates a new project with specified name, parent project, color and other settings.
|
||||
|
||||
### How it works
|
||||
Takes project details and creates via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Name | Name of the project |
|
||||
| Parent ID | Optional parent project ID |
|
||||
| Color | Optional color of project icon |
|
||||
| Is Favorite | Whether project is favorite |
|
||||
| View Style | Display style (list/board) |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether creation succeeded |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Creating new projects programmatically for workflow automation.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Get Project
|
||||
|
||||
### What it is
|
||||
A block that retrieves details for a specific project.
|
||||
|
||||
### What it does
|
||||
Fetches complete details of a single project by ID.
|
||||
|
||||
### How it works
|
||||
Uses project ID to retrieve details via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Project ID | ID of project to get |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Project ID | ID of the project |
|
||||
| Project Name | Name of the project |
|
||||
| Project URL | URL of the project |
|
||||
| Complete Data | Complete project data |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Looking up project details for verification or editing.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Update Project
|
||||
|
||||
### What it is
|
||||
A block that updates an existing project.
|
||||
|
||||
### What it does
|
||||
Updates specified fields of an existing project.
|
||||
|
||||
### How it works
|
||||
Takes project ID and updated fields, applies via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Project ID | ID of project to update |
|
||||
| Name | New project name |
|
||||
| Color | New color for icon |
|
||||
| Is Favorite | New favorite status |
|
||||
| View Style | New display style |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether update succeeded |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Modifying project settings or reorganizing projects.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Delete Project
|
||||
|
||||
### What it is
|
||||
A block that deletes a project and its contents.
|
||||
|
||||
### What it does
|
||||
Permanently removes a project including sections and tasks.
|
||||
|
||||
### How it works
|
||||
Uses project ID to delete via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Project ID | ID of project to delete |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether deletion succeeded |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Removing completed or obsolete projects.
|
||||
|
||||
---
|
||||
|
||||
## Todoist List Collaborators
|
||||
|
||||
### What it is
|
||||
A block that retrieves collaborators on a project.
|
||||
|
||||
### What it does
|
||||
Fetches all collaborators and their details for a specific project.
|
||||
|
||||
### How it works
|
||||
Uses project ID to get collaborator list via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Project ID | ID of project to check |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Collaborator IDs | List of collaborator IDs |
|
||||
| Collaborator Names | List of collaborator names |
|
||||
| Collaborator Emails | List of collaborator emails |
|
||||
| Complete Data | Complete collaborator data |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Managing project sharing and collaboration.
|
||||
|
||||
---
|
||||
|
||||
## Todoist List Sections
|
||||
|
||||
### What it is
|
||||
A block that retrieves sections from Todoist.
|
||||
|
||||
### What it does
|
||||
Fetches all sections, optionally filtered by project.
|
||||
|
||||
### How it works
|
||||
Connects to Todoist API to retrieve sections list.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Project ID | Optional project filter |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Names List | List of section names |
|
||||
| IDs List | List of section IDs |
|
||||
| Complete Data | Complete section data |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Getting section information for task organization.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Get Section
|
||||
|
||||
### What it is
|
||||
A block that retrieves details for a specific section.
|
||||
|
||||
### What it does
|
||||
Fetches complete details of a single section by ID.
|
||||
|
||||
### How it works
|
||||
Uses section ID to retrieve details via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Section ID | ID of section to get |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| ID | Section ID |
|
||||
| Project ID | Parent project ID |
|
||||
| Order | Section order |
|
||||
| Name | Section name |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Looking up section details for task management.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Delete Section
|
||||
|
||||
### What it is
|
||||
A block that deletes a section and its tasks.
|
||||
|
||||
### What it does
|
||||
Permanently removes a section including all tasks.
|
||||
|
||||
### How it works
|
||||
Uses section ID to delete via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Section ID | ID of section to delete |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether deletion succeeded |
|
||||
| Error | Error message if failed |
|
||||
|
||||
### Possible use case
|
||||
Removing unused sections or reorganizing projects.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Create Comment
|
||||
|
||||
### What it is
|
||||
A block that creates a new comment on a Todoist task or project.
|
||||
|
||||
### What it does
|
||||
Creates a comment with specified content on either a task or project.
|
||||
|
||||
### How it works
|
||||
Takes comment content and task/project ID, creates comment via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Content | Comment content |
|
||||
| ID Type | Task ID or Project ID to comment on |
|
||||
| Attachment | Optional file attachment |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| ID | ID of created comment |
|
||||
| Content | Comment content |
|
||||
| Posted At | Comment timestamp |
|
||||
| Task ID | Associated task ID |
|
||||
| Project ID | Associated project ID |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Adding notes and comments to tasks or projects automatically.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Get Comments
|
||||
|
||||
### What it is
|
||||
A block that retrieves all comments for a task or project.
|
||||
|
||||
### What it does
|
||||
Fetches all comments associated with a specific task or project.
|
||||
|
||||
### How it works
|
||||
Uses task/project ID to get comments list via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| ID Type | Task ID or Project ID to get comments for |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Comments | List of comments |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Reviewing comment history on tasks or projects.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Get Comment
|
||||
|
||||
### What it is
|
||||
A block that retrieves a specific comment by ID.
|
||||
|
||||
### What it does
|
||||
Fetches details of a single comment using its ID.
|
||||
|
||||
### How it works
|
||||
Uses comment ID to retrieve details via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Comment ID | ID of comment to retrieve |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Content | Comment content |
|
||||
| ID | Comment ID |
|
||||
| Posted At | Comment timestamp |
|
||||
| Project ID | Associated project ID |
|
||||
| Task ID | Associated task ID |
|
||||
| Attachment | Optional file attachment |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Looking up specific comment details for reference.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Update Comment
|
||||
|
||||
### What it is
|
||||
A block that updates an existing comment.
|
||||
|
||||
### What it does
|
||||
Updates the content of a specific comment.
|
||||
|
||||
### How it works
|
||||
Takes comment ID and new content, updates via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Comment ID | ID of comment to update |
|
||||
| Content | New content for the comment |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether update succeeded |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Modifying existing comments to fix errors or update information.
|
||||
|
||||
---
|
||||
|
||||
## Todoist Delete Comment
|
||||
|
||||
### What it is
|
||||
A block that deletes a comment.
|
||||
|
||||
### What it does
|
||||
Permanently removes a comment from a task or project.
|
||||
|
||||
### How it works
|
||||
Uses comment ID to delete via Todoist API.
|
||||
|
||||
### Inputs
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| Credentials | Todoist API credentials |
|
||||
| Comment ID | ID of comment to delete |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| Success | Whether deletion succeeded |
|
||||
| Error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
Removing outdated or incorrect comments from tasks/projects.
|
||||
@@ -122,22 +122,22 @@ It uses the Twitter API (Tweepy) to fetch quote tweets for a given tweet ID, han
|
||||
| max_results | Maximum number of results to return (max 100) |
|
||||
| exclude | Types of tweets to exclude |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
|--------|-------------|
|
||||
| ids | List of quote tweet IDs |
|
||||
| texts | List of quote tweet text contents |
|
||||
| next_token | Token for retrieving next page [more info](twitter/twitter.md#common-output). |
|
||||
| next_token | Token for retrieving next page [more info](twitter.md#common-output). |
|
||||
| data | Complete tweet data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -219,12 +219,12 @@ It uses the Twitter API (Tweepy) to fetch retweeter information for a given twee
|
||||
| tweet_id | ID of the tweet to get retweeters for |
|
||||
| max_results | Maximum number of results per page (1-100) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -234,8 +234,8 @@ It uses the Twitter API (Tweepy) to fetch retweeter information for a given twee
|
||||
| usernames | List of usernames who retweeted |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete user data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -261,12 +261,12 @@ It queries the Twitter API (Tweepy) with the provided user ID to fetch tweets me
|
||||
| user_id | ID of user to get mentions for |
|
||||
| max_results | Number of results per page (5-100) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -277,8 +277,8 @@ It queries the Twitter API (Tweepy) with the provided user ID to fetch tweets me
|
||||
| userNames | List of usernames who mentioned target user |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete tweet data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -303,12 +303,12 @@ It uses the Twitter API (Tweepy) to fetch tweets from the home timeline, handlin
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| max_results | Number of results per page (5-100) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -319,8 +319,8 @@ It uses the Twitter API (Tweepy) to fetch tweets from the home timeline, handlin
|
||||
| userNames | List of usernames who authored tweets |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete tweet data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -346,12 +346,12 @@ It uses the Twitter API (Tweepy) to fetch tweets from a specified user's timelin
|
||||
| user_id | ID of user to get tweets from |
|
||||
| max_results | Number of results per page (5-100) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -362,8 +362,8 @@ It uses the Twitter API (Tweepy) to fetch tweets from a specified user's timelin
|
||||
| userNames | List of usernames who authored tweets |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete tweet data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -387,12 +387,12 @@ It uses the Twitter API (Tweepy) to fetch a single tweet by its ID, handling aut
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| tweet_id | ID of the tweet to fetch |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -402,8 +402,8 @@ It uses the Twitter API (Tweepy) to fetch a single tweet by its ID, handling aut
|
||||
| userId | ID of tweet author |
|
||||
| userName | Username of tweet author |
|
||||
| data | Complete tweet data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Tweet metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Tweet metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -427,12 +427,12 @@ It uses the Twitter API (Tweepy) to batch fetch tweets by their IDs, handling au
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| tweet_ids | List of tweet IDs to fetch (max 100) |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -442,8 +442,8 @@ It uses the Twitter API (Tweepy) to batch fetch tweets by their IDs, handling au
|
||||
| userIds | List of tweet author IDs |
|
||||
| userNames | List of tweet author usernames |
|
||||
| data | Complete tweet data array |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Tweet metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Tweet metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -497,9 +497,9 @@ It uses the Twitter API (Tweepy) to fetch information about users who liked a gi
|
||||
| tweet_id | ID of tweet to get liking users for |
|
||||
| max_results | Maximum number of results to return (1-100) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -508,8 +508,8 @@ It uses the Twitter API (Tweepy) to fetch information about users who liked a gi
|
||||
| username | List of usernames who liked |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete user data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -535,12 +535,12 @@ It uses the Twitter API (Tweepy) to fetch tweets liked by a given user ID, handl
|
||||
| user_id | ID of user to get liked tweets for |
|
||||
| max_results | Maximum number of results per page (5-100) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -551,8 +551,8 @@ It uses the Twitter API (Tweepy) to fetch tweets liked by a given user ID, handl
|
||||
| userNames | List of tweet author usernames |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete tweet data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -689,12 +689,12 @@ It uses the Twitter API (Tweepy) to fetch bookmarked tweets, handling pagination
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| max_results | Maximum number of results per page (1-100) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -705,8 +705,8 @@ It uses the Twitter API (Tweepy) to fetch bookmarked tweets, handling pagination
|
||||
| userName | List of tweet author usernames |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete tweet data |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -906,9 +906,9 @@ It uses the Twitter API (Tweepy) to fetch followers for a given user ID, handlin
|
||||
| target_user_id | ID of user to get followers for |
|
||||
| max_results | Maximum number of results per page (1-1000) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -917,8 +917,8 @@ It uses the Twitter API (Tweepy) to fetch followers for a given user ID, handlin
|
||||
| usernames | List of follower usernames |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete user data |
|
||||
| includes | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| includes | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -944,9 +944,9 @@ It uses the Twitter API (Tweepy) to fetch following list for a given user ID, ha
|
||||
| target_user_id | ID of user to get following list for |
|
||||
| max_results | Maximum number of results per page (1-1000) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -955,8 +955,8 @@ It uses the Twitter API (Tweepy) to fetch following list for a given user ID, ha
|
||||
| usernames | List of following usernames |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete user data |
|
||||
| includes | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| includes | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -1009,9 +1009,9 @@ It uses the Twitter API (Tweepy) to fetch muted users, handling authentication a
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| max_results | Maximum results per page (1-1000, default 10) |
|
||||
| pagination_token | Token for getting next/previous page |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1073,9 +1073,9 @@ It uses the Twitter API (Tweepy) to fetch user data for a single user identified
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| identifier | User identifier (either user ID or username) |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1108,9 +1108,9 @@ It uses the Twitter API (Tweepy) to batch fetch user data for multiple users ide
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| identifier | List of user identifiers (either user IDs or usernames, max 100) |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1145,9 +1145,9 @@ It uses the Twitter API (Tweepy) to search for Spaces matching the query paramet
|
||||
| query | Search term to find in Space titles |
|
||||
| max_results | Maximum number of results to return (1-100, default 10) |
|
||||
| state | Type of Spaces to return (live, scheduled, or all) |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| space_fields | Space-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| space_fields | Space-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1182,9 +1182,9 @@ It uses the Twitter API (Tweepy) to batch fetch Space data for multiple Spaces,
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| identifier | Choice of lookup by Space IDs or creator user IDs |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| space_fields | Space-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| space_fields | Space-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1216,9 +1216,9 @@ It uses the Twitter API (Tweepy) to fetch Space data for a single Space ID, hand
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| space_id | ID of Space to retrieve |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| space_fields | Space-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| space_fields | Space-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1251,8 +1251,8 @@ It uses the Twitter API (Tweepy) to fetch buyer information for a Space, handlin
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| space_id | ID of Space to get buyers for |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1284,12 +1284,12 @@ It uses the Twitter API (Tweepy) to fetch tweets from a Space, handling authenti
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| space_id | ID of Space to get tweets for |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1322,9 +1322,9 @@ It uses the Twitter API (Tweepy) to fetch list data for a single list ID, handli
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| list_id | ID of the Twitter List to retrieve |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| list_fields | List-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| list_fields | List-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1361,9 +1361,9 @@ It uses the Twitter API (Tweepy) to fetch owned lists for a given user ID, handl
|
||||
| user_id | ID of user whose Lists to retrieve |
|
||||
| max_results | Maximum results per page (1-100, default 10) |
|
||||
| pagination_token | Token for getting next page |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| list_fields | List-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| list_fields | List-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1532,12 +1532,12 @@ It uses the Twitter API (Tweepy) to fetch tweets from a specified List, handling
|
||||
| list_id | ID of the List to get tweets from |
|
||||
| max_results | Maximum number of results per page (1-100, default 10) |
|
||||
| pagination_token | Token for getting next page of results |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| media_fields | Media-related fields to include [more info](twitter.md#common-input). |
|
||||
| place_fields | Location-related fields to include [more info](twitter.md#common-input). |
|
||||
| poll_fields | Poll-related fields to include [more info](twitter.md#common-input). |
|
||||
| tweet_fields | Tweet-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1546,8 +1546,8 @@ It uses the Twitter API (Tweepy) to fetch tweets from a specified List, handling
|
||||
| texts | List of tweet text contents |
|
||||
| next_token | Token for retrieving next page |
|
||||
| data | Complete tweet data array |
|
||||
| included | Additional requested data [more info](twitter/twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter/twitter.md#common-output). |
|
||||
| included | Additional requested data [more info](twitter.md#common-output). |
|
||||
| meta | Pagination and result metadata [more info](twitter.md#common-output). |
|
||||
| error | Error message if request failed |
|
||||
|
||||
### Possible use case
|
||||
@@ -1715,9 +1715,9 @@ It uses the Twitter API (Tweepy) to fetch pinned Lists data, handling authentica
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| credentials | Twitter API credentials with required scopes |
|
||||
| expansions | Additional data fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| list_fields | List-specific fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter/twitter.md#common-input). |
|
||||
| expansions | Additional data fields to include [more info](twitter.md#common-input). |
|
||||
| list_fields | List-specific fields to include [more info](twitter.md#common-input). |
|
||||
| user_fields | User-related fields to include [more info](twitter.md#common-input). |
|
||||
|
||||
### Outputs
|
||||
| Output | Description |
|
||||
@@ -1905,3 +1905,62 @@ Information about Twitter users
|
||||
- For user data in Tweets, add `expansions=Author_User_ID` and appropriate `user_fields`.
|
||||
|
||||
- Data returned under `includes` helps cross-reference expanded data objects with their parent entities using IDs.
|
||||
|
||||
## Common Output
|
||||
|
||||
The Twitter API returns standardized response elements across many endpoints. Here are the common output fields you'll encounter:
|
||||
|
||||
### data
|
||||
The primary data requested in the response
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| ID | Unique identifier for the object |
|
||||
| Type | Type of object (tweet, user, etc) |
|
||||
| Properties | Object-specific fields like text for tweets |
|
||||
|
||||
### includes
|
||||
Additional expanded data objects referenced in the primary data
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| Tweets | Full tweet objects that were referenced |
|
||||
| Users | User profile data for authors/mentions |
|
||||
| Places | Location data for geo-tagged content |
|
||||
| Media | Details about attached photos/videos |
|
||||
| Polls | Information about embedded polls |
|
||||
|
||||
### meta
|
||||
Metadata about the response and pagination
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| Result_Count | Number of items returned |
|
||||
| Next_Token | Token to get next page of results |
|
||||
| Previous_Token | Token to get previous page |
|
||||
| Newest_ID | Most recent ID in results |
|
||||
| Oldest_ID | Oldest ID in results |
|
||||
| Total_Tweet_Count | Total matching tweets (search) |
|
||||
|
||||
### errors
|
||||
Details about any errors that occurred
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| Title | Brief error description |
|
||||
| Detail | Detailed error message |
|
||||
| Type | Error category/classification |
|
||||
| Status | HTTP status code |
|
||||
|
||||
### Non-paginated responses
|
||||
For single-object lookups:
|
||||
- data: Contains requested object
|
||||
- includes: Referenced objects
|
||||
- errors: Any errors encountered
|
||||
|
||||
### Paginated responses
|
||||
For multi-object lookups:
|
||||
- data: Array of objects
|
||||
- includes: Referenced objects
|
||||
- meta: Pagination details
|
||||
- errors: Any errors encountered
|
||||
|
||||
Reference in New Issue
Block a user