XEP-0231: API changes
- ``get_bob`` and ``set_bob`` are now coroutines. - ``del_bob`` returns a Future.
This commit is contained in:
parent
ab87b25030
commit
9947d3db85
3 changed files with 64 additions and 22 deletions
|
@ -9,6 +9,40 @@ XEP-0231: Bits of Binary
|
||||||
:exclude-members: session_bind, plugin_init, plugin_end
|
:exclude-members: session_bind, plugin_init, plugin_end
|
||||||
|
|
||||||
|
|
||||||
|
Internal API methods
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The default API handlers for this plugin manage an in-memory cache of
|
||||||
|
bits of binary by content-id.
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
set_bob
|
||||||
|
- **jid**: :class:`~.JID` sending the bob
|
||||||
|
- **node**: unused
|
||||||
|
- **ifrom**: :class:`~JID` receiving the bob
|
||||||
|
- **args**: :class:`~.BitsOfBinary` element.
|
||||||
|
|
||||||
|
Set a BoB in the cache.
|
||||||
|
|
||||||
|
get_bob
|
||||||
|
- **jid**: :class:`~.JID` receiving the bob
|
||||||
|
- **node**: unused
|
||||||
|
- **ifrom**: :class:`~JID` sending the bob
|
||||||
|
- **args**: ``str`` content-id of the bob
|
||||||
|
- **returns**: :class:`~.BitsOfBinary` element.
|
||||||
|
|
||||||
|
Get a BoB from the cache.
|
||||||
|
|
||||||
|
del_bob
|
||||||
|
- **jid**: unused
|
||||||
|
- **node**: unused
|
||||||
|
- **ifrom**: :class:`~JID` sending the bob
|
||||||
|
- **args**: ``str`` content-id of the bob
|
||||||
|
|
||||||
|
Delete a BoB from the cache.
|
||||||
|
|
||||||
|
|
||||||
Stanza elements
|
Stanza elements
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ class TestBOB(SlixIntegration):
|
||||||
|
|
||||||
async def test_bob(self):
|
async def test_bob(self):
|
||||||
"""Check we can send and receive a BOB."""
|
"""Check we can send and receive a BOB."""
|
||||||
cid = self.clients[0]['xep_0231'].set_bob(
|
cid = await self.clients[0]['xep_0231'].set_bob(
|
||||||
self.data,
|
self.data,
|
||||||
'image/jpeg',
|
'image/jpeg',
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,7 +12,7 @@ from typing import Optional
|
||||||
from slixmpp import future_wrapper, JID
|
from slixmpp import future_wrapper, JID
|
||||||
from slixmpp.stanza import Iq, Message, Presence
|
from slixmpp.stanza import Iq, Message, Presence
|
||||||
from slixmpp.exceptions import XMPPError
|
from slixmpp.exceptions import XMPPError
|
||||||
from slixmpp.xmlstream.handler import Callback
|
from slixmpp.xmlstream.handler import CoroutineCallback
|
||||||
from slixmpp.xmlstream.matcher import StanzaPath
|
from slixmpp.xmlstream.matcher import StanzaPath
|
||||||
from slixmpp.xmlstream import register_stanza_plugin
|
from slixmpp.xmlstream import register_stanza_plugin
|
||||||
from slixmpp.plugins.base import BasePlugin
|
from slixmpp.plugins.base import BasePlugin
|
||||||
|
@ -40,17 +40,17 @@ class XEP_0231(BasePlugin):
|
||||||
register_stanza_plugin(Presence, BitsOfBinary)
|
register_stanza_plugin(Presence, BitsOfBinary)
|
||||||
|
|
||||||
self.xmpp.register_handler(
|
self.xmpp.register_handler(
|
||||||
Callback('Bits of Binary - Iq',
|
CoroutineCallback('Bits of Binary - Iq',
|
||||||
StanzaPath('iq/bob'),
|
StanzaPath('iq/bob'),
|
||||||
self._handle_bob_iq))
|
self._handle_bob_iq))
|
||||||
|
|
||||||
self.xmpp.register_handler(
|
self.xmpp.register_handler(
|
||||||
Callback('Bits of Binary - Message',
|
CoroutineCallback('Bits of Binary - Message',
|
||||||
StanzaPath('message/bob'),
|
StanzaPath('message/bob'),
|
||||||
self._handle_bob))
|
self._handle_bob))
|
||||||
|
|
||||||
self.xmpp.register_handler(
|
self.xmpp.register_handler(
|
||||||
Callback('Bits of Binary - Presence',
|
CoroutineCallback('Bits of Binary - Presence',
|
||||||
StanzaPath('presence/bob'),
|
StanzaPath('presence/bob'),
|
||||||
self._handle_bob))
|
self._handle_bob))
|
||||||
|
|
||||||
|
@ -67,13 +67,14 @@ class XEP_0231(BasePlugin):
|
||||||
def session_bind(self, jid):
|
def session_bind(self, jid):
|
||||||
self.xmpp['xep_0030'].add_feature('urn:xmpp:bob')
|
self.xmpp['xep_0030'].add_feature('urn:xmpp:bob')
|
||||||
|
|
||||||
def set_bob(self, data: bytes, mtype: str, cid: Optional[str] = None,
|
async def set_bob(self, data: bytes, mtype: str, cid: Optional[str] = None,
|
||||||
max_age: Optional[int] = None) -> str:
|
max_age: Optional[int] = None) -> str:
|
||||||
"""Register a blob of binary data as a BOB.
|
"""Register a blob of binary data as a BOB.
|
||||||
|
|
||||||
.. versionchanged:: 1.8.0
|
.. versionchanged:: 1.8.0
|
||||||
If ``max_age`` is specified, the registered data will be destroyed
|
If ``max_age`` is specified, the registered data will be destroyed
|
||||||
after that time.
|
after that time.
|
||||||
|
This function is now a coroutine.
|
||||||
|
|
||||||
:param data: Data to register.
|
:param data: Data to register.
|
||||||
:param mtype: Mime Type of the data (e.g. ``image/jpeg``).
|
:param mtype: Mime Type of the data (e.g. ``image/jpeg``).
|
||||||
|
@ -90,27 +91,27 @@ class XEP_0231(BasePlugin):
|
||||||
bob['cid'] = cid
|
bob['cid'] = cid
|
||||||
bob['max_age'] = max_age
|
bob['max_age'] = max_age
|
||||||
|
|
||||||
self.api['set_bob'](args=bob)
|
await self.api['set_bob'](args=bob)
|
||||||
# Schedule destruction of the data
|
# Schedule destruction of the data
|
||||||
if max_age is not None and max_age > 0:
|
if max_age is not None and max_age > 0:
|
||||||
self.xmpp.loop.call_later(max_age, self.del_bob, cid)
|
self.xmpp.loop.call_later(max_age, self.del_bob, cid)
|
||||||
return cid
|
return cid
|
||||||
|
|
||||||
@future_wrapper
|
async def get_bob(self, jid: Optional[JID] = None, cid: Optional[str] = None,
|
||||||
def get_bob(self, jid: Optional[JID] = None, cid: Optional[str] = None,
|
|
||||||
cached: bool = True, ifrom: Optional[JID] = None,
|
cached: bool = True, ifrom: Optional[JID] = None,
|
||||||
**iqkwargs) -> Future:
|
**iqkwargs) -> Iq:
|
||||||
"""Get a BOB.
|
"""Get a BOB.
|
||||||
|
|
||||||
.. versionchanged:: 1.8.0
|
.. versionchanged:: 1.8.0
|
||||||
Results not in cache do not raise an error when ``cached`` is True.
|
Results not in cache do not raise an error when ``cached`` is True.
|
||||||
|
This function is now a coroutine.
|
||||||
|
|
||||||
:param jid: JID to fetch the BOB from.
|
:param jid: JID to fetch the BOB from.
|
||||||
:param cid: Content ID (actually required).
|
:param cid: Content ID (actually required).
|
||||||
:param cached: To fetch the BOB from the local cache first (from CID only)
|
:param cached: To fetch the BOB from the local cache first (from CID only)
|
||||||
"""
|
"""
|
||||||
if cached:
|
if cached:
|
||||||
data = self.api['get_bob'](None, None, ifrom, args=cid)
|
data = await self.api['get_bob'](None, None, ifrom, args=cid)
|
||||||
if data is not None:
|
if data is not None:
|
||||||
if not isinstance(data, Iq):
|
if not isinstance(data, Iq):
|
||||||
iq = self.xmpp.Iq()
|
iq = self.xmpp.Iq()
|
||||||
|
@ -120,19 +121,24 @@ class XEP_0231(BasePlugin):
|
||||||
|
|
||||||
iq = self.xmpp.make_iq_get(ito=jid, ifrom=ifrom)
|
iq = self.xmpp.make_iq_get(ito=jid, ifrom=ifrom)
|
||||||
iq['bob']['cid'] = cid
|
iq['bob']['cid'] = cid
|
||||||
return iq.send(**iqkwargs)
|
return await iq.send(**iqkwargs)
|
||||||
|
|
||||||
def del_bob(self, cid: str):
|
def del_bob(self, cid: str) -> Future:
|
||||||
self.api['del_bob'](args=cid)
|
"""Delete a stored BoB.
|
||||||
|
|
||||||
def _handle_bob_iq(self, iq: Iq):
|
.. versionchanged:: 1.8.0
|
||||||
|
This function now returns a Future.
|
||||||
|
"""
|
||||||
|
return self.api['del_bob'](args=cid)
|
||||||
|
|
||||||
|
async def _handle_bob_iq(self, iq: Iq):
|
||||||
cid = iq['bob']['cid']
|
cid = iq['bob']['cid']
|
||||||
|
|
||||||
if iq['type'] == 'result':
|
if iq['type'] == 'result':
|
||||||
self.api['set_bob'](iq['from'], None, iq['to'], args=iq['bob'])
|
await self.api['set_bob'](iq['from'], None, iq['to'], args=iq['bob'])
|
||||||
self.xmpp.event('bob', iq)
|
self.xmpp.event('bob', iq)
|
||||||
elif iq['type'] == 'get':
|
elif iq['type'] == 'get':
|
||||||
data = self.api['get_bob'](iq['to'], None, iq['from'], args=cid)
|
data = await self.api['get_bob'](iq['to'], None, iq['from'], args=cid)
|
||||||
if isinstance(data, Iq):
|
if isinstance(data, Iq):
|
||||||
data['id'] = iq['id']
|
data['id'] = iq['id']
|
||||||
data.send()
|
data.send()
|
||||||
|
@ -142,9 +148,11 @@ class XEP_0231(BasePlugin):
|
||||||
iq.append(data)
|
iq.append(data)
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
def _handle_bob(self, stanza):
|
async def _handle_bob(self, stanza):
|
||||||
self.api['set_bob'](stanza['from'], None,
|
await self.api['set_bob'](
|
||||||
stanza['to'], args=stanza['bob'])
|
stanza['from'], None,
|
||||||
|
stanza['to'], args=stanza['bob']
|
||||||
|
)
|
||||||
self.xmpp.event('bob', stanza)
|
self.xmpp.event('bob', stanza)
|
||||||
|
|
||||||
# =================================================================
|
# =================================================================
|
||||||
|
|
Loading…
Reference in a new issue