adding documentation for twitter block

This commit is contained in:
abhi1992002
2025-01-03 11:45:53 +05:30
parent 428c012a43
commit d75c08e348
52 changed files with 2020 additions and 144 deletions

View File

@@ -342,7 +342,7 @@ class TweetPostBuilder:
def __init__(self):
self.params: Dict[str, Any] = {"user_auth": False}
def add_text(self, text: str):
def add_text(self, text: str | None):
if text:
self.params["text"] = text
return self

View File

@@ -79,7 +79,6 @@ class TwitterUnfollowListBlock(Block):
except Exception as e:
yield "error", handle_tweepy_exception(e)
class TwitterFollowListBlock(Block):
"""
Follows a Twitter list for the authenticated user

View File

@@ -118,9 +118,10 @@ class TwitterGetListBlock(Block):
meta = {}
owner_id = ""
owner_username = ""
included = {}
included = IncludesSerializer.serialize(response.includes)
data_dict = ResponseDataSerializer.serialize_dict(response.data)
if response.includes:
included = IncludesSerializer.serialize(response.includes)
if "users" in included:
owner_id = str(included["users"][0]["id"])
@@ -130,6 +131,7 @@ class TwitterGetListBlock(Block):
meta = response.meta
if response.data:
data_dict = ResponseDataSerializer.serialize_dict(response.data)
return data_dict, included, meta, owner_id, owner_username
raise Exception("List not found")
@@ -185,7 +187,7 @@ class TwitterGetOwnedListsBlock(Block):
required=True,
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results per page (1-100)",
placeholder="Enter max results (default 100)",
advanced=True,
@@ -250,7 +252,7 @@ class TwitterGetOwnedListsBlock(Block):
def get_owned_lists(
credentials: TwitterCredentials,
user_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: ListExpansionsFilter | None,
user_fields: TweetUserFieldsFilter | None,
@@ -281,6 +283,7 @@ class TwitterGetOwnedListsBlock(Block):
response = cast(Response, client.get_owned_lists(**params))
meta = {}
included={}
list_ids = []
list_names = []
next_token = None
@@ -289,16 +292,17 @@ class TwitterGetOwnedListsBlock(Block):
meta = response.meta
next_token = meta.get("next_token")
included = IncludesSerializer.serialize(response.includes)
data = ResponseDataSerializer.serialize_list(response.data)
if response.includes:
included = IncludesSerializer.serialize(response.includes)
if response.data:
list_ids = [str(item.id) for item in response.data]
list_names = [item.name for item in response.data]
data = ResponseDataSerializer.serialize_list(response.data)
list_ids = [str(item.id) for item in response.data if hasattr(item, 'id')]
list_names = [item.name for item in response.data if hasattr(item, 'name')]
return data, included, meta, list_ids, list_names, next_token
raise Exception("Lists not found")
raise Exception("User have no owned list")
except tweepy.TweepyException:
raise

View File

@@ -198,7 +198,7 @@ class TwitterGetListMembersBlock(Block):
required=True,
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results per page (1-100)",
placeholder="Enter max results",
default=10,
@@ -274,7 +274,7 @@ class TwitterGetListMembersBlock(Block):
def get_list_members(
credentials: TwitterCredentials,
list_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,
@@ -305,6 +305,7 @@ class TwitterGetListMembersBlock(Block):
response = cast(Response, client.get_list_members(**params))
meta = {}
included = {}
next_token = None
user_ids = []
usernames = []
@@ -313,10 +314,11 @@ class TwitterGetListMembersBlock(Block):
meta = response.meta
next_token = meta.get("next_token")
included = IncludesSerializer.serialize(response.includes)
data = ResponseDataSerializer.serialize_list(response.data)
if response.includes:
included = IncludesSerializer.serialize(response.includes)
if response.data:
data = ResponseDataSerializer.serialize_list(response.data)
user_ids = [str(user.id) for user in response.data]
usernames = [user.username for user in response.data]
return user_ids, usernames, data, included, meta, next_token
@@ -377,7 +379,7 @@ class TwitterGetListMembershipsBlock(Block):
required=True,
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results per page (1-100)",
placeholder="Enter max results",
advanced=True,
@@ -438,7 +440,7 @@ class TwitterGetListMembershipsBlock(Block):
def get_list_memberships(
credentials: TwitterCredentials,
user_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: ListExpansionsFilter | None,
user_fields: TweetUserFieldsFilter | None,
@@ -469,6 +471,7 @@ class TwitterGetListMembershipsBlock(Block):
response = cast(Response, client.get_list_memberships(**params))
meta = {}
included = {}
next_token = None
list_ids = []
@@ -476,10 +479,11 @@ class TwitterGetListMembershipsBlock(Block):
meta = response.meta
next_token = meta.get("next_token")
included = IncludesSerializer.serialize(response.includes)
data = ResponseDataSerializer.serialize_list(response.data)
if response.includes:
included = IncludesSerializer.serialize(response.includes)
if response.data:
data = ResponseDataSerializer.serialize_list(response.data)
list_ids = [str(lst.id) for lst in response.data]
return data, included, meta, list_ids, next_token

View File

@@ -45,7 +45,7 @@ class TwitterGetListTweetsBlock(Block):
required=True,
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results per page (1-100)",
placeholder="Enter max results",
default=10,
@@ -116,7 +116,7 @@ class TwitterGetListTweetsBlock(Block):
def get_list_tweets(
credentials: TwitterCredentials,
list_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: ExpansionFilter | None,
media_fields: TweetMediaFieldsFilter | None,
@@ -153,6 +153,7 @@ class TwitterGetListTweetsBlock(Block):
response = cast(Response, client.get_list_tweets(**params))
meta = {}
included = {}
tweet_ids = []
texts = []
next_token = None
@@ -161,10 +162,11 @@ class TwitterGetListTweetsBlock(Block):
meta = response.meta
next_token = meta.get("next_token")
included = IncludesSerializer.serialize(response.includes)
data = ResponseDataSerializer.serialize_list(response.data)
if response.includes:
included = IncludesSerializer.serialize(response.includes)
if response.data:
data = ResponseDataSerializer.serialize_list(response.data)
tweet_ids = [str(item.id) for item in response.data]
texts = [item.text for item in response.data]

View File

@@ -77,7 +77,6 @@ class TwitterDeleteListBlock(Block):
except Exception as e:
yield "error", handle_tweepy_exception(e)
class TwitterUpdateListBlock(Block):
"""
Updates a Twitter List owned by the authenticated user
@@ -94,14 +93,14 @@ class TwitterUpdateListBlock(Block):
advanced=False,
)
name: str = SchemaField(
name: str | None = SchemaField(
description="New name for the List",
placeholder="Enter list name",
default="",
advanced=False,
)
description: str = SchemaField(
description: str | None = SchemaField(
description="New description for the List",
placeholder="Enter list description",
default="",
@@ -133,7 +132,7 @@ class TwitterUpdateListBlock(Block):
@staticmethod
def update_list(
credentials: TwitterCredentials, list_id: str, name: str, description: str
credentials: TwitterCredentials, list_id: str, name: str | None, description: str | None
):
try:
client = tweepy.Client(
@@ -165,14 +164,13 @@ class TwitterUpdateListBlock(Block):
credentials,
input_data.list_id,
input_data.name,
input_data.description,
input_data.description
)
yield "success", success
except Exception as e:
yield "error", handle_tweepy_exception(e)
class TwitterCreateListBlock(Block):
"""
Creates a Twitter List owned by the authenticated user
@@ -190,7 +188,7 @@ class TwitterCreateListBlock(Block):
default="",
)
description: str = SchemaField(
description: str | None = SchemaField(
description="Description of the List",
placeholder="Enter list description",
advanced=False,
@@ -231,7 +229,7 @@ class TwitterCreateListBlock(Block):
@staticmethod
def create_list(
credentials: TwitterCredentials, name: str, description: str, private: bool
credentials: TwitterCredentials, name: str, description: str | None, private: bool
):
try:
client = tweepy.Client(

View File

@@ -234,16 +234,19 @@ class TwitterGetPinnedListsBlock(Block):
response = cast(Response, client.get_pinned_lists(**params))
meta = {}
included = {}
list_ids = []
list_names = []
if response.meta:
meta = response.meta
included = IncludesSerializer.serialize(response.includes)
data = ResponseDataSerializer.serialize_list(response.data)
if response.includes:
included = IncludesSerializer.serialize(response.includes)
if response.data:
data = ResponseDataSerializer.serialize_list(response.data)
list_ids = [str(item.id) for item in response.data]
list_names = [item.name for item in response.data]
return data, included, meta, list_ids, list_names

View File

@@ -42,7 +42,7 @@ class TwitterSearchSpacesBlock(Block):
placeholder="Enter search query",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results to return (1-100)",
placeholder="Enter max results",
default=10,
@@ -111,7 +111,7 @@ class TwitterSearchSpacesBlock(Block):
def search_spaces(
credentials: TwitterCredentials,
query: str,
max_results: int,
max_results: int | None,
state: SpaceStatesFilter,
expansions: SpaceExpansionsFilter | None,
space_fields: SpaceFieldsFilter | None,
@@ -145,9 +145,9 @@ class TwitterSearchSpacesBlock(Block):
data = ResponseDataSerializer.serialize_list(response.data)
if response.data:
ids = [str(space["id"]) for space in response.data]
titles = [space["title"] for space in data]
host_ids = [space["host_ids"] for space in data]
ids = [str(space["id"]) for space in response.data if "id" in space]
titles = [space["title"] for space in data if "title" in space]
host_ids = [space["host_ids"] for space in data if "host_ids" in space]
return data, included, meta, ids, titles, host_ids, next_token

View File

@@ -1,5 +1,6 @@
from typing import cast
from typing import Literal, Union, cast
from pydantic import BaseModel
import tweepy
from tweepy.client import Response
@@ -37,6 +38,23 @@ from backend.blocks.twitter.tweepy_exceptions import handle_tweepy_exception
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import SchemaField
class SpaceList(BaseModel):
discriminator: Literal['space_list']
space_ids: list[str] = SchemaField(
description="List of Space IDs to lookup (up to 100)",
placeholder="Enter Space IDs",
default=[],
advanced=False,
)
class UserList(BaseModel):
discriminator: Literal['user_list']
user_ids: list[str] = SchemaField(
description="List of user IDs to lookup their Spaces (up to 100)",
placeholder="Enter user IDs",
default=[],
advanced=False,
)
class TwitterGetSpacesBlock(Block):
"""
@@ -48,17 +66,9 @@ class TwitterGetSpacesBlock(Block):
["spaces.read", "users.read", "offline.access"]
)
space_ids: list[str] = SchemaField(
description="List of Space IDs to lookup (up to 100)",
placeholder="Enter Space IDs",
default=[],
advanced=False,
)
user_ids: list[str] = SchemaField(
description="List of user IDs to lookup their Spaces (up to 100)",
placeholder="Enter user IDs",
default=[],
identifier: Union[SpaceList, UserList] = SchemaField(
discriminator='discriminator',
description="Choose whether to lookup spaces by their IDs or by creator user IDs",
advanced=False,
)
@@ -82,8 +92,10 @@ class TwitterGetSpacesBlock(Block):
input_schema=TwitterGetSpacesBlock.Input,
output_schema=TwitterGetSpacesBlock.Output,
test_input={
"space_ids": ["1DXxyRYNejbKM"],
"user_ids": [],
"identifier": {
"discriminator": "space_list",
"space_ids": ["1DXxyRYNejbKM"]
},
"credentials": TEST_CREDENTIALS_INPUT,
"expansions": None,
"space_fields": None,
@@ -123,8 +135,7 @@ class TwitterGetSpacesBlock(Block):
@staticmethod
def get_spaces(
credentials: TwitterCredentials,
space_ids: list[str],
user_ids: list[str],
identifier: Union[SpaceList, UserList],
expansions: SpaceExpansionsFilter | None,
space_fields: SpaceFieldsFilter | None,
user_fields: TweetUserFieldsFilter | None,
@@ -135,8 +146,8 @@ class TwitterGetSpacesBlock(Block):
)
params = {
"ids": None if space_ids == [] else space_ids,
"user_ids": None if user_ids == [] else user_ids,
"ids": identifier.space_ids if isinstance(identifier, SpaceList) else None,
"user_ids": identifier.user_ids if isinstance(identifier, UserList) else None,
}
params = (
@@ -156,8 +167,8 @@ class TwitterGetSpacesBlock(Block):
if response.data:
data = ResponseDataSerializer.serialize_list(response.data)
ids = [space["id"] for space in data]
titles = [space["title"] for space in data]
ids = [space["id"] for space in data if "id" in space]
titles = [space["title"] for space in data if "title" in space]
return data, included, ids, titles
@@ -176,8 +187,7 @@ class TwitterGetSpacesBlock(Block):
try:
data, included, ids, titles = self.get_spaces(
credentials,
input_data.space_ids,
input_data.user_ids,
input_data.identifier,
input_data.expansions,
input_data.space_fields,
input_data.user_fields,
@@ -196,7 +206,6 @@ class TwitterGetSpacesBlock(Block):
except Exception as e:
yield "error", handle_tweepy_exception(e)
class TwitterGetSpaceByIdBlock(Block):
"""
Gets information about a single Twitter Space specified by Space ID
@@ -340,9 +349,14 @@ class TwitterGetSpaceByIdBlock(Block):
# Common outputs
if space_data:
yield "id", space_data.get("id")
yield "title", space_data.get("title")
yield "host_ids", space_data.get("host_ids")
if "id" in space_data:
yield "id", space_data.get("id")
if "title" in space_data:
yield "title", space_data.get("title")
if "host_ids" in space_data:
yield "host_ids", space_data.get("host_ids")
if space_data:
yield "data", space_data
@@ -352,7 +366,6 @@ class TwitterGetSpaceByIdBlock(Block):
except Exception as e:
yield "error", handle_tweepy_exception(e)
# Not tested yet, might have some problem
class TwitterGetSpaceBuyersBlock(Block):
"""

View File

@@ -107,7 +107,7 @@ class TwitterGetBookmarkedTweetsBlock(Block):
["tweet.read", "bookmark.read", "users.read", "offline.access"]
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results to return (1-100)",
placeholder="Enter max results",
default=10,
@@ -183,7 +183,7 @@ class TwitterGetBookmarkedTweetsBlock(Block):
@staticmethod
def get_bookmarked_tweets(
credentials: TwitterCredentials,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: ExpansionFilter | None,
media_fields: TweetMediaFieldsFilter | None,

View File

@@ -119,7 +119,7 @@ class TwitterGetLikingUsersBlock(Block):
description="ID of the tweet to get liking users for",
placeholder="Enter tweet ID",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results to return (1-100)",
placeholder="Enter max results",
default=10,
@@ -190,7 +190,7 @@ class TwitterGetLikingUsersBlock(Block):
def get_liking_users(
credentials: TwitterCredentials,
tweet_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,
@@ -293,7 +293,7 @@ class TwitterGetLikedTweetsBlock(Block):
description="ID of the user to get liked tweets for",
placeholder="Enter user ID",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results to return (5-100)",
placeholder="100",
default=10,
@@ -384,7 +384,7 @@ class TwitterGetLikedTweetsBlock(Block):
def get_liked_tweets(
credentials: TwitterCredentials,
user_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: ExpansionFilter | None,
media_fields: TweetMediaFieldsFilter | None,

View File

@@ -69,9 +69,11 @@ class TwitterPostTweetBlock(Block):
["tweet.read", "tweet.write", "users.read", "offline.access"]
)
tweet_text: str = SchemaField(
tweet_text: str | None = SchemaField(
description="Text of the tweet to post",
placeholder="Enter your tweet",
default = None,
advanced= False
)
for_super_followers_only: bool = SchemaField(
@@ -149,8 +151,8 @@ class TwitterPostTweetBlock(Block):
def post_tweet(
self,
credentials: TwitterCredentials,
input_txt: str,
attachment: Union[Media, DeepLink, Poll, Place, Quote],
input_txt: str | None,
attachment: Union[Media, DeepLink, Poll, Place, Quote] | None,
for_super_followers_only: bool,
exclude_reply_user_ids: Optional[List[str]],
in_reply_to_tweet_id: Optional[str],

View File

@@ -45,7 +45,7 @@ class TwitterGetQuoteTweetsBlock(Block):
placeholder="Enter tweet ID",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Number of results to return (max 100)",
default=10,
advanced=True,
@@ -125,7 +125,7 @@ class TwitterGetQuoteTweetsBlock(Block):
def get_quote_tweets(
credentials: TwitterCredentials,
tweet_id: str,
max_results: int,
max_results: int | None,
exclude: TweetExcludesFilter | None,
pagination_token: str | None,
expansions: ExpansionFilter | None,

View File

@@ -191,7 +191,7 @@ class TwitterGetRetweetersBlock(Block):
placeholder="Enter tweet ID",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results per page (1-100)",
default=10,
placeholder="Enter max results",
@@ -270,7 +270,7 @@ class TwitterGetRetweetersBlock(Block):
def get_retweeters(
credentials: TwitterCredentials,
tweet_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,

View File

@@ -49,7 +49,7 @@ class TwitterGetUserMentionsBlock(Block):
placeholder="Enter user ID",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Number of tweets to retrieve (5-100)",
default=10,
advanced=True,
@@ -143,7 +143,7 @@ class TwitterGetUserMentionsBlock(Block):
def get_mentions(
credentials: TwitterCredentials,
user_id: str,
max_results: int,
max_results: int | None,
start_time: datetime | None,
end_time: datetime | None,
since_id: str | None,
@@ -279,7 +279,6 @@ class TwitterGetUserMentionsBlock(Block):
except Exception as e:
yield "error", handle_tweepy_exception(e)
class TwitterGetHomeTimelineBlock(Block):
"""
Returns a collection of the most recent Tweets and Retweets posted by you and users you follow
@@ -290,7 +289,7 @@ class TwitterGetHomeTimelineBlock(Block):
["tweet.read", "users.read", "offline.access"]
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Number of tweets to retrieve (5-100)",
default=10,
advanced=True,
@@ -376,7 +375,7 @@ class TwitterGetHomeTimelineBlock(Block):
@staticmethod
def get_timeline(
credentials: TwitterCredentials,
max_results: int,
max_results: int | None,
start_time: datetime | None,
end_time: datetime | None,
since_id: str | None,
@@ -510,7 +509,6 @@ class TwitterGetHomeTimelineBlock(Block):
except Exception as e:
yield "error", handle_tweepy_exception(e)
class TwitterGetUserTweetsBlock(Block):
"""
Returns Tweets composed by a single user, specified by the requested user ID
@@ -526,7 +524,7 @@ class TwitterGetUserTweetsBlock(Block):
placeholder="Enter user ID",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Number of tweets to retrieve (5-100)",
default=10,
advanced=True,
@@ -620,7 +618,7 @@ class TwitterGetUserTweetsBlock(Block):
def get_user_tweets(
credentials: TwitterCredentials,
user_id: str,
max_results: int,
max_results: int | None,
start_time: datetime | None,
end_time: datetime | None,
since_id: str | None,

View File

@@ -25,7 +25,7 @@ from backend.data.model import SchemaField
class TwitterUnblockUserBlock(Block):
"""
Unblock a specific user on Twitter
Unblock a specific user on Twitter. The request succeeds with no action when the user sends a request to a user they're not blocking or have already unblocked.
"""
class Input(BlockSchema):
@@ -98,7 +98,7 @@ class TwitterGetBlockedUsersBlock(Block):
["users.read", "offline.access", "block.read"]
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results to return (1-1000, default 100)",
placeholder="Enter max results",
default=10,
@@ -156,7 +156,7 @@ class TwitterGetBlockedUsersBlock(Block):
@staticmethod
def get_blocked_users(
credentials: TwitterCredentials,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,

View File

@@ -28,7 +28,8 @@ from backend.data.model import SchemaField
class TwitterUnfollowUserBlock(Block):
"""
Allows a user to unfollow another user specified by target user ID
Allows a user to unfollow another user specified by target user ID.
The request succeeds with no action when the authenticated user sends a request to a user they're not following or have already unfollowed.
"""
class Input(BlockSchema):
@@ -96,7 +97,10 @@ class TwitterUnfollowUserBlock(Block):
class TwitterFollowUserBlock(Block):
"""
Allows a user to follow another user specified by target user ID
Allows a user to follow another user specified by target user ID. If the target user does not have public Tweets,
this endpoint will send a follow request. The request succeeds with no action when the authenticated user sends a
request to a user they're already following, or if they're sending a follower request to a user that does not have
public Tweets.
"""
class Input(BlockSchema):
@@ -175,7 +179,7 @@ class TwitterGetFollowersBlock(Block):
placeholder="Enter target user ID",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results to return (1-1000, default 100)",
placeholder="Enter max results",
default=10,
@@ -240,7 +244,7 @@ class TwitterGetFollowersBlock(Block):
def get_followers(
credentials: TwitterCredentials,
target_user_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,
@@ -348,7 +352,7 @@ class TwitterGetFollowingBlock(Block):
placeholder="Enter target user ID",
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="Maximum number of results to return (1-1000, default 100)",
placeholder="Enter max results",
default=10,
@@ -413,7 +417,7 @@ class TwitterGetFollowingBlock(Block):
def get_following(
credentials: TwitterCredentials,
target_user_id: str,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,

View File

@@ -28,7 +28,8 @@ from backend.data.model import SchemaField
class TwitterUnmuteUserBlock(Block):
"""
Allows a user to unmute another user specified by target user ID
Allows a user to unmute another user specified by target user ID.
The request succeeds with no action when the user sends a request to a user they're not muting or have already unmuted.
"""
class Input(BlockSchema):
@@ -104,7 +105,7 @@ class TwitterGetMutedUsersBlock(Block):
["users.read", "offline.access"]
)
max_results: int = SchemaField(
max_results: int | None = SchemaField(
description="The maximum number of results to be returned per page (1-1000). Default is 100.",
placeholder="Enter max results",
default=10,
@@ -176,7 +177,7 @@ class TwitterGetMutedUsersBlock(Block):
@staticmethod
def get_muted_users(
credentials: TwitterCredentials,
max_results: int,
max_results: int | None,
pagination_token: str | None,
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,

View File

@@ -1,5 +1,6 @@
from typing import cast
from typing import Literal, Union, cast
from pydantic import BaseModel
import tweepy
from tweepy.client import Response
@@ -25,28 +26,35 @@ from backend.blocks.twitter.tweepy_exceptions import handle_tweepy_exception
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from backend.data.model import SchemaField
class UserId(BaseModel):
discriminator: Literal['user_id']
user_id: str = SchemaField(
description="The ID of the user to lookup",
default=""
)
class Username(BaseModel):
discriminator: Literal['username']
username: str = SchemaField(
description="The Twitter username (handle) of the user",
default=""
)
class TwitterGetUserBlock(Block):
"""
Gets information about a single Twitter user specified by ID or username
"""
class Input(UserExpansionInputs):
credentials: TwitterCredentialsInput = TwitterCredentialsField(
["users.read", "offline.access"]
)
user_id: str = SchemaField(
description="The ID of the user to lookup",
placeholder="Enter user ID",
default="",
advanced=False,
)
username: str = SchemaField(
description="The Twitter username (handle) of the user",
placeholder="Enter username",
default="",
identifier: Union[UserId, Username] = SchemaField(
discriminator='discriminator',
description="Choose whether to identify the user by their unique Twitter ID or by their username",
advanced=False,
)
@@ -71,8 +79,10 @@ class TwitterGetUserBlock(Block):
input_schema=TwitterGetUserBlock.Input,
output_schema=TwitterGetUserBlock.Output,
test_input={
"user_id": "",
"username": "twitter",
"identifier": {
"discriminator": "username",
"username": "twitter"
},
"credentials": TEST_CREDENTIALS_INPUT,
"expansions": None,
"tweet_fields": None,
@@ -114,8 +124,7 @@ class TwitterGetUserBlock(Block):
@staticmethod
def get_user(
credentials: TwitterCredentials,
user_id: str,
username: str,
identifier: Union[UserId, Username],
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,
user_fields: TweetUserFieldsFilter | None,
@@ -126,8 +135,8 @@ class TwitterGetUserBlock(Block):
)
params = {
"id": None if not user_id else user_id,
"username": None if not username else username,
"id": identifier.user_id if isinstance(identifier, UserId) else None,
"username": identifier.username if isinstance(identifier, Username) else None,
"user_auth": False,
}
@@ -171,11 +180,10 @@ class TwitterGetUserBlock(Block):
try:
data, included, username, id, name = self.get_user(
credentials,
input_data.user_id,
input_data.username,
input_data.identifier,
input_data.expansions,
input_data.tweet_fields,
input_data.user_fields,
input_data.user_fields
)
if id:
yield "id", id
@@ -191,6 +199,24 @@ class TwitterGetUserBlock(Block):
yield "error", handle_tweepy_exception(e)
class UserIdList(BaseModel):
discriminator: Literal['user_id_list']
user_ids: list[str] = SchemaField(
description="List of user IDs to lookup (max 100)",
placeholder="Enter user IDs",
default=[],
advanced=False,
)
class UsernameList(BaseModel):
discriminator: Literal['username_list']
usernames: list[str] = SchemaField(
description="List of Twitter usernames/handles to lookup (max 100)",
placeholder="Enter usernames",
default=[],
advanced=False,
)
class TwitterGetUsersBlock(Block):
"""
Gets information about multiple Twitter users specified by IDs or usernames
@@ -201,17 +227,9 @@ class TwitterGetUsersBlock(Block):
["users.read", "offline.access"]
)
user_ids: list[str] = SchemaField(
description="List of user IDs to lookup (max 100)",
placeholder="Enter user IDs",
default=[],
advanced=False,
)
usernames: list[str] = SchemaField(
description="List of Twitter usernames/handles to lookup (max 100)",
placeholder="Enter usernames",
default=[],
identifier: Union[UserIdList, UsernameList] = SchemaField(
discriminator='discriminator',
description="Choose whether to identify users by their unique Twitter IDs or by their usernames",
advanced=False,
)
@@ -236,8 +254,10 @@ class TwitterGetUsersBlock(Block):
input_schema=TwitterGetUsersBlock.Input,
output_schema=TwitterGetUsersBlock.Output,
test_input={
"user_ids": [],
"usernames": ["twitter", "twitterdev"],
"identifier": {
"discriminator": "username_list",
"usernames": ["twitter", "twitterdev"]
},
"credentials": TEST_CREDENTIALS_INPUT,
"expansions": None,
"tweet_fields": None,
@@ -281,8 +301,7 @@ class TwitterGetUsersBlock(Block):
@staticmethod
def get_users(
credentials: TwitterCredentials,
user_ids: list[str],
usernames: list[str],
identifier: Union[UserIdList, UsernameList],
expansions: UserExpansionsFilter | None,
tweet_fields: TweetFieldsFilter | None,
user_fields: TweetUserFieldsFilter | None,
@@ -293,8 +312,8 @@ class TwitterGetUsersBlock(Block):
)
params = {
"ids": None if not user_ids else user_ids,
"usernames": None if not usernames else usernames,
"ids": ",".join(identifier.user_ids) if isinstance(identifier, UserIdList) else None,
"usernames": ",".join(identifier.usernames) if isinstance(identifier, UsernameList) else None,
"user_auth": False,
}
@@ -339,8 +358,7 @@ class TwitterGetUsersBlock(Block):
try:
data, included, usernames, ids, names = self.get_users(
credentials,
input_data.user_ids,
input_data.usernames,
input_data.identifier,
input_data.expansions,
input_data.tweet_fields,
input_data.user_fields,

View File

@@ -409,7 +409,7 @@ export const NodeGenericInputField: FC<{
(subSchema) => "type" in subSchema && subSchema.type == "boolean",
) &&
Object.keys((propSchema.anyOf[0] as BlockIOObjectSubSchema).properties)
.length >= 3
.length >= 1
) {
const options = Object.keys(
(propSchema.anyOf[0] as BlockIOObjectSubSchema).properties,
@@ -666,6 +666,7 @@ const NodeOneOfDiscriminatorField: FC<{
)?.schema;
function getEntryKey(key: string): string {
// use someKey for handle purpose (not childKey)
return `${propKey}_#_${key}`;
}
@@ -702,21 +703,21 @@ const NodeOneOfDiscriminatorField: FC<{
if (someKey === "discriminator") {
return null;
}
const childKey = propKey ? `${propKey}.${someKey}` : someKey;
const childKey = propKey ? `${propKey}.${someKey}` : someKey; // for history redo/undo purpose
return (
<div
key={childKey}
className="mb-4 flex w-full flex-col justify-between space-y-2"
>
<NodeHandle
keyName={getEntryKey(childKey)}
keyName={getEntryKey(someKey)}
schema={childSchema as BlockIOSubSchema}
isConnected={isConnected(getEntryKey(childKey))}
isConnected={isConnected(getEntryKey(someKey))}
isRequired={false}
side="left"
/>
{!isConnected(childKey) && (
{!isConnected(someKey) && (
<NodeGenericInputField
nodeId={nodeId}
key={propKey}

View File

@@ -129,4 +129,42 @@ Below is a comprehensive list of all available blocks, categorized by their prim
| [GitHub Unassign PR Reviewer](github/pull_requests.md#github-unassign-pr-reviewer) | Removes an assigned reviewer from a specific GitHub pull request |
| [GitHub List PR Reviewers](github/pull_requests.md#github-list-pr-reviewers) | Retrieves a list of all assigned reviewers for a specific GitHub pull request |
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.
## Twitter Integration
| Block Name | Description |
|------------|-------------|
| [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 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 |
| [Twitter Get Retweeters](twitter/twitter.md#twitter-get-retweeters-block) | Gets list of users who have retweeted a specified tweet with pagination and filtering options |
| [Twitter Get User Mentions](twitter/twitter.md#twitter-get-user-mentions-block) | Gets tweets where a specific user is mentioned using their user ID |
| [Twitter Get Home Timeline](twitter/twitter.md#twitter-get-home-timeline-block) | Gets recent tweets and retweets from authenticated user and followed accounts |
| [Twitter Get User](twitter/twitter.md#twitter-get-user-block) | Gets detailed profile information for a single Twitter user |
| [Twitter Get Users](twitter/twitter.md#twitter-get-users-block) | Gets profile information for multiple Twitter users (up to 100) |
| [Twitter Search Spaces](twitter/twitter.md#twitter-search-spaces-block) | Searches for Twitter Spaces matching title keywords with state filtering |
| [Twitter Get Spaces](twitter/twitter.md#twitter-get-spaces-block) | Gets information about multiple Twitter Spaces by Space IDs or creator IDs |
| [Twitter Get Space By Id](twitter/twitter.md#twitter-get-space-by-id-block) | Gets detailed information about a single Twitter Space |
| [Twitter Get Space Tweets](twitter/twitter.md#twitter-get-space-tweets-block) | Gets tweets that were shared during a Twitter Space session |
| [Twitter Follow List](twitter/twitter.md#twitter-follow-list-block) | Follows a Twitter List using its List ID |
| [Twitter Unfollow List](twitter/twitter.md#twitter-unfollow-list-block) | Unfollows a previously followed Twitter List |
| [Twitter Get List](twitter/twitter.md#twitter-get-list-block) | Gets detailed information about a specific Twitter List |
| [Twitter Get Owned Lists](twitter/twitter.md#twitter-get-owned-lists-block) | Gets all Twitter Lists owned by a specified user |
| [Twitter Get List Members](twitter/twitter.md#twitter-get-list-members-block) | Gets information about members of a specified Twitter List |
| [Twitter Add List Member](twitter/twitter.md#twitter-add-list-member-block) | Adds a specified user as a member to a Twitter List |
| [Twitter Remove List Member](twitter/twitter.md#twitter-remove-list-member-block) | Removes a specified user from a Twitter List |
| [Twitter Get List Tweets](twitter/twitter.md#twitter-get-list-tweets-block) | Gets tweets posted within a specified Twitter List |
| [Twitter Create List](twitter/twitter.md#twitter-create-list-block) | Creates a new Twitter List with specified name and settings |
| [Twitter Update List](twitter/twitter.md#twitter-update-list-block) | Updates name and/or description of an existing Twitter List |
| [Twitter Delete List](twitter/twitter.md#twitter-delete-list-block) | Deletes a specified Twitter List |
| [Twitter Pin List](twitter/twitter.md#twitter-pin-list-block) | Pins a Twitter List to appear at top of Lists |
| [Twitter Unpin List](twitter/twitter.md#twitter-unpin-list-block) | Removes a Twitter List from pinned Lists |
| [Twitter Get Pinned Lists](twitter/twitter.md#twitter-get-pinned-lists-block) | Gets all Twitter Lists that are currently pinned |
| Twitter List Get Followers | Working... Gets all followers of a specified Twitter List |
| Twitter Get Followed Lists | Working... Gets all Lists that a user follows |
| Twitter Get DM Events | Working... Retrieves direct message events for a user |
| Twitter Send Direct Message | Working... Sends a direct message to a specified user |
| Twitter Create DM Conversation | Working... Creates a new direct message conversation |
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.

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 504 KiB

After

Width:  |  Height:  |  Size: 504 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 309 KiB

After

Width:  |  Height:  |  Size: 309 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 113 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 184 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

Before

Width:  |  Height:  |  Size: 240 KiB

After

Width:  |  Height:  |  Size: 240 KiB

View File

Before

Width:  |  Height:  |  Size: 560 KiB

After

Width:  |  Height:  |  Size: 560 KiB

View File

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 184 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 436 KiB

After

Width:  |  Height:  |  Size: 436 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB