Mercurial > libervia-backend
annotate libervia/backend/plugins/plugin_comp_ap_gateway/events.py @ 4309:b56b1eae7994
component email gateway: add multicasting:
XEP-0033 multicasting is now supported both for incoming and outgoing messages. XEP-0033
metadata are converted to suitable Email headers and vice versa.
Email address and JID are both supported, and delivery is done by the gateway when
suitable on incoming messages.
rel 450
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 26 Sep 2024 16:12:01 +0200 |
parents | 0d7bb4df2343 |
children |
rev | line source |
---|---|
3904 | 1 #!/usr/bin/env python3 |
2 | |
3 # Libervia ActivityPub Gateway | |
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
5 | |
6 # This program is free software: you can redistribute it and/or modify | |
7 # it under the terms of the GNU Affero General Public License as published by | |
8 # the Free Software Foundation, either version 3 of the License, or | |
9 # (at your option) any later version. | |
10 | |
11 # This program is distributed in the hope that it will be useful, | |
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 # GNU Affero General Public License for more details. | |
15 | |
16 # You should have received a copy of the GNU Affero General Public License | |
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | |
19 from typing import Tuple | |
20 | |
21 import mimetypes | |
22 import html | |
23 | |
24 import shortuuid | |
25 from twisted.words.xish import domish | |
26 from twisted.words.protocols.jabber import jid | |
27 | |
4071
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
28 from libervia.backend.core.i18n import _ |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
29 from libervia.backend.core.log import getLogger |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
30 from libervia.backend.core import exceptions |
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
31 from libervia.backend.tools.common import date_utils, uri |
3904 | 32 |
33 from .constants import NS_AP_PUBLIC, TYPE_ACTOR, TYPE_EVENT, TYPE_ITEM | |
34 | |
35 | |
36 log = getLogger(__name__) | |
37 | |
38 # direct copy of what Mobilizon uses | |
39 AP_EVENTS_CONTEXT = { | |
40 "@language": "und", | |
41 "Hashtag": "as:Hashtag", | |
42 "PostalAddress": "sc:PostalAddress", | |
43 "PropertyValue": "sc:PropertyValue", | |
44 "address": {"@id": "sc:address", "@type": "sc:PostalAddress"}, | |
45 "addressCountry": "sc:addressCountry", | |
46 "addressLocality": "sc:addressLocality", | |
47 "addressRegion": "sc:addressRegion", | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
48 "anonymousParticipationEnabled": { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
49 "@id": "mz:anonymousParticipationEnabled", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
50 "@type": "sc:Boolean", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
51 }, |
3904 | 52 "category": "sc:category", |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
53 "commentsEnabled": {"@id": "pt:commentsEnabled", "@type": "sc:Boolean"}, |
3904 | 54 "discoverable": "toot:discoverable", |
55 "discussions": {"@id": "mz:discussions", "@type": "@id"}, | |
56 "events": {"@id": "mz:events", "@type": "@id"}, | |
57 "ical": "http://www.w3.org/2002/12/cal/ical#", | |
58 "inLanguage": "sc:inLanguage", | |
59 "isOnline": {"@id": "mz:isOnline", "@type": "sc:Boolean"}, | |
60 "joinMode": {"@id": "mz:joinMode", "@type": "mz:joinModeType"}, | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
61 "joinModeType": {"@id": "mz:joinModeType", "@type": "rdfs:Class"}, |
3904 | 62 "location": {"@id": "sc:location", "@type": "sc:Place"}, |
63 "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", | |
64 "maximumAttendeeCapacity": "sc:maximumAttendeeCapacity", | |
65 "memberCount": {"@id": "mz:memberCount", "@type": "sc:Integer"}, | |
66 "members": {"@id": "mz:members", "@type": "@id"}, | |
67 "mz": "https://joinmobilizon.org/ns#", | |
68 "openness": {"@id": "mz:openness", "@type": "@id"}, | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
69 "participantCount": {"@id": "mz:participantCount", "@type": "sc:Integer"}, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
70 "participationMessage": {"@id": "mz:participationMessage", "@type": "sc:Text"}, |
3904 | 71 "postalCode": "sc:postalCode", |
72 "posts": {"@id": "mz:posts", "@type": "@id"}, | |
73 "propertyID": "sc:propertyID", | |
74 "pt": "https://joinpeertube.org/ns#", | |
75 "remainingAttendeeCapacity": "sc:remainingAttendeeCapacity", | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
76 "repliesModerationOption": { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
77 "@id": "mz:repliesModerationOption", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
78 "@type": "mz:repliesModerationOptionType", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
79 }, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
80 "repliesModerationOptionType": { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
81 "@id": "mz:repliesModerationOptionType", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
82 "@type": "rdfs:Class", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
83 }, |
3904 | 84 "resources": {"@id": "mz:resources", "@type": "@id"}, |
85 "sc": "http://schema.org#", | |
86 "streetAddress": "sc:streetAddress", | |
87 "timezone": {"@id": "mz:timezone", "@type": "sc:Text"}, | |
88 "todos": {"@id": "mz:todos", "@type": "@id"}, | |
89 "toot": "http://joinmastodon.org/ns#", | |
90 "uuid": "sc:identifier", | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
91 "value": "sc:value", |
3904 | 92 } |
93 | |
94 | |
95 class APEvents: | |
96 """XMPP Events <=> AP Events conversion""" | |
97 | |
98 def __init__(self, apg): | |
99 self.host = apg.host | |
100 self.apg = apg | |
4027
26c3e1bc7fb7
plugin XEP-0471: renamed "events" plugin to XEP-0471 now that there is a XEP
Goffi <goffi@goffi.org>
parents:
4023
diff
changeset
|
101 self._events = self.host.plugins["XEP-0471"] |
3904 | 102 |
103 async def event_data_2_ap_item( | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
104 self, event_data: dict, author_jid: jid.JID, is_new: bool = True |
3904 | 105 ) -> dict: |
106 """Convert event data to AP activity | |
107 | |
108 @param event_data: event data as used in [plugin_exp_events] | |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
109 @param author_jid: jid of the publisher of the event |
3904 | 110 @param is_new: if True, the item is a new one (no instance has been found in |
111 cache). | |
112 If True, a "Create" activity will be generated, otherwise an "Update" one will | |
113 be | |
114 @return: AP activity wrapping an Event object | |
115 """ | |
116 if not event_data.get("id"): | |
117 event_data["id"] = shortuuid.uuid() | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4027
diff
changeset
|
118 ap_account = await self.apg.get_ap_account_from_jid_and_node( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
119 author_jid, self._events.namespace |
3904 | 120 ) |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4027
diff
changeset
|
121 url_actor = self.apg.build_apurl(TYPE_ACTOR, ap_account) |
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4027
diff
changeset
|
122 url_item = self.apg.build_apurl(TYPE_ITEM, ap_account, event_data["id"]) |
3904 | 123 ap_object = { |
124 "actor": url_actor, | |
125 "attributedTo": url_actor, | |
126 "to": [NS_AP_PUBLIC], | |
127 "id": url_item, | |
128 "type": TYPE_EVENT, | |
129 "name": next(iter(event_data["name"].values())), | |
130 "startTime": date_utils.date_fmt(event_data["start"], "iso"), | |
131 "endTime": date_utils.date_fmt(event_data["end"], "iso"), | |
132 "url": url_item, | |
133 } | |
134 | |
135 attachment = ap_object["attachment"] = [] | |
136 | |
137 # FIXME: we only handle URL head-picture for now | |
138 # TODO: handle jingle and use file metadata | |
139 try: | |
140 head_picture_url = event_data["head-picture"]["sources"][0]["url"] | |
141 except (KeyError, IndexError, TypeError): | |
142 pass | |
143 else: | |
144 media_type = mimetypes.guess_type(head_picture_url, False)[0] or "image/jpeg" | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
145 attachment.append( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
146 { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
147 "name": "Banner", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
148 "type": "Document", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
149 "mediaType": media_type, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
150 "url": head_picture_url, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
151 } |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
152 ) |
3904 | 153 |
154 descriptions = event_data.get("descriptions") | |
155 if descriptions: | |
156 for description in descriptions: | |
157 content = description["description"] | |
158 if description["type"] == "xhtml": | |
159 break | |
160 else: | |
161 content = f"<p>{html.escape(content)}</p>" # type: ignore | |
162 ap_object["content"] = content | |
163 | |
164 categories = event_data.get("categories") | |
165 if categories: | |
166 tag = ap_object["tag"] = [] | |
167 for category in categories: | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
168 tag.append( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
169 { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
170 "name": f"#{category['term']}", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
171 "type": "Hashtag", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
172 } |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
173 ) |
3904 | 174 |
175 locations = event_data.get("locations") | |
176 if locations: | |
177 ap_loc = ap_object["location"] = {} | |
178 # we only use the first found location | |
179 location = locations[0] | |
180 for source, dest in ( | |
181 ("description", "name"), | |
182 ("lat", "latitude"), | |
183 ("lon", "longitude"), | |
184 ): | |
185 value = location.get(source) | |
186 if value is not None: | |
187 ap_loc[dest] = value | |
188 for source, dest in ( | |
189 ("country", "addressCountry"), | |
190 ("locality", "addressLocality"), | |
191 ("region", "addressRegion"), | |
192 ("postalcode", "postalCode"), | |
193 ("street", "streetAddress"), | |
194 ): | |
195 value = location.get(source) | |
196 if value is not None: | |
197 ap_loc.setdefault("address", {})[dest] = value | |
198 | |
199 if event_data.get("comments"): | |
200 ap_object["commentsEnabled"] = True | |
201 | |
202 extra = event_data.get("extra") | |
203 | |
204 if extra: | |
205 status = extra.get("status") | |
206 if status: | |
207 ap_object["ical:status"] = status.upper() | |
208 | |
209 website = extra.get("website") | |
210 if website: | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
211 attachment.append( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
212 { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
213 "href": website, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
214 "mediaType": "text/html", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
215 "name": "Website", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
216 "type": "Link", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
217 } |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
218 ) |
3904 | 219 |
220 accessibility = extra.get("accessibility") | |
221 if accessibility: | |
222 wheelchair = accessibility.get("wheelchair") | |
223 if wheelchair: | |
224 if wheelchair == "full": | |
225 ap_wc_value = "fully" | |
226 elif wheelchair == "partial": | |
227 ap_wc_value = "partially" | |
228 elif wheelchair == "no": | |
229 ap_wc_value = "no" | |
230 else: | |
231 log.error(f"unexpected wheelchair value: {wheelchair}") | |
232 ap_wc_value = None | |
233 if ap_wc_value is not None: | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
234 attachment.append( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
235 { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
236 "propertyID": "mz:accessibility:wheelchairAccessible", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
237 "type": "PropertyValue", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
238 "value": ap_wc_value, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
239 } |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
240 ) |
3904 | 241 |
4023
78b5f356900c
component AP gateway: handle attachments
Goffi <goffi@goffi.org>
parents:
3904
diff
changeset
|
242 activity = self.apg.create_activity( |
3904 | 243 "Create" if is_new else "Update", url_actor, ap_object, activity_id=url_item |
244 ) | |
245 activity["@context"].append(AP_EVENTS_CONTEXT) | |
246 return activity | |
247 | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
248 async def ap_item_2_event_data(self, requestor_actor_id: str, ap_item: dict) -> dict: |
3904 | 249 """Convert AP activity or object to event data |
250 | |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
251 @param requestor_actor_id: ID of the actor doing the request. |
3904 | 252 @param ap_item: ActivityPub item to convert |
253 Can be either an activity of an object | |
254 @return: AP Item's Object and event data | |
255 @raise exceptions.DataError: something is invalid in the AP item | |
256 """ | |
257 is_activity = self.apg.is_activity(ap_item) | |
258 if is_activity: | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
259 ap_object = await self.apg.ap_get_object( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
260 requestor_actor_id, ap_item, "object" |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
261 ) |
3904 | 262 if not ap_object: |
263 log.warning(f'No "object" found in AP item {ap_item!r}') | |
264 raise exceptions.DataError | |
265 else: | |
266 ap_object = ap_item | |
267 | |
268 # id | |
269 if "_repeated" in ap_item: | |
270 # if the event is repeated, we use the original one ID | |
271 repeated_uri = ap_item["_repeated"]["uri"] | |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4027
diff
changeset
|
272 parsed_uri = uri.parse_xmpp_uri(repeated_uri) |
3904 | 273 object_id = parsed_uri["item"] |
274 else: | |
275 object_id = ap_object.get("id") | |
276 if not object_id: | |
277 raise exceptions.DataError('"id" is missing in AP object') | |
278 | |
279 if ap_item["type"] != TYPE_EVENT: | |
280 raise exceptions.DataError("AP Object is not an event") | |
281 | |
282 # author | |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
283 actor = await self.apg.ap_get_sender_actor(requestor_actor_id, ap_object) |
3904 | 284 |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
285 account = await self.apg.get_ap_account_from_id(requestor_actor_id, actor) |
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
4027
diff
changeset
|
286 author_jid = self.apg.get_local_jid_from_account(account).full() |
3904 | 287 |
288 # name, start, end | |
289 event_data = { | |
290 "id": object_id, | |
291 "name": {"": ap_object.get("name") or "unnamed"}, | |
292 "start": date_utils.date_parse(ap_object["startTime"]), | |
293 "end": date_utils.date_parse(ap_object["endTime"]), | |
294 } | |
295 | |
296 # attachments/extra | |
297 event_data["extra"] = extra = {} | |
298 attachments = ap_object.get("attachment") or [] | |
299 for attachment in attachments: | |
300 name = attachment.get("name") | |
301 if name == "Banner": | |
302 try: | |
303 url = attachment["url"] | |
304 except KeyError: | |
305 log.warning(f"invalid attachment: {attachment}") | |
306 continue | |
307 event_data["head-picture"] = {"sources": [{"url": url}]} | |
308 elif name == "Website": | |
309 try: | |
310 url = attachment["href"] | |
311 except KeyError: | |
312 log.warning(f"invalid attachment: {attachment}") | |
313 continue | |
314 extra["website"] = url | |
315 else: | |
316 log.debug(f"unmanaged attachment: {attachment}") | |
317 | |
318 # description | |
319 content = ap_object.get("content") | |
320 if content: | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
321 event_data["descriptions"] = [{"type": "xhtml", "description": content}] |
3904 | 322 |
323 # categories | |
324 tags = ap_object.get("tag") | |
325 if tags: | |
326 categories = event_data["categories"] = [] | |
327 for tag in tags: | |
328 if tag.get("type") == "Hashtag": | |
329 try: | |
330 term = tag["name"][1:] | |
331 except KeyError: | |
332 log.warning(f"invalid tag: {tag}") | |
333 continue | |
334 categories.append({"term": term}) | |
335 | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
336 # location |
3904 | 337 ap_location = ap_object.get("location") |
338 if ap_location: | |
339 location = {} | |
340 for source, dest in ( | |
341 ("name", "description"), | |
342 ("latitude", "lat"), | |
343 ("longitude", "lon"), | |
344 ): | |
345 value = ap_location.get(source) | |
346 if value is not None: | |
347 location[dest] = value | |
348 address = ap_location.get("address") | |
349 if address: | |
350 for source, dest in ( | |
351 ("addressCountry", "country"), | |
352 ("addressLocality", "locality"), | |
353 ("addressRegion", "region"), | |
354 ("postalCode", "postalcode"), | |
355 ("streetAddress", "street"), | |
356 ): | |
357 value = address.get(source) | |
358 if value is not None: | |
359 location[dest] = value | |
360 if location: | |
361 event_data["locations"] = [location] | |
362 | |
363 # rsvp | |
364 # So far Mobilizon seems to only handle participate/don't participate, thus we use | |
365 # a simple "yes"/"no" form. | |
366 rsvp_data = {"fields": []} | |
367 event_data["rsvp"] = [rsvp_data] | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
368 rsvp_data["fields"].append( |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
369 { |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
370 "type": "list-single", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
371 "name": "attending", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
372 "label": "Attending", |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
373 "options": [ |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
374 {"label": "yes", "value": "yes"}, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
375 {"label": "no", "value": "no"}, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
376 ], |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
377 "required": True, |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
378 } |
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
379 ) |
3904 | 380 |
381 # comments | |
382 | |
383 if ap_object.get("commentsEnabled"): | |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
384 __, comments_node = await self.apg.get_comments_nodes( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
385 requestor_actor_id, object_id, None |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
386 ) |
3904 | 387 event_data["comments"] = { |
388 "service": author_jid, | |
389 "node": comments_node, | |
390 } | |
391 | |
392 # extra | |
393 # part of extra come from "attachment" above | |
394 | |
395 status = ap_object.get("ical:status") | |
396 if status is None: | |
397 pass | |
398 elif status in ("CONFIRMED", "CANCELLED", "TENTATIVE"): | |
399 extra["status"] = status.lower() | |
400 else: | |
401 log.warning(f"unknown event status: {status}") | |
402 | |
403 return event_data | |
404 | |
405 async def ap_item_2_event_data_and_elt( | |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
406 self, requestor_actor_id: str, ap_item: dict |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
407 ) -> tuple[dict, domish.Element]: |
3904 | 408 """Convert AP item to parsed event data and corresponding item element""" |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
409 event_data = await self.ap_item_2_event_data(requestor_actor_id, ap_item) |
3904 | 410 event_elt = self._events.event_data_2_event_elt(event_data) |
411 item_elt = domish.Element((None, "item")) | |
412 item_elt["id"] = event_data["id"] | |
413 item_elt.addChild(event_elt) | |
414 return event_data, item_elt | |
415 | |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
416 async def ap_item_2_event_elt( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
417 self, requestor_actor_id: str, ap_item: dict |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
418 ) -> domish.Element: |
3904 | 419 """Convert AP item to XMPP item element""" |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
420 __, item_elt = await self.ap_item_2_event_data_and_elt( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4259
diff
changeset
|
421 requestor_actor_id, ap_item |
4259
49019947cc76
component AP Gateway: implement HTTP GET signature.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
422 ) |
3904 | 423 return item_elt |