2023-09-02 13:51:00 +00:00
|
|
|
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
|
|
|
|
|
2023-09-02 14:15:15 +00:00
|
|
|
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)
|
2023-09-02 13:51:00 +00:00
|
|
|
|
|
|
|
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()
|
2023-09-02 14:15:15 +00:00
|
|
|
_connection.presence_sink(muc_room.jid, muc_room, "method", "_receive_internal_presence")
|
2023-09-02 13:51:00 +00:00
|
|
|
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,
|
|
|
|
"<x xmlns='http://jabber.org/protocol/muc'/>")
|
|
|
|
if not result.is_ok:
|
|
|
|
return result
|
|
|
|
|
2023-09-02 14:15:15 +00:00
|
|
|
var response = Stanza.presence_result(yield(room, "_presence_received"))
|
2023-09-02 13:51:00 +00:00
|
|
|
if not response.is_ok:
|
|
|
|
return response
|
|
|
|
|
|
|
|
while true:
|
2023-09-02 14:15:15 +00:00
|
|
|
response = Stanza.presence_result(yield(room, "_presence_received"))
|
2023-09-02 13:51:00 +00:00
|
|
|
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:
|
2023-09-02 14:15:15 +00:00
|
|
|
if child.is_element() and child.name == "status" and child.attributes["code"] == "110":
|
2023-09-02 13:51:00 +00:00
|
|
|
return Sums.Result.make_value(room.members[nick])
|
|
|
|
|
|
|
|
return Sums.Result.make_error(null)
|