comparison sat/plugins/plugin_xep_0471.py @ 4037:524856bd7b19

massive refactoring to switch from camelCase to snake_case: historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a pre-PEP8 code, to use the same coding style as in Twisted. However, snake_case is more readable and it's better to follow PEP8 best practices, so it has been decided to move on full snake_case. Because Libervia has a huge codebase, this ended with a ugly mix of camelCase and snake_case. To fix that, this patch does a big refactoring by renaming every function and method (including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case. This is a massive change, and may result in some bugs.
author Goffi <goffi@goffi.org>
date Sat, 08 Apr 2023 13:54:42 +0200
parents 26c3e1bc7fb7
children
comparison
equal deleted inserted replaced
4036:c4464d7ae97b 4037:524856bd7b19
78 self._g = host.plugins["XEP-0080"] 78 self._g = host.plugins["XEP-0080"]
79 self._b = host.plugins.get("XEP-0277") 79 self._b = host.plugins.get("XEP-0277")
80 self._sfs = host.plugins["XEP-0447"] 80 self._sfs = host.plugins["XEP-0447"]
81 self._a = host.plugins["XEP-0470"] 81 self._a = host.plugins["XEP-0470"]
82 # self._i = host.plugins.get("EMAIL_INVITATION") 82 # self._i = host.plugins.get("EMAIL_INVITATION")
83 host.registerNamespace("events", NS_EVENTS) 83 host.register_namespace("events", NS_EVENTS)
84 self._a.register_attachment_handler("rsvp", NS_EVENTS, self.rsvp_get, self.rsvp_set) 84 self._a.register_attachment_handler("rsvp", NS_EVENTS, self.rsvp_get, self.rsvp_set)
85 # host.plugins["PUBSUB_INVITATION"].register(NS_EVENTS, self) 85 # host.plugins["PUBSUB_INVITATION"].register(NS_EVENTS, self)
86 host.bridge.addMethod( 86 host.bridge.add_method(
87 "eventsGet", 87 "events_get",
88 ".plugin", 88 ".plugin",
89 in_sign="ssasss", 89 in_sign="ssasss",
90 out_sign="s", 90 out_sign="s",
91 method=self._events_get, 91 method=self._events_get,
92 async_=True, 92 async_=True,
93 ) 93 )
94 host.bridge.addMethod( 94 host.bridge.add_method(
95 "eventCreate", 95 "event_create",
96 ".plugin", 96 ".plugin",
97 in_sign="sssss", 97 in_sign="sssss",
98 out_sign="", 98 out_sign="",
99 method=self._event_create, 99 method=self._event_create,
100 async_=True, 100 async_=True,
101 ) 101 )
102 host.bridge.addMethod( 102 host.bridge.add_method(
103 "eventModify", 103 "event_modify",
104 ".plugin", 104 ".plugin",
105 in_sign="sssss", 105 in_sign="sssss",
106 out_sign="", 106 out_sign="",
107 method=self._event_modify, 107 method=self._event_modify,
108 async_=True, 108 async_=True,
109 ) 109 )
110 host.bridge.addMethod( 110 host.bridge.add_method(
111 "eventInviteeGet", 111 "event_invitee_get",
112 ".plugin", 112 ".plugin",
113 in_sign="sssasss", 113 in_sign="sssasss",
114 out_sign="s", 114 out_sign="s",
115 method=self._event_invitee_get, 115 method=self._event_invitee_get,
116 async_=True, 116 async_=True,
117 ) 117 )
118 host.bridge.addMethod( 118 host.bridge.add_method(
119 "eventInviteeSet", 119 "event_invitee_set",
120 ".plugin", 120 ".plugin",
121 in_sign="sssss", 121 in_sign="sssss",
122 out_sign="", 122 out_sign="",
123 method=self._event_invitee_set, 123 method=self._event_invitee_set,
124 async_=True, 124 async_=True,
125 ) 125 )
126 host.bridge.addMethod( 126 host.bridge.add_method(
127 "eventInviteesList", 127 "event_invitees_list",
128 ".plugin", 128 ".plugin",
129 in_sign="sss", 129 in_sign="sss",
130 out_sign="a{sa{ss}}", 130 out_sign="a{sa{ss}}",
131 method=self._eventInviteesList, 131 method=self._event_invitees_list,
132 async_=True, 132 async_=True,
133 ), 133 ),
134 host.bridge.addMethod( 134 host.bridge.add_method(
135 "eventInvite", 135 "event_invite",
136 ".plugin", 136 ".plugin",
137 in_sign="sssss", 137 in_sign="sssss",
138 out_sign="", 138 out_sign="",
139 method=self._invite, 139 method=self._invite,
140 async_=True, 140 async_=True,
141 ) 141 )
142 host.bridge.addMethod( 142 host.bridge.add_method(
143 "eventInviteByEmail", 143 "event_invite_by_email",
144 ".plugin", 144 ".plugin",
145 in_sign="ssssassssssss", 145 in_sign="ssssassssssss",
146 out_sign="", 146 out_sign="",
147 method=self._invite_by_email, 147 method=self._invite_by_email,
148 async_=True, 148 async_=True,
149 ) 149 )
150 150
151 def getHandler(self, client): 151 def get_handler(self, client):
152 return EventsHandler(self) 152 return EventsHandler(self)
153 153
154 def _parseEventElt(self, event_elt): 154 def _parse_event_elt(self, event_elt):
155 """Helper method to parse event element 155 """Helper method to parse event element
156 156
157 @param (domish.Element): event_elt 157 @param (domish.Element): event_elt
158 @return (tuple[int, dict[unicode, unicode]): timestamp, event_data 158 @return (tuple[int, dict[unicode, unicode]): timestamp, event_data
159 """ 159 """
189 189
190 for uri_type in ("invitees", "blog"): 190 for uri_type in ("invitees", "blog"):
191 try: 191 try:
192 elt = next(event_elt.elements(NS_EVENT, uri_type)) 192 elt = next(event_elt.elements(NS_EVENT, uri_type))
193 uri = data[uri_type + "_uri"] = elt["uri"] 193 uri = data[uri_type + "_uri"] = elt["uri"]
194 uri_data = xmpp_uri.parseXMPPUri(uri) 194 uri_data = xmpp_uri.parse_xmpp_uri(uri)
195 if uri_data["type"] != "pubsub": 195 if uri_data["type"] != "pubsub":
196 raise ValueError 196 raise ValueError
197 except StopIteration: 197 except StopIteration:
198 log.warning(_("no {uri_type} element found!").format(uri_type=uri_type)) 198 log.warning(_("no {uri_type} element found!").format(uri_type=uri_type))
199 except KeyError: 199 except KeyError:
347 seen_rsvp_lang.add(rsvp_lang) 347 seen_rsvp_lang.add(rsvp_lang)
348 rsvp_form = data_form.findForm(rsvp_elt, NS_RSVP) 348 rsvp_form = data_form.findForm(rsvp_elt, NS_RSVP)
349 if rsvp_form is None: 349 if rsvp_form is None:
350 log.warning(f"RSVP form is missing: {rsvp_elt.toXml()}") 350 log.warning(f"RSVP form is missing: {rsvp_elt.toXml()}")
351 continue 351 continue
352 rsvp_data = xml_tools.dataForm2dataDict(rsvp_form) 352 rsvp_data = xml_tools.data_form_2_data_dict(rsvp_form)
353 if rsvp_lang: 353 if rsvp_lang:
354 rsvp_data["language"] = rsvp_lang 354 rsvp_data["language"] = rsvp_lang
355 event_data.setdefault("rsvp", []).append(rsvp_data) 355 event_data.setdefault("rsvp", []).append(rsvp_data)
356 356
357 # linked pubsub nodes 357 # linked pubsub nodes
417 return event_data 417 return event_data
418 418
419 def _events_get( 419 def _events_get(
420 self, service: str, node: str, event_ids: List[str], extra: str, profile_key: str 420 self, service: str, node: str, event_ids: List[str], extra: str, profile_key: str
421 ): 421 ):
422 client = self.host.getClient(profile_key) 422 client = self.host.get_client(profile_key)
423 d = defer.ensureDeferred( 423 d = defer.ensureDeferred(
424 self.events_get( 424 self.events_get(
425 client, 425 client,
426 jid.JID(service) if service else None, 426 jid.JID(service) if service else None,
427 node if node else NS_EVENTS, 427 node if node else NS_EVENTS,
447 @param event_id: pubsub item ID 447 @param event_id: pubsub item ID
448 @return: event data: 448 @return: event data:
449 """ 449 """
450 if service is None: 450 if service is None:
451 service = client.jid.userhostJID() 451 service = client.jid.userhostJID()
452 items, __ = await self._p.getItems( 452 items, __ = await self._p.get_items(
453 client, service, node, item_ids=events_ids, extra=extra 453 client, service, node, item_ids=events_ids, extra=extra
454 ) 454 )
455 events = [] 455 events = []
456 for item in items: 456 for item in items:
457 try: 457 try:
469 service: str, 469 service: str,
470 node: str, 470 node: str,
471 event_id: str = "", 471 event_id: str = "",
472 profile_key: str = C.PROF_KEY_NONE 472 profile_key: str = C.PROF_KEY_NONE
473 ): 473 ):
474 client = self.host.getClient(profile_key) 474 client = self.host.get_client(profile_key)
475 return defer.ensureDeferred( 475 return defer.ensureDeferred(
476 self.event_create( 476 self.event_create(
477 client, 477 client,
478 data_format.deserialise(data_s), 478 data_format.deserialise(data_s),
479 jid.JID(service) if service else None, 479 jid.JID(service) if service else None,
521 locations(list[dict]) 521 locations(list[dict])
522 list of location dict as used in plugin XEP-0080 [get_geoloc_elt]. 522 list of location dict as used in plugin XEP-0080 [get_geoloc_elt].
523 If several locations are used, they must have distinct IDs 523 If several locations are used, they must have distinct IDs
524 rsvp(list[dict]) 524 rsvp(list[dict])
525 RSVP data. The dict is a data dict as used in 525 RSVP data. The dict is a data dict as used in
526 sat.tools.xml_tools.dataDict2dataForm with some extra keys. 526 sat.tools.xml_tools.data_dict_2_data_form with some extra keys.
527 The "attending" key is automatically added if it's not already present, 527 The "attending" key is automatically added if it's not already present,
528 except if the "no_default" key is present. Thus, an empty dict can be used 528 except if the "no_default" key is present. Thus, an empty dict can be used
529 to use default RSVP. 529 to use default RSVP.
530 If several dict are present in the list, they must have different "lang" 530 If several dict are present in the list, they must have different "lang"
531 keys. 531 keys.
700 {"label": "no", "value": "no"} 700 {"label": "no", "value": "no"}
701 ], 701 ],
702 "required": True 702 "required": True
703 }) 703 })
704 rsvp_data["namespace"] = NS_RSVP 704 rsvp_data["namespace"] = NS_RSVP
705 rsvp_form = xml_tools.dataDict2dataForm(rsvp_data) 705 rsvp_form = xml_tools.data_dict_2_data_form(rsvp_data)
706 rsvp_elt.addChild(rsvp_form.toElement()) 706 rsvp_elt.addChild(rsvp_form.toElement())
707 707
708 for node_type in ("invitees", "comments", "blog", "schedule"): 708 for node_type in ("invitees", "comments", "blog", "schedule"):
709 node_data = event_data.get(node_type) 709 node_data = event_data.get(node_type)
710 if not node_data: 710 if not node_data:
788 event_id = shortuuid.uuid() 788 event_id = shortuuid.uuid()
789 event_elt = self.event_data_2_event_elt(event_data) 789 event_elt = self.event_data_2_event_elt(event_data)
790 790
791 item_elt = pubsub.Item(id=event_id, payload=event_elt) 791 item_elt = pubsub.Item(id=event_id, payload=event_elt)
792 options = {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_WHITELIST} 792 options = {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_WHITELIST}
793 await self._p.createIfNewNode( 793 await self._p.create_if_new_node(
794 client, service, nodeIdentifier=node, options=options 794 client, service, nodeIdentifier=node, options=options
795 ) 795 )
796 await self._p.publish(client, service, node, items=[item_elt]) 796 await self._p.publish(client, service, node, items=[item_elt])
797 if event_data.get("rsvp"): 797 if event_data.get("rsvp"):
798 await self._a.create_attachments_node(client, service, node, event_id) 798 await self._a.create_attachments_node(client, service, node, event_id)
803 event_id: str, 803 event_id: str,
804 service: str, 804 service: str,
805 node: str, 805 node: str,
806 profile_key: str = C.PROF_KEY_NONE 806 profile_key: str = C.PROF_KEY_NONE
807 ) -> None: 807 ) -> None:
808 client = self.host.getClient(profile_key) 808 client = self.host.get_client(profile_key)
809 defer.ensureDeferred( 809 defer.ensureDeferred(
810 self.event_modify( 810 self.event_modify(
811 client, 811 client,
812 data_format.deserialise(data_s), 812 data_format.deserialise(data_s),
813 event_id, 813 event_id,
853 pass 853 pass
854 else: 854 else:
855 rsvp_form = data_form.findForm(rsvp_elt, NS_RSVP) 855 rsvp_form = data_form.findForm(rsvp_elt, NS_RSVP)
856 if rsvp_form is not None: 856 if rsvp_form is not None:
857 data["rsvp"] = rsvp_data = dict(rsvp_form) 857 data["rsvp"] = rsvp_data = dict(rsvp_form)
858 self._a.setTimestamp(rsvp_elt, rsvp_data) 858 self._a.set_timestamp(rsvp_elt, rsvp_data)
859 859
860 def rsvp_set( 860 def rsvp_set(
861 self, 861 self,
862 client: SatXMPPEntity, 862 client: SatXMPPEntity,
863 data: Dict[str, Any], 863 data: Dict[str, Any],
888 item: str, 888 item: str,
889 invitees_s: List[str], 889 invitees_s: List[str],
890 extra: str, 890 extra: str,
891 profile_key: str 891 profile_key: str
892 ) -> defer.Deferred: 892 ) -> defer.Deferred:
893 client = self.host.getClient(profile_key) 893 client = self.host.get_client(profile_key)
894 if invitees_s: 894 if invitees_s:
895 invitees = [jid.JID(i) for i in invitees_s] 895 invitees = [jid.JID(i) for i in invitees_s]
896 else: 896 else:
897 invitees = None 897 invitees = None
898 d = defer.ensureDeferred( 898 d = defer.ensureDeferred(
921 921
922 @param service: PubSub service 922 @param service: PubSub service
923 @param node: PubSub node of the event 923 @param node: PubSub node of the event
924 @param item: PubSub item of the event 924 @param item: PubSub item of the event
925 @param invitees: if set, only retrieve RSVPs from those guests 925 @param invitees: if set, only retrieve RSVPs from those guests
926 @param extra: extra data used to retrieve items as for [getAttachments] 926 @param extra: extra data used to retrieve items as for [get_attachments]
927 @return: mapping of invitee bare JID to their RSVP 927 @return: mapping of invitee bare JID to their RSVP
928 an empty dict is returned if nothing has been answered yed 928 an empty dict is returned if nothing has been answered yed
929 """ 929 """
930 if service is None: 930 if service is None:
931 service = client.jid.userhostJID() 931 service = client.jid.userhostJID()
932 if node is None: 932 if node is None:
933 node = NS_EVENTS 933 node = NS_EVENTS
934 attachments, metadata = await self._a.getAttachments( 934 attachments, metadata = await self._a.get_attachments(
935 client, service, node, item, invitees, extra 935 client, service, node, item, invitees, extra
936 ) 936 )
937 ret = {} 937 ret = {}
938 for attachment in attachments: 938 for attachment in attachments:
939 try: 939 try:
950 node: str, 950 node: str,
951 item: str, 951 item: str,
952 rsvp_s: str, 952 rsvp_s: str,
953 profile_key: str 953 profile_key: str
954 ): 954 ):
955 client = self.host.getClient(profile_key) 955 client = self.host.get_client(profile_key)
956 return defer.ensureDeferred( 956 return defer.ensureDeferred(
957 self.event_invitee_set( 957 self.event_invitee_set(
958 client, 958 client,
959 jid.JID(service) if service else None, 959 jid.JID(service) if service else None,
960 node or None, 960 node or None,
987 "node": node, 987 "node": node,
988 "id": item, 988 "id": item,
989 "extra": {"rsvp": rsvp} 989 "extra": {"rsvp": rsvp}
990 }) 990 })
991 991
992 def _eventInviteesList(self, service, node, profile_key): 992 def _event_invitees_list(self, service, node, profile_key):
993 service = jid.JID(service) if service else None 993 service = jid.JID(service) if service else None
994 node = node if node else NS_EVENT 994 node = node if node else NS_EVENT
995 client = self.host.getClient(profile_key) 995 client = self.host.get_client(profile_key)
996 return defer.ensureDeferred( 996 return defer.ensureDeferred(
997 self.eventInviteesList(client, service, node) 997 self.event_invitees_list(client, service, node)
998 ) 998 )
999 999
1000 async def eventInviteesList(self, client, service, node): 1000 async def event_invitees_list(self, client, service, node):
1001 """Retrieve attendance from event node 1001 """Retrieve attendance from event node
1002 1002
1003 @param service(unicode, None): PubSub service 1003 @param service(unicode, None): PubSub service
1004 @param node(unicode): PubSub node of the event 1004 @param node(unicode): PubSub node of the event
1005 @return (dict): a dict with current attendance status, 1005 @return (dict): a dict with current attendance status,
1006 an empty dict is returned if nothing has been answered yed 1006 an empty dict is returned if nothing has been answered yed
1007 """ 1007 """
1008 items, metadata = await self._p.getItems(client, service, node) 1008 items, metadata = await self._p.get_items(client, service, node)
1009 invitees = {} 1009 invitees = {}
1010 for item in items: 1010 for item in items:
1011 try: 1011 try:
1012 event_elt = next(item.elements(NS_EVENT, "invitee")) 1012 event_elt = next(item.elements(NS_EVENT, "invitee"))
1013 except StopIteration: 1013 except StopIteration:
1023 except KeyError: 1023 except KeyError:
1024 continue 1024 continue
1025 invitees[item["id"]] = data 1025 invitees[item["id"]] = data
1026 return invitees 1026 return invitees
1027 1027
1028 async def invitePreflight( 1028 async def invite_preflight(
1029 self, 1029 self,
1030 client: SatXMPPEntity, 1030 client: SatXMPPEntity,
1031 invitee_jid: jid.JID, 1031 invitee_jid: jid.JID,
1032 service: jid.JID, 1032 service: jid.JID,
1033 node: str, 1033 node: str,
1046 log.debug(_("got event data")) 1046 log.debug(_("got event data"))
1047 invitees_service = jid.JID(event_data["invitees_service"]) 1047 invitees_service = jid.JID(event_data["invitees_service"])
1048 invitees_node = event_data["invitees_node"] 1048 invitees_node = event_data["invitees_node"]
1049 blog_service = jid.JID(event_data["blog_service"]) 1049 blog_service = jid.JID(event_data["blog_service"])
1050 blog_node = event_data["blog_node"] 1050 blog_node = event_data["blog_node"]
1051 await self._p.setNodeAffiliations( 1051 await self._p.set_node_affiliations(
1052 client, invitees_service, invitees_node, {invitee_jid: "publisher"} 1052 client, invitees_service, invitees_node, {invitee_jid: "publisher"}
1053 ) 1053 )
1054 log.debug( 1054 log.debug(
1055 f"affiliation set on invitee node (jid: {invitees_service}, " 1055 f"affiliation set on invitee node (jid: {invitees_service}, "
1056 f"node: {invitees_node!r})" 1056 f"node: {invitees_node!r})"
1057 ) 1057 )
1058 await self._p.setNodeAffiliations( 1058 await self._p.set_node_affiliations(
1059 client, blog_service, blog_node, {invitee_jid: "member"} 1059 client, blog_service, blog_node, {invitee_jid: "member"}
1060 ) 1060 )
1061 blog_items, __ = await self._b.mbGet(client, blog_service, blog_node, None) 1061 blog_items, __ = await self._b.mb_get(client, blog_service, blog_node, None)
1062 1062
1063 for item in blog_items: 1063 for item in blog_items:
1064 try: 1064 try:
1065 comments_service = jid.JID(item["comments_service"]) 1065 comments_service = jid.JID(item["comments_service"])
1066 comments_node = item["comments_node"] 1066 comments_node = item["comments_node"]
1069 "no comment service set for item {item_id}".format( 1069 "no comment service set for item {item_id}".format(
1070 item_id=item["id"] 1070 item_id=item["id"]
1071 ) 1071 )
1072 ) 1072 )
1073 else: 1073 else:
1074 await self._p.setNodeAffiliations( 1074 await self._p.set_node_affiliations(
1075 client, comments_service, comments_node, {invitee_jid: "publisher"} 1075 client, comments_service, comments_node, {invitee_jid: "publisher"}
1076 ) 1076 )
1077 log.debug(_("affiliation set on blog and comments nodes")) 1077 log.debug(_("affiliation set on blog and comments nodes"))
1078 1078
1079 def _invite(self, invitee_jid, service, node, item_id, profile): 1079 def _invite(self, invitee_jid, service, node, item_id, profile):
1080 return self.host.plugins["PUBSUB_INVITATION"]._sendPubsubInvitation( 1080 return self.host.plugins["PUBSUB_INVITATION"]._send_pubsub_invitation(
1081 invitee_jid, service, node, item_id or NS_EVENT, profile_key=profile 1081 invitee_jid, service, node, item_id or NS_EVENT, profile_key=profile
1082 ) 1082 )
1083 1083
1084 def _invite_by_email(self, service, node, id_=NS_EVENT, email="", emails_extra=None, 1084 def _invite_by_email(self, service, node, id_=NS_EVENT, email="", emails_extra=None,
1085 name="", host_name="", language="", url_template="", 1085 name="", host_name="", language="", url_template="",
1086 message_subject="", message_body="", 1086 message_subject="", message_body="",
1087 profile_key=C.PROF_KEY_NONE): 1087 profile_key=C.PROF_KEY_NONE):
1088 client = self.host.getClient(profile_key) 1088 client = self.host.get_client(profile_key)
1089 kwargs = { 1089 kwargs = {
1090 "profile": client.profile, 1090 "profile": client.profile,
1091 "emails_extra": [str(e) for e in emails_extra], 1091 "emails_extra": [str(e) for e in emails_extra],
1092 } 1092 }
1093 for key in ( 1093 for key in (
1119 if self._b is None: 1119 if self._b is None:
1120 raise exceptions.FeatureNotFound( 1120 raise exceptions.FeatureNotFound(
1121 _('"XEP-0277" (blog) plugin is needed for this feature') 1121 _('"XEP-0277" (blog) plugin is needed for this feature')
1122 ) 1122 )
1123 service = service or client.jid.userhostJID() 1123 service = service or client.jid.userhostJID()
1124 event_uri = xmpp_uri.buildXMPPUri( 1124 event_uri = xmpp_uri.build_xmpp_uri(
1125 "pubsub", path=service.full(), node=node, item=id_ 1125 "pubsub", path=service.full(), node=node, item=id_
1126 ) 1126 )
1127 kwargs["extra"] = {"event_uri": event_uri} 1127 kwargs["extra"] = {"event_uri": event_uri}
1128 invitation_data = await self._i.create(**kwargs) 1128 invitation_data = await self._i.create(**kwargs)
1129 invitee_jid = invitation_data["jid"] 1129 invitee_jid = invitation_data["jid"]
1144 event_elt = item_elt.event 1144 event_elt = item_elt.event
1145 link_elt = event_elt.addElement("link") 1145 link_elt = event_elt.addElement("link")
1146 link_elt["service"] = service.full() 1146 link_elt["service"] = service.full()
1147 link_elt["node"] = node 1147 link_elt["node"] = node
1148 link_elt["item"] = item_id 1148 link_elt["item"] = item_id
1149 __, event_data = self._parseEventElt(event_elt) 1149 __, event_data = self._parse_event_elt(event_elt)
1150 try: 1150 try:
1151 name = event_data["name"] 1151 name = event_data["name"]
1152 except KeyError: 1152 except KeyError:
1153 pass 1153 pass
1154 else: 1154 else: