Merge branch 'more-xeps' into 'master'

Add a batch of newer XEPs

See merge request poezio/slixmpp!69
This commit is contained in:
Link Mauve 2020-12-04 20:03:32 +01:00
commit 05749c4969
24 changed files with 815 additions and 6 deletions

View file

@ -506,6 +506,13 @@
<xmpp:status>unknown</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0359.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0332.html"/>
@ -521,7 +528,14 @@
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:supportedxep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0359.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:supportedxep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0363.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:version>1.0.0</xmpp:version>
@ -531,7 +545,8 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0369.html"/>
<xmpp:status>unknown</xmpp:status>
<xmpp:status>partial</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
@ -543,19 +558,22 @@
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0403.html"/>
<xmpp:status>unknown</xmpp:status>
<xmpp:status>partial</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0404.html"/>
<xmpp:status>unknown</xmpp:status>
<xmpp:status>partial</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0405.html"/>
<xmpp:status>unknown</xmpp:status>
<xmpp:status>partial</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
@ -564,10 +582,47 @@
<xmpp:status>unknown</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0422.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0424.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0425.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0428.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0439.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:since>NEXT</xmpp:since>
<xmpp:vaersion>0.1.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0444.html"/>
<xmpp:status>unknown</xmpp:status>
<xmpp:status>complete</xmpp:status>
<xmpp:since>0.1.0</xmpp:since>
</xmpp:SupportedXep>
</implements>

View file

@ -86,6 +86,7 @@ __all__ = [
'xep_0325', # IoT Systems Control
'xep_0332', # HTTP Over XMPP Transport
'xep_0353', # Jingle Message Initiation
'xep_0359', # Unique and Stable Stanza IDs
'xep_0363', # HTTP File Upload
'xep_0369', # MIX-CORE
'xep_0377', # Spam reporting
@ -93,5 +94,10 @@ __all__ = [
'xep_0404', # MIX-Anon
'xep_0405', # MIX-PAM
'xep_0421', # Anonymous unique occupant identifiers for MUCs
'xep_0422', # Message Fastening
'xep_0424', # Message Retraction
'xep_0425', # Message Moderation
'xep_0428', # Message Fallback
'xep_0439', # Quick Response
'xep_0444', # Message Reactions
]

View file

@ -0,0 +1,13 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.base import register_plugin
from slixmpp.plugins.xep_0359.stanza import *
from slixmpp.plugins.xep_0359.stanzaid import XEP_0359
register_plugin(XEP_0359)

View file

@ -0,0 +1,35 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permissio
"""
from slixmpp.stanza import Message
from slixmpp.xmlstream import (
ElementBase,
register_stanza_plugin,
)
NS = 'urn:xmpp:sid:0'
class StanzaID(ElementBase):
namespace = NS
name = 'stanza-id'
plugin_attrib = 'stanza_id'
interfaces = {'id', 'by'}
class OriginID(ElementBase):
namespace = NS
name = 'origin-id'
plugin_attrib = 'origin_id'
interfaces = {'id'}
def register_plugins():
register_stanza_plugin(Message, StanzaID)
register_stanza_plugin(Message, OriginID)

View file

@ -0,0 +1,22 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.xep_0359 import stanza
class XEP_0359(BasePlugin):
'''XEP-0359: Unique and Stable Stanza IDs'''
name = 'xep_0359'
description = 'Unique and Stable Stanza IDs'
dependencies = set()
stanza = stanza
namespace = stanza.NS
def plugin_init(self) -> None:
stanza.register_plugins()

View file

@ -0,0 +1,13 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.base import register_plugin
from slixmpp.plugins.xep_0422.stanza import *
from slixmpp.plugins.xep_0422.fastening import XEP_0422
register_plugin(XEP_0422)

View file

@ -0,0 +1,28 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.xep_0422 import stanza
class XEP_0422(BasePlugin):
'''XEP-0422: Message Fastening'''
name = 'xep_0422'
description = 'Message Fastening'
dependencies = {'xep_0030'}
stanza = stanza
namespace = stanza.NS
def plugin_init(self) -> None:
stanza.register_plugins()
def session_bind(self, jid):
self.xmpp.plugin['xep_0030'].add_feature(feature=stanza.NS)
def plugin_end(self):
self.xmpp.plugin['xep_0030'].del_feature(feature=stanza.NS)

View file

@ -0,0 +1,42 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permissio
"""
from slixmpp.stanza import Message
from slixmpp.xmlstream import (
ElementBase,
register_stanza_plugin,
)
NS = 'urn:xmpp:fasten:0'
class ApplyTo(ElementBase):
namespace = NS
name = 'apply-to'
plugin_attrib = 'apply_to'
interfaces = {'id', 'shell'}
def set_shell(self, value: bool):
if value:
self.xml.attrib['shell'] = str(value).lower()
else:
if 'shell' in self.xml.attrib:
del self.xml.attrib['shell']
class External(ElementBase):
namespace = NS
name = 'external'
plugin_attrib = 'external'
interfaces = {'name'}
def register_plugins():
register_stanza_plugin(Message, ApplyTo)
register_stanza_plugin(ApplyTo, External)

View file

@ -0,0 +1,13 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.base import register_plugin
from slixmpp.plugins.xep_0424.stanza import *
from slixmpp.plugins.xep_0424.retraction import XEP_0424
register_plugin(XEP_0424)

View file

@ -0,0 +1,62 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from typing import Optional
from slixmpp import JID, Message
from slixmpp.exceptions import IqError, IqTimeout
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.xep_0424 import stanza
DEFAULT_FALLBACK = (
'This person attempted to retract a previous message, but your client '
'does not support it.'
)
class XEP_0424(BasePlugin):
'''XEP-0424: Message Retraction'''
name = 'xep_0424'
description = 'Message Retraction'
dependencies = {'xep_0422', 'xep_0030', 'xep_0359', 'xep_0428', 'xep_0334'}
stanza = stanza
namespace = stanza.NS
def plugin_init(self) -> None:
stanza.register_plugins()
def session_bind(self, jid):
self.xmpp.plugin['xep_0030'].add_feature(feature=stanza.NS)
def plugin_end(self):
self.xmpp.plugin['xep_0030'].del_feature(feature=stanza.NS)
def send_retraction(self, mto: JID, id: str, mtype: str = 'chat',
include_fallback: bool = True,
fallback_text: Optional[str] = None, *,
mfrom: Optional[JID] = None):
"""
Send a message retraction
:param JID mto: The JID to retract the message from
:param str id: Message ID to retract
:param str mtype: Message type
:param bool include_fallback: Whether to include a fallback body
:param Optional[str] fallback_text: The contet of the fallback
body. None will set the default value.
"""
if fallback_text is None:
fallback_text = DEFAULT_FALLBACK
msg = self.xmpp.make_message(mto=mto, mtype=mtype, mfrom=mfrom)
if include_fallback:
msg['body'] = fallback_text
msg.enable('fallback')
msg['apply_to']['id'] = id
msg['apply_to'].enable('retract')
msg.enable('store')
msg.send()

View file

@ -0,0 +1,38 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permissio
"""
from slixmpp.stanza import Message
from slixmpp.xmlstream import (
ElementBase,
register_stanza_plugin,
)
from slixmpp.plugins.xep_0422.stanza import ApplyTo
from slixmpp.plugins.xep_0359 import OriginID
NS = 'urn:xmpp:message-retract:0'
class Retract(ElementBase):
namespace = NS
name = 'retract'
plugin_attrib = 'retract'
class Retracted(ElementBase):
namespace = NS
name = 'retracted'
plugin_attrib = 'retracted'
interfaces = {'stamp'}
def register_plugins():
register_stanza_plugin(ApplyTo, Retract)
register_stanza_plugin(Message, Retracted)
register_stanza_plugin(Retracted, OriginID)

View file

@ -0,0 +1,13 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.base import register_plugin
from slixmpp.plugins.xep_0425.stanza import *
from slixmpp.plugins.xep_0425.moderation import XEP_0425
register_plugin(XEP_0425)

View file

@ -0,0 +1,39 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from typing import Optional
from slixmpp import JID, Message
from slixmpp.exceptions import IqError, IqTimeout
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.xep_0425 import stanza
class XEP_0425(BasePlugin):
'''XEP-0425: Message Moderation'''
name = 'xep_0425'
description = 'Message Moderation'
dependencies = {'xep_0424', 'xep_0421'}
stanza = stanza
namespace = stanza.NS
def plugin_init(self) -> None:
stanza.register_plugins()
def session_bind(self, jid):
self.xmpp.plugin['xep_0030'].add_feature(feature=stanza.NS)
def plugin_end(self):
self.xmpp.plugin['xep_0030'].del_feature(feature=stanza.NS)
async def moderate(self, room: JID, id: str, reason: str = '', *,
ifrom: Optional[JID] = None, **iqkwargs):
iq = self.xmpp.make_iq_set(ito=room.bare, ifrom=ifrom)
iq['apply_to']['id'] = id
iq['apply_to']['moderate']['reason'] = reason
await iq.send(**iqkwargs)

View file

@ -0,0 +1,46 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permissio
"""
from slixmpp.stanza import Message, Iq
from slixmpp.xmlstream import (
ElementBase,
register_stanza_plugin,
)
from slixmpp.plugins.xep_0422.stanza import ApplyTo
from slixmpp.plugins.xep_0421.stanza import OccupantId
from slixmpp.plugins.xep_0424.stanza import Retract, Retracted
NS = 'urn:xmpp:message-moderate:0'
class Moderate(ElementBase):
namespace = NS
name = 'moderate'
plugin_attrib = 'moderate'
interfaces = {'reason'}
sub_interfaces = {'reason'}
class Moderated(ElementBase):
namespace = NS
name = 'moderated'
plugin_attrib = 'moderated'
interfaces = {'reason', 'by'}
sub_interfaces = {'reason'}
def register_plugins():
register_stanza_plugin(Iq, ApplyTo)
register_stanza_plugin(ApplyTo, Moderate)
register_stanza_plugin(Moderate, Retract)
register_stanza_plugin(Message, Moderated)
register_stanza_plugin(ApplyTo, Moderated)
register_stanza_plugin(Moderated, Retracted)
register_stanza_plugin(Moderated, OccupantId)

View file

@ -0,0 +1,13 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.base import register_plugin
from slixmpp.plugins.xep_0428.stanza import *
from slixmpp.plugins.xep_0428.fallback import XEP_0428
register_plugin(XEP_0428)

View file

@ -0,0 +1,22 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.xep_0428 import stanza
class XEP_0428(BasePlugin):
'''XEP-0428: Fallback Indication'''
name = 'xep_0428'
description = 'Fallback Indication'
dependencies = set()
stanza = stanza
namespace = stanza.NS
def plugin_init(self) -> None:
stanza.register_plugins()

View file

@ -0,0 +1,26 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permissio
"""
from slixmpp.stanza import Message
from slixmpp.xmlstream import (
ElementBase,
register_stanza_plugin,
)
NS = 'urn:xmpp:fallback:0'
class Fallback(ElementBase):
namespace = NS
name = 'fallback'
plugin_attrib = 'fallback'
def register_plugins():
register_stanza_plugin(Message, Fallback)

View file

@ -0,0 +1,13 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from slixmpp.plugins.base import register_plugin
from slixmpp.plugins.xep_0439.stanza import *
from slixmpp.plugins.xep_0439.quickresponse import XEP_0439
register_plugin(XEP_0439)

View file

@ -0,0 +1,91 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permission.
"""
from typing import (
Iterable,
Optional,
Tuple,
)
from slixmpp import JID
from slixmpp.plugins import BasePlugin
from slixmpp.plugins.xep_0439 import stanza
class XEP_0439(BasePlugin):
'''XEP-0439: Quick Response'''
name = 'xep_0439'
description = 'Quick Response'
dependencies = set()
stanza = stanza
namespace = stanza.NS
def plugin_init(self) -> None:
stanza.register_plugins()
def ask_for_responses(self, mto: JID, body: str,
responses: Iterable[Tuple[str, str]],
mtype: str = 'chat', lang: Optional[str] = None, *,
mfrom: Optional[JID] = None):
"""
Send a message with a set of responses.
:param JID mto: The JID of the entity which will receive the message
:param str body: The message body of the question
:param Iterable[Tuple[str, str]] responses: A set of tuples containing
(value, label) for each response
:param str mtype: The message type
:param str lang: The lang of the message (if not use, the default
for this session will be used.
"""
if lang is None:
lang = self.xmpp.default_lang
msg = self.xmpp.make_message(mto=mto, mfrom=mfrom, mtype=mtype)
msg['body|%s' % lang] = body
values = set()
for value, label in responses:
if value in values:
raise ValueError("Duplicate values")
values.add(value)
elem = stanza.Response()
elem['lang'] = lang
elem['value'] = value
elem['label'] = label
msg.append(elem)
msg.send()
def ask_for_actions(self, mto: JID, body: str,
actions: Iterable[Tuple[str, str]],
mtype: str = 'chat', lang: Optional[str] = None, *,
mfrom: Optional[JID] = None):
"""
Send a message with a set of actions.
:param JID mto: The JID of the entity which will receive the message
:param str body: The message body of the question
:param Iterable[Tuple[str, str]] actions: A set of tuples containing
(action, label) for each action
:param str mtype: The message type
:param str lang: The lang of the message (if not use, the default
for this session will be used.
"""
if lang is None:
lang = self.xmpp.default_lang
msg = self.xmpp.make_message(mto=mto, mfrom=mfrom, mtype=mtype)
msg['body|%s' % lang] = body
ids = set()
for id, label in actions:
if id in ids:
raise ValueError("Duplicate ids")
ids.add(id)
elem = stanza.Action()
elem['lang'] = lang
elem['id'] = id
elem['label'] = label
msg.append(elem)
msg.send()

View file

@ -0,0 +1,43 @@
"""
Slixmpp: The Slick XMPP Library
Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
This file is part of Slixmpp.
See the file LICENSE for copying permissio
"""
from slixmpp.stanza import Message
from slixmpp.xmlstream import (
ElementBase,
register_stanza_plugin,
)
NS = 'urn:xmpp:tmp:quick-response'
class Response(ElementBase):
namespace = NS
name = 'response'
plugin_attrib = 'response'
interfaces = {'value', 'label'}
class Action(ElementBase):
namespace = NS
name = 'action'
plugin_attrib = 'action'
interfaces = {'id', 'label'}
class ActionSelected(ElementBase):
namespace = NS
name = 'action-selected'
plugin_attrib = 'action_selected'
interfaces = {'id'}
def register_plugins():
register_stanza_plugin(Message, Action, iterable=True)
register_stanza_plugin(Message, ActionSelected)
register_stanza_plugin(Message, Response, iterable=True)

View file

@ -0,0 +1,33 @@
import unittest
from slixmpp import Message
from slixmpp.test import SlixTest
from slixmpp.xmlstream import ET
from slixmpp.plugins.xep_0422 import stanza
class TestFastening(SlixTest):
def setUp(self):
stanza.register_plugins()
def testFastenExternal(self):
message = Message()
message['apply_to']['id'] = 'some-id'
message['apply_to'].xml.append(
ET.fromstring('<test xmlns="urn:tmp:test">Test</test>')
)
message['apply_to']['external']['name'] = 'body'
message['body'] = 'Toto'
self.check(message, """
<message>
<apply-to xmlns="urn:xmpp:fasten:0" id="some-id">
<test xmlns="urn:tmp:test">Test</test>
<external name='body'/>
</apply-to>
<body>Toto</body>
</message>
""", use_values=False)
suite = unittest.TestLoader().loadTestsFromTestCase(TestFastening)

View file

@ -0,0 +1,39 @@
import unittest
from slixmpp import Message
from slixmpp.test import SlixTest
from slixmpp.plugins.xep_0424 import stanza
class TestRetraction(SlixTest):
def setUp(self):
stanza.register_plugins()
def testRetract(self):
message = Message()
message['apply_to']['id'] = 'some-id'
message['apply_to']['retract']
self.check(message, """
<message>
<apply-to xmlns="urn:xmpp:fasten:0" id="some-id">
<retract xmlns="urn:xmpp:message-retract:0"/>
</apply-to>
</message>
""", use_values=False)
def testRetracted(self):
message = Message()
message['retracted']['stamp'] = '2019-09-20T23:09:32Z'
message['retracted']['origin_id']['id'] = 'originid'
self.check(message, """
<message>
<retracted stamp="2019-09-20T23:09:32Z" xmlns="urn:xmpp:message-retract:0">
<origin-id xmlns="urn:xmpp:sid:0" id="originid"/>
</retracted>
</message>
""")
suite = unittest.TestLoader().loadTestsFromTestCase(TestRetraction)

View file

@ -0,0 +1,47 @@
import unittest
from slixmpp import Message, Iq, JID
from slixmpp.test import SlixTest
from slixmpp.plugins.xep_0425 import stanza
class TestModeration(SlixTest):
def setUp(self):
stanza.register_plugins()
def testModerate(self):
iq = Iq()
iq['type'] = 'set'
iq['id'] = 'a'
iq['apply_to']['id'] = 'some-id'
iq['apply_to']['moderate'].enable('retract')
iq['apply_to']['moderate']['reason'] = 'R'
self.check(iq, """
<iq type='set' id='a'>
<apply-to id="some-id" xmlns="urn:xmpp:fasten:0">
<moderate xmlns='urn:xmpp:message-moderate:0'>
<retract xmlns='urn:xmpp:message-retract:0'/>
<reason>R</reason>
</moderate>
</apply-to>
</iq>
""", use_values=False)
def testModerated(self):
message = Message()
message['moderated']['by'] = JID('toto@titi')
message['moderated']['retracted']['stamp'] = '2019-09-20T23:09:32Z'
message['moderated']['reason'] = 'R'
self.check(message, """
<message>
<moderated xmlns="urn:xmpp:message-moderate:0" by="toto@titi">
<retracted stamp="2019-09-20T23:09:32Z" xmlns="urn:xmpp:message-retract:0" />
<reason>R</reason>
</moderated>
</message>
""")
suite = unittest.TestLoader().loadTestsFromTestCase(TestModeration)

View file

@ -0,0 +1,57 @@
import unittest
from slixmpp import Message
from slixmpp.test import SlixTest
from slixmpp.plugins.xep_0439 import stanza
class TestQuickResponse(SlixTest):
def setUp(self):
stanza.register_plugins()
def testResponse(self):
message = Message()
message['body'] = 'Reply 1 or 2?'
for (value, label) in [('1', 'Rep 1'), ('2', 'Rep 2')]:
rep = stanza.Response()
rep['value'] = value
rep['label'] = label
message.append(rep)
self.check(message, """
<message>
<body>Reply 1 or 2?</body>
<response xmlns="urn:xmpp:tmp:quick-response" value="1" label="Rep 1" />
<response xmlns="urn:xmpp:tmp:quick-response" value="2" label="Rep 2" />
</message>
""", use_values=False)
def testAction(self):
message = Message()
message['body'] = 'action 1 or 2?'
for (id_, label) in [('1', 'action 1'), ('2', 'action 2')]:
act = stanza.Action()
act['id'] = id_
act['label'] = label
message.append(act)
self.check(message, """
<message>
<body>action 1 or 2?</body>
<action xmlns="urn:xmpp:tmp:quick-response" id="1" label="action 1" />
<action xmlns="urn:xmpp:tmp:quick-response" id="2" label="action 2" />
</message>
""", use_values=False)
def testActionSelected(self):
message = Message()
message['action_selected']['id'] = 'act1'
self.check(message, """
<message>
<action-selected xmlns="urn:xmpp:tmp:quick-response" id="act1" />
</message>
""", use_values=False)
suite = unittest.TestLoader().loadTestsFromTestCase(TestQuickResponse)