Mercurial > libervia-backend
comparison libervia/backend/plugins/plugin_misc_lists.py @ 4270:0d7bb4df2343
Reformatted code base using black.
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 19 Jun 2024 18:44:57 +0200 |
parents | 4b842c1fb686 |
children | a5d27f69eedb |
comparison
equal
deleted
inserted
replaced
4269:64a85ce8be70 | 4270:0d7bb4df2343 |
---|---|
38 PLUGIN_INFO = { | 38 PLUGIN_INFO = { |
39 C.PI_NAME: _("Pubsub Lists"), | 39 C.PI_NAME: _("Pubsub Lists"), |
40 C.PI_IMPORT_NAME: "LISTS", | 40 C.PI_IMPORT_NAME: "LISTS", |
41 C.PI_TYPE: "EXP", | 41 C.PI_TYPE: "EXP", |
42 C.PI_PROTOCOLS: [], | 42 C.PI_PROTOCOLS: [], |
43 C.PI_DEPENDENCIES: ["XEP-0060", "XEP-0346", "XEP-0277", "IDENTITY", | 43 C.PI_DEPENDENCIES: [ |
44 "PUBSUB_INVITATION"], | 44 "XEP-0060", |
45 "XEP-0346", | |
46 "XEP-0277", | |
47 "IDENTITY", | |
48 "PUBSUB_INVITATION", | |
49 ], | |
45 C.PI_MAIN: "PubsubLists", | 50 C.PI_MAIN: "PubsubLists", |
46 C.PI_HANDLER: "no", | 51 C.PI_HANDLER: "no", |
47 C.PI_DESCRIPTION: _("""Pubsub lists management plugin"""), | 52 C.PI_DESCRIPTION: _("""Pubsub lists management plugin"""), |
48 } | 53 } |
49 | 54 |
61 { | 66 { |
62 "name": "status", | 67 "name": "status", |
63 "label": D_("status"), | 68 "label": D_("status"), |
64 "type": "list-single", | 69 "type": "list-single", |
65 "options": [ | 70 "options": [ |
66 { | 71 {"label": D_("to do"), "value": "todo"}, |
67 "label": D_("to do"), | 72 {"label": D_("in progress"), "value": "in_progress"}, |
68 "value": "todo" | 73 {"label": D_("done"), "value": "done"}, |
69 }, | 74 ], |
70 { | 75 "value": "todo", |
71 "label": D_("in progress"), | |
72 "value": "in_progress" | |
73 }, | |
74 { | |
75 "label": D_("done"), | |
76 "value": "done" | |
77 }, | |
78 ], | |
79 "value": "todo" | |
80 }, | 76 }, |
81 { | 77 { |
82 "name": "priority", | 78 "name": "priority", |
83 "label": D_("priority"), | 79 "label": D_("priority"), |
84 "type": "list-single", | 80 "type": "list-single", |
85 "options": [ | 81 "options": [ |
86 { | 82 {"label": D_("major"), "value": "major"}, |
87 "label": D_("major"), | 83 {"label": D_("normal"), "value": "normal"}, |
88 "value": "major" | 84 {"label": D_("minor"), "value": "minor"}, |
89 }, | 85 ], |
90 { | 86 "value": "normal", |
91 "label": D_("normal"), | |
92 "value": "normal" | |
93 }, | |
94 { | |
95 "label": D_("minor"), | |
96 "value": "minor" | |
97 }, | |
98 ], | |
99 "value": "normal" | |
100 }, | 87 }, |
101 {"name": "body", "type": "xhtml"}, | 88 {"name": "body", "type": "xhtml"}, |
102 {"name": "comments_uri"}, | 89 {"name": "comments_uri"}, |
103 ] | 90 ], |
104 }, | 91 }, |
105 "grocery": { | 92 "grocery": { |
106 "name": D_("Grocery List"), | 93 "name": D_("Grocery List"), |
107 "icon": "basket", | 94 "icon": "basket", |
108 "fields": [ | 95 "fields": [ |
111 { | 98 { |
112 "name": "status", | 99 "name": "status", |
113 "label": D_("status"), | 100 "label": D_("status"), |
114 "type": "list-single", | 101 "type": "list-single", |
115 "options": [ | 102 "options": [ |
116 { | 103 {"label": D_("to buy"), "value": "to_buy"}, |
117 "label": D_("to buy"), | 104 {"label": D_("bought"), "value": "bought"}, |
118 "value": "to_buy" | 105 ], |
119 }, | 106 "value": "to_buy", |
120 { | 107 }, |
121 "label": D_("bought"), | 108 ], |
122 "value": "bought" | |
123 }, | |
124 ], | |
125 "value": "to_buy" | |
126 }, | |
127 ] | |
128 }, | 109 }, |
129 "tickets": { | 110 "tickets": { |
130 "name": D_("Tickets"), | 111 "name": D_("Tickets"), |
131 "icon": "clipboard", | 112 "icon": "clipboard", |
132 "fields": [ | 113 "fields": [ |
138 { | 119 { |
139 "name": "type", | 120 "name": "type", |
140 "label": D_("type"), | 121 "label": D_("type"), |
141 "type": "list-single", | 122 "type": "list-single", |
142 "options": [ | 123 "options": [ |
143 { | 124 {"label": D_("bug"), "value": "bug"}, |
144 "label": D_("bug"), | 125 {"label": D_("feature request"), "value": "feature"}, |
145 "value": "bug" | 126 ], |
146 }, | 127 "value": "bug", |
147 { | |
148 "label": D_("feature request"), | |
149 "value": "feature" | |
150 }, | |
151 ], | |
152 "value": "bug" | |
153 }, | 128 }, |
154 { | 129 { |
155 "name": "status", | 130 "name": "status", |
156 "label": D_("status"), | 131 "label": D_("status"), |
157 "type": "list-single", | 132 "type": "list-single", |
158 "options": [ | 133 "options": [ |
159 { | 134 {"label": D_("queued"), "value": "queued"}, |
160 "label": D_("queued"), | 135 {"label": D_("started"), "value": "started"}, |
161 "value": "queued" | 136 {"label": D_("review"), "value": "review"}, |
162 }, | 137 {"label": D_("closed"), "value": "closed"}, |
163 { | 138 ], |
164 "label": D_("started"), | 139 "value": "queued", |
165 "value": "started" | |
166 }, | |
167 { | |
168 "label": D_("review"), | |
169 "value": "review" | |
170 }, | |
171 { | |
172 "label": D_("closed"), | |
173 "value": "closed" | |
174 }, | |
175 ], | |
176 "value": "queued" | |
177 }, | 140 }, |
178 { | 141 { |
179 "name": "priority", | 142 "name": "priority", |
180 "label": D_("priority"), | 143 "label": D_("priority"), |
181 "type": "list-single", | 144 "type": "list-single", |
182 "options": [ | 145 "options": [ |
183 { | 146 {"label": D_("major"), "value": "major"}, |
184 "label": D_("major"), | 147 {"label": D_("normal"), "value": "normal"}, |
185 "value": "major" | 148 {"label": D_("minor"), "value": "minor"}, |
186 }, | 149 ], |
187 { | 150 "value": "normal", |
188 "label": D_("normal"), | |
189 "value": "normal" | |
190 }, | |
191 { | |
192 "label": D_("minor"), | |
193 "value": "minor" | |
194 }, | |
195 ], | |
196 "value": "normal" | |
197 }, | 151 }, |
198 {"name": "body", "type": "xhtml"}, | 152 {"name": "body", "type": "xhtml"}, |
199 {"name": "comments_uri"}, | 153 {"name": "comments_uri"}, |
200 ] | 154 ], |
201 } | 155 }, |
202 } | 156 } |
203 | 157 |
204 | 158 |
205 class PubsubLists: | 159 class PubsubLists: |
206 | 160 |
209 self.host = host | 163 self.host = host |
210 self._s = self.host.plugins["XEP-0346"] | 164 self._s = self.host.plugins["XEP-0346"] |
211 self.namespace = self._s.get_submitted_ns(APP_NS_TICKETS) | 165 self.namespace = self._s.get_submitted_ns(APP_NS_TICKETS) |
212 host.register_namespace("tickets", APP_NS_TICKETS) | 166 host.register_namespace("tickets", APP_NS_TICKETS) |
213 host.register_namespace("tickets_type", NS_TICKETS_TYPE) | 167 host.register_namespace("tickets_type", NS_TICKETS_TYPE) |
214 self.host.plugins["PUBSUB_INVITATION"].register( | 168 self.host.plugins["PUBSUB_INVITATION"].register(APP_NS_TICKETS, self) |
215 APP_NS_TICKETS, self | |
216 ) | |
217 self._p = self.host.plugins["XEP-0060"] | 169 self._p = self.host.plugins["XEP-0060"] |
218 self._m = self.host.plugins["XEP-0277"] | 170 self._m = self.host.plugins["XEP-0277"] |
219 host.bridge.add_method( | 171 host.bridge.add_method( |
220 "list_get", | 172 "list_get", |
221 ".plugin", | 173 ".plugin", |
222 in_sign="ssiassss", | 174 in_sign="ssiassss", |
223 out_sign="s", | 175 out_sign="s", |
224 method=lambda service, node, max_items, items_ids, sub_id, extra, profile_key: | 176 method=lambda service, node, max_items, items_ids, sub_id, extra, profile_key: self._s._get( |
225 self._s._get( | |
226 service, | 177 service, |
227 node, | 178 node, |
228 max_items, | 179 max_items, |
229 items_ids, | 180 items_ids, |
230 sub_id, | 181 sub_id, |
235 "author": self._s.value_or_publisher_filter, | 186 "author": self._s.value_or_publisher_filter, |
236 "created": self._s.date_filter, | 187 "created": self._s.date_filter, |
237 "updated": self._s.date_filter, | 188 "updated": self._s.date_filter, |
238 "time_limit": self._s.date_filter, | 189 "time_limit": self._s.date_filter, |
239 }, | 190 }, |
240 profile_key=profile_key), | 191 profile_key=profile_key, |
192 ), | |
241 async_=True, | 193 async_=True, |
242 ) | 194 ) |
243 host.bridge.add_method( | 195 host.bridge.add_method( |
244 "list_set", | 196 "list_set", |
245 ".plugin", | 197 ".plugin", |
260 "list_schema_get", | 212 "list_schema_get", |
261 ".plugin", | 213 ".plugin", |
262 in_sign="sss", | 214 in_sign="sss", |
263 out_sign="s", | 215 out_sign="s", |
264 method=lambda service, nodeIdentifier, profile_key: self._s._get_ui_schema( | 216 method=lambda service, nodeIdentifier, profile_key: self._s._get_ui_schema( |
265 service, nodeIdentifier, default_node=self.namespace, | 217 service, |
266 profile_key=profile_key), | 218 nodeIdentifier, |
219 default_node=self.namespace, | |
220 profile_key=profile_key, | |
221 ), | |
267 async_=True, | 222 async_=True, |
268 ) | 223 ) |
269 host.bridge.add_method( | 224 host.bridge.add_method( |
270 "lists_list", | 225 "lists_list", |
271 ".plugin", | 226 ".plugin", |
304 name: str, | 259 name: str, |
305 extra: dict, | 260 extra: dict, |
306 service: jid.JID, | 261 service: jid.JID, |
307 node: str, | 262 node: str, |
308 item_id: Optional[str], | 263 item_id: Optional[str], |
309 item_elt: domish.Element | 264 item_elt: domish.Element, |
310 ) -> None: | 265 ) -> None: |
311 try: | 266 try: |
312 schema = await self._s.get_schema_form(client, service, node) | 267 schema = await self._s.get_schema_form(client, service, node) |
313 except Exception as e: | 268 except Exception as e: |
314 log.warning(f"Can't retrive node schema as {node!r} [{service}]: {e}") | 269 log.warning(f"Can't retrive node schema as {node!r} [{service}]: {e}") |
319 log.debug("no type found in list schema") | 274 log.debug("no type found in list schema") |
320 else: | 275 else: |
321 list_elt = extra["element"] = domish.Element((APP_NS_TICKETS, "list")) | 276 list_elt = extra["element"] = domish.Element((APP_NS_TICKETS, "list")) |
322 list_elt["type"] = field_type | 277 list_elt["type"] = field_type |
323 | 278 |
324 def _set(self, service, node, values, schema=None, item_id=None, extra_s='', | 279 def _set( |
325 profile_key=C.PROF_KEY_NONE): | 280 self, |
281 service, | |
282 node, | |
283 values, | |
284 schema=None, | |
285 item_id=None, | |
286 extra_s="", | |
287 profile_key=C.PROF_KEY_NONE, | |
288 ): | |
326 client, service, node, schema, item_id, extra = self._s.prepare_bridge_set( | 289 client, service, node, schema, item_id, extra = self._s.prepare_bridge_set( |
327 service, node, schema, item_id, extra_s, profile_key | 290 service, node, schema, item_id, extra_s, profile_key |
328 ) | 291 ) |
329 d = defer.ensureDeferred(self.set( | 292 d = defer.ensureDeferred( |
330 client, service, node, values, schema, item_id, extra, deserialise=True | 293 self.set( |
331 )) | 294 client, service, node, values, schema, item_id, extra, deserialise=True |
295 ) | |
296 ) | |
332 d.addCallback(lambda ret: ret or "") | 297 d.addCallback(lambda ret: ret or "") |
333 return d | 298 return d |
334 | 299 |
335 async def set( | 300 async def set( |
336 self, client, service, node, values, schema=None, item_id=None, extra=None, | 301 self, |
337 deserialise=False, form_ns=APP_NS_TICKETS | 302 client, |
303 service, | |
304 node, | |
305 values, | |
306 schema=None, | |
307 item_id=None, | |
308 extra=None, | |
309 deserialise=False, | |
310 form_ns=APP_NS_TICKETS, | |
338 ): | 311 ): |
339 """Publish a tickets | 312 """Publish a tickets |
340 | 313 |
341 @param node(unicode, None): Pubsub node to use | 314 @param node(unicode, None): Pubsub node to use |
342 None to use default tickets node | 315 None to use default tickets node |
359 comments_service = await self._m.get_comments_service(client, service) | 332 comments_service = await self._m.get_comments_service(client, service) |
360 | 333 |
361 # we need to use uuid for comments node, because we don't know item id in | 334 # we need to use uuid for comments node, because we don't know item id in |
362 # advance (we don't want to set it ourselves to let the server choose, so we | 335 # advance (we don't want to set it ourselves to let the server choose, so we |
363 # can have a nicer id if serial ids is activated) | 336 # can have a nicer id if serial ids is activated) |
364 comments_node = self._m.get_comments_node( | 337 comments_node = self._m.get_comments_node(node + "_" + str(shortuuid.uuid())) |
365 node + "_" + str(shortuuid.uuid()) | |
366 ) | |
367 options = { | 338 options = { |
368 self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN, | 339 self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN, |
369 self._p.OPT_PERSIST_ITEMS: 1, | 340 self._p.OPT_PERSIST_ITEMS: 1, |
370 self._p.OPT_DELIVER_PAYLOADS: 1, | 341 self._p.OPT_DELIVER_PAYLOADS: 1, |
371 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1, | 342 self._p.OPT_SEND_ITEM_SUBSCRIBE: 1, |
381 | 352 |
382 return await self._s.set( | 353 return await self._s.set( |
383 client, service, node, values, schema, item_id, extra, deserialise, form_ns | 354 client, service, node, values, schema, item_id, extra, deserialise, form_ns |
384 ) | 355 ) |
385 | 356 |
386 def _delete( | 357 def _delete(self, service_s, nodeIdentifier, itemIdentifier, notify, profile_key): |
387 self, service_s, nodeIdentifier, itemIdentifier, notify, profile_key | |
388 ): | |
389 client = self.host.get_client(profile_key) | 358 client = self.host.get_client(profile_key) |
390 return defer.ensureDeferred(self.delete( | 359 return defer.ensureDeferred( |
391 client, | 360 self.delete( |
392 jid.JID(service_s) if service_s else None, | 361 client, |
393 nodeIdentifier, | 362 jid.JID(service_s) if service_s else None, |
394 itemIdentifier, | 363 nodeIdentifier, |
395 notify | 364 itemIdentifier, |
396 )) | 365 notify, |
366 ) | |
367 ) | |
397 | 368 |
398 async def delete( | 369 async def delete( |
399 self, | 370 self, |
400 client: SatXMPPEntity, | 371 client: SatXMPPEntity, |
401 service: Optional[jid.JID], | 372 service: Optional[jid.JID], |
402 node: Optional[str], | 373 node: Optional[str], |
403 itemIdentifier: str, | 374 itemIdentifier: str, |
404 notify: Optional[bool] = None | 375 notify: Optional[bool] = None, |
405 ) -> None: | 376 ) -> None: |
406 if not node: | 377 if not node: |
407 node = self.namespace | 378 node = self.namespace |
408 return await self._p.retract_items( | 379 return await self._p.retract_items( |
409 service, node, (itemIdentifier,), notify, client.profile | 380 service, node, (itemIdentifier,), notify, client.profile |
416 d = defer.ensureDeferred(self.lists_list(client, service, node)) | 387 d = defer.ensureDeferred(self.lists_list(client, service, node)) |
417 d.addCallback(data_format.serialise) | 388 d.addCallback(data_format.serialise) |
418 return d | 389 return d |
419 | 390 |
420 async def lists_list( | 391 async def lists_list( |
421 self, client, service: Optional[jid.JID], node: Optional[str]=None | 392 self, client, service: Optional[jid.JID], node: Optional[str] = None |
422 ) -> List[dict]: | 393 ) -> List[dict]: |
423 """Retrieve list of pubsub lists registered in personal interests | 394 """Retrieve list of pubsub lists registered in personal interests |
424 | 395 |
425 @return list: list of lists metadata | 396 @return list: list of lists metadata |
426 """ | 397 """ |
427 items, metadata = await self.host.plugins['LIST_INTEREST'].list_interests( | 398 items, metadata = await self.host.plugins["LIST_INTEREST"].list_interests( |
428 client, service, node, namespace=APP_NS_TICKETS) | 399 client, service, node, namespace=APP_NS_TICKETS |
400 ) | |
429 lists = [] | 401 lists = [] |
430 for item in items: | 402 for item in items: |
431 interest_elt = item.interest | 403 interest_elt = item.interest |
432 if interest_elt is None: | 404 if interest_elt is None: |
433 log.warning(f"invalid interest for {client.profile}: {item.toXml}") | 405 log.warning(f"invalid interest for {client.profile}: {item.toXml}") |
459 return data_format.serialise(self.get_templates_names(client, language)) | 431 return data_format.serialise(self.get_templates_names(client, language)) |
460 | 432 |
461 def get_templates_names(self, client, language: str) -> list: | 433 def get_templates_names(self, client, language: str) -> list: |
462 """Retrieve well known list templates""" | 434 """Retrieve well known list templates""" |
463 | 435 |
464 templates = [{"id": tpl_id, "name": d["name"], "icon": d["icon"]} | 436 templates = [ |
465 for tpl_id, d in TEMPLATES.items()] | 437 {"id": tpl_id, "name": d["name"], "icon": d["icon"]} |
438 for tpl_id, d in TEMPLATES.items() | |
439 ] | |
466 return templates | 440 return templates |
467 | 441 |
468 def _get_template(self, name, language, profile): | 442 def _get_template(self, name, language, profile): |
469 client = self.host.get_client(profile) | 443 client = self.host.get_client(profile) |
470 return data_format.serialise(self.get_template(client, name, language)) | 444 return data_format.serialise(self.get_template(client, name, language)) |
473 """Retrieve a well known template""" | 447 """Retrieve a well known template""" |
474 return TEMPLATES[name] | 448 return TEMPLATES[name] |
475 | 449 |
476 def _create_template(self, template_id, name, access_model, profile): | 450 def _create_template(self, template_id, name, access_model, profile): |
477 client = self.host.get_client(profile) | 451 client = self.host.get_client(profile) |
478 d = defer.ensureDeferred(self.create_template( | 452 d = defer.ensureDeferred( |
479 client, template_id, name, access_model | 453 self.create_template(client, template_id, name, access_model) |
480 )) | 454 ) |
481 d.addCallback(lambda node_data: (node_data[0].full(), node_data[1])) | 455 d.addCallback(lambda node_data: (node_data[0].full(), node_data[1])) |
482 return d | 456 return d |
483 | 457 |
484 async def create_template( | 458 async def create_template( |
485 self, client, template_id: str, name: str, access_model: str | 459 self, client, template_id: str, name: str, access_model: str |
488 name = name.strip() | 462 name = name.strip() |
489 if not name: | 463 if not name: |
490 name = shortuuid.uuid() | 464 name = shortuuid.uuid() |
491 fields = TEMPLATES[template_id]["fields"].copy() | 465 fields = TEMPLATES[template_id]["fields"].copy() |
492 fields.insert( | 466 fields.insert( |
493 0, | 467 0, {"type": "hidden", "name": NS_TICKETS_TYPE, "value": template_id} |
494 {"type": "hidden", "name": NS_TICKETS_TYPE, "value": template_id} | |
495 ) | 468 ) |
496 schema = xml_tools.data_dict_2_data_form( | 469 schema = xml_tools.data_dict_2_data_form( |
497 {"namespace": APP_NS_TICKETS, "fields": fields} | 470 {"namespace": APP_NS_TICKETS, "fields": fields} |
498 ).toElement() | 471 ).toElement() |
499 | 472 |
509 await self._p.createNode(client, service, node, options) | 482 await self._p.createNode(client, service, node, options) |
510 await self._s.set_schema(client, service, node, schema) | 483 await self._s.set_schema(client, service, node, schema) |
511 list_elt = domish.Element((APP_NS_TICKETS, "list")) | 484 list_elt = domish.Element((APP_NS_TICKETS, "list")) |
512 list_elt["type"] = template_id | 485 list_elt["type"] = template_id |
513 try: | 486 try: |
514 await self.host.plugins['LIST_INTEREST'].register_pubsub( | 487 await self.host.plugins["LIST_INTEREST"].register_pubsub( |
515 client, APP_NS_TICKETS, service, node, creator=True, | 488 client, |
516 name=name, element=list_elt) | 489 APP_NS_TICKETS, |
490 service, | |
491 node, | |
492 creator=True, | |
493 name=name, | |
494 element=list_elt, | |
495 ) | |
517 except Exception as e: | 496 except Exception as e: |
518 log.warning(f"Can't add list to interests: {e}") | 497 log.warning(f"Can't add list to interests: {e}") |
519 return service, node | 498 return service, node |