tochie-facade/scenes/MucService.gd

130 lines
4.3 KiB
GDScript3
Raw Permalink Normal View History

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)