XEP-0153: API changes
This commit is contained in:
parent
e24e2f58d4
commit
ab87b25030
@ -9,6 +9,42 @@ XEP-0153: vCard-Based Avatars
|
|||||||
:exclude-members: session_bind, plugin_init, plugin_end
|
: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
|
Stanza elements
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
# See the file LICENSE for copying permission.
|
# See the file LICENSE for copying permission.
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
from asyncio import Future, ensure_future
|
from asyncio import Future
|
||||||
from typing import (
|
from typing import (
|
||||||
Dict,
|
Dict,
|
||||||
Optional,
|
Optional,
|
||||||
@ -13,7 +13,7 @@ from typing import (
|
|||||||
|
|
||||||
from slixmpp import JID
|
from slixmpp import JID
|
||||||
from slixmpp.stanza import Presence
|
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.xmlstream import register_stanza_plugin, ElementBase
|
||||||
from slixmpp.plugins.base import BasePlugin
|
from slixmpp.plugins.base import BasePlugin
|
||||||
from slixmpp.plugins.xep_0153 import stanza, VCardTempUpdate
|
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_chat', self._recv_presence)
|
||||||
self.xmpp.del_event_handler('presence_away', self._recv_presence)
|
self.xmpp.del_event_handler('presence_away', self._recv_presence)
|
||||||
|
|
||||||
@future_wrapper
|
|
||||||
def set_avatar(self, jid: Optional[JID] = None,
|
def set_avatar(self, jid: Optional[JID] = None,
|
||||||
avatar: Optional[bytes] = None,
|
avatar: Optional[bytes] = None,
|
||||||
mtype: Optional[str] = None, **iqkwargs) -> Future:
|
mtype: Optional[str] = None, **iqkwargs) -> Future:
|
||||||
@ -97,10 +96,10 @@ class XEP_0153(BasePlugin):
|
|||||||
except IqTimeout as exc:
|
except IqTimeout as exc:
|
||||||
timeout_cb(exc)
|
timeout_cb(exc)
|
||||||
raise
|
raise
|
||||||
self.api['reset_hash'](jid)
|
await self.api['reset_hash'](jid)
|
||||||
self.xmpp.roster[jid].send_last_presence()
|
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):
|
async def _start(self, event):
|
||||||
try:
|
try:
|
||||||
@ -110,22 +109,22 @@ class XEP_0153(BasePlugin):
|
|||||||
new_hash = ''
|
new_hash = ''
|
||||||
else:
|
else:
|
||||||
new_hash = hashlib.sha1(data).hexdigest()
|
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:
|
except XMPPError:
|
||||||
log.debug('Could not retrieve vCard for %s', self.xmpp.boundjid.bare)
|
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):
|
if not isinstance(stanza, Presence):
|
||||||
return stanza
|
return stanza
|
||||||
|
|
||||||
if stanza['type'] not in ('available', 'dnd', 'chat', 'away', 'xa'):
|
if stanza['type'] not in ('available', 'dnd', 'chat', 'away', 'xa'):
|
||||||
return stanza
|
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
|
stanza['vcard_temp_update']['photo'] = current_hash
|
||||||
return stanza
|
return stanza
|
||||||
|
|
||||||
def _recv_presence(self, pres: Presence):
|
async def _recv_presence(self, pres: Presence):
|
||||||
try:
|
try:
|
||||||
if pres.get_plugin('muc', check=True):
|
if pres.get_plugin('muc', check=True):
|
||||||
# Don't process vCard avatars for MUC occupants
|
# Don't process vCard avatars for MUC occupants
|
||||||
@ -135,7 +134,7 @@ class XEP_0153(BasePlugin):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if not pres.match('presence/vcard_temp_update'):
|
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
|
return
|
||||||
|
|
||||||
data = pres['vcard_temp_update']['photo']
|
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)
|
own_jid = (jid.bare == self.xmpp.boundjid.bare)
|
||||||
if self.xmpp.is_component:
|
if self.xmpp.is_component:
|
||||||
own_jid = (jid.domain == self.xmpp.boundjid.domain)
|
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:
|
if own_jid:
|
||||||
self.xmpp.roster[jid].send_last_presence()
|
self.xmpp.roster[jid].send_last_presence()
|
||||||
|
|
||||||
def callback(iq):
|
try:
|
||||||
if iq['type'] == 'error':
|
iq = await self.xmpp['xep_0054'].get_vcard(jid=jid.bare, ifrom=ifrom)
|
||||||
log.debug('Could not retrieve vCard for %s', jid)
|
except (IqError, IqTimeout):
|
||||||
return
|
log.debug('Could not retrieve vCard for %s', jid)
|
||||||
try:
|
return
|
||||||
data = iq['vcard_temp']['PHOTO']['BINVAL']
|
try:
|
||||||
except ValueError:
|
data = iq['vcard_temp']['PHOTO']['BINVAL']
|
||||||
log.debug('Invalid BINVAL in vCard’s PHOTO for %s:', jid, exc_info=True)
|
except ValueError:
|
||||||
data = None
|
log.debug('Invalid BINVAL in vCard’s PHOTO for %s:', jid, exc_info=True)
|
||||||
if not data:
|
data = None
|
||||||
new_hash = ''
|
if not data:
|
||||||
else:
|
new_hash = ''
|
||||||
new_hash = hashlib.sha1(data).hexdigest()
|
else:
|
||||||
|
new_hash = hashlib.sha1(data).hexdigest()
|
||||||
|
|
||||||
self.api['set_hash'](jid, args=new_hash)
|
await self.api['set_hash'](jid, args=new_hash)
|
||||||
|
|
||||||
self.xmpp['xep_0054'].get_vcard(jid=jid.bare, ifrom=ifrom,
|
|
||||||
callback=callback)
|
|
||||||
|
|
||||||
def _get_hash(self, jid: JID, node: str, ifrom: JID, args: Dict):
|
def _get_hash(self, jid: JID, node: str, ifrom: JID, args: Dict):
|
||||||
return self._hashes.get(jid.bare, None)
|
return self._hashes.get(jid.bare, None)
|
||||||
|
Loading…
Reference in New Issue
Block a user