extends Reference class_name MucService ## https://xmpp.org/extensions/xep-0045.html class MucRoom extends Reference: var jid: String var name: String var members: Dictionary # nick to MucMember signal message_received(message) signal member_presence(member) signal _presence_received(presence) func _receive_internal_presence(presence) -> void: ## First do internal book keeping ... if presence.children.size() > 0: var x = presence.get_named_child_element("x") if x.name == "x" and x.attributes["xmlns"] == "http://jabber.org/protocol/muc#user": ## Member information came. var item = x.get_named_child_element("item") var nick = Stanza.extract_resource_part(presence.attributes["from"]) var member = MucMember.new() member.jid = presence.attributes["from"] member.nick = nick member.role = item.attributes["role"] member.affiliation = item.attributes["affiliation"] # member.room = self members[nick] = member emit_signal("member_presence", member) ## ... then propagate outside. emit_signal("_presence_received", presence) func as_string() -> String: return "MucRoom \"%s\", Jid: \"%s\"" % [name, jid] class MucMember extends Reference: var jid: String var nick: String var role: String # var room: MucRoom var affiliation: String var jid: String var _connection: Connections.Connection var _rooms_promise: Sums.Promise = null func try_init(connection: Connections.Connection, p_jid: String, disco_info: Xml.XmlElement): var is_muc := false for item in disco_info.children: if item.is_element() and item.name == "feature": if item.attributes["var"] == "http://jabber.org/protocol/muc": is_muc = true break if not is_muc: return null self.jid = p_jid self._connection = connection return self func request_rooms() -> Sums.Promise: if self._rooms_promise != null: return self._rooms_promise self._rooms_promise = _connection.promise_iq( jid, "get", Stanza.disco_items_queury, _iq_rooms()) return self._rooms_promise func _iq_rooms() -> Sums.Result: var response = yield() if not response.is_ok: return response var query := Stanza.unwrap_query_result(response.value) if not query.is_ok: return query var rooms := Array() for item in query.value.children: if item.is_element() and item.name == "item": var muc_room := MucRoom.new() _connection.presence_sink(muc_room.jid, muc_room, "method", "_receive_internal_presence") muc_room.jid = item.attributes["jid"] muc_room.name = item.attributes["name"] rooms.push_back(muc_room) return Sums.Result.make_value(rooms) ## Returns MucMemeber that is registered on behalf on user. func join_room(room: MucRoom, nick: String) -> Sums.Promise: # todo: https://xmpp.org/extensions/xep-0045.html#reservednick return Sums.Promise.from(_join_room(room, nick)) func _join_room(room: MucRoom, nick: String) -> Sums.Result: var member_jid = room.jid + '/' + nick var result = _connection.push_presence(member_jid, null, "") if not result.is_ok: return result var response = Stanza.presence_result(yield(room, "_presence_received")) if not response.is_ok: return response while true: response = Stanza.presence_result(yield(room, "_presence_received")) if not response.is_ok: return response if response.value.attributes["from"] == member_jid: if response.value.children.size() == 0: continue var x = response.value.children[0] if x.name != "x" and x.attributes["xmlns"] != "http://jabber.org/protocol/muc#user": continue for child in x.children: if child.is_element() and child.name == "status" and child.attributes["code"] == "110": return Sums.Result.make_value(room.members[nick]) return Sums.Result.make_error(null)