| author | Stephen Paul Weber
<singpolyma@singpolyma.net> 2025-11-19 19:46:26 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2025-11-19 19:46:26 UTC |
| parent | 78200c923ecb8d868321155b0156230de2c507cd |
| borogove/Chat.hx | +25 | -5 |
| borogove/MucUser.hx | +35 | -0 |
| borogove/Presence.hx | +3 | -2 |
diff --git a/borogove/Chat.hx b/borogove/Chat.hx index 58f823f..3ef2f9c 100644 --- a/borogove/Chat.hx +++ b/borogove/Chat.hx @@ -694,6 +694,13 @@ abstract class Chat { } } + /** + Can the user send messages to this chat? + **/ + public function canSend() { + return Caps.withFeature(getCaps(), "urn:xmpp:noreply:0").length < 1; + } + /** Does this chat provide a menu of commands? **/ @@ -1200,13 +1207,25 @@ class Channel extends Chat { return disco?.data?.find(d -> d.field("FORM_TYPE")?.value?.at(0) == "http://jabber.org/protocol/muc#roominfo"); } + @HaxeCBridge.noemit // on superclass as abstract + override public function canSend() { + if (!super.canSend()) return false; + if (_nickInUse == null) return true; + + final p = presence[_nickInUse]; + if (p == null) return true; + + return p.mucUser.role != "visitor"; + } + @:allow(borogove) override private function getCaps():KeyValueIterator<String, Caps> { return ["" => disco].keyValueIterator(); } - override public function setPresence(resource:String, presence:Presence) { - final oneTen = presence?.mucUser?.allTags("status").find((status) -> status.attr.get("code") == "110"); + @:allow(borogove) + override private function setPresence(resource:String, presence:Presence) { + final oneTen = presence?.mucUser?.statusCodes?.find((status) -> status == "110"); if (oneTen != null) { _nickInUse = resource; outbox.start(); @@ -1216,14 +1235,15 @@ class Channel extends Chat { } if (presence != null && presence.mucUser != null && oneTen == null) { final existing = this.presence.get(resource); - if (existing != null && existing?.mucUser?.allTags("status").find((status) -> status.attr.get("code") == "110") != null) { - presence.mucUser.tag("status", { code: "110" }); + if (existing != null && existing?.mucUser?.statusCodes?.find((status) -> status == "110") != null) { + final mucUser: Stanza = presence.mucUser; + mucUser.tag("status", { code: "110" }).up(); setPresence(resource, presence); return; } } super.setPresence(resource, presence); - final tripleThree = presence?.mucUser?.allTags("status").find((status) -> status.attr.get("code") == "333"); + final tripleThree = presence?.mucUser?.statusCodes?.find((status) -> status == "333"); if (oneTen != null && tripleThree != null) { selfPing(true); } diff --git a/borogove/MucUser.hx b/borogove/MucUser.hx new file mode 100644 index 0000000..1c8ced7 --- /dev/null +++ b/borogove/MucUser.hx @@ -0,0 +1,35 @@ +package borogove; + +import borogove.Stanza; +import borogove.JID; + +@:forward(toString) +abstract MucUser(Stanza) from Stanza to Stanza { + public var statusCodes(get, never): Array<String>; + public var role(get, never): String; + public var affiliation(get, never): String; + public var jid(get, never): Null<JID>; + + inline private function get_statusCodes() { + return this.allTags("status").map(el -> el.attr.get("code")); + } + + inline private function get_role() { + return item()?.attr?.get("role") ?? "none"; + } + + inline private function get_affiliation() { + return item()?.attr?.get("affiliation") ?? "none"; + } + + inline private function get_jid() { + final jid = item()?.attr?.get("jid"); + if (jid == null) return null; + + return JID.parse(jid); + } + + inline private function item() { + return this.getChild("item"); + } +} diff --git a/borogove/Presence.hx b/borogove/Presence.hx index 64b9261..987e916 100644 --- a/borogove/Presence.hx +++ b/borogove/Presence.hx @@ -1,14 +1,15 @@ package borogove; +import borogove.MucUser; import borogove.Hash; @:expose class Presence { public var caps:Null<Caps>; - public final mucUser:Null<Stanza>; + public final mucUser:Null<MucUser>; public final avatarHash:Null<Hash>; - public function new(caps: Null<Caps>, mucUser: Null<Stanza>, avatarHash: Null<Hash>) { + public function new(caps: Null<Caps>, mucUser: Null<MucUser>, avatarHash: Null<Hash>) { this.caps = caps; this.mucUser = mucUser; this.avatarHash = avatarHash;