diff options
Diffstat (limited to 'xmpp-vala/src/module/xep')
-rw-r--r-- | xmpp-vala/src/module/xep/0045_muc/flag.vala | 65 | ||||
-rw-r--r-- | xmpp-vala/src/module/xep/0045_muc/module.vala | 109 |
2 files changed, 139 insertions, 35 deletions
diff --git a/xmpp-vala/src/module/xep/0045_muc/flag.vala b/xmpp-vala/src/module/xep/0045_muc/flag.vala index e5e0af6e..159f0193 100644 --- a/xmpp-vala/src/module/xep/0045_muc/flag.vala +++ b/xmpp-vala/src/module/xep/0045_muc/flag.vala @@ -11,21 +11,32 @@ public class Flag : XmppStreamFlag { private HashMap<string, string> own_nicks = new HashMap<string, string>(); private HashMap<string, string> subjects = new HashMap<string, string>(); private HashMap<string, string> subjects_by = new HashMap<string, string>(); + private HashMap<string, string> occupant_real_jids = new HashMap<string, string>(); - private HashMap<string, string> occupant_affiliation = new HashMap<string, string>(); - private HashMap<string, string> occupant_role = new HashMap<string, string>(); + private HashMap<string, HashMap<string, Affiliation>> affiliations = new HashMap<string, HashMap<string, Affiliation>>(); + private HashMap<string, Role> occupant_role = new HashMap<string, Role>(); public string? get_real_jid(string full_jid) { return occupant_real_jids[full_jid]; } - public void set_real_jid(string full_jid, string real_jid) { occupant_real_jids[full_jid] = real_jid; } - - public string? get_occupant_affiliation(string full_jid) { return occupant_affiliation[full_jid]; } - - public void set_occupant_affiliation(string full_jid, string affiliation) { occupant_affiliation[full_jid] = affiliation; } + public Gee.List<string> get_offline_members(string full_jid) { + Gee.List<string> ret = new ArrayList<string>(); + foreach (string muc_jid in affiliations.keys) { + foreach (string jid in affiliations[muc_jid].keys) { + if (!jid.has_prefix(muc_jid)) ret.add(jid); + } + } + return ret; + } - public string? get_occupant_role(string full_jid) { return occupant_role[full_jid]; } + public Affiliation? get_affiliation(string muc_jid, string full_jid) { + if (affiliations.has_key(muc_jid) && affiliations[muc_jid].has_key(full_jid)) return affiliations[muc_jid][full_jid]; + return Affiliation.NONE; + } - public void set_occupant_role(string full_jid, string role) { occupant_role[full_jid] = role; } + public Role? get_occupant_role(string full_jid) { + if (occupant_role.has_key(full_jid)) return occupant_role[full_jid]; + return Role.NONE; + } public string? get_muc_nick(string bare_jid) { return own_nicks[bare_jid]; } @@ -42,22 +53,41 @@ public class Flag : XmppStreamFlag { public string? get_muc_subject(string bare_jid) { return subjects[bare_jid]; } - public void set_muc_subject(string full_jid, string? subject) { + internal void set_real_jid(string full_jid, string real_jid) { occupant_real_jids[full_jid] = real_jid; } + + internal void set_offline_member(string muc_jid, string real_jid, Affiliation affiliation) { + set_affiliation(muc_jid, real_jid, affiliation); + } + + internal void set_affiliation(string muc_jid, string full_jid, Affiliation affiliation) { + if (!affiliations.has_key(muc_jid)) affiliations[muc_jid] = new HashMap<string, Affiliation>(); + if (affiliation == Affiliation.NONE) { + affiliations[muc_jid].unset(full_jid); + } else { + affiliations[muc_jid][full_jid] = affiliation; + } + } + + internal void set_occupant_role(string full_jid, Role role) { + occupant_role[full_jid] = role; + } + + internal void set_muc_subject(string full_jid, string? subject) { string bare_jid = get_bare_jid(full_jid); subjects[bare_jid] = subject; subjects_by[bare_jid] = full_jid; } - public void start_muc_enter(string bare_jid, string presence_id) { + internal void start_muc_enter(string bare_jid, string presence_id) { enter_ids[bare_jid] = presence_id; } - public void finish_muc_enter(string bare_jid, string? nick = null) { + internal void finish_muc_enter(string bare_jid, string? nick = null) { if (nick != null) own_nicks[bare_jid] = nick; enter_ids.unset(bare_jid); } - public void left_muc(XmppStream stream, string muc) { + internal void left_muc(XmppStream stream, string muc) { own_nicks.unset(muc); subjects.unset(muc); subjects_by.unset(muc); @@ -69,15 +99,16 @@ public class Flag : XmppStreamFlag { } } - public void remove_occupant_info(string full_jid) { + internal void remove_occupant_info(string full_jid) { occupant_real_jids.unset(full_jid); - occupant_affiliation.unset(full_jid); + string bare_jid = get_bare_jid(full_jid); + if (affiliations.has_key(full_jid)) affiliations[bare_jid].unset(full_jid); occupant_role.unset(full_jid); } - public override string get_ns() { return NS_URI; } + internal override string get_ns() { return NS_URI; } - public override string get_id() { return IDENTITY.id; } + internal override string get_id() { return IDENTITY.id; } } }
\ No newline at end of file diff --git a/xmpp-vala/src/module/xep/0045_muc/module.vala b/xmpp-vala/src/module/xep/0045_muc/module.vala index badb7d60..9893f8a3 100644 --- a/xmpp-vala/src/module/xep/0045_muc/module.vala +++ b/xmpp-vala/src/module/xep/0045_muc/module.vala @@ -8,17 +8,6 @@ private const string NS_URI = "http://jabber.org/protocol/muc"; private const string NS_URI_ADMIN = NS_URI + "#admin"; private const string NS_URI_USER = NS_URI + "#user"; -public const string AFFILIATION_ADMIN = "admin"; -public const string AFFILIATION_MEMBER = "member"; -public const string AFFILIATION_NONE = "none"; -public const string AFFILIATION_OUTCAST = "outcast"; -public const string AFFILIATION_OWNER = "owner"; - -public const string ROLE_MODERATOR = "moderator"; -public const string ROLE_NONE = "none"; -public const string ROLE_PARTICIPANT = "participant"; -public const string ROLE_VISITOR = "visitor"; - public enum MucEnterError { PASSWORD_REQUIRED, NOT_IN_MEMBER_LIST, @@ -28,12 +17,27 @@ public enum MucEnterError { ROOM_DOESNT_EXIST } +public enum Affiliation { + ADMIN, + MEMBER, + NONE, + OUTCAST, + OWNER +} + +public enum Role { + MODERATOR, + NONE, + PARTICIPANT, + VISITOR +} + public class Module : XmppStreamModule { public static ModuleIdentity<Module> IDENTITY = new ModuleIdentity<Module>(NS_URI, "0045_muc_module"); - public signal void received_occupant_affiliation(XmppStream stream, string jid, string? affiliation); + public signal void received_occupant_affiliation(XmppStream stream, string jid, Affiliation? affiliation); public signal void received_occupant_jid(XmppStream stream, string jid, string? real_jid); - public signal void received_occupant_role(XmppStream stream, string jid, string? role); + public signal void received_occupant_role(XmppStream stream, string jid, Role? role); public signal void subject_set(XmppStream stream, string subject, string jid); public signal void room_configuration_changed(XmppStream stream, string jid, StatusCode code); @@ -92,6 +96,12 @@ public class Module : XmppStreamModule { if (stream.get_module(ServiceDiscovery.Module.IDENTITY) != null) { stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI); } + + room_entered.connect((stream, jid, nick) => { + query_affiliation(stream, jid, "member", null, null); + query_affiliation(stream, jid, "admin", null, null); + query_affiliation(stream, jid, "owner", null, null); + }); } public override void detach(XmppStream stream) { @@ -167,8 +177,10 @@ public class Module : XmppStreamModule { flag.finish_muc_enter(bare_jid, get_resource_part(presence.from)); } } - string? affiliation = x_node.get_deep_attribute("item", "affiliation"); - if (affiliation != null) { + string? affiliation_str = x_node.get_deep_attribute("item", "affiliation"); + if (affiliation_str != null) { + Affiliation affiliation = parse_affiliation(affiliation_str); + flag.set_affiliation(get_bare_jid(presence.from), presence.from, affiliation); received_occupant_affiliation(stream, presence.from, affiliation); } string? jid = x_node.get_deep_attribute("item", "jid"); @@ -176,8 +188,10 @@ public class Module : XmppStreamModule { flag.set_real_jid(presence.from, jid); received_occupant_jid(stream, presence.from, jid); } - string? role = x_node.get_deep_attribute("item", "role"); - if (role != null) { + string? role_str = x_node.get_deep_attribute("item", "role"); + if (role_str != null) { + Role role = parse_role(role_str); + flag.set_occupant_role(presence.from, role); received_occupant_role(stream, presence.from, role); } } @@ -211,13 +225,72 @@ public class Module : XmppStreamModule { } } - private ArrayList<int> get_status_codes(StanzaNode x_node) { + [CCode (has_target = false)] public delegate void OnResult(XmppStream stream, Gee.List<string> jids, Object? store); + private void query_affiliation(XmppStream stream, string jid, string affiliation, OnResult? on_result, Object? store) { + Iq.Stanza iq = new Iq.Stanza.get( + new StanzaNode.build("query", NS_URI_ADMIN) + .add_self_xmlns() + .put_node(new StanzaNode.build("item", NS_URI_ADMIN) + .put_attribute("affiliation", affiliation)) + ) { to=jid }; + stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, (stream, iq, store) => { + Tuple<OnResult?, Object?> tuple = store as Tuple<OnResult?, Object?>; + if (iq.is_error()) return; + StanzaNode? query_node = iq.stanza.get_subnode("query", NS_URI_ADMIN); + if (query_node == null) return; + Gee.List<StanzaNode> item_nodes = query_node.get_subnodes("item", NS_URI_ADMIN); + Gee.List<string> ret_jids = new ArrayList<string>(); + foreach (StanzaNode item in item_nodes) { + string? jid_ = item.get_attribute("jid"); + string? affiliation_ = item.get_attribute("affiliation"); + if (jid_ != null && affiliation_ != null) { + stream.get_flag(Muc.Flag.IDENTITY).set_offline_member(iq.from, jid_, parse_affiliation(affiliation_)); + ret_jids.add(jid_); + } + } + if (tuple.a != null) tuple.a(stream, ret_jids, tuple.b); + }, Tuple.create(on_result, store)); + } + + private static ArrayList<int> get_status_codes(StanzaNode x_node) { ArrayList<int> ret = new ArrayList<int>(); foreach (StanzaNode status_node in x_node.get_subnodes("status", NS_URI_USER)) { ret.add(int.parse(status_node.get_attribute("code"))); } return ret; } + + private static Affiliation parse_affiliation(string affiliation_str) { + Affiliation affiliation; + switch (affiliation_str) { + case "admin": + affiliation = Affiliation.ADMIN; break; + case "member": + affiliation = Affiliation.MEMBER; break; + case "outcast": + affiliation = Affiliation.OUTCAST; break; + case "owner": + affiliation = Affiliation.OWNER; break; + default: + affiliation = Affiliation.NONE; break; + } + return affiliation; + } + + private static Role parse_role(string role_str) { + Role role; + switch (role_str) { + case "moderator": + role = Role.MODERATOR; break; + case "participant": + role = Role.PARTICIPANT; break; + case "visitor": + role = Role.VISITOR; break; + default: + role = Role.NONE; break; + } + return role; + } } } |