comparison libervia/backend/plugins/plugin_xep_0084.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
comparison
equal deleted inserted replaced
4269:64a85ce8be70 4270:0d7bb4df2343
63 log.info(_("XEP-0084 (User Avatar) plugin initialization")) 63 log.info(_("XEP-0084 (User Avatar) plugin initialization"))
64 host.register_namespace("avatar_metadata", NS_AVATAR_METADATA) 64 host.register_namespace("avatar_metadata", NS_AVATAR_METADATA)
65 host.register_namespace("avatar_data", NS_AVATAR_DATA) 65 host.register_namespace("avatar_data", NS_AVATAR_DATA)
66 self.host = host 66 self.host = host
67 self._p = host.plugins["XEP-0060"] 67 self._p = host.plugins["XEP-0060"]
68 self._i = host.plugins['IDENTITY'] 68 self._i = host.plugins["IDENTITY"]
69 self._i.register( 69 self._i.register(
70 IMPORT_NAME, 70 IMPORT_NAME, "avatar", self.get_avatar, self.set_avatar, priority=2000
71 "avatar",
72 self.get_avatar,
73 self.set_avatar,
74 priority=2000
75 ) 71 )
76 host.plugins["XEP-0163"].add_pep_event( 72 host.plugins["XEP-0163"].add_pep_event(
77 None, NS_AVATAR_METADATA, self._on_metadata_update 73 None, NS_AVATAR_METADATA, self._on_metadata_update
78 ) 74 )
79 75
83 def _on_metadata_update(self, itemsEvent, profile): 79 def _on_metadata_update(self, itemsEvent, profile):
84 client = self.host.get_client(profile) 80 client = self.host.get_client(profile)
85 defer.ensureDeferred(self.on_metadata_update(client, itemsEvent)) 81 defer.ensureDeferred(self.on_metadata_update(client, itemsEvent))
86 82
87 async def on_metadata_update( 83 async def on_metadata_update(
88 self, 84 self, client: SatXMPPEntity, itemsEvent: pubsub.ItemsEvent
89 client: SatXMPPEntity,
90 itemsEvent: pubsub.ItemsEvent
91 ) -> None: 85 ) -> None:
92 entity = client.jid.userhostJID() 86 entity = client.jid.userhostJID()
93 avatar_metadata = await self.get_avatar(client, entity) 87 avatar_metadata = await self.get_avatar(client, entity)
94 await self._i.update(client, IMPORT_NAME, "avatar", avatar_metadata, entity) 88 await self._i.update(client, IMPORT_NAME, "avatar", avatar_metadata, entity)
95 89
96 async def get_avatar( 90 async def get_avatar(
97 self, 91 self, client: SatXMPPEntity, entity_jid: jid.JID
98 client: SatXMPPEntity, 92 ) -> Optional[dict]:
99 entity_jid: jid.JID
100 ) -> Optional[dict]:
101 """Get avatar data 93 """Get avatar data
102 94
103 @param entity: entity to get avatar from 95 @param entity: entity to get avatar from
104 @return: avatar metadata, or None if no avatar has been found 96 @return: avatar metadata, or None if no avatar has been found
105 """ 97 """
106 service = entity_jid.userhostJID() 98 service = entity_jid.userhostJID()
107 # metadata 99 # metadata
108 try: 100 try:
109 items, __ = await self._p.get_items( 101 items, __ = await self._p.get_items(
110 client, 102 client, service, NS_AVATAR_METADATA, max_items=1
111 service,
112 NS_AVATAR_METADATA,
113 max_items=1
114 ) 103 )
115 except exceptions.NotFound: 104 except exceptions.NotFound:
116 return None 105 return None
117 106
118 if not items: 107 if not items:
128 for info_elt in metadata_elt.elements(NS_AVATAR_METADATA, "info"): 117 for info_elt in metadata_elt.elements(NS_AVATAR_METADATA, "info"):
129 try: 118 try:
130 metadata = { 119 metadata = {
131 "id": str(info_elt["id"]), 120 "id": str(info_elt["id"]),
132 "size": int(info_elt["bytes"]), 121 "size": int(info_elt["bytes"]),
133 "media_type": str(info_elt["type"]) 122 "media_type": str(info_elt["type"]),
134 } 123 }
135 avatar_id = metadata["id"] 124 avatar_id = metadata["id"]
136 if not avatar_id: 125 if not avatar_id:
137 raise ValueError 126 raise ValueError
138 except (KeyError, ValueError): 127 except (KeyError, ValueError):
148 137
149 cache_data = self.host.common_cache.get_metadata(avatar_id) 138 cache_data = self.host.common_cache.get_metadata(avatar_id)
150 if not cache_data: 139 if not cache_data:
151 try: 140 try:
152 data_items, __ = await self._p.get_items( 141 data_items, __ = await self._p.get_items(
153 client, 142 client, service, NS_AVATAR_DATA, item_ids=[avatar_id]
154 service,
155 NS_AVATAR_DATA,
156 item_ids=[avatar_id]
157 ) 143 )
158 data_item_elt = data_items[0] 144 data_item_elt = data_items[0]
159 except (error.StanzaError, IndexError) as e: 145 except (error.StanzaError, IndexError) as e:
160 log.warning( 146 log.warning(
161 f"Can't retrieve avatar of {service.full()} with ID {avatar_id!r}: " 147 f"Can't retrieve avatar of {service.full()} with ID {avatar_id!r}: "
171 f"invalid data element for {service.full()} with avatar ID " 157 f"invalid data element for {service.full()} with avatar ID "
172 f"{avatar_id!r}: {e}\n{data_item_elt.toXml()}" 158 f"{avatar_id!r}: {e}\n{data_item_elt.toXml()}"
173 ) 159 )
174 return None 160 return None
175 with self.host.common_cache.cache_data( 161 with self.host.common_cache.cache_data(
176 IMPORT_NAME, 162 IMPORT_NAME, avatar_id, metadata["media_type"]
177 avatar_id,
178 metadata["media_type"]
179 ) as f: 163 ) as f:
180 f.write(avatar_buf) 164 f.write(avatar_buf)
181 cache_data = { 165 cache_data = {"path": Path(f.name), "mime_type": metadata["media_type"]}
182 "path": Path(f.name),
183 "mime_type": metadata["media_type"]
184 }
185 166
186 return self._i.avatar_build_metadata( 167 return self._i.avatar_build_metadata(
187 cache_data['path'], cache_data['mime_type'], avatar_id 168 cache_data["path"], cache_data["mime_type"], avatar_id
188 ) 169 )
189 170
190 def build_item_data_elt(self, avatar_data: Dict[str, Any]) -> domish.Element: 171 def build_item_data_elt(self, avatar_data: Dict[str, Any]) -> domish.Element:
191 """Generate the item for the data node 172 """Generate the item for the data node
192 173
211 info_elt["type"] = avatar_data["media_type"] 192 info_elt["type"] = avatar_data["media_type"]
212 info_elt["bytes"] = str(avatar_data["path"].stat().st_size) 193 info_elt["bytes"] = str(avatar_data["path"].stat().st_size)
213 return pubsub.Item(id=self._p.ID_SINGLETON, payload=metadata_elt) 194 return pubsub.Item(id=self._p.ID_SINGLETON, payload=metadata_elt)
214 195
215 async def set_avatar( 196 async def set_avatar(
216 self, 197 self, client: SatXMPPEntity, avatar_data: Dict[str, Any], entity: jid.JID
217 client: SatXMPPEntity,
218 avatar_data: Dict[str, Any],
219 entity: jid.JID
220 ) -> None: 198 ) -> None:
221 """Set avatar of the profile 199 """Set avatar of the profile
222 200
223 @param avatar_data(dict): data of the image to use as avatar, as built by 201 @param avatar_data(dict): data of the image to use as avatar, as built by
224 IDENTITY plugin. 202 IDENTITY plugin.
233 NS_AVATAR_DATA, 211 NS_AVATAR_DATA,
234 options={ 212 options={
235 self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN, 213 self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN,
236 self._p.OPT_PERSIST_ITEMS: 1, 214 self._p.OPT_PERSIST_ITEMS: 1,
237 self._p.OPT_MAX_ITEMS: 1, 215 self._p.OPT_MAX_ITEMS: 1,
238 } 216 },
239 ) 217 )
240 item_data_elt = self.build_item_data_elt(avatar_data) 218 item_data_elt = self.build_item_data_elt(avatar_data)
241 await self._p.send_items(client, service, NS_AVATAR_DATA, [item_data_elt]) 219 await self._p.send_items(client, service, NS_AVATAR_DATA, [item_data_elt])
242 220
243 # Metadata 221 # Metadata
247 NS_AVATAR_METADATA, 225 NS_AVATAR_METADATA,
248 options={ 226 options={
249 self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN, 227 self._p.OPT_ACCESS_MODEL: self._p.ACCESS_OPEN,
250 self._p.OPT_PERSIST_ITEMS: 1, 228 self._p.OPT_PERSIST_ITEMS: 1,
251 self._p.OPT_MAX_ITEMS: 1, 229 self._p.OPT_MAX_ITEMS: 1,
252 } 230 },
253 ) 231 )
254 item_metadata_elt = self.build_item_metadata_elt(avatar_data) 232 item_metadata_elt = self.build_item_metadata_elt(avatar_data)
255 await self._p.send_items(client, service, NS_AVATAR_METADATA, [item_metadata_elt]) 233 await self._p.send_items(client, service, NS_AVATAR_METADATA, [item_metadata_elt])
256 234
257 235
259 class XEP_0084_Handler(XMPPHandler): 237 class XEP_0084_Handler(XMPPHandler):
260 238
261 def getDiscoInfo(self, requestor, service, nodeIdentifier=""): 239 def getDiscoInfo(self, requestor, service, nodeIdentifier=""):
262 return [ 240 return [
263 disco.DiscoFeature(NS_AVATAR_METADATA), 241 disco.DiscoFeature(NS_AVATAR_METADATA),
264 disco.DiscoFeature(NS_AVATAR_DATA) 242 disco.DiscoFeature(NS_AVATAR_DATA),
265 ] 243 ]
266 244
267 def getDiscoItems(self, requestor, service, nodeIdentifier=""): 245 def getDiscoItems(self, requestor, service, nodeIdentifier=""):
268 return [] 246 return []