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 and asyncio.Future.

Join a multi-user chat at mucjid with nick. Return a Room instance which is used to track the MUC locally and a aioxmpp.Future which becomes done when the join succeeded (with a None value) or failed (with an exception).

In addition, the on_conversation_added() signal is emitted immediately with the new Room.

It is recommended to attach the desired signals to the Room before yielding next (e.g. in a non-deferred event handler to the on_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 after join() returned. (This is also the reason why join() 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:

coroutine 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:aioxmpp.forms.Data

See also

ConfigurationForm
for a form template to work with the returned form

New in version 0.7.

coroutine set_affiliation(mucjid, jid, affiliation, *, reason=None)[source]

Change the affiliation of an entity with a MUC.

Parameters:
  • mucjid (JID) – The bare JID identifying the MUC.
  • jid (JID) – The bare JID of the entity whose affiliation shall be changed.
  • affiliation (str) – The new affiliation for the entity.
  • reason (str or None) – Optional reason for the affiliation change.

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.

coroutine 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 query
  • data (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.

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 or None) – The address of the inviter.
  • mode (im.InviteMode) – The type of the invitation.
  • password (str or None) – Password for the MUC.
  • reason (str or None) – Text accompanying 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 the muc_ 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 match AbstractConversation.

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 this Room tracks.

me

A Occupant instance which tracks the local user. This is None until on_enter() is emitted; it is never set to None again, but the identity of the object changes on each on_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 until on_exit() is emitted.

When it becomes false, the Room is removed from the bookkeeping of the MUCClient 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 is None, this can be cleared after on_enter() has been emitted.

The following methods and properties provide interaction with the MUC itself:

coroutine ban(member, reason=None, *, request_kick=True)[source]

Ban an occupant from re-joining the MUC.

Parameters:
  • member (Occupant) – The occupant to ban.
  • reason (str) – A reason to show to the members of the conversation including the banned member.
  • request_kick (bool) – A flag indicating that the member should be removed from the conversation immediately, too.

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.

coroutine kick(member, reason=None)[source]

Kick an occupant from the MUC.

Parameters:
  • member (Occupant) – The member to kick.
  • reason (str) – A reason to show to the members of the conversation including the kicked member.
Raises:

aioxmpp.errors.XMPPError – if the server returned an error for the kick command.

See also

AbstractConversation.kick() for the full interface specification.

coroutine leave()[source]

Leave the MUC.

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:StanzaToken

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 the response attribute.

Note

Two things:

  1. 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.
  2. 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() before on_join() has emitted will cause the member object in the resulting on_message() event to be None (the message will be delivered just fine).

Using send_message_tracked() before history replay is over will cause the on_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.

coroutine 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.

coroutine 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.

coroutine 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.

coroutine muc_set_role(nick, role, *, reason=None)[source]

Change the role of an occupant.

Parameters:
  • nick (str) – The nickname of the occupant whose role shall be changed.
  • role (str) – The new role for the occupant.
  • reason – An optional reason to show to the occupant (and all others).

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.

coroutine 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 to mucjid.

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 corresponding UserExt, 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 the AbstractConversation 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 of int or StatusCode) – The set of status codes received in the initial join.

New in version 0.10.

signal on_message(msg, member, source, **kwargs)

A message occured 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 (see send_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, all Occupant 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 of members. 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 or None) – 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, only on_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:
  • member (Occupant) – The occupant whose nick has changed.
  • old_nick (str or None) – The old nickname of the member.
  • new_nick (str) – The new nickname of the member.
  • muc_status_codes (Set of int or StatusCode) – The set of status codes received in the leave notification.

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 or None) – 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 chagne 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 of int or StatusCode) – 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 before on_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 of int or StatusCode) – 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 then on_leave() (with LeaveMode.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 of int or StatusCode) – 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 of int or StatusCode) – 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:

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 of muc_ping_timeout or muc_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.

class aioxmpp.muc.RoomState[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[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.

ERROR

The user was removed due to an error when communicating with the client or the users server.

Not all servers support this. If not supported by the server, one will typically see a KICKED status code with an appropriate status message.

New in version 0.10.

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.

conversation_jid

The JID of the conversation member relative to the conversation.

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.

affiliation

The affiliation of the occupant with the room. This may be None with faulty MUC implementations.

role

The current role of the occupant within the room. This may be None with faulty MUC implementations.

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.

affiliation None

The affiliation of the service. Always None.

role None

The role of the service. Always None.

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[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 field muc#roomconfig_allowinvites

Whether to Allow Occupants to Invite Others

allowpm

list-single field muc#roomconfig_allowpm

Roles that May Send Private Messages

changesubject

boolean field muc#roomconfig_changesubject

Whether to Allow Occupants to Change Subject

enablelogging

boolean field muc#roomconfig_enablelogging

Whether to Enable Public Logging of Room Conversations

getmemberlist

list-multi field muc#roomconfig_getmemberlist

Roles and Affiliations that May Retrieve Member List

lang

text-single field muc#roomconfig_lang

Natural Language for Room Discussions

maxhistoryfetch

text-single field muc#maxhistoryfetch

Maximum Number of History Messages Returned by Room

maxusers

list-single field muc#roomconfig_maxusers

Maximum Number of Room Occupants

membersonly

boolean field muc#roomconfig_membersonly

Whether to Make Room Members-Only

moderatedroom

boolean field muc#roomconfig_moderatedroom

Whether to Make Room Moderated

passwordprotectedroom

boolean field muc#roomconfig_passwordprotectedroom

Whether a Password is Required to Enter

persistentroom

boolean field muc#roomconfig_persistentroom

Whether to Make Room Persistent

presencebroadcast

list-multi field muc#roomconfig_presencebroadcast

Roles for which Presence is Broadcasted

publicroom

boolean field muc#roomconfig_publicroom

Whether to Allow Public Searching for Room

pubsub

text-single field muc#roomconfig_pubsub

XMPP URI of Associated Publish-Subscribe Node

roomadmins

jid-multi field muc#roomconfig_roomadmins

Full List of Room Admins

roomdesc

text-single field muc#roomconfig_roomdesc

Short Description of Room

roomname

text-single field muc#roomconfig_roomname

Natural-Language Room Name

roomowners

jid-multi field muc#roomconfig_roomowners

Full List of Room Owners

roomsecret

text-private field muc#roomconfig_roomsecret

The Room Password

whois

list-single field muc#roomconfig_whois

Affiliations that May Discover Real JIDs of Occupants

class aioxmpp.muc.InfoForm[source]
contactjid

jid-multi field muc#roominfo_contactjid

Contact Addresses (normally, room owner or owners)

description

text-single field muc#roominfo_description

Short Description of Room

lang

text-single field muc#roominfo_lang

Natural Language for Room Discussions

ldapgroup

text-single field muc#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 field muc#roominfo_logs

URL for Archived Discussion Logs

maxhistoryfetch

text-single field muc#maxhistoryfetch

Maximum Number of History Messages Returned by Room

occupants

text-single field muc#roominfo_occupants

Current Number of Occupants in Room

subject

text-single field muc#roominfo_subject

Current Discussion Topic

subjectmod

boolean field muc#roominfo_subjectmod

The room subject can be modified by participants

class aioxmpp.muc.VoiceRequestForm[source]
jid

jid-single field muc#jid

User ID

request_allow

boolean field muc#request_allow

Whether to grant voice

role

list-single field muc#role

Requested role

roomnick

text-single field muc#roomnick

Room Nickname

XSOs

class aioxmpp.muc.StatusCode[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 interchangably.

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.

Inform occupants that a non-privacy related configuration change has occured.

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 or None.

aioxmpp.Message.xep0045_muc_user

A UserExt object or None.

aioxmpp.Presence.xep0045_muc

A GenericExt object or None.

aioxmpp.Presence.xep0045_muc_user

A UserExt object or None.

aioxmpp.Message.xep0249_direct_invite

A DirectInvite object or None.

Generic namespace

class aioxmpp.muc.xso.GenericExt(*args, **kwargs)[source]
class aioxmpp.muc.xso.History(*, maxchars=None, maxstanzas=None, seconds=None, since=None)[source]

User namespace

class aioxmpp.muc.xso.UserExt(status_codes=[], destroy=None, decline=None, invites=[], items=[], password=None)[source]
class aioxmpp.muc.xso.Status(code)[source]
class aioxmpp.muc.xso.DestroyNotification(*args, **kwargs)[source]
class aioxmpp.muc.xso.Decline(*args, **kwargs)[source]
class aioxmpp.muc.xso.Invite(*args, **kwargs)[source]
class aioxmpp.muc.xso.UserItem(affiliation=None, jid=None, nick=None, role=None, reason=None)[source]
class aioxmpp.muc.xso.UserActor(*args, **kwargs)[source]
class aioxmpp.muc.xso.Continue(*args, **kwargs)[source]

Admin namespace

class aioxmpp.muc.xso.AdminQuery(*, items=[])[source]
class aioxmpp.muc.xso.AdminItem(affiliation=None, jid=None, nick=None, role=None, reason=None)[source]
class aioxmpp.muc.xso.AdminActor(*args, **kwargs)[source]

Owner namespace

class aioxmpp.muc.xso.OwnerQuery(*, form=None, destroy=None)[source]
class aioxmpp.muc.xso.DestroyRequest(*args, **kwargs)[source]

XEP-0249 Direct Invitations

class aioxmpp.muc.xso.DirectInvite(jid, *, reason=None, password=None, continue_=False, thread=None)[source]