muc.vala
changeset 11 0f0cf428409f
parent 9 d3260253f0bd
--- a/muc.vala	Wed Oct 24 15:07:07 2012 +0400
+++ b/muc.vala	Mon Nov 05 23:53:52 2012 +0400
@@ -35,6 +35,15 @@
         }
         return Role.NONE;
     }
+    static string role_to_string(Role role) {
+        switch (role) {
+            case Role.MODERATOR: return "moderator";
+            case Role.PARTICIPANT: return "participant";
+            case Role.VISITOR: return "visitor";
+        }
+        return "none";
+    }
+
     static Affiliation affil_from_string(string affil) {
         switch (affil) {
             case "owner": return Affiliation.OWNER;
@@ -44,6 +53,15 @@
         }
         return Affiliation.NONE;
     }
+    static string affil_to_string(Affiliation affil) {
+        switch (affil) {
+            case Affiliation.OWNER: return "owner";
+            case Affiliation.ADMIN: return "admin";
+            case Affiliation.MEMBER: return "member";
+            case Affiliation.OUTCAST: return "outcast";
+        }
+        return "none";
+    }
 
     public class Occupant : Object {
         public weak Conference conference;
@@ -53,6 +71,12 @@
         public Affiliation affil;
         public Role role;
         public bool isme;
+        public void public_message(string text) {
+            var msg = new Lm.Message(conference.jid, Lm.MessageType.MESSAGE);
+            msg.node.set_attribute("type","groupchat");
+            msg.node.add_child("body",nick+": "+text);
+            conference.module.conn.cn.send(msg);
+        }
     }
 
     public enum State {
@@ -84,7 +108,9 @@
         public State state { get { return _state; } }
         public Gee.HashMap<string,Occupant> occupants;
         protected string presence_join_id;
-        protected weak ModuleMuc module;
+        public string pingcheck_id;
+        public time_t last_check;
+        public weak ModuleMuc module;
 
         protected void _change_state(State new_state, string description) {
             var old_state = this._state;
@@ -201,6 +227,7 @@
                                     occupant.role = role;
                                     occupant.affil = affil;
                                     occupant.nick = from[1];
+                                    occupant.conference = this;
                                     occupants[from[1]] = occupant;
                                     occupant.isme = statuses.contains(110);
                                     log("Muc", LogLevelFlags.LEVEL_INFO, "MUC<%s> %s has joined as %s/%s.", this.jid, from[1], affil.to_string(), role.to_string());
@@ -209,8 +236,11 @@
                                         _change_state(State.CONNECTED, "got own presence. we are "+this.nick);
                                     }
                                     module.on_join(this, occupant);
-                                } else
+                                } else {
+                                    if (statuses.contains(110))
+                                        _change_state(State.DISCONNECTED, "got role none while joining");
                                     log("Muc", LogLevelFlags.LEVEL_WARNING, "Got NONE role for new participant. Maybe we are reconnecting.");
+                                }
                             }
                             
                             stdout.printf("User list: ");
@@ -229,19 +259,27 @@
                         }
                         break;
                 }
-            } else if ((message.get_type()==Lm.MessageType.MESSAGE)&&(type=="groupchat")) {
-                var subj = node.get_attribute("subject");
-                var occupant = (from.length > 1) ? occupants[from[1]] : null;
-                if (subj != null) {
-                    if (subj != this.subject) {
-                        this.subject = subj;
-                        module.on_subject(this, occupant);
-                    }
-                } else {
-                    var body = node.find_child("body");
-                    module.on_message(this, occupant, node, (body!=null) ? body.get_value() : null);
+            } else if (message.get_type()==Lm.MessageType.MESSAGE)
+                switch (type) {
+                    case "groupchat":
+                        var subj = node.get_attribute("subject");
+                        var occupant = (from.length > 1) ? occupants[from[1]] : null;
+                        if (subj != null) {
+                            if (subj != this.subject) {
+                                this.subject = subj;
+                                module.on_subject(this, occupant);
+                            }
+                        } else {
+                            var body = node.find_child("body");
+                            module.on_message(this, occupant, node, (body!=null) ? body.get_value() : null);
+                        }
+                        break;
+                    case "error":
+                        if (node.get_attribute("id")==pingcheck_id) {
+                            _change_state(State.DISCONNECTED, node.get_child("error").to_string());
+                        }
+                        break;
                 }
-            }
             return Lm.HandlerResult.ALLOW_MORE_HANDLERS;
         }
         public void part(string desc) {
@@ -305,6 +343,18 @@
                     if (room.enabled) {
                         if (room.state == State.DISCONNECTED)
                             room.join("Reconnect");
+                        else {
+                            time_t curtime = time_t();
+                            if ((curtime - room.last_check) > 60) { // crappy check for netsplits
+                                room.last_check = curtime;
+                                var msg = new Lm.Message(room.jid, Lm.MessageType.MESSAGE);
+                                room.pingcheck_id = room.jid+"_"+Random.next_int().to_string();
+                                msg.node.set_attribute("id",room.pingcheck_id);
+                                log("Muc", LogLevelFlags.LEVEL_DEBUG, "Ping check to %s", room.jid);
+                                room.module.conn.cn.send(msg);
+
+                            }
+                        }
                     } else {
                         if (room.state == State.CONNECTED)
                             room.part("Disabled");