user keeping

This commit is contained in:
veclav talica 2023-09-02 19:15:15 +05:00
parent 2779ee566e
commit 9647c5a3b4
6 changed files with 52 additions and 30 deletions

View File

@ -50,7 +50,7 @@ _global_script_class_icons={
[application]
config/name="tochie"
config/name="tochie-facade"
run/main_scene="res://scenes/App.tscn"
run/low_processor_mode=true
config/icon="res://icon.png"

View File

@ -31,3 +31,7 @@ func _ready():
for room in rooms_request.value:
var me = service.muc.join_room(room, "tochie-facade")
if not me.is_done:
yield(me, "done")
print("Chat joined")

View File

@ -12,7 +12,7 @@ class Connection extends Reference:
var _id_counter: int = 0
var _pending_iqs: Dictionary # of id to GDScriptFunctionState
var _presence_sinks: Dictionary # of Jid to [[WeakRef, String]]
var _presence_sinks: Dictionary # of Jid to [[WeakRef, String, String]]
var _xml_parser := Xml.Parser.new()
# todo: Route signals to particular receivers, based on 'from' or 'to'
@ -59,9 +59,9 @@ class Connection extends Reference:
return Sums.Result.make_value(null)
func presence_sink(p_base_jid: String, p_sink: Object, p_signal: String) -> void:
func presence_sink(p_base_jid: String, p_sink: Object, p_type: String, p_signal: String) -> void:
self._presence_sinks[p_base_jid] = \
self._presence_sinks.get(p_base_jid, []) + [[weakref(p_sink), p_signal]]
self._presence_sinks.get(p_base_jid, []) + [[weakref(p_sink), p_type, p_signal]]
## Registry of connections used for poking of pending iqs.
var _connections: Array # of WeakRef to Connection
@ -91,7 +91,6 @@ func _process_connections() -> void:
response = null
var stanza := connection._xml_parser.take_root()
print(stanza.as_string())
if stanza.name == "iq":
if "to" in stanza.attributes and stanza.attributes["to"] != connection.jid:
@ -118,8 +117,17 @@ func _process_connections() -> void:
if not stanza.attributes["from"].begins_with(base_jid):
continue
for to_emit in connection._presence_sinks[base_jid]:
to_emit[0].emit_signal(to_emit[1], stanza)
var sink = connection._presence_sinks[base_jid]
var sink_idx := 0
while sink_idx < sink.size():
var ref = sink[sink_idx][0].get_ref()
if ref == null:
sink.remove(sink_idx)
else:
if sink[sink_idx][1] == "signal":
ref.emit_signal(sink[sink_idx][2], stanza)
else: ref.call(sink[sink_idx][2], stanza)
sink_idx += 1
## Collect dropped connections.
for idx in range(to_remove.size() - 1, 0, -1):

View File

@ -8,27 +8,31 @@ class MucRoom extends Reference:
var name: String
var members: Dictionary # nick to MucMember
signal presence_received(presence)
signal message_received(message)
signal member_presence(member)
func _init() -> void:
if self.connect("presence_received", self, "_presence_received") != OK:
assert(false)
signal _presence_received(presence)
func _presence_received(presence) -> void:
if presence.children.size() == 0:
return
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 = presence.attributes["from"].rsplit("/").pop_front()
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
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]
@ -84,7 +88,7 @@ func _iq_rooms() -> Sums.Result:
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, "presence_received")
_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)
@ -103,12 +107,12 @@ func _join_room(room: MucRoom, nick: String) -> Sums.Result:
if not result.is_ok:
return result
var response = Stanza.presence_result(yield(room, "presence_received"))
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"))
response = Stanza.presence_result(yield(room, "_presence_received"))
if not response.is_ok:
return response
@ -119,7 +123,7 @@ func _join_room(room: MucRoom, nick: String) -> Sums.Result:
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.attrbiutes["code"] == "110":
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)

View File

@ -19,6 +19,7 @@ func _service_discovery(connection: Connections.Connection) -> Sums.Result:
var poly_services := Array()
for item in query.value.children:
# todo: Do this at the same time, in separate coroutines.
if not item.is_element() or item.name != "item":
continue

View File

@ -43,3 +43,8 @@ static func presence_result(stanza: Xml.XmlElement) -> Sums.Result:
return Sums.Result.make_error(stanza)
else:
return Sums.Result.make_value(stanza)
static func extract_resource_part(jid: String) -> String:
var parts = jid.rsplit("/")
assert(parts.size() > 0)
return parts[parts.size() - 1]