From 6b67421f7a005f28ece313b3a4de901da3df0feb Mon Sep 17 00:00:00 2001 From: Jamesb Date: Sun, 21 Apr 2024 12:27:53 +0100 Subject: [PATCH] feat: add bookmarks supportg --- test_bookmarks.py | 17 +++++++++++++++++ twscrape/api.py | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test_bookmarks.py diff --git a/test_bookmarks.py b/test_bookmarks.py new file mode 100644 index 0000000..5b97b69 --- /dev/null +++ b/test_bookmarks.py @@ -0,0 +1,17 @@ +import asyncio + +import twscrape +from twscrape.utils import gather + +async def main(): + api = twscrape.API() + # add accounts here or before from cli (see README.md for examples) + await api.pool.add_account("BookmarkTe60140", "", '', '') + await api.pool.login_all() + bms = await gather(api.bookmarks()) + for bm in bms: + print(bm.rawContent) + print('-----') + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/twscrape/api.py b/twscrape/api.py index 14c44ef..ffc83f4 100644 --- a/twscrape/api.py +++ b/twscrape/api.py @@ -23,6 +23,7 @@ OP_BlueVerifiedFollowers = "AXsZSOWx3FCvneEIzxDj6A/BlueVerifiedFollowers" OP_UserCreatorSubscriptions = "NHT8e7FjnCS3TP0QfP_OUQ/UserCreatorSubscriptions" OP_UserMedia = "aQQLnkexAl5z9ec_UgbEIA/UserMedia" +OP_UserBookmarks = "yzqS_xq0glDD7YZJ2YDaiA/Bookmarks" GQL_URL = "https://twitter.com/i/api/graphql" @@ -385,6 +386,30 @@ async def user_tweets_and_replies(self, uid: int, limit=-1, kv=None): yield x # user_media + + async def bookmarks_raw(self, limit=-1, kv=None): + op = OP_UserBookmarks + kv = { + "count": 20, + "includePromotedContent": False, + "withClientEventToken": False, + "withBirdwatchNotes": False, + "withVoice": True, + "withV2Timeline": True, + **(kv or {}), + } + ft = { + 'graphql_timeline_v2_bookmark_timeline': True, + } + async with aclosing(self._gql_items(op, kv, ft, limit=limit)) as gen: + async for x in gen: + yield x + + async def bookmarks(self, limit=-1, kv=None): + async with aclosing(self.bookmarks_raw(limit=limit, kv=kv)) as gen: + async for rep in gen: + for x in parse_tweets(rep.json(), limit): + yield x async def user_media_raw(self, uid: int, limit=-1, kv=None): op = OP_UserMedia