diff libervia/backend/plugins/plugin_comp_ap_gateway/http_server.py @ 4270:0d7bb4df2343

Reformatted code base using black.
author Goffi <goffi@goffi.org>
date Wed, 19 Jun 2024 18:44:57 +0200
parents 49019947cc76
children
line wrap: on
line diff
--- a/libervia/backend/plugins/plugin_comp_ap_gateway/http_server.py	Tue Jun 18 12:06:45 2024 +0200
+++ b/libervia/backend/plugins/plugin_comp_ap_gateway/http_server.py	Wed Jun 19 18:44:57 2024 +0200
@@ -41,11 +41,29 @@
 from libervia.backend.memory.sqla_mapping import SubscriptionState
 
 from .constants import (
-    NS_AP, MEDIA_TYPE_AP, MEDIA_TYPE_AP_ALT, CONTENT_TYPE_WEBFINGER, CONTENT_TYPE_AP,
-    TYPE_ACTOR, TYPE_INBOX, TYPE_SHARED_INBOX, TYPE_OUTBOX, TYPE_EVENT, AP_REQUEST_TYPES,
-    PAGE_SIZE, ACTIVITY_TYPES_LOWER, ACTIVIY_NO_ACCOUNT_ALLOWED, SIGN_HEADERS, HS2019,
-    SIGN_EXP, TYPE_FOLLOWERS, TYPE_FOLLOWING, TYPE_ITEM, TYPE_LIKE, TYPE_REACTION,
-    ST_AP_CACHE
+    NS_AP,
+    MEDIA_TYPE_AP,
+    MEDIA_TYPE_AP_ALT,
+    CONTENT_TYPE_WEBFINGER,
+    CONTENT_TYPE_AP,
+    TYPE_ACTOR,
+    TYPE_INBOX,
+    TYPE_SHARED_INBOX,
+    TYPE_OUTBOX,
+    TYPE_EVENT,
+    AP_REQUEST_TYPES,
+    PAGE_SIZE,
+    ACTIVITY_TYPES_LOWER,
+    ACTIVIY_NO_ACCOUNT_ALLOWED,
+    SIGN_HEADERS,
+    HS2019,
+    SIGN_EXP,
+    TYPE_FOLLOWERS,
+    TYPE_FOLLOWING,
+    TYPE_ITEM,
+    TYPE_LIKE,
+    TYPE_REACTION,
+    ST_AP_CACHE,
 )
 from .regex import RE_SIG_PARAM
 
@@ -53,13 +71,13 @@
 log = getLogger(__name__)
 
 VERSION = unicodedata.normalize(
-    'NFKD',
-    f"{C.APP_NAME} ActivityPub Gateway {C.APP_VERSION}"
+    "NFKD", f"{C.APP_NAME} ActivityPub Gateway {C.APP_VERSION}"
 )
 
 
 class HTTPAPGServer(web_resource.Resource):
     """HTTP Server handling ActivityPub S2S protocol"""
+
     isLeaf = True
 
     def __init__(self, ap_gateway):
@@ -68,30 +86,23 @@
         super().__init__()
 
     def response_code(
-        self,
-        request: "HTTPRequest",
-        http_code: int,
-        msg: Optional[str] = None
+        self, request: "HTTPRequest", http_code: int, msg: Optional[str] = None
     ) -> None:
         """Log and set HTTP return code and associated message"""
         if msg is not None:
             log.warning(msg)
         request.setResponseCode(http_code, None if msg is None else msg.encode())
 
-    def _on_request_error(self, failure_: failure.Failure, request: "HTTPRequest") -> None:
+    def _on_request_error(
+        self, failure_: failure.Failure, request: "HTTPRequest"
+    ) -> None:
         exc = failure_.value
         if isinstance(exc, exceptions.NotFound):
-            self.response_code(
-                request,
-                http.NOT_FOUND,
-                str(exc)
-            )
+            self.response_code(request, http.NOT_FOUND, str(exc))
         else:
             log.exception(f"Internal error: {failure_.value}")
             self.response_code(
-                request,
-                http.INTERNAL_SERVER_ERROR,
-                f"internal error: {failure_.value}"
+                request, http.INTERNAL_SERVER_ERROR, f"internal error: {failure_.value}"
             )
             request.finish()
             raise failure_
@@ -105,7 +116,7 @@
         account = resource[5:].strip()
         if not resource.startswith("acct:") or not account:
             return web_resource.ErrorPage(
-                http.BAD_REQUEST, "Bad Request" , "Invalid webfinger resource"
+                http.BAD_REQUEST, "Bad Request", "Invalid webfinger resource"
             ).render(request)
 
         actor_url = self.apg.build_apurl(TYPE_ACTOR, account)
@@ -114,12 +125,8 @@
             "aliases": [actor_url],
             "subject": resource,
             "links": [
-                {
-                    "rel": "self",
-                    "type": "application/activity+json",
-                    "href": actor_url
-                }
-            ]
+                {"rel": "self", "type": "application/activity+json", "href": actor_url}
+            ],
         }
         request.setHeader("content-type", CONTENT_TYPE_WEBFINGER)
         request.write(json.dumps(resp).encode())
@@ -134,7 +141,7 @@
         node: Optional[str],
         ap_account: str,
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ) -> None:
         if node is None:
             node = self.apg._m.namespace
@@ -181,9 +188,11 @@
             elif type_ == TYPE_LIKE:
                 await self.handle_attachment_item(client, obj, {"noticed": False})
             elif type_ == TYPE_REACTION:
-                await self.handle_attachment_item(client, obj, {
-                    "reactions": {"operation": "update", "remove": [obj["content"]]}
-                })
+                await self.handle_attachment_item(
+                    client,
+                    obj,
+                    {"reactions": {"operation": "update", "remove": [obj["content"]]}},
+                )
             else:
                 log.warning(f"Unmanaged undo type: {type_!r}")
 
@@ -196,7 +205,7 @@
         node: Optional[str],
         ap_account: str,
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ) -> None:
         if node is None:
             node = self.apg._m.namespace
@@ -207,7 +216,7 @@
                 account_jid,
                 node,
                 # subscriptions from AP are always public
-                options=self.apg._pps.set_public_opt()
+                options=self.apg._pps.set_public_opt(),
             )
         except pubsub.SubscriptionPending:
             log.info(f"subscription to node {node!r} of {account_jid} is pending")
@@ -218,9 +227,7 @@
                 raise exceptions.InternalError('"subscribed" state was expected')
             inbox = await self.apg.get_ap_inbox_from_id(signing_actor, use_shared=False)
             actor_id = self.apg.build_apurl(TYPE_ACTOR, ap_account)
-            accept_data = self.apg.create_activity(
-                "Accept", actor_id, object_=data
-            )
+            accept_data = self.apg.create_activity("Accept", actor_id, object_=data)
             await self.apg.sign_and_post(inbox, actor_id, accept_data)
         await self.apg._c.synchronise(client, account_jid, node, resync=False)
 
@@ -233,7 +240,7 @@
         node: Optional[str],
         ap_account: str,
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ) -> None:
         if node is None:
             node = self.apg._m.namespace
@@ -253,7 +260,9 @@
                     continue
                 try:
                     sub = next(
-                        s for s in follow_node.subscriptions if s.subscriber==account_jid
+                        s
+                        for s in follow_node.subscriptions
+                        if s.subscriber == account_jid
                     )
                 except StopIteration:
                     log.warning(
@@ -283,7 +292,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ):
         if node is None:
             node = self.apg._m.namespace
@@ -325,13 +334,9 @@
             if repeated:
                 # we don't check sender when item is repeated, as it should be different
                 # from post author in this case
-                sender_jid = await self.apg.get_jid_from_id(
-                    requestor_actor_id,
-                    sender
-                )
+                sender_jid = await self.apg.get_jid_from_id(requestor_actor_id, sender)
                 repeater_jid = await self.apg.get_jid_from_id(
-                    requestor_actor_id,
-                    signing_actor
+                    requestor_actor_id, signing_actor
                 )
                 repeated_item_id = obj["id"]
                 if self.apg.is_local_url(repeated_item_id):
@@ -347,13 +352,14 @@
                         if not url_account or not url_item_id:
                             raise ValueError
                     except (RuntimeError, ValueError):
-                        raise exceptions.DataError(
-                            "local URI is invalid: {repeated_id}"
-                        )
+                        raise exceptions.DataError("local URI is invalid: {repeated_id}")
                     else:
                         url_jid, url_node = await self.apg.get_jid_and_node(url_account)
-                        if ((url_jid != sender_jid
-                             or url_node and url_node != self.apg._m.namespace)):
+                        if (
+                            url_jid != sender_jid
+                            or url_node
+                            and url_node != self.apg._m.namespace
+                        ):
                             raise exceptions.DataError(
                                 "announced ID doesn't match sender ({sender}): "
                                 f"[repeated_item_id]"
@@ -368,17 +374,15 @@
                         "pubsub",
                         path=sender_jid.full(),
                         node=self.apg._m.namespace,
-                        item=repeated_item_id
-                    )
+                        item=repeated_item_id,
+                    ),
                 }
                 # we must use activity's id and targets, not the original item ones
                 for field in ("id", "to", "bto", "cc", "bcc"):
                     obj[field] = data.get(field)
             else:
                 if sender != signing_actor:
-                    log.warning(
-                        "Ignoring object not attributed to signing actor: {obj}"
-                    )
+                    log.warning("Ignoring object not attributed to signing actor: {obj}")
                     continue
 
             await self.apg.new_ap_item(client, account_jid, node, obj)
@@ -392,7 +396,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ):
         await self.handle_new_ap_items(
             requestor_actor_id, request, data, account_jid, node, signing_actor
@@ -407,7 +411,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ):
         # Update is the same as create: the item ID stays the same, thus the item will be
         # overwritten
@@ -424,7 +428,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ):
         # we create a new item
         await self.handle_new_ap_items(
@@ -434,14 +438,11 @@
             account_jid,
             node,
             signing_actor,
-            repeated=True
+            repeated=True,
         )
 
     async def handle_attachment_item(
-        self,
-        client: SatXMPPEntity,
-        data: dict,
-        attachment_data: dict
+        self, client: SatXMPPEntity, data: dict, attachment_data: dict
     ) -> None:
         target_ids = data.get("object")
         if not target_ids:
@@ -485,11 +486,7 @@
                 author_jid, item_node, item_id
             )
             cached_node = await self.apg.host.memory.storage.get_pubsub_node(
-                client,
-                author_jid,
-                attachment_node,
-                with_subscriptions=True,
-                create=True
+                client, author_jid, attachment_node, with_subscriptions=True, create=True
             )
             found_items, __ = await self.apg.host.memory.storage.get_items(
                 cached_node, item_ids=[client.jid.userhost()]
@@ -501,19 +498,13 @@
                 old_item_elt = found_item.data
 
             item_elt = await self.apg._pa.apply_set_handler(
-                client,
-                {"extra": attachment_data},
-                old_item_elt,
-                None
+                client, {"extra": attachment_data}, old_item_elt, None
             )
             # we reparse the element, as there can be other attachments
             attachments_data = self.apg._pa.items_2_attachment_data(client, [item_elt])
             # and we update the cache
             await self.apg.host.memory.storage.cache_pubsub_items(
-                client,
-                cached_node,
-                [item_elt],
-                attachments_data or [{}]
+                client, cached_node, [item_elt], attachments_data or [{}]
             )
 
             if self.apg.is_virtual_jid(author_jid):
@@ -525,7 +516,7 @@
                     self.apg.pubsub_service.notifyPublish(
                         author_jid,
                         attachment_node,
-                        [(subscription.subscriber, None, [item_elt])]
+                        [(subscription.subscriber, None, [item_elt])],
                     )
             else:
                 # the attachment is on an XMPP item, we publish it to the attachment node
@@ -542,7 +533,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ) -> None:
         client = await self.apg.get_virtual_client(requestor_actor_id, signing_actor)
         await self.handle_attachment_item(client, data, {"noticed": True})
@@ -556,12 +547,12 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ) -> None:
         client = await self.apg.get_virtual_client(requestor_actor_id, signing_actor)
-        await self.handle_attachment_item(client, data, {
-            "reactions": {"operation": "update", "add": [data["content"]]}
-        })
+        await self.handle_attachment_item(
+            client, data, {"reactions": {"operation": "update", "add": [data["content"]]}}
+        )
 
     async def handle_join_activity(
         self,
@@ -572,7 +563,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ) -> None:
         client = await self.apg.get_virtual_client(requestor_actor_id, signing_actor)
         await self.handle_attachment_item(client, data, {"rsvp": {"attending": "yes"}})
@@ -586,7 +577,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: str
+        signing_actor: str,
     ) -> None:
         client = await self.apg.get_virtual_client(requestor_actor_id, signing_actor)
         await self.handle_attachment_item(client, data, {"rsvp": {"attending": "no"}})
@@ -599,7 +590,7 @@
         node: Optional[str],
         ap_account: str,
         ap_url: str,
-        signing_actor: Optional[str]
+        signing_actor: Optional[str],
     ) -> dict:
         inbox = self.apg.build_apurl(TYPE_INBOX, ap_account)
         shared_inbox = self.apg.build_apurl(TYPE_SHARED_INBOX)
@@ -623,9 +614,8 @@
         actor_data = {
             "@context": [
                 "https://www.w3.org/ns/activitystreams",
-                "https://w3id.org/security/v1"
+                "https://w3id.org/security/v1",
             ],
-
             # XXX: Mastodon doesn't like percent-encode arobas, so we have to unescape it
             #   if it is escaped
             "id": ap_url.replace("%40", "@"),
@@ -639,7 +629,7 @@
             "publicKey": {
                 "id": f"{ap_url}#main-key",
                 "owner": ap_url,
-                "publicKeyPem": self.apg.public_key_pem
+                "publicKeyPem": self.apg.public_key_pem,
             },
             "endpoints": {
                 "sharedInbox": shared_inbox,
@@ -664,7 +654,7 @@
                 actor_data["icon"] = {
                     "type": "Image",
                     "url": avatar_url,
-                    "mediaType": media_type
+                    "mediaType": media_type,
                 }
 
         return actor_data
@@ -672,13 +662,12 @@
     def get_canonical_url(self, request: "HTTPRequest") -> str:
         return parse.urljoin(
             f"https://{self.apg.public_url}",
-            request.path.decode().rstrip("/")
-        # we unescape "@" for the same reason as in [ap_actor_request]
+            request.path.decode().rstrip("/"),
+            # we unescape "@" for the same reason as in [ap_actor_request]
         ).replace("%40", "@")
 
     def query_data_2_rsm_request(
-        self,
-        query_data: Dict[str, List[str]]
+        self, query_data: Dict[str, List[str]]
     ) -> rsm.RSMRequest:
         """Get RSM kwargs to use with RSMRequest from query data"""
         page = query_data.get("page")
@@ -690,7 +679,7 @@
         else:
             for query_key in ("index", "before", "after"):
                 try:
-                    kwargs={query_key: query_data[query_key][0], "max_": PAGE_SIZE}
+                    kwargs = {query_key: query_data[query_key][0], "max_": PAGE_SIZE}
                 except (KeyError, IndexError, ValueError):
                     pass
                 else:
@@ -705,7 +694,7 @@
         node: Optional[str],
         ap_account: str,
         ap_url: str,
-        query_data: Dict[str, List[str]]
+        query_data: Dict[str, List[str]],
     ) -> dict:
         if node is None:
             node = self.apg._m.namespace
@@ -719,7 +708,7 @@
                 service=account_jid,
                 node=node,
                 rsm_request=self.query_data_2_rsm_request(query_data),
-                extra = {C.KEY_USE_CACHE: False}
+                extra={C.KEY_USE_CACHE: False},
             )
         except error.StanzaError as e:
             log.warning(f"Can't get data from pubsub node {node} at {account_jid}: {e}")
@@ -730,8 +719,7 @@
         if node and node.startswith(self.apg._events.namespace):
             ordered_items = [
                 await self.apg.ap_events.event_data_2_ap_item(
-                    self.apg._events.event_elt_2_event_data(item),
-                    account_jid
+                    self.apg._events.event_elt_2_event_data(item), account_jid
                 )
                 for item in reversed(items)
             ]
@@ -740,11 +728,8 @@
                 await self.apg.mb_data_2_ap_item(
                     self.apg.client,
                     await self.apg._m.item_2_mb_data(
-                        self.apg.client,
-                        item,
-                        account_jid,
-                        node
-                    )
+                        self.apg.client, item, account_jid, node
+                    ),
                 )
                 for item in reversed(items)
             ]
@@ -753,7 +738,7 @@
             "id": url,
             "type": "OrderedCollectionPage",
             "partOf": base_url,
-            "orderedItems": ordered_items
+            "orderedItems": ordered_items,
         }
 
         if "rsm" not in metadata:
@@ -764,13 +749,13 @@
         # of what we get with RSM (at least with Libervia Pubsub)
         if not metadata["complete"]:
             try:
-                last= metadata["rsm"]["last"]
+                last = metadata["rsm"]["last"]
             except KeyError:
                 last = None
             ret_data["prev"] = f"{base_url}?{parse.urlencode({'after': last})}"
         if metadata["rsm"]["index"] != 0:
             try:
-                first= metadata["rsm"]["first"]
+                first = metadata["rsm"]["first"]
             except KeyError:
                 first = None
             ret_data["next"] = f"{base_url}?{parse.urlencode({'before': first})}"
@@ -785,7 +770,7 @@
         node: Optional[str],
         ap_account: str,
         ap_url: str,
-        signing_actor: Optional[str]
+        signing_actor: Optional[str],
     ) -> dict:
         if node is None:
             node = self.apg._m.namespace
@@ -809,7 +794,7 @@
                 node=node,
                 max_items=0,
                 rsm_request=rsm.RSMRequest(max_=0),
-                extra = {C.KEY_USE_CACHE: False}
+                extra={C.KEY_USE_CACHE: False},
             )
         except error.StanzaError as e:
             log.warning(f"Can't get data from pubsub node {node} at {account_jid}: {e}")
@@ -844,7 +829,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: Optional[str]
+        signing_actor: Optional[str],
     ) -> None:
         assert data is not None
         if signing_actor is None:
@@ -855,14 +840,14 @@
             return self.response_code(
                 request,
                 http.UNSUPPORTED_MEDIA_TYPE,
-                f"request is not an activity, ignoring"
+                f"request is not an activity, ignoring",
             )
 
         if account_jid is None and activity_type not in ACTIVIY_NO_ACCOUNT_ALLOWED:
             return self.response_code(
                 request,
                 http.UNSUPPORTED_MEDIA_TYPE,
-                f"{activity_type.title()!r} activity must target an account"
+                f"{activity_type.title()!r} activity must target an account",
             )
 
         try:
@@ -871,12 +856,18 @@
             return self.response_code(
                 request,
                 http.UNSUPPORTED_MEDIA_TYPE,
-                f"{activity_type.title()} activity is not yet supported"
+                f"{activity_type.title()} activity is not yet supported",
             )
         else:
             await method(
-                requestor_actor_id, request, data, account_jid, node, ap_account, ap_url,
-                signing_actor
+                requestor_actor_id,
+                request,
+                data,
+                account_jid,
+                node,
+                ap_account,
+                ap_url,
+                signing_actor,
             )
 
     async def ap_followers_request(
@@ -887,7 +878,7 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: Optional[str]
+        signing_actor: Optional[str],
     ) -> dict:
         if node is None:
             node = self.apg._m.namespace
@@ -902,20 +893,22 @@
                 ap_account = self.apg._e.unescape(subscriber.user)
             else:
                 # regular XMPP user
-                ap_account = await self.apg.get_ap_account_from_jid_and_node(subscriber, node)
+                ap_account = await self.apg.get_ap_account_from_jid_and_node(
+                    subscriber, node
+                )
             followers.append(ap_account)
 
         url = self.get_canonical_url(request)
         return {
-          "@context": ["https://www.w3.org/ns/activitystreams"],
-          "type": "OrderedCollection",
-          "id": url,
-          "totalItems": len(subscribers),
-          "first": {
-            "type": "OrderedCollectionPage",
+            "@context": ["https://www.w3.org/ns/activitystreams"],
+            "type": "OrderedCollection",
             "id": url,
-            "orderedItems": followers
-          }
+            "totalItems": len(subscribers),
+            "first": {
+                "type": "OrderedCollectionPage",
+                "id": url,
+                "orderedItems": followers,
+            },
         }
 
     async def ap_following_request(
@@ -926,12 +919,10 @@
         node: Optional[str],
         ap_account: Optional[str],
         ap_url: str,
-        signing_actor: Optional[str]
+        signing_actor: Optional[str],
     ) -> dict[str, Any]:
         client = self.apg.client
-        subscriptions = await self.apg._pps.subscriptions(
-            client, account_jid, node
-        )
+        subscriptions = await self.apg._pps.subscriptions(client, account_jid, node)
         following = []
         for sub_dict in subscriptions:
             service = jid.JID(sub_dict["service"])
@@ -947,15 +938,15 @@
 
         url = self.get_canonical_url(request)
         return {
-          "@context": ["https://www.w3.org/ns/activitystreams"],
-          "type": "OrderedCollection",
-          "id": url,
-          "totalItems": len(subscriptions),
-          "first": {
-            "type": "OrderedCollectionPage",
+            "@context": ["https://www.w3.org/ns/activitystreams"],
+            "type": "OrderedCollection",
             "id": url,
-            "orderedItems": following
-          }
+            "totalItems": len(subscriptions),
+            "first": {
+                "type": "OrderedCollectionPage",
+                "id": url,
+                "orderedItems": following,
+            },
         }
 
     def _get_to_log(
@@ -965,24 +956,23 @@
     ) -> List[str]:
         """Get base data to logs in verbose mode"""
         from pprint import pformat
+
         to_log = [
             "",
-            f"<<< got {request.method.decode()} request - {request.uri.decode()}"
+            f"<<< got {request.method.decode()} request - {request.uri.decode()}",
         ]
         if data is not None:
             to_log.append(pformat(data))
-        if self.apg.verbose>=3:
+        if self.apg.verbose >= 3:
             headers = "\n".join(
                 f"    {k.decode()}: {v.decode()}"
-                for k,v in request.getAllHeaders().items()
+                for k, v in request.getAllHeaders().items()
             )
             to_log.append(f"  headers:\n{headers}")
         return to_log
 
     def get_requestor_actor_id(
-        self,
-        data: dict|None = None,
-        uri_extra_args: list[str]|None = None
+        self, data: dict | None = None, uri_extra_args: list[str] | None = None
     ) -> str:
         """Find the actor ID of the requestor.
 
@@ -1034,33 +1024,30 @@
 
         # Still nothing, we'll have to use a generic actor.
         log.warning(
-            "Can't find destinee in \"to\" field, using generic requestor for signature."
+            'Can\'t find destinee in "to" field, using generic requestor for signature.'
         )
-        return self.apg.build_apurl(
-            TYPE_ACTOR, f"libervia@{self.apg.public_url}"
-        )
+        return self.apg.build_apurl(TYPE_ACTOR, f"libervia@{self.apg.public_url}")
 
     async def ap_request(
         self,
         request: "HTTPRequest",
-        data: dict|None = None,
-        signing_actor: str|None = None,
-        requestor_actor_id: str|None = None,
+        data: dict | None = None,
+        signing_actor: str | None = None,
+        requestor_actor_id: str | None = None,
     ) -> None:
         if self.apg.verbose:
             to_log = self._get_to_log(request, data)
 
         path = request.path.decode()
-        ap_url = parse.urljoin(
-            f"https://{self.apg.public_url}",
-            path
-        )
+        ap_url = parse.urljoin(f"https://{self.apg.public_url}", path)
         request_type, extra_args = self.apg.parse_apurl(ap_url)
 
         header_accept = request.getHeader("accept") or ""
-        if ((MEDIA_TYPE_AP not in header_accept
-             and MEDIA_TYPE_AP_ALT not in header_accept
-             and request_type in self.apg.html_redirect)):
+        if (
+            MEDIA_TYPE_AP not in header_accept
+            and MEDIA_TYPE_AP_ALT not in header_accept
+            and request_type in self.apg.html_redirect
+        ):
             # this is not a AP request, and we have a redirections for it
             kw = {}
             if extra_args:
@@ -1081,14 +1068,14 @@
                 if not filters:
                     break
                 # if we have filter, they must all match
-                elif all(v in kw[k] for k,v in filters.items()):
+                elif all(v in kw[k] for k, v in filters.items()):
                     break
             else:
                 # no redirection is matching
                 redirection = None
 
             if redirection is not None:
-                kw = {k: parse.quote(str(v), safe="") for k,v in kw.items()}
+                kw = {k: parse.quote(str(v), safe="") for k, v in kw.items()}
                 target_url = redirection["url"].format(**kw)
                 content = web_util.redirectTo(target_url.encode(), request)
                 request.write(content)
@@ -1096,9 +1083,7 @@
                 return
 
         if requestor_actor_id is None:
-            requestor_actor_id = self.get_requestor_actor_id(
-                data, extra_args
-            )
+            requestor_actor_id = self.get_requestor_actor_id(data, extra_args)
         if len(extra_args) == 0:
             if request_type != "shared_inbox":
                 raise exceptions.DataError(f"Invalid request type: {request_type!r}")
@@ -1121,21 +1106,29 @@
             ap_account = extra_args[0]
             account_jid, node = await self.apg.get_jid_and_node(ap_account)
             if request_type not in AP_REQUEST_TYPES.get(
-                    request.method.decode().upper(), []
+                request.method.decode().upper(), []
             ):
                 raise exceptions.DataError(f"Invalid request type: {request_type!r}")
             method = getattr(self, f"ap_{request_type}_request")
             ret_data = await method(
-                requestor_actor_id, request, data, account_jid, node, ap_account, ap_url, signing_actor
+                requestor_actor_id,
+                request,
+                data,
+                account_jid,
+                node,
+                ap_account,
+                ap_url,
+                signing_actor,
             )
         if ret_data is not None:
             request.setHeader("content-type", CONTENT_TYPE_AP)
             request.write(json.dumps(ret_data).encode())
         if self.apg.verbose:
             to_log.append(f"--- RET (code: {request.code})---")
-            if self.apg.verbose>=2:
+            if self.apg.verbose >= 2:
                 if ret_data is not None:
                     from pprint import pformat
+
                     to_log.append(f"{pformat(ret_data)}")
                     to_log.append("---")
             log.info("\n".join(to_log))
@@ -1149,15 +1142,13 @@
                 self.response_code(
                     request,
                     http.BAD_REQUEST,
-                    f"invalid body, was expecting a JSON object"
+                    f"invalid body, was expecting a JSON object",
                 )
                 request.finish()
                 return
         except (json.JSONDecodeError, ValueError) as e:
             self.response_code(
-                request,
-                http.BAD_REQUEST,
-                f"invalid json in inbox request: {e}"
+                request, http.BAD_REQUEST, f"invalid json in inbox request: {e}"
             )
             request.finish()
             return
@@ -1185,18 +1176,12 @@
                 to_log.append(f"  body: {request.content.read()!r}")
                 request.content.seek(0)
                 log.info("\n".join(to_log))
-            self.response_code(
-                request,
-                http.FORBIDDEN,
-                f"invalid signature: {e}"
-            )
+            self.response_code(request, http.FORBIDDEN, f"invalid signature: {e}")
             request.finish()
             return
         except Exception as e:
             self.response_code(
-                request,
-                http.INTERNAL_SERVER_ERROR,
-                f"Can't check signature: {e}"
+                request, http.INTERNAL_SERVER_ERROR, f"Can't check signature: {e}"
             )
             request.finish()
             return
@@ -1219,10 +1204,7 @@
             self._on_request_error(failure.Failure(e), request)
 
     async def check_signing_actor(
-        self,
-        requestor_actor_id: str,
-        data: dict,
-        signing_actor: str
+        self, requestor_actor_id: str, data: dict, signing_actor: str
     ) -> None:
         """That that signing actor correspond to actor declared in data
 
@@ -1241,9 +1223,7 @@
             )
 
     async def check_signature(
-        self,
-        requestor_actor_id: str,
-        request: "HTTPRequest"
+        self, requestor_actor_id: str, request: "HTTPRequest"
     ) -> str:
         """Check and validate HTTP signature
 
@@ -1264,10 +1244,11 @@
         except KeyError:
             raise exceptions.EncryptionError('"keyId" is missing from signature')
         algorithm = sign_data.get("algorithm", HS2019)
-        signed_headers = sign_data.get(
-            "headers",
-            "(created)" if algorithm==HS2019 else "date"
-        ).lower().split()
+        signed_headers = (
+            sign_data.get("headers", "(created)" if algorithm == HS2019 else "date")
+            .lower()
+            .split()
+        )
         try:
             headers_to_check = SIGN_HEADERS[None] + SIGN_HEADERS[request.method]
         except KeyError:
@@ -1284,9 +1265,7 @@
                         f"at least one of following header must be signed: {header}"
                     )
             elif header not in signed_headers:
-                raise exceptions.EncryptionError(
-                    f"the {header!r} header must be signed"
-                )
+                raise exceptions.EncryptionError(f"the {header!r} header must be signed")
 
         body = request.content.read()
         request.content.seek(0)
@@ -1329,7 +1308,8 @@
                     if forwarded is not None:
                         try:
                             host = [
-                                f[5:] for f in forwarded.split(";")
+                                f[5:]
+                                for f in forwarded.split(";")
                                 if f.startswith("host=")
                             ][0] or None
                         except IndexError:
@@ -1342,7 +1322,8 @@
                         value = host
                 elif to_sign == "digest":
                     hashes = {
-                        algo.lower(): hash_ for algo, hash_ in (
+                        algo.lower(): hash_
+                        for algo, hash_ in (
                             digest.split("=", 1) for digest in value.split(",")
                         )
                     }
@@ -1367,7 +1348,6 @@
         else:
             created = date_utils.date_parse(headers["date"])
 
-
         try:
             expires = float(headers["expires"])
         except KeyError:
@@ -1386,23 +1366,17 @@
 
         try:
             return await self.apg.check_signature(
-                requestor_actor_id,
-                sign_data["signature"],
-                key_id,
-                headers
+                requestor_actor_id, sign_data["signature"], key_id, headers
             )
         except exceptions.EncryptionError:
-            method, url = headers["(request-target)"].rsplit(' ', 1)
+            method, url = headers["(request-target)"].rsplit(" ", 1)
             headers["(request-target)"] = f"{method} {parse.unquote(url)}"
             log.debug(
                 "Using workaround for (request-target) encoding bug in signature, "
                 "see https://github.com/mastodon/mastodon/issues/18871"
             )
             return await self.apg.check_signature(
-                requestor_actor_id,
-                sign_data["signature"],
-                key_id,
-                headers
+                requestor_actor_id, sign_data["signature"], key_id, headers
             )
 
     def render(self, request):