annotate sat/plugins/plugin_comp_ap_gateway/pubsub_service.py @ 3832:201a22bfbb74

component AP gateway: convert AP mention to XEP-0372 mentions: when a mentions are found in AP items (either with people specified directly as target, of with `mention` tags as in https://www.w3.org/TR/activitystreams-vocabulary/#microsyntaxes), they are converted to XEP-0372 `mention` references. This is only done for Pubsub items (i.e. not for private messages). rel 369
author Goffi <goffi@goffi.org>
date Sun, 10 Jul 2022 15:16:15 +0200
parents 6329ee6b6df4
children 59fbb66b2923
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 # Libervia ActivityPub Gateway
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
5
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # (at your option) any later version.
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
18
3824
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
19 from typing import Optional, Tuple, List, Dict, Any, Union
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
20 from urllib.parse import urlparse
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
21 from pathlib import Path
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
22 from base64 import b64encode
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
23 import tempfile
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
24
3824
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
25 from twisted.internet import defer, threads
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
26 from twisted.words.protocols.jabber import jid, error
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
27 from twisted.words.xish import domish
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
28 from wokkel import rsm, pubsub, disco
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
29
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
30 from sat.core.i18n import _
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
31 from sat.core import exceptions
3824
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
32 from sat.core.core_types import SatXMPPEntity
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 from sat.core.log import getLogger
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
34 from sat.core.constants import Const as C
3824
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
35 from sat.tools import image
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
36 from sat.tools.utils import ensure_deferred
3824
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
37 from sat.tools.web import downloadFile
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
38 from sat.memory.sqla_mapping import PubsubSub, SubscriptionState
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
39
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
40 from .constants import (
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
41 TYPE_ACTOR,
3824
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
42 ST_AVATAR,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
43 MAX_AVATAR_SIZE
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
44 )
3682
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
45
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
46
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 log = getLogger(__name__)
7c990aaa49d3 comp AP Gateway: ActivityPub Component first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
48
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
49 # all nodes have the same config
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
50 NODE_CONFIG = [
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
51 {"var": "pubsub#persist_items", "type": "boolean", "value": True},
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
52 {"var": "pubsub#max_items", "value": "max"},
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
53 {"var": "pubsub#access_model", "type": "list-single", "value": "open"},
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
54 {"var": "pubsub#publish_model", "type": "list-single", "value": "open"},
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
55
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
56 ]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
57
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
58 NODE_CONFIG_VALUES = {c["var"]: c["value"] for c in NODE_CONFIG}
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
59 NODE_OPTIONS = {c["var"]: {} for c in NODE_CONFIG}
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
60 for c in NODE_CONFIG:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
61 NODE_OPTIONS[c["var"]].update({k:v for k,v in c.items() if k not in ("var", "value")})
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
62
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
63
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
64 class APPubsubService(rsm.PubSubService):
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
65 """Pubsub service for XMPP requests"""
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
66
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
67 def __init__(self, apg):
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
68 super(APPubsubService, self).__init__()
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
69 self.host = apg.host
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
70 self.apg = apg
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
71 self.discoIdentity = {
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
72 "category": "pubsub",
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
73 "type": "service",
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
74 "name": "Libervia ActivityPub Gateway",
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
75 }
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
76
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
77 async def getAPActorIdsAndInbox(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
78 self,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
79 requestor: jid.JID,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
80 recipient: jid.JID,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
81 ) -> Tuple[str, str, str]:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
82 """Get AP actor IDs from requestor and destinee JIDs
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
83
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
84 @param requestor: XMPP entity doing a request to an AP actor via the gateway
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
85 @param recipient: JID mapping an AP actor via the gateway
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
86 @return: requestor actor ID, recipient actor ID and recipient inbox
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
87 @raise error.StanzaError: "item-not-found" is raised if not user part is specified
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
88 in requestor
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
89 """
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
90 if not recipient.user:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
91 raise error.StanzaError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
92 "item-not-found",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
93 text="No user part specified"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
94 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
95 requestor_actor_id = self.apg.buildAPURL(TYPE_ACTOR, requestor.userhost())
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
96 recipient_account = self.apg._e.unescape(recipient.user)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
97 recipient_actor_id = await self.apg.getAPActorIdFromAccount(recipient_account)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
98 inbox = await self.apg.getAPInboxFromId(recipient_actor_id)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
99 return requestor_actor_id, recipient_actor_id, inbox
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
100
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
101
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
102 @ensure_deferred
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
103 async def publish(self, requestor, service, nodeIdentifier, items):
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
104 if self.apg.local_only and not self.apg.isLocal(requestor):
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
105 raise error.StanzaError(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
106 "forbidden",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
107 "Only local users can publish on this gateway."
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
108 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
109 if not service.user:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
110 raise error.StanzaError(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
111 "bad-request",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
112 "You must specify an ActivityPub actor account in JID user part."
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
113 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
114 ap_account = self.apg._e.unescape(service.user)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
115 if ap_account.count("@") != 1:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
116 raise error.StanzaError(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
117 "bad-request",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
118 f"{ap_account!r} is not a valid ActivityPub actor account."
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
119 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
120
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
121 client = self.apg.client.getVirtualClient(requestor)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
122 await self.apg.convertAndPostItems(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
123 client, ap_account, service, nodeIdentifier, items
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
124 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
125
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
126 async def apFollowing2Elt(self, ap_item: dict) -> domish.Element:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
127 """Convert actor ID from following collection to XMPP item"""
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
128 actor_id = ap_item["id"]
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
129 actor_jid = await self.apg.getJIDFromId(actor_id)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
130 subscription_elt = self.apg._pps.buildSubscriptionElt(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
131 self.apg._m.namespace, actor_jid
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
132 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
133 item_elt = pubsub.Item(id=actor_id, payload=subscription_elt)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
134 return item_elt
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
135
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
136 async def apFollower2Elt(self, ap_item: dict) -> domish.Element:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
137 """Convert actor ID from followers collection to XMPP item"""
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
138 actor_id = ap_item["id"]
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
139 actor_jid = await self.apg.getJIDFromId(actor_id)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
140 subscriber_elt = self.apg._pps.buildSubscriberElt(actor_jid)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
141 item_elt = pubsub.Item(id=actor_id, payload=subscriber_elt)
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
142 return item_elt
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
143
3824
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
144 async def generateVCard(self, ap_account: str) -> domish.Element:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
145 """Generate vCard4 (XEP-0292) item element from ap_account's metadata"""
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
146 actor_data = await self.apg.getAPActorDataFromAccount(ap_account)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
147 identity_data = {}
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
148
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
149 summary = actor_data.get("summary")
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
150 # summary is HTML, we have to convert it to text
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
151 if summary:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
152 identity_data["description"] = await self.apg._t.convert(
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
153 summary,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
154 self.apg._t.SYNTAX_XHTML,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
155 self.apg._t.SYNTAX_TEXT,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
156 False,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
157 )
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
158
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
159 for field in ("name", "preferredUsername"):
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
160 value = actor_data.get(field)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
161 if value:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
162 identity_data.setdefault("nicknames", []).append(value)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
163 vcard_elt = self.apg._v.dict2VCard(identity_data)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
164 item_elt = domish.Element((pubsub.NS_PUBSUB, "item"))
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
165 item_elt.addChild(vcard_elt)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
166 item_elt["id"] = self.apg._p.ID_SINGLETON
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
167 return item_elt
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
168
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
169 async def getAvatarData(
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
170 self,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
171 client: SatXMPPEntity,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
172 ap_account: str
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
173 ) -> Dict[str, Any]:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
174 """Retrieve actor's avatar if any, cache it and file actor_data
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
175
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
176 ``cache_uid``, `path``` and ``media_type`` keys are always files
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
177 ``base64`` key is only filled if the file was not already in cache
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
178 """
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
179 actor_data = await self.apg.getAPActorDataFromAccount(ap_account)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
180
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
181 for icon in await self.apg.apGetList(actor_data, "icon"):
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
182 url = icon.get("url")
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
183 if icon["type"] != "Image" or not url:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
184 continue
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
185 parsed_url = urlparse(url)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
186 if not parsed_url.scheme in ("http", "https"):
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
187 log.warning(f"unexpected URL scheme: {url!r}")
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
188 continue
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
189 filename = Path(parsed_url.path).name
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
190 if not filename:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
191 log.warning(f"ignoring URL with invald path: {url!r}")
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
192 continue
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
193 break
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
194 else:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
195 raise error.StanzaError("item-not-found")
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
196
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
197 key = f"{ST_AVATAR}{url}"
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
198 cache_uid = await client._ap_storage.get(key)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
199
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
200 if cache_uid is None:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
201 cache = None
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
202 else:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
203 cache = self.apg.host.common_cache.getMetadata(cache_uid)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
204
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
205 if cache is None:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
206 with tempfile.TemporaryDirectory() as dir_name:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
207 dest_path = Path(dir_name, filename)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
208 await downloadFile(url, dest_path, max_size=MAX_AVATAR_SIZE)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
209 avatar_data = {
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
210 "path": dest_path,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
211 "filename": filename,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
212 'media_type': image.guess_type(dest_path),
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
213 }
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
214
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
215 await self.apg._i.cacheAvatar(
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
216 self.apg.IMPORT_NAME,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
217 avatar_data
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
218 )
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
219 else:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
220 avatar_data = {
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
221 "cache_uid": cache["uid"],
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
222 "path": cache["path"],
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
223 "media_type": cache["mime_type"]
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
224 }
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
225
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
226 return avatar_data
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
227
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
228 async def generateAvatarMetadata(
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
229 self,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
230 client: SatXMPPEntity,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
231 ap_account: str
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
232 ) -> domish.Element:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
233 """Generate the metadata element for user avatar
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
234
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
235 @raise StanzaError("item-not-found"): no avatar is present in actor data (in
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
236 ``icon`` field)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
237 """
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
238 avatar_data = await self.getAvatarData(client, ap_account)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
239 return self.apg._a.buildItemMetadataElt(avatar_data)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
240
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
241 def _blockingB64EncodeAvatar(self, avatar_data: Dict[str, Any]) -> None:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
242 with avatar_data["path"].open("rb") as f:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
243 avatar_data["base64"] = b64encode(f.read()).decode()
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
244
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
245 async def generateAvatarData(
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
246 self,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
247 client: SatXMPPEntity,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
248 ap_account: str,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
249 itemIdentifiers: Optional[List[str]],
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
250 ) -> domish.Element:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
251 """Generate the data element for user avatar
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
252
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
253 @raise StanzaError("item-not-found"): no avatar cached with requested ID
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
254 """
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
255 if not itemIdentifiers:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
256 avatar_data = await self.getAvatarData(client, ap_account)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
257 if "base64" not in avatar_data:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
258 await threads.deferToThread(self._blockingB64EncodeAvatar, avatar_data)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
259 else:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
260 if len(itemIdentifiers) > 1:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
261 # only a single item ID is supported
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
262 raise error.StanzaError("item-not-found")
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
263 item_id = itemIdentifiers[0]
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
264 # just to be sure that that we don't have an empty string
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
265 assert item_id
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
266 cache_data = self.apg.host.common_cache.getMetadata(item_id)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
267 if cache_data is None:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
268 raise error.StanzaError("item-not-found")
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
269 avatar_data = {
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
270 "cache_uid": item_id,
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
271 "path": cache_data["path"]
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
272 }
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
273 await threads.deferToThread(self._blockingB64EncodeAvatar, avatar_data)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
274
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
275 return self.apg._a.buildItemDataElt(avatar_data)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
276
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
277 @ensure_deferred
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
278 async def items(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
279 self,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
280 requestor: jid.JID,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
281 service: jid.JID,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
282 node: str,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
283 maxItems: Optional[int],
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
284 itemIdentifiers: Optional[List[str]],
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
285 rsm_req: Optional[rsm.RSMRequest]
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
286 ) -> Tuple[List[domish.Element], Optional[rsm.RSMResponse]]:
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
287 if not service.user:
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
288 return [], None
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
289 ap_account = self.host.plugins["XEP-0106"].unescape(service.user)
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
290 if ap_account.count("@") != 1:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
291 log.warning(f"Invalid AP account used by {requestor}: {ap_account!r}")
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
292 return [], None
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
293
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
294 kwargs = {}
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
295
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
296 if node == self.apg._pps.subscriptions_node:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
297 collection_name = "following"
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
298 parser = self.apFollowing2Elt
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
299 kwargs["only_ids"] = True
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
300 use_cache = False
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
301 elif node.startswith(self.apg._pps.subscribers_node_prefix):
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
302 collection_name = "followers"
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
303 parser = self.apFollower2Elt
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
304 kwargs["only_ids"] = True
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
305 use_cache = False
3824
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
306 elif node == self.apg._v.node:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
307 # vCard4 request
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
308 item_elt = await self.generateVCard(ap_account)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
309 return [item_elt], None
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
310 elif node == self.apg._a.namespace_metadata:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
311 item_elt = await self.generateAvatarMetadata(self.apg.client, ap_account)
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
312 return [item_elt], None
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
313 elif node == self.apg._a.namespace_data:
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
314 item_elt = await self.generateAvatarData(
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
315 self.apg.client, ap_account, itemIdentifiers
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
316 )
6329ee6b6df4 component AP: convert AP identity data to XMPP:
Goffi <goffi@goffi.org>
parents: 3792
diff changeset
317 return [item_elt], None
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
318 else:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
319 if not node.startswith(self.apg._m.namespace):
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
320 raise error.StanzaError(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
321 "feature-not-implemented",
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
322 text=f"AP Gateway {C.APP_VERSION} only supports "
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
323 f"{self.apg._m.namespace} node for now"
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
324 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
325 collection_name = "outbox"
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
326 parser = self.apg.apItem2Elt
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
327 use_cache = True
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
328
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
329 client = self.apg.client
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
330 if use_cache:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
331 cached_node = await self.host.memory.storage.getPubsubNode(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
332 client, service, node
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
333 )
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
334 # TODO: check if node is synchronised
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
335 if cached_node is not None:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
336 # the node is cached, we return items from cache
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
337 log.debug(f"node {node!r} from {service} is in cache")
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
338 pubsub_items, metadata = await self.apg._c.getItemsFromCache(
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
339 client, cached_node, maxItems, itemIdentifiers, rsm_request=rsm_req
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
340 )
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
341 try:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
342 rsm_resp = rsm.RSMResponse(**metadata["rsm"])
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
343 except KeyError:
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
344 rsm_resp = None
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
345 return [i.data for i in pubsub_items], rsm_resp
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
346
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
347 if itemIdentifiers:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
348 items = []
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
349 for item_id in itemIdentifiers:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
350 item_data = await self.apg.apGet(item_id)
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
351 item_elt = await parser(item_data)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
352 items.append(item_elt)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
353 return items, None
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
354 else:
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
355 if rsm_req is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
356 if maxItems is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
357 maxItems = 20
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
358 kwargs.update({
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
359 "max_items": maxItems,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
360 "chronological_pagination": False,
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
361 })
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
362 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
363 if len(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
364 [v for v in (rsm_req.after, rsm_req.before, rsm_req.index)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
365 if v is not None]
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
366 ) > 1:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
367 raise error.StanzaError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
368 "bad-request",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
369 text="You can't use after, before and index at the same time"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
370 )
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
371 kwargs.update({"max_items": rsm_req.max})
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
372 if rsm_req.after is not None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
373 kwargs["after_id"] = rsm_req.after
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
374 elif rsm_req.before is not None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
375 kwargs["chronological_pagination"] = False
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
376 if rsm_req.before != "":
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
377 kwargs["after_id"] = rsm_req.before
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
378 elif rsm_req.index is not None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
379 kwargs["start_index"] = rsm_req.index
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
380
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
381 log.info(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
382 f"No cache found for node {node} at {service} (AP account {ap_account}), "
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
383 "using Collection Paging to RSM translation"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
384 )
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
385 if self.apg._m.isCommentNode(node):
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
386 parent_item = self.apg._m.getParentItem(node)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
387 try:
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
388 parent_data = await self.apg.apGet(parent_item)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
389 collection = await self.apg.apGetObject(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
390 parent_data.get("object", {}),
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
391 "replies"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
392 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
393 except Exception as e:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
394 raise error.StanzaError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
395 "item-not-found",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
396 text=e
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
397 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
398 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
399 actor_data = await self.apg.getAPActorDataFromAccount(ap_account)
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
400 collection = await self.apg.apGetObject(actor_data, collection_name)
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
401 if not collection:
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
402 raise error.StanzaError(
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
403 "item-not-found",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
404 text=f"No collection found for node {node!r} (account: {ap_account})"
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
405 )
3764
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
406
125c7043b277 comp AP gateway: publish, (un)subscribe/(un)follow, public subscription/following/followers:
Goffi <goffi@goffi.org>
parents: 3745
diff changeset
407 kwargs["parser"] = parser
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
408 return await self.apg.getAPItems(collection, **kwargs)
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
409
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
410 @ensure_deferred
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
411 async def retract(self, requestor, service, nodeIdentifier, itemIdentifiers):
3792
865167c34b82 comp AP gateway: convert pubsub item retractation to AP `Delete` activity:
Goffi <goffi@goffi.org>
parents: 3764
diff changeset
412 raise error.StanzaError("forbidden")
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
413
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
414 @ensure_deferred
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
415 async def subscribe(self, requestor, service, nodeIdentifier, subscriber):
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
416 # TODO: handle comments nodes
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
417 client = self.apg.client
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
418 node = await self.host.memory.storage.getPubsubNode(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
419 client, service, nodeIdentifier, with_subscriptions=True
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
420 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
421 if node is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
422 node = await self.host.memory.storage.setPubsubNode(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
423 client,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
424 service,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
425 nodeIdentifier,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
426 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
427 subscription = None
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
428 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
429 try:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
430 subscription = next(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
431 s for s in node.subscriptions
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
432 if s.subscriber == requestor.userhostJID()
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
433 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
434 except StopIteration:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
435 subscription = None
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
436
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
437 if subscription is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
438 subscription = PubsubSub(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
439 subscriber=requestor.userhostJID(),
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
440 state=SubscriptionState.PENDING
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
441 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
442 node.subscriptions.append(subscription)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
443 await self.host.memory.storage.add(node)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
444 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
445 if subscription.state is None:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
446 subscription.state = SubscriptionState.PENDING
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
447 await self.host.memory.storage.add(node)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
448 elif subscription.state == SubscriptionState.SUBSCRIBED:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
449 log.info(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
450 f"{requestor.userhostJID()} has already a subscription to {node!r} "
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
451 f"at {service}. Doing the request anyway."
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
452 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
453 elif subscription.state == SubscriptionState.PENDING:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
454 log.info(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
455 f"{requestor.userhostJID()} has already a pending subscription to "
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
456 f"{node!r} at {service}. Doing the request anyway."
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
457 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
458 else:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
459 raise exceptions.InternalError(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
460 f"unmanaged subscription state: {subscription.state}"
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
461 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
462
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
463 req_actor_id, recip_actor_id, inbox = await self.getAPActorIdsAndInbox(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
464 requestor, service
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
465 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
466
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
467 data = self.apg.createActivity("Follow", req_actor_id, recip_actor_id)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
468
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
469 resp = await self.apg.signAndPost(inbox, req_actor_id, data)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
470 if resp.code >= 400:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
471 text = await resp.text()
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
472 raise error.StanzaError("service-unavailable", text=text)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
473 return pubsub.Subscription(nodeIdentifier, requestor, "subscribed")
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
474
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
475 @ensure_deferred
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
476 async def unsubscribe(self, requestor, service, nodeIdentifier, subscriber):
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
477 req_actor_id, recip_actor_id, inbox = await self.getAPActorIdsAndInbox(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
478 requestor, service
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
479 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
480 data = self.apg.createActivity(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
481 "Undo",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
482 req_actor_id,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
483 self.apg.createActivity(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
484 "Follow",
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
485 req_actor_id,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
486 recip_actor_id
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
487 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
488 )
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
489
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
490 resp = await self.apg.signAndPost(inbox, req_actor_id, data)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
491 if resp.code >= 400:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
492 text = await resp.text()
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
493 raise error.StanzaError("service-unavailable", text=text)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
494
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
495 def getConfigurationOptions(self):
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
496 return NODE_OPTIONS
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
497
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
498 def getConfiguration(
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
499 self,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
500 requestor: jid.JID,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
501 service: jid.JID,
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
502 nodeIdentifier: str
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
503 ) -> defer.Deferred:
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
504 return defer.succeed(NODE_CONFIG_VALUES)
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
505
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
506 def getNodeInfo(
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
507 self,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
508 requestor: jid.JID,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
509 service: jid.JID,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
510 nodeIdentifier: str,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
511 pep: bool = False,
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
512 recipient: Optional[jid.JID] = None
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
513 ) -> Optional[dict]:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
514 if not nodeIdentifier:
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
515 return None
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
516 info = {
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
517 "type": "leaf",
3745
a8c7e5cef0cb comp AP gateway: signature checking, caching and threads management:
Goffi <goffi@goffi.org>
parents: 3729
diff changeset
518 "meta-data": NODE_CONFIG
3728
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
519 }
b15644cae50d component AP gateway: JID/node ⟺ AP outbox conversion:
Goffi <goffi@goffi.org>
parents: 3684
diff changeset
520 return info