From c37a1c06c83edadfea6cc51b1de9343db2a42393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Tue, 16 Jun 2020 14:27:22 +0200 Subject: [PATCH] [twitter] add extractor for liked tweets (closes #837) You need to be logged in to get access to anyone's liked tweets, it seems. --- docs/supportedsites.rst | 2 +- gallery_dl/extractor/twitter.py | 44 ++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/supportedsites.rst b/docs/supportedsites.rst index 82b9bd42..4bb4a732 100644 --- a/docs/supportedsites.rst +++ b/docs/supportedsites.rst @@ -160,6 +160,6 @@ Turboimagehost https://www.turboimagehost.com/ individual Images .. |pixiv-C| replace:: Favorites, Follows, pixiv.me Links, Rankings, Search Results, User Profiles, individual Images .. |reddit-C| replace:: individual Images, Submissions, Subreddits, User Profiles .. |smugmug-C| replace:: Albums, individual Images, Images from Users and Folders -.. |twitter-C| replace:: Bookmarks, Media Timelines, Search Results, Timelines, Tweets +.. |twitter-C| replace:: Bookmarks, Likes, Media Timelines, Search Results, Timelines, Tweets .. |wallhaven-A| replace:: Optional (`API Key `__) .. |yuki-S| replace:: yuki.la 4chan archive diff --git a/gallery_dl/extractor/twitter.py b/gallery_dl/extractor/twitter.py index 2e4ef42e..6841dd90 100644 --- a/gallery_dl/extractor/twitter.py +++ b/gallery_dl/extractor/twitter.py @@ -264,6 +264,27 @@ class TwitterMediaExtractor(TwitterExtractor): return TwitterAPI(self).timeline_media(self.user) +class TwitterLikesExtractor(TwitterExtractor): + """Extractor for liked tweets""" + subcategory = "likes" + pattern = (r"(?:https?://)?(?:www\.|mobile\.)?twitter\.com" + r"/(?!search)([^/?&#]+)/likes(?!\w)") + test = ("https://twitter.com/supernaturepics/likes",) + + def tweets(self): + return TwitterAPI(self).timeline_favorites(self.user) + + +class TwitterBookmarkExtractor(TwitterExtractor): + """Extractor for bookmarked tweets""" + subcategory = "bookmark" + pattern = r"(?:https?://)?(?:www\.|mobile\.)?twitter\.com/i/bookmarks()" + test = ("https://twitter.com/i/bookmarks",) + + def tweets(self): + return TwitterAPI(self).timeline_bookmark() + + class TwitterSearchExtractor(TwitterExtractor): """Extractor for all images from a search timeline""" subcategory = "search" @@ -344,16 +365,6 @@ class TwitterTweetExtractor(TwitterExtractor): return TwitterAPI(self).tweet(self.tweet_id) -class TwitterBookmarkExtractor(TwitterExtractor): - """Extractor for bookmarked tweets""" - subcategory = "bookmark" - pattern = r"(?:https?://)?(?:www\.|mobile\.)?twitter\.com/i/bookmarks()" - test = ("https://twitter.com/i/bookmarks",) - - def tweets(self): - return TwitterAPI(self).bookmarks() - - class TwitterAPI(): def __init__(self, extractor): @@ -430,6 +441,15 @@ class TwitterAPI(): endpoint = "2/timeline/media/{}.json".format(user["rest_id"]) return self._pagination(endpoint) + def timeline_favorites(self, screen_name): + user = self.user_by_screen_name(screen_name) + endpoint = "2/timeline/favorites/{}.json".format(user["rest_id"]) + return self._pagination(endpoint) + + def timeline_bookmark(self): + endpoint = "2/timeline/bookmark.json" + return self._pagination(endpoint) + def search(self, query): endpoint = "2/search/adaptive.json" params = self.params.copy() @@ -437,10 +457,6 @@ class TwitterAPI(): return self._pagination( endpoint, params, "sq-I-t-", "sq-cursor-bottom") - def bookmarks(self): - endpoint = "2/timeline/bookmark.json" - return self._pagination(endpoint) - def user_by_screen_name(self, screen_name): endpoint = "graphql/-xfUfZsnR_zqjFd-IfrN5A/UserByScreenName" params = {