aboutsummaryrefslogtreecommitdiffstats
path: root/gallery_dl/extractor/bluesky.py
diff options
context:
space:
mode:
Diffstat (limited to 'gallery_dl/extractor/bluesky.py')
-rw-r--r--gallery_dl/extractor/bluesky.py60
1 files changed, 24 insertions, 36 deletions
diff --git a/gallery_dl/extractor/bluesky.py b/gallery_dl/extractor/bluesky.py
index 6f4abd5..e2c5334 100644
--- a/gallery_dl/extractor/bluesky.py
+++ b/gallery_dl/extractor/bluesky.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright 2024 Mike Fährmann
+# Copyright 2024-2025 Mike Fährmann
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -8,7 +8,7 @@
"""Extractors for https://bsky.app/"""
-from .common import Extractor, Message
+from .common import Extractor, Message, Dispatch
from .. import text, util, exception
from ..cache import cache, memcache
@@ -26,8 +26,7 @@ class BlueskyExtractor(Extractor):
root = "https://bsky.app"
def _init(self):
- meta = self.config("metadata") or ()
- if meta:
+ if meta := self.config("metadata") or ():
if isinstance(meta, str):
meta = meta.replace(" ", "").split(",")
elif not isinstance(meta, (list, tuple)):
@@ -62,9 +61,8 @@ class BlueskyExtractor(Extractor):
yield Message.Directory, post
if files:
did = post["author"]["did"]
- base = (
- "{}/xrpc/com.atproto.sync.getBlob?did={}&cid=".format(
- self.api.service_endpoint(did), did))
+ base = (f"{self.api.service_endpoint(did)}/xrpc"
+ f"/com.atproto.sync.getBlob?did={did}&cid=")
for post["num"], file in enumerate(files, 1):
post.update(file)
yield Message.Url, base + file["filename"], post
@@ -96,7 +94,7 @@ class BlueskyExtractor(Extractor):
uri = record["value"]["subject"]["uri"]
if "/app.bsky.feed.post/" in uri:
yield from self.api.get_post_thread_uri(uri, depth)
- except exception.StopExtraction:
+ except exception.ControlException:
pass # deleted post
except Exception as exc:
self.log.debug(record, exc_info=exc)
@@ -210,16 +208,12 @@ class BlueskyExtractor(Extractor):
},)
-class BlueskyUserExtractor(BlueskyExtractor):
- subcategory = "user"
+class BlueskyUserExtractor(Dispatch, BlueskyExtractor):
pattern = USER_PATTERN + r"$"
example = "https://bsky.app/profile/HANDLE"
- def initialize(self):
- pass
-
def items(self):
- base = "{}/profile/{}/".format(self.root, self.groups[0])
+ base = f"{self.root}/profile/{self.groups[0]}/"
default = ("posts" if self.config("quoted", False) or
self.config("reposts", False) else "media")
return self._dispatch_extractors((
@@ -415,11 +409,9 @@ class BlueskyAPI():
def get_feed(self, actor, feed):
endpoint = "app.bsky.feed.getFeed"
- params = {
- "feed" : "at://{}/app.bsky.feed.generator/{}".format(
- self._did_from_actor(actor), feed),
- "limit": "100",
- }
+ uri = (f"at://{self._did_from_actor(actor)}"
+ f"/app.bsky.feed.generator/{feed}")
+ params = {"feed": uri, "limit": "100"}
return self._pagination(endpoint, params)
def get_follows(self, actor):
@@ -432,16 +424,13 @@ class BlueskyAPI():
def get_list_feed(self, actor, list):
endpoint = "app.bsky.feed.getListFeed"
- params = {
- "list" : "at://{}/app.bsky.graph.list/{}".format(
- self._did_from_actor(actor), list),
- "limit": "100",
- }
+ uri = f"at://{self._did_from_actor(actor)}/app.bsky.graph.list/{list}"
+ params = {"list" : uri, "limit": "100"}
return self._pagination(endpoint, params)
def get_post_thread(self, actor, post_id):
- uri = "at://{}/app.bsky.feed.post/{}".format(
- self._did_from_actor(actor), post_id)
+ uri = (f"at://{self._did_from_actor(actor)}"
+ f"/app.bsky.feed.post/{post_id}")
depth = self.extractor.config("depth", "0")
return self.get_post_thread_uri(uri, depth)
@@ -498,7 +487,7 @@ class BlueskyAPI():
url = "https://plc.directory/" + did
try:
- data = self.extractor.request(url).json()
+ data = self.extractor.request_json(url)
for service in data["service"]:
if service["type"] == "AtprotoPersonalDataServer":
return service["serviceEndpoint"]
@@ -551,15 +540,15 @@ class BlueskyAPI():
"password" : self.password,
}
- url = "{}/xrpc/{}".format(self.root, endpoint)
+ url = f"{self.root}/xrpc/{endpoint}"
response = self.extractor.request(
url, method="POST", headers=headers, json=data, fatal=None)
data = response.json()
if response.status_code != 200:
self.log.debug("Server response: %s", data)
- raise exception.AuthenticationError('"{}: {}"'.format(
- data.get("error"), data.get("message")))
+ raise exception.AuthenticationError(
+ f"\"{data.get('error')}: {data.get('message')}\"")
_refresh_token_cache.update(self.username, data["refreshJwt"])
return "Bearer " + data["accessJwt"]
@@ -567,7 +556,7 @@ class BlueskyAPI():
def _call(self, endpoint, params, root=None):
if root is None:
root = self.root
- url = "{}/xrpc/{}".format(root, endpoint)
+ url = f"{root}/xrpc/{endpoint}"
while True:
self.authenticate()
@@ -581,16 +570,15 @@ class BlueskyAPI():
self.extractor.wait(until=until)
continue
+ msg = "API request failed"
try:
data = response.json()
- msg = "API request failed ('{}: {}')".format(
- data["error"], data["message"])
+ msg = f"{msg} ('{data['error']}: {data['message']}')"
except Exception:
- msg = "API request failed ({} {})".format(
- response.status_code, response.reason)
+ msg = f"{msg} ({response.status_code} {response.reason})"
self.extractor.log.debug("Server response: %s", response.text)
- raise exception.StopExtraction(msg)
+ raise exception.AbortExtraction(msg)
def _pagination(self, endpoint, params,
key="feed", root=None, check_empty=False):