summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2021-02-14 12:00:25 +0100
committermathieui <mathieui@mathieui.net>2021-02-26 00:08:56 +0100
commitab87b2503042ec9cf226574fa68af1b5b9809cc7 (patch)
tree285f4c588de15d37a5d7be361a6d46bc640dfde3
parente24e2f58d4e9c71ef005a4dfe88abac7bff1cc6b (diff)
downloadslixmpp-ab87b2503042ec9cf226574fa68af1b5b9809cc7.tar.gz
slixmpp-ab87b2503042ec9cf226574fa68af1b5b9809cc7.tar.bz2
slixmpp-ab87b2503042ec9cf226574fa68af1b5b9809cc7.tar.xz
slixmpp-ab87b2503042ec9cf226574fa68af1b5b9809cc7.zip
XEP-0153: API changes
-rw-r--r--docs/api/plugins/xep_0153.rst36
-rw-r--r--slixmpp/plugins/xep_0153/vcard_avatar.py57
2 files changed, 63 insertions, 30 deletions
diff --git a/docs/api/plugins/xep_0153.rst b/docs/api/plugins/xep_0153.rst
index 00e22098..bdcbc07c 100644
--- a/docs/api/plugins/xep_0153.rst
+++ b/docs/api/plugins/xep_0153.rst
@@ -9,6 +9,42 @@ XEP-0153: vCard-Based Avatars
:exclude-members: session_bind, plugin_init, plugin_end
+Internal API methods
+--------------------
+
+The internal API is used here to maintain an in-memory JID→avatar hash
+cache.
+
+.. glossary::
+
+ set_hash
+ - **jid**: :class:`~.JID` of whom to retrieve the last activity
+ - **node**: unused
+ - **ifrom**: unused
+ - **args**: ``str``, avatar hash
+
+ Set the avatar hash for a JID.
+
+ reset_hash
+ - **jid**: :class:`~.JID` of whom to retrieve the last activity
+ - **node**: unused
+ - **ifrom**: :class:`~.JID` of the entity requesting the reset.
+ - **args**: unused
+ - **returns**
+ information.
+
+ Reset the avatar hash for a JID. This downloads the vcard and computes
+ the hash.
+
+ get_hash
+ - **jid**: :class:`~.JID` of whom to retrieve the last activity
+ - **node**: unused
+ - **ifrom**: unused
+ - **args**: unused
+ - **returns**: ``Optional[str]``, the avatar hash
+
+ Get the avatar hash for a JID.
+
Stanza elements
---------------
diff --git a/slixmpp/plugins/xep_0153/vcard_avatar.py b/slixmpp/plugins/xep_0153/vcard_avatar.py
index 56bf899a..e2d98b0a 100644
--- a/slixmpp/plugins/xep_0153/vcard_avatar.py
+++ b/slixmpp/plugins/xep_0153/vcard_avatar.py
@@ -5,7 +5,7 @@
# See the file LICENSE for copying permission.
import hashlib
import logging
-from asyncio import Future, ensure_future
+from asyncio import Future
from typing import (
Dict,
Optional,
@@ -13,7 +13,7 @@ from typing import (
from slixmpp import JID
from slixmpp.stanza import Presence
-from slixmpp.exceptions import XMPPError, IqTimeout
+from slixmpp.exceptions import XMPPError, IqTimeout, IqError
from slixmpp.xmlstream import register_stanza_plugin, ElementBase
from slixmpp.plugins.base import BasePlugin
from slixmpp.plugins.xep_0153 import stanza, VCardTempUpdate
@@ -59,7 +59,6 @@ class XEP_0153(BasePlugin):
self.xmpp.del_event_handler('presence_chat', self._recv_presence)
self.xmpp.del_event_handler('presence_away', self._recv_presence)
- @future_wrapper
def set_avatar(self, jid: Optional[JID] = None,
avatar: Optional[bytes] = None,
mtype: Optional[str] = None, **iqkwargs) -> Future:
@@ -97,10 +96,10 @@ class XEP_0153(BasePlugin):
except IqTimeout as exc:
timeout_cb(exc)
raise
- self.api['reset_hash'](jid)
+ await self.api['reset_hash'](jid)
self.xmpp.roster[jid].send_last_presence()
- return ensure_future(get_and_set_avatar(), loop=self.xmpp.loop)
+ return self.xmpp.wrap(get_and_set_avatar())
async def _start(self, event):
try:
@@ -110,22 +109,22 @@ class XEP_0153(BasePlugin):
new_hash = ''
else:
new_hash = hashlib.sha1(data).hexdigest()
- self.api['set_hash'](self.xmpp.boundjid, args=new_hash)
+ await self.api['set_hash'](self.xmpp.boundjid, args=new_hash)
except XMPPError:
log.debug('Could not retrieve vCard for %s', self.xmpp.boundjid.bare)
- def _update_presence(self, stanza: ElementBase) -> ElementBase:
+ async def _update_presence(self, stanza: ElementBase) -> ElementBase:
if not isinstance(stanza, Presence):
return stanza
if stanza['type'] not in ('available', 'dnd', 'chat', 'away', 'xa'):
return stanza
- current_hash = self.api['get_hash'](stanza['from'])
+ current_hash = await self.api['get_hash'](stanza['from'])
stanza['vcard_temp_update']['photo'] = current_hash
return stanza
- def _recv_presence(self, pres: Presence):
+ async def _recv_presence(self, pres: Presence):
try:
if pres.get_plugin('muc', check=True):
# Don't process vCard avatars for MUC occupants
@@ -135,7 +134,7 @@ class XEP_0153(BasePlugin):
pass
if not pres.match('presence/vcard_temp_update'):
- self.api['set_hash'](pres['from'], args=None)
+ await self.api['set_hash'](pres['from'], args=None)
return
data = pres['vcard_temp_update']['photo']
@@ -145,33 +144,31 @@ class XEP_0153(BasePlugin):
# =================================================================
- def _reset_hash(self, jid: JID, node: str, ifrom: JID, args: Dict):
+ async def _reset_hash(self, jid: JID, node: str, ifrom: JID, args: Dict):
own_jid = (jid.bare == self.xmpp.boundjid.bare)
if self.xmpp.is_component:
own_jid = (jid.domain == self.xmpp.boundjid.domain)
- self.api['set_hash'](jid, args=None)
+ await self.api['set_hash'](jid, args=None)
if own_jid:
self.xmpp.roster[jid].send_last_presence()
- def callback(iq):
- if iq['type'] == 'error':
- log.debug('Could not retrieve vCard for %s', jid)
- return
- try:
- data = iq['vcard_temp']['PHOTO']['BINVAL']
- except ValueError:
- log.debug('Invalid BINVAL in vCard’s PHOTO for %s:', jid, exc_info=True)
- data = None
- if not data:
- new_hash = ''
- else:
- new_hash = hashlib.sha1(data).hexdigest()
-
- self.api['set_hash'](jid, args=new_hash)
-
- self.xmpp['xep_0054'].get_vcard(jid=jid.bare, ifrom=ifrom,
- callback=callback)
+ try:
+ iq = await self.xmpp['xep_0054'].get_vcard(jid=jid.bare, ifrom=ifrom)
+ except (IqError, IqTimeout):
+ log.debug('Could not retrieve vCard for %s', jid)
+ return
+ try:
+ data = iq['vcard_temp']['PHOTO']['BINVAL']
+ except ValueError:
+ log.debug('Invalid BINVAL in vCard’s PHOTO for %s:', jid, exc_info=True)
+ data = None
+ if not data:
+ new_hash = ''
+ else:
+ new_hash = hashlib.sha1(data).hexdigest()
+
+ await self.api['set_hash'](jid, args=new_hash)
def _get_hash(self, jid: JID, node: str, ifrom: JID, args: Dict):
return self._hashes.get(jid.bare, None)