@@ -93,6 +93,21 @@ def register_actions(self) -> None:
93
93
],
94
94
description = "Fetch tweet replies"
95
95
),
96
+ "get-user-details" : Action (
97
+ name = "get-user-details" ,
98
+ parameters = [
99
+ ActionParameter ("user_ids" , True , list , "IDs of the user to get details for" ),
100
+ ActionParameter ("usernames" , True , list , "Usernames of the user to get details for" )
101
+ ],
102
+ description = "Get details for user(s) by ID or username"
103
+ ),
104
+ "get-tweet-details" : Action (
105
+ name = "get-tweet-details" ,
106
+ parameters = [
107
+ ActionParameter ("tweet_id" , True , str , "ID of the tweet to get details for" )
108
+ ],
109
+ description = "Get details for a specific tweet"
110
+ ),
96
111
"stream-tweets" : Action (
97
112
name = "stream-tweets" ,
98
113
parameters = [
@@ -517,6 +532,47 @@ def get_tweet_replies(self, tweet_id: str, count: int = 10, **kwargs) -> List[di
517
532
518
533
logger .info (f"Retrieved { len (replies )} replies" )
519
534
return replies
535
+
536
+ def get_user_details (self , user_ids : list , usernames : list , ** kwargs ) -> dict :
537
+ """Get details for user(s) by ID or username"""
538
+ logger .debug (f"Getting details for user_ids: { user_ids } or usernames: { usernames } " )
539
+
540
+ params = {"user.fields" : "username" }
541
+
542
+ if user_ids :
543
+ params ["ids" ] = "," .join (user_ids )
544
+ endpoint = "users"
545
+ else :
546
+ params ["usernames" ] = "," .join (usernames )
547
+ endpoint = f"users/by/"
548
+
549
+ response = self ._make_request ('get' , endpoint , params = params )
550
+
551
+ users = response .get ("data" , [])
552
+
553
+ logger .info ("Retrieved user details" )
554
+ return users
555
+
556
+ def get_tweet_details (self , tweet_id : str , ** kwargs ) -> dict :
557
+ """Get details for a specific tweet"""
558
+ logger .debug (f"Getting details for tweet { tweet_id } " )
559
+
560
+ params = {
561
+ "tweet.fields" : "author_id,created_at,text,attachments,referenced_tweets" ,
562
+ "expansions" : "author_id" ,
563
+ "user.fields" : "username" ,
564
+ "ids" : tweet_id
565
+ }
566
+
567
+ response = self ._make_request ('get' , 'tweets' , params = params )
568
+ tweet = response .get ("data" , [])[0 ]
569
+
570
+ if "includes" in response and "users" in response ["includes" ]:
571
+ author = response ["includes" ]["users" ][0 ]
572
+ tweet ["author_username" ] = author ["username" ]
573
+
574
+ logger .info ("Retrieved tweet details" )
575
+ return tweet
520
576
521
577
def _bearer_oauth (self ,r ):
522
578
bearer_token = self ._get_credentials ().get ("TWITTER_BEARER_TOKEN" )
@@ -553,17 +609,30 @@ def stream_tweets(self, filter_string:str,**kwargs) ->Iterator[Dict[str, Any]]:
553
609
rules = self ._get_rules ()
554
610
self ._delete_rules (rules )
555
611
self ._build_rule (filter_string )
556
- logger .info ("Starting Twitter stream" )
557
612
try :
613
+ params = {
614
+ "tweet.fields" : "author_id,created_at,text,attachments,referenced_tweets" ,
615
+ "user.fields" : "username" ,
616
+ "expansions" : "author_id"
617
+ }
558
618
response = self ._make_request ('get' , 'tweets/search/stream' ,
559
- use_bearer = True , stream = True )
619
+ use_bearer = True , stream = True , params = params )
560
620
561
621
if response .status_code != 200 :
562
622
raise TwitterAPIError (f"Stream connection failed with status { response .status_code } : { response .text } " )
563
623
564
624
for line in response .iter_lines ():
625
+
565
626
if line :
566
- tweet_data = json .loads (line )['data' ]
627
+ tweet_json = json .loads (line )
628
+
629
+ tweet_data = tweet_json .get ("data" , {})
630
+ includes = tweet_json .get ("includes" , {})
631
+
632
+ if includes and "users" in includes :
633
+ author = includes ["users" ][0 ]
634
+ tweet_data ["author_username" ] = author ["username" ]
635
+
567
636
yield tweet_data
568
637
569
638
except Exception as e :
0 commit comments