From ee7c054855f2b38c12aeb1663089e41c1f79eea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20F=C3=A4hrmann?= Date: Fri, 16 Feb 2024 15:56:25 +0100 Subject: [PATCH] [bluesky] add 'search' extractor (#4438) Both https://bsky.app/search?q=QUERY and https://bsky.app/search/QUERY are recognized as search URLs, where QUERY gets forwarded unmodified as 'q' parameter for app.bsky.feed.searchPosts . User searches are not supported yet. --- docs/supportedsites.md | 2 +- gallery_dl/extractor/bluesky.py | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/supportedsites.md b/docs/supportedsites.md index 29232591..7b702d6c 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -124,7 +124,7 @@ Consider all listed sites to potentially be NSFW. Bluesky https://bsky.app/ - Feeds, Followed Users, Likes, Lists, Media Files, Posts, Replies, User Profiles + Avatars, Backgrounds, Feeds, Followed Users, Likes, Lists, Media Files, Posts, Replies, Search Results, User Profiles Supported diff --git a/gallery_dl/extractor/bluesky.py b/gallery_dl/extractor/bluesky.py index 5dae14bc..8de0d7bf 100644 --- a/gallery_dl/extractor/bluesky.py +++ b/gallery_dl/extractor/bluesky.py @@ -43,7 +43,8 @@ class BlueskyExtractor(Extractor): def items(self): for post in self.posts(): - post = post["post"] + if "post" in post: + post = post["post"] post.update(post["record"]) del post["record"] @@ -265,6 +266,15 @@ class BlueskyBackgroundExtractor(BlueskyExtractor): return self._make_post(self.user, "banner") +class BlueskySearchExtractor(BlueskyExtractor): + subcategory = "search" + pattern = BASE_PATTERN + r"/search(?:/|\?q=)(.+)" + example = "https://bsky.app/search?q=QUERY" + + def posts(self): + return self.api.search_posts(self.user) + + class BlueskyAPI(): """Interface for the Bluesky API @@ -360,6 +370,14 @@ class BlueskyAPI(): params = {"handle": handle} return self._call(endpoint, params)["did"] + def search_posts(self, query): + endpoint = "app.bsky.feed.searchPosts" + params = { + "q" : query, + "limit": "100", + } + return self._pagination(endpoint, params, "posts") + def _did_from_actor(self, actor): if actor.startswith("did:"): did = actor