muc
— Multi-User-Chat support (XEP-0045)¶
This subpackage provides client-side support for XEP-0045.
New in version 0.5.
Changed in version 0.9: Nearly the whole public interface of this module has been re-written in
0.9 to make it coherent with the Modern IM interface defined by
aioxmpp.im
.
Using Multi-User-Chats¶
To start using MUCs in your application, you have to load the Service
into the client, using summon()
.
-
class
aioxmpp.
MUCClient
(client, **kwargs)[source]¶ Conversation Implementation for Multi-User Chats (XEP-0045).
See also
AbstractConversationService
for useful common signals
This service provides access to Multi-User Chats using the conversation interface defined by
aioxmpp.im
.Client service implementing the a Multi-User Chat client. By loading it into a client, it is possible to join multi-user chats and implement interaction with them.
Private Messages into the MUC are not handled by this service. They are handled by the normal
p2p.Service
.-
join
(mucjid, nick, *, password=None, history=None, autorejoin=True)[source]¶ Join a multi-user chat and create a conversation for it.
- Parameters
mucjid (
JID
.) – The bare JID of the room to join.nick (
str
) – The nickname to use in the room.password (
str
) – The password to join the room, if required.history (
xso.History
) – Specification for how much and which history to fetch.autorejoin (
bool
) – Flag to indicate that the MUC should be automatically rejoined after a disconnect.
- Raises
ValueError – if the MUC JID is invalid.
- Returns
The Conversation and a future on the join.
- Return type
tuple of
Room
andasyncio.Future
.
Join a multi-user chat at mucjid with nick. Return a
Room
instance which is used to track the MUC locally and aaioxmpp.Future
which becomes done when the join succeeded (with aNone
value) or failed (with an exception).In addition, the
on_conversation_added()
signal is emitted immediately with the newRoom
.It is recommended to attach the desired signals to the
Room
before yielding next (e.g. in a non-deferred event handler to theon_conversation_added()
signal), to avoid races with the server. It is guaranteed that no signals are emitted before the next yield, and thus, it is safe to attach the signals right afterjoin()
returned. (This is also the reason whyjoin()
is not a coroutine, but instead returns the room and a future to wait for.)Any other interaction with the room must go through the
Room
instance.If the multi-user chat at mucjid is already or currently being joined, the existing
Room
and future is returned. The nick and other options for the new join are ignored.If the mucjid is not a bare JID,
ValueError
is raised.password may be a string used as password for the MUC. It will be remembered and stored at the returned
Room
instance.history may be a
History
instance to request a specific amount of history; otherwise, the server will return a default amount of history.If autorejoin is true, the MUC will be re-joined after the stream has been destroyed and re-established. In that case, the service will request history since the stream destruction and ignore the history object passed here.
If the stream is currently not established, the join is deferred until the stream is established.
Manage rooms:
-
async
get_room_config
(mucjid)[source]¶ Query and return the room configuration form for the given MUC.
- Parameters
mucjid (bare
JID
) – JID of the room to query- Returns
data form template for the room configuration
- Return type
See also
ConfigurationForm
for a form template to work with the returned form
New in version 0.7.
-
async
set_room_config
(mucjid, data)[source]¶ Set the room configuration using a XEP-0004 data form.
- Parameters
mucjid (bare
JID
) – JID of the room to querydata (
aioxmpp.forms.Data
) – Filled-out configuration form
See also
ConfigurationForm
for a form template to generate the required form
A sensible workflow to, for example, set a room to be moderated, could be this:
form = aioxmpp.muc.ConfigurationForm.from_xso( (await muc_service.get_room_config(mucjid)) ) form.moderatedroom = True await muc_service.set_rooom_config(mucjid, form.render_reply())
New in version 0.7.
-
async
get_affiliated
(mucjid, affiliation)[source]¶ Retrieve the list of JIDs with the given affiliation with a MUC.
-
async
set_affiliation
(mucjid, jid, affiliation, *, reason=None)[source]¶ Change the affiliation of an entity with a MUC.
- Parameters
Change the affiliation of the given jid with the MUC identified by the bare mucjid to the given new affiliation. Optionally, a reason can be given.
If you are joined in the MUC,
Room.muc_set_affiliation()
may be more convenient, but it is possible to modify the affiliations of a MUC without being joined, given sufficient privilegues.Setting the different affiliations require different privilegues of the local user. The details can be checked in XEP-0045 and are enforced solely by the server, not local code.
The coroutine returns when the change in affiliation has been acknowledged by the server. If the server returns an error, an appropriate
aioxmpp.errors.XMPPError
subclass is raised.
Global events:
-
signal
on_muc_invitation
(stanza, muc_address, inviter_address, mode, *, password=None, reason=None, **kwargs)¶ Emits when a MUC invitation has been received.
New in version 0.10.
- Parameters
stanza (
aioxmpp.Message
) – The stanza containing the invitation.muc_address (
aioxmpp.JID
) – The address of the MUC to which the invitation points.inviter_address (
aioxmpp.JID
orNone
) – The address of the inviter.mode (
im.InviteMode
) – The type of the invitation.
The format of the inviter_address depends on the mode:
DIRECT
For direct invitations, the inviter_address is the full or bare JID of the entity which sent the invitation. Usually, this will be a full JID of a users client.
MEDIATED
For mediated invitations, the inviter_address is either the occupant JID of the inviting occupant or the real bare or full JID of the occupant (XEP-0045 leaves it up to the service to decide). May also be
None
.
Warning
Neither invitation type is perfect and has issues. Mediated invites can easily be spoofed by MUCs (both their intent and the inviter address) and might be used by spam rooms to trick users into joining. Direct invites may not reach the recipient due to local policy, but they allow proper sender attribution.
inviter_address values which are not an occupant JID should not be trusted for mediated invites!
How to deal with this is a policy decision which
aioxmpp
can not make for your application.
Changed in version 0.8: This class was formerly known as
aioxmpp.muc.Service
. It is still available under that name, but the alias will be removed in 1.0.Changed in version 0.9: This class was completely remodeled in 0.9 to conform with the
aioxmpp.im
interface.Changed in version 0.10: This class now conforms to the
AbstractConversationService
interface.
-
class
aioxmpp.muc.
Service
¶ Alias of
MUCClient
.Deprecated since version 0.8: The alias will be removed in 1.0.
The service returns Room
objects which are used to track joined MUCs:
-
class
aioxmpp.muc.
Room
(service, mucjid)[source]¶ Conversation representing a single XEP-0045 Multi-User Chat.
Note
This is an implementation of
AbstractConversation
. The members which do not carry themuc_
prefix usually have more extensive documentation there. This documentation here only provides a short synopsis for those members plus the changes with respect to the base interface.Changed in version 0.9: In 0.9, the
Room
interface was re-designed to matchAbstractConversation
.The following properties are provided:
-
features
¶ The set of features supported by this MUC. This may vary depending on features exported by the MUC service, so be sure to check this for each individual MUC.
-
jid
¶ The (bare)
aioxmpp.JID
of the MUC which thisRoom
tracks.
-
me
¶ A
Occupant
instance which tracks the local user. This isNone
untilon_enter()
is emitted; it is never set toNone
again, but the identity of the object changes on eachon_enter()
.
-
members
¶ A copy of the list of occupants. The local user is always the first item in the list, unless the
on_enter()
has not fired yet.
-
service_member
¶ A
ServiceMember
object which represents the MUC service itself.This is used when messages from the MUC service are received.
See also
service_member
For more documentation on the semantics of
service_member
.
New in version 0.10.
These properties are specific to MUC:
-
muc_active
¶ A boolean attribute indicating whether the connection to the MUC is currently live.
This becomes true when
joined
first becomes true. It becomes false whenever the connection to the MUC is interrupted in a way which requires re-joining the MUC (this implies that if stream management is being used, active does not become false on temporary connection interruptions).
-
muc_joined
¶ This attribute becomes true when
on_enter()
is first emitted and stays true untilon_exit()
is emitted.When it becomes false, the
Room
is removed from the bookkeeping of theMUCClient
to which it belongs and is thus dead.
-
muc_state
¶ The state the MUC is in. This is one of the
RoomState
enumeration values. See there for documentation on the meaning.This state is more detailed than
muc_active
.
-
muc_subject
¶ The current subject of the MUC, as
LanguageMap
.
-
muc_subject_setter
¶ The nick name of the entity who set the subject.
-
muc_autorejoin
¶ A boolean flag indicating whether this MUC is supposed to be automatically rejoined when the stream it is used gets destroyed and re-estabished.
-
muc_password
¶ The password to use when (re-)joining. If
autorejoin
isNone
, this can be cleared afteron_enter()
has been emitted.
The following methods and properties provide interaction with the MUC itself:
-
async
ban
(member, reason=None, *, request_kick=True)[source]¶ Ban an occupant from re-joining the MUC.
- Parameters
request_kick is supported by MUC, but setting it to false has no effect: banned members are always immediately kicked.
See also
AbstractConversation.ban()
for the full interface specification.
-
async
kick
(member, reason=None)[source]¶ Kick an occupant from the MUC.
- Parameters
- Raises
aioxmpp.errors.XMPPError – if the server returned an error for the kick command.
See also
AbstractConversation.kick()
for the full interface specification.
-
send_message
(msg)[source]¶ Send a message to the MUC.
- Parameters
msg (
aioxmpp.Message
) – The message to send.- Returns
The stanza token of the message.
- Return type
There is no need to set the address attributes or the type of the message correctly; those will be overridden by this method to conform to the requirements of a message to the MUC. Other attributes are left untouched (except that
autoset_id()
is called) and can be used as desired for the message.See also
AbstractConversation.send_message()
for the full interface specification.
-
send_message_tracked
(msg)[source]¶ Send a message to the MUC with tracking.
- Parameters
msg (
aioxmpp.Message
) – The message to send.
Warning
Please read General Remarks about Tracking and Memory Consumption. This is especially relevant for MUCs because tracking is not guaranteed to work due to how XEP-0045 is written. It will work in many cases, probably in all cases you test during development, but it may fail to work for some individual messages and it may fail to work consistently for some services. See the implementation details below for reasons.
The message is tracked and is considered
DELIVERED_TO_RECIPIENT
when it is reflected back to us by the MUC service. The reflected message is then available in theresponse
attribute.Note
Two things:
The MUC service may change the contents of the message. An example of this is the Prosody developer MUC which replaces messages with more than a few lines with a pastebin link.
Reflected messages which are caught by tracking are not emitted through
on_message()
.
There is no need to set the address attributes or the type of the message correctly; those will be overridden by this method to conform to the requirements of a message to the MUC. Other attributes are left untouched (except that
autoset_id()
is called) and can be used as desired for the message.Warning
Using
send_message_tracked()
beforeon_join()
has emitted will cause the member object in the resultingon_message()
event to beNone
(the message will be delivered just fine).Using
send_message_tracked()
before history replay is over will cause theon_message()
event to be emitted during history replay, even though everyone else in the MUC will – of course – only see the message after the history.send_message()
is not affected by these quirks.See also
AbstractConversation.send_message_tracked()
for the full interface specification.Implementation details: Currently, we try to detect reflected messages using two different criteria. First, if we see a message with the same message ID (note that message IDs contain 120 bits of entropy) as the message we sent, we consider it as the reflection. As some MUC services re-write the message ID in the reflection, as a fallback, we also consider messages which originate from the correct sender and have the correct body a reflection.
Obviously, this fails consistently in MUCs which re-write the body and re-write the ID and randomly if the MUC always re-writes the ID but only sometimes the body.
-
async
set_nick
(new_nick)[source]¶ Change the nick name of the occupant.
- Parameters
new_nick (
str
) – New nickname to use
This sends the request to change the nickname and waits for the request to be sent over the stream.
The nick change may or may not happen, or the service may modify the nickname; observe the
on_nick_change()
event.See also
AbstractConversation.set_nick()
for the full interface specification.
-
async
set_topic
(new_topic)[source]¶ Change the (possibly publicly) visible topic of the conversation.
- Parameters
new_topic (
str
) – The new topic for the conversation.
Request to set the subject to new_topic. new_topic must be a mapping which maps
LanguageTag
tags to strings;None
is a valid key.
-
async
muc_request_voice
()[source]¶ Request voice (participant role) in the room and wait for the request to be sent.
The participant role allows occupants to send messages while the room is in moderated mode.
There is no guarantee that the request will be granted. To detect that voice has been granted, observe the
on_role_change()
signal.New in version 0.8.
-
async
muc_set_role
(nick, role, *, reason=None)[source]¶ Change the role of an occupant.
- Parameters
Change the role of an occupant, identified by their nick, to the given new role. Optionally, a reason for the role change can be provided.
Setting the different roles require different privilegues of the local user. The details can be checked in XEP-0045 and are enforced solely by the server, not local code.
The coroutine returns when the role change has been acknowledged by the server. If the server returns an error, an appropriate
aioxmpp.errors.XMPPError
subclass is raised.
-
async
muc_set_affiliation
(jid, affiliation, *, reason=None)[source]¶ Convenience wrapper around
MUCClient.set_affiliation()
. See there for details, and consider its mucjid argument to be set tomucjid
.
The interface provides signals for most of the rooms events. The following keyword arguments are used at several signal handlers (which is also noted at their respective documentation):
- muc_actor =
None
The
UserActor
instance of the correspondingUserExt
, describing which other occupant caused the event.Note that the muc_actor is in fact not a
Occupant
.- muc_reason =
None
The reason text in the corresponding
UserExt
, which gives more information on why an action was triggered.
Note
Signal handlers attached to any of the signals below must accept arbitrary keyword arguments for forward compatibility. For details see the documentation on
AbstractConversation
.-
signal
on_enter
(**kwargs)¶ Emits when the initial room
Presence
stanza for the local JID is received. This means that the join to the room is complete; the message history and subject are not transferred yet though.See also
on_muc_enter()
is an extended version of this signal which contains additional MUC-specific information.
Changed in version 0.10: The
on_enter()
signal does not receive any arguments anymore to make MUC comply with theAbstractConversation
spec.
-
signal
on_muc_enter
(presence, occupant, *, muc_status_codes=set(), **kwargs)¶ This is an extended version of
on_enter()
which adds MUC-specific arguments.- Parameters
presence – The initial presence stanza.
occupant – The
Occupant
which will be used to track the local user.muc_status_codes (
Set
ofint
orStatusCode
) – The set of status codes received in the initial join.
New in version 0.10.
-
signal
on_message
(msg, member, source, **kwargs)¶ A message occurred in the conversation.
- Parameters
msg (
aioxmpp.Message
) – Message which was received.member (
Occupant
) – The member object of the sender.source (
MessageSource
) – How the message was acquired
The notable specialities about MUCs compared to the base specification at
AbstractConversation.on_message()
are:Carbons do not happen for MUC messages.
MUC Private Messages are not handled here; see
MUCClient
for MUC PM details.MUCs reflect messages; to make this as easy to handle as possible, reflected messages are not emitted via the
on_message()
event if and only if they were sent with tracking (seesend_message_tracked()
) and they were detected as reflection.See
send_message_tracked()
for details and caveats on the tracking implementation.
When history replay happens, since joins and leaves are not part of the history, it is not always possible to reason about the identity of the sender of a history message. To avoid possible spoofing attacks, the following caveats apply to the
Occupant
objects handed as member during history replay:Two identical
Occupant
objects are only used iff the nickname and the actual address of the entity are equal. This implies that unless this client has the permission to see JIDs of occupants of the MUC, allOccupant
objects during history replay will be different instances.If the nickname and the actual address of a message from history match, the current
Occupant
object for the respective occupant is used.Occupant
objects which are created for history replay are never part ofmembers
. They are only used to convey the information passed in the messages from the history replay, which would otherwise be inaccessible.
See also
AbstractConversation.on_message()
for the full specification.
-
signal
on_presence_changed
(member, resource, presence, **kwargs)¶ The presence state of an occupant has changed.
- Parameters
member (
Occupant
) – The member object of the affected member.resource (
str
orNone
) – The resource of the member which changed presence.presence (
aioxmpp.Presence
) – The presence stanza
resource is always
None
for MUCs and unavailable presence implies that the occupant left the room. In this case, onlyon_leave()
is emitted.See also
AbstractConversation.on_presence_changed()
for the full specification.
-
signal
on_nick_changed
(member, old_nick, new_nick, *, muc_status_codes=set(), **kwargs)¶ The nickname of an occupant has changed
- Parameters
The new nickname is already set in the member object. Both old_nick and new_nick are not
None
.See also
AbstractConversation.on_nick_changed()
for the full specification.Changed in version 0.10: The muc_status_codes argument was added.
-
signal
on_topic_changed
(member, new_topic, *, muc_nick=None, **kwargs)¶ The topic of the conversation has changed.
- Parameters
member (
Occupant
orNone
) – The member object who changed the topic.new_topic (
LanguageMap
) – The new topic of the conversation.muc_nick (
str
) – The nickname of the occupant who changed the topic.
The member is matched by nickname. It is possible that the member is not in the room at the time the topic change is received (for example on a join).
muc_nick is always the nickname of the entity who changed the topic. If the entity is currently not joined or has changed nick since the topic was set, member will be
None
, but muc_nick is still the nickname of the actor.Note
on_topic_changed()
is emitted during join, iff a topic is set in the MUC.
-
signal
on_join
(member, **kwargs)¶ A new occupant has joined the MUC.
- Parameters
member (
Occupant
) – The member object of the new member.
When this signal is called, the member is already included in the
members
.
-
signal
on_leave
(member, *, muc_leave_mode=None, muc_actor=None, muc_reason=None, **kwargs)¶ An occupant has left the conversation.
- Parameters
member (
Occupant
) – The member object of the previous occupant.muc_leave_mode (
LeaveMode
member) – The cause of the removal.muc_actor (
UserActor
) – The actor object if available.muc_reason (
str
) – The reason for the cause, as given by the actor.muc_status_codes (
Set
ofint
orStatusCode
) – The set of status codes received in the leave notification.
When this signal is called, the member has already been removed from the
members
.Changed in version 0.10: The muc_status_codes argument was added.
-
signal
on_muc_suspend
()¶ Emits when the stream used by this MUC gets destroyed (see
on_stream_destroyed()
) and the MUC is configured to automatically rejoin the user when the stream is re-established.
-
signal
on_muc_resume
()¶ Emits when the MUC is about to be rejoined on a new stream. This can be used by implementations to clear their MUC state, as it is emitted before any events like presence are emitted.
The internal state of
Room
is cleared beforeon_resume()
is emitted, which implies that presence events will be emitted for all occupants on re-join, independent on their presence before the connection was lost.Note that on a rejoin, all presence is re-emitted.
-
signal
on_muc_role_request
(form, submission_future)¶ Emits when an unprivileged occupant requests a role change and the MUC service wants this occupant to approve or deny it.
- Parameters
form (
VoiceRequestForm
) – The approval form as presented by the service.submission_future (
asyncio.Future
) – A future to which the form to submit must be sent.
To decide on a role change request, a handler of this signal must fill in the form and set the form as a result of the submission_future.
Once the result is set, the reply is sent by the MUC service automatically.
It is required for signal handlers to check whether the submission_future is already done before processing the form (as it is possible that multiple handlers are connected to this signal).
-
signal
on_exit
(*, muc_leave_mode=None, muc_actor=None, muc_reason=None, muc_status_codes=set(), **kwargs)¶ Emits when the unavailable
Presence
stanza for the local JID is received.- Parameters
muc_leave_mode (
LeaveMode
member) – The cause of the removal.muc_actor (
UserActor
) – The actor object if available.muc_reason (
str
) – The reason for the cause, as given by the actor.muc_status_codes (
Set
ofint
orStatusCode
) – The set of status codes received in the leave notification.
Note
The keyword arguments muc_actor, muc_reason and muc_status_codes are not always given. Be sure to default them accordingly.
Changed in version 0.10: The muc_status_codes argument was added.
-
signal
on_muc_stale
(**kwargs)¶ Emits when the
muc_hard_timeout
expires.This signal is emitted only up to once for each pause in data reception. As long as data is received often enough, the timeout will not trigger. When the timeout triggers due to silence, the signal is emitted once, and not again until after data has been received for the next time.
This signal is only informational. It does not imply that the MUC is unreachable or that the local occupant has been removed from the MUC, but it is very likely that no messages can currently be sent or received.
It is not clear whether messages are being lost.
A prominent example on when this condition can occur is highlighted in the specification for the feature this is built on (XEP-0410). Often, the MUC service is on a remote domain, which means that there are at least two network connections involved, sometimes three (c2s, s2s, and from the remote server to the MUC component).
When the s2s connection (for example) fails in certain ways, it is possible that no error replies are generated by any party; stanzas are essentially blackholed. When the network connection resumes, it depends on the exact failure mode whether the occupant is still in the room and which messages (if any) which were sent in the meantime will have been delivered to any participant.
After
on_muc_stale()
emits, exactly one of the following will happen, given infinite time:on_muc_fresh()
is emitted, which means that connectivity to the MUC has been re-confirmed.on_muc_suspend()
is emitted, which means that the local client has disconnected (but autorejoin is enabled).on_exit()
is emitted, which means that the client has been removed from the MUC or the local client has disconnected (and autorejoin is disabled).
The aliveness checks are only enabled after presence synchronisation has begun.
-
signal
on_muc_fresh
(**kwargs)¶ Emits after
on_muc_stale()
when connectivity is re-confirmed.See
on_muc_stale()
for details.
The following signals inform users about state changes related to other occupants in the chat room. Note that different events may fire for the same presence stanza. A common example is a ban, which triggers
on_affiliation_change()
(as the occupants affiliation is set to"outcast"
) and thenon_leave()
(withLeaveMode.BANNED
mode).-
signal
on_muc_affiliation_changed
(member, *, actor=None, reason=None, status_codes=set(), **kwargs)¶ Emits when the affiliation of a member with the room changes.
- Parameters
occupant (
Occupant
) – The member of the room.actor (
UserActor
) – The actor object if available.reason (
str
) – The reason for the change, as given by the actor.status_codes (
Set
ofint
orStatusCode
) – The set of status codes received in the change notification.
occupant is the
Occupant
instance tracking the occupant whose affiliation changed.Changed in version 0.10: The status_codes argument was added.
-
signal
on_muc_role_changed
(member, *, actor=None, reason=None, status_codes=set(), **kwargs)¶ Emits when the role of an occupant in the room changes.
- Parameters
occupant (
Occupant
) – The member of the room.actor (
UserActor
) – The actor object if available.reason (
str
) – The reason for the change, as given by the actor.status_codes (
Set
ofint
orStatusCode
) – The set of status codes received in the change notification.
occupant is the
Occupant
instance tracking the occupant whose role changed.Changed in version 0.10: The status_codes argument was added.
Timeout control:
See also
-
muc_soft_timeout
¶ The soft timeout of the MUC aliveness timeout logic as
datetime.timedelta
.New in version 0.11.
-
muc_hard_timeout
¶ The hard timeout of the MUC aliveness timeout logic as
datetime.timedelta
.New in version 0.11.
-
muc_ping_interval
¶ The interval at which pings are sent after the soft timeout expires as
datetime.timedelta
.Warning
Please see the notes on
muc_ping_timeout
when changing the value ofmuc_ping_timeout
ormuc_ping_interval
.New in version 0.11.
-
muc_ping_timeout
¶ The maximum time to wait for a ping reply for each individual ping as
datetime.timedelta
.Warning
Pings are continued to be sent even when other pings are already in-flight. This means that up to
math.ceil(muc_ping_timeout / muc_ping_interval)
pings are in-flight at the same time. Each ping which is in-flight unfortunately requires a small amount of memory and an entry in a map which associates the stanza ID with the handler/future for the reply.New in version 0.11.
See also
-
-
class
aioxmpp.muc.
RoomState
(value)[source]¶ Enumeration which describes the state a
Room
is in.-
JOIN_PRESENCE
¶ The room is in the process of being joined and the presence state transfer is going on.
-
HISTORY
¶ Presence state transfer has happened, but the room subject has not been received yet. This is where history replay messages are received.
When entering this state,
muc_active
becomes true.
-
ACTIVE
¶ The join has completed, including history replay and receiving the subject.
-
DISCONNECTED
¶ The MUC is suspended or disconnected. If the MUC is disconnected,
muc_joined
will be false, too.
-
-
class
aioxmpp.muc.
LeaveMode
(value)[source]¶ The different reasons for a user to leave or be removed from MUC.
-
DISCONNECTED
¶ The local client disconnected. This only occurs in events referring to the local entity.
-
SYSTEM_SHUTDOWN
¶ The remote server shut down.
-
NORMAL
¶ The leave was initiated by the occupant themselves and was not a kick or ban.
-
KICKED
¶ The user was kicked from the room.
-
AFFILIATION_CHANGE
¶ Changes in the affiliation of the user caused them to be removed.
-
MODERATION_CHANGE
¶ Changes in the moderation settings of the room caused the user to be removed.
-
BANNED
¶ The user was banned from the room.
-
Inside rooms, there are occupants:
-
class
aioxmpp.muc.
Occupant
(occupantjid, is_self, presence_state=<PresenceState available>, presence_status={}, affiliation=None, role=None, jid=None)[source]¶ A tracking object to track a single occupant in a
Room
.See also
AbstractConversationMember
for additional notes on some of the pre-defined attributes.
-
direct_jid
¶ The real
JID
of the occupant.If the MUC is anonymous and we do not have the permission to see the real JIDs of occupants, this is
None
.
-
uid
¶ This is either a random identifier if the real JID of the occupant is not known, or an identifier derived from the real JID of the occupant.
Note that as per the semantics of the
uid
, users must treat it as opaque.See also
uid
Documentation of the attribute on the base class, with additional information on semantics.
-
nick
¶ The nickname of the occupant.
-
presence_state
¶ The
PresenceState
of the occupant.
-
presence_status
¶ The
LanguageMap
holding the presence status text of the occupant.
-
class
aioxmpp.muc.
ServiceMember
(muc_address)[source]¶ A
AbstractConversationMember
which represents a MUC service.New in version 0.10.
Objects of this instance are used for the
Room.service_member
property of rooms.Aside from the mandatory conversation member attributes, the following attributes for compatibility with
Occupant
are provided:-
nick
¶
-
presence_state
aioxmpp.structs.PresenceState(False)¶ The presence state of the service. Always unavailable.
-
presence_status
{}¶ The presence status of the service as
LanguageMap
. Always empty.
-
Timeout controls / XEP-0410 (MUC Self-Ping) support¶
New in version 0.11: XEP-0410 support and aliveness detection.
Motivation¶
In XMPP, multi-user chat services may reside on a server different than the one the user is at. This may either be due to the service running on a remote domain, or due to the service being connected via the network to the users server as component (see e.g. XEP-0114).
When the connection between the MUC service and the user’s server is broken when stanzas need to be delivered, stanzas can be lost. This can lead to the MUC getting “out of sync”, in the sense that different participants have different views of what happens and who even is in the MUC; this uncertainty can go as far as a client assuming that they’re still joined, while they were long removed from the MUC.
These types of breakages are hard to detect, unless the user tries to send a message through the MUC (in which case the lack of reflection or an error reply will give a clue that something is wrong). In the worst case, with an always-on client, it may appear that the MUC has been silent for days, while in fact everyone has been chatting away happily.
Solution¶
The underlying problem (networks get split) cannot be solved. While Stream Management on the s2s links could mitigate the issue to some extent, there will always be limits and circumstances at play which can still cause the out-of-sync situation.
While loss of messages can be compensated for by fetching the messages from the archive (doing this automatically on an interruption is out of scope for aioxmpp), there is no way for an application to detect that the client has been removed from the MUC except by explicitly pinging or sending messages.
To codify the complex rules which are needed to silently (i.e. invisible to other participants) check whether a client is still joined, XEP-0410 was written. It specifies the use of XEP-0199 pings through the MUC to the clients occupant (i.e. pinging oneself). MUC services explicitly reject the ping request if the sending client is not an occupant.
Self-Ping Implementation and Logic¶
The XEP-0410 implementation in aioxmpp is controlled with several attributes
and lines of defense. In the first line of defense, there is a
AlivenessMonitor
instance (this class is also used to
manage pinging the main XML stream). It is configured through
aioxmpp.muc.Room.muc_soft_timeout
and
muc_hard_timeout
.
The two timers run concurrently. When the soft timeout expires, the pinger (see
below) task is started. When the hard timeout expires, the MUC is marked stale
(this means, the on_muc_stale()
event fires). The
timers for both timeouts are reset whenever a presence or message stanza is
received from the MUC, preventing unnecessary pinging.
The pinger task emits pings in a defined interval
(muc_ping_interval
). The pings have a timeout of
muc_ping_timeout
. If a ping is replied to, the result
is interpreted according to XEP-0410. If the result is positive (= user
still joined), the soft and hard timeout timers mentioned above are reset
(the pinger, thus, ideally prevents the hard timeout from being triggered if
the connection to the MUC is fine after the soft timeout expired). If the
result is inconclusive, pinging continues. If the result is negative (= user
is not joined anymore), the MUC room is marked as exited (with the reason
DISCONNECTED
), except if it is set to
autorejoin, in which case a re-join (just as if the XML stream had been
disconnected) is attempted.
The default timeouts are set reasonably high to work reliably even on mobile links.
Warning
Please see the notes on muc_ping_timeout
when changing the value of muc_ping_timeout
or
muc_ping_interval
.
Forms¶
-
class
aioxmpp.muc.
ConfigurationForm
(*args, **kwargs)[source]¶ This is a XEP-0004 form template (see
aioxmpp.forms
) for MUC configuration forms.The attribute documentation is auto-generated from XEP-0045; see there for details on the semantics of each field.
New in version 0.7.
-
allowinvites
¶ boolean
fieldmuc#roomconfig_allowinvites
Whether to Allow Occupants to Invite Others
-
allowpm
¶ list-single
fieldmuc#roomconfig_allowpm
Roles that May Send Private Messages
-
changesubject
¶ boolean
fieldmuc#roomconfig_changesubject
Whether to Allow Occupants to Change Subject
-
enablelogging
¶ boolean
fieldmuc#roomconfig_enablelogging
Whether to Enable Public Logging of Room Conversations
-
getmemberlist
¶ list-multi
fieldmuc#roomconfig_getmemberlist
Roles and Affiliations that May Retrieve Member List
-
lang
¶ text-single
fieldmuc#roomconfig_lang
Natural Language for Room Discussions
-
maxhistoryfetch
¶ text-single
fieldmuc#maxhistoryfetch
Maximum Number of History Messages Returned by Room
-
maxusers
¶ list-single
fieldmuc#roomconfig_maxusers
Maximum Number of Room Occupants
-
membersonly
¶ boolean
fieldmuc#roomconfig_membersonly
Whether to Make Room Members-Only
-
moderatedroom
¶ boolean
fieldmuc#roomconfig_moderatedroom
Whether to Make Room Moderated
-
passwordprotectedroom
¶ boolean
fieldmuc#roomconfig_passwordprotectedroom
Whether a Password is Required to Enter
-
persistentroom
¶ boolean
fieldmuc#roomconfig_persistentroom
Whether to Make Room Persistent
-
presencebroadcast
¶ list-multi
fieldmuc#roomconfig_presencebroadcast
Roles for which Presence is Broadcasted
-
publicroom
¶ boolean
fieldmuc#roomconfig_publicroom
Whether to Allow Public Searching for Room
-
pubsub
¶ text-single
fieldmuc#roomconfig_pubsub
XMPP URI of Associated Publish-Subscribe Node
-
roomadmins
¶ jid-multi
fieldmuc#roomconfig_roomadmins
Full List of Room Admins
-
roomdesc
¶ text-single
fieldmuc#roomconfig_roomdesc
Short Description of Room
-
roomname
¶ text-single
fieldmuc#roomconfig_roomname
Natural-Language Room Name
-
roomowners
¶ jid-multi
fieldmuc#roomconfig_roomowners
Full List of Room Owners
-
roomsecret
¶ text-private
fieldmuc#roomconfig_roomsecret
The Room Password
-
whois
¶ list-single
fieldmuc#roomconfig_whois
Affiliations that May Discover Real JIDs of Occupants
-
-
class
aioxmpp.muc.
InfoForm
(*args, **kwargs)[source]¶ -
contactjid
¶ jid-multi
fieldmuc#roominfo_contactjid
Contact Addresses (normally, room owner or owners)
-
description
¶ text-single
fieldmuc#roominfo_description
Short Description of Room
-
lang
¶ text-single
fieldmuc#roominfo_lang
Natural Language for Room Discussions
-
ldapgroup
¶ text-single
fieldmuc#roominfo_ldapgroup
An associated LDAP group that defines room membership; this should be an LDAP Distinguished Name according to an implementation-specific or deployment-specific definition of a group.
-
logs
¶ text-single
fieldmuc#roominfo_logs
URL for Archived Discussion Logs
-
maxhistoryfetch
¶ text-single
fieldmuc#maxhistoryfetch
Maximum Number of History Messages Returned by Room
-
occupants
¶ text-single
fieldmuc#roominfo_occupants
Current Number of Occupants in Room
-
subject
¶ text-single
fieldmuc#roominfo_subject
Current Discussion Topic
-
subjectmod
¶ boolean
fieldmuc#roominfo_subjectmod
The room subject can be modified by participants
-
XSOs¶
-
class
aioxmpp.muc.
StatusCode
(value)[source]¶ This integer enumeration (see
enum.IntEnum
) is used for the status codes defined in XEP-0045.Note that members of this enumeration are equal to their respective integer values, making it ideal for backward- and forward-compatible code and a replacement for magic numbers.
New in version 0.10: Before version 0.10, this enum did not exist and the numeric codes were used bare. Since this is an
IntEnum
, it is possible to use the named enum members and their numeric codes interchangeably.-
NON_ANONYMOUS
= 100¶ Included when entering a room where every user can see every users real JID.
-
AFFILIATION_CHANGE
= 101¶ Included in out-of-band messages informing about affiliation changes.
-
SHOWING_UNAVAILABLE
= 102¶ Inform occupants that room now shows unavailable members.
-
NOT_SHOWING_UNAVAILABLE
= 103¶ Inform occupants that room now does not show unavailable members.
-
CONFIG_NON_PRIVACY_RELATED
= 104¶ Inform occupants that a non-privacy related configuration change has occurred.
-
SELF
= 110¶ Inform that the stanza refers to the addressee themselves.
-
CONFIG_ROOM_LOGGING
= 170¶ Inform that the room is now logged.
-
CONFIG_NO_ROOM_LOGGING
= 171¶ Inform that the room is not logged anymore.
-
CONFIG_NON_ANONYMOUS
= 172¶ Inform that the room is now not anonymous.
-
CONFIG_SEMI_ANONYMOUS
= 173¶ Inform that the room is now semi-anonymous.
-
CREATED
= 201¶ Inform that the room was created during the join operation.
-
REMOVED_BANNED
= 301¶ Inform that the user was banned from the room.
-
NICKNAME_CHANGE
= 303¶ Inform about new nickname.
-
REMOVED_KICKED
= 307¶ Inform that the occupant was kicked.
-
REMOVED_AFFILIATION_CHANGE
= 321¶ Inform that the occupant was removed from the room due to a change in affiliation.
-
REMOVED_NONMEMBER_IN_MEMBERS_ONLY
= 322¶ Inform that the occupant was removed from the room because the room was changed to members-only and the occupant was not a member.
-
REMOVED_SERVICE_SHUTDOWN
= 332¶ Inform that the occupant is being removed because the MUC service is being shut down.
-
REMOVED_ERROR
= 333¶ Inform that the occupant is being removed because there was an error while communicating with them or their server.
-
Attributes added to existing XSOs¶
-
aioxmpp.Message.
xep0045_muc
¶ A
GenericExt
object orNone
.
-
aioxmpp.Presence.
xep0045_muc
¶ A
GenericExt
object orNone
.
-
aioxmpp.Message.
xep0249_direct_invite
¶ A
DirectInvite
object orNone
.