--- a/muc.vala Fri Oct 19 00:38:54 2012 +0400
+++ b/muc.vala Tue Oct 23 18:33:49 2012 +0400
@@ -10,6 +10,8 @@
}
class ModuleMuc : Module {
+ public static const string NS_MUC_USER = "http://jabber.org/protocol/muc#user";
+
public enum Affiliation {
NONE,
OUTCAST,
@@ -66,12 +68,14 @@
public signal void on_role(Conference conf, Occupant occupant, Role prev);
public signal void on_affil(Conference conf, Occupant occupant, Affiliation prev);
public signal void on_nick(Conference conf, Occupant occupant, string prev);
+ public signal void on_message(Conference conf, Occupant occupant, Lm.MessageNode message, string body);
public signal void on_subject(Conference conf);
public class Conference : Object {
public string jid;
public string nick;
public string desired_nick;
+ public bool enabled;
public string subject;
protected State _state;
@@ -87,6 +91,8 @@
this._state = new_state;
stderr.printf("MUC State changed %s -> %s : %s\n",old_state.to_string(), new_state.to_string(), description);
module.state_changed(this, old_state, new_state, description);
+ if (new_state == State.DISCONNECTED)
+ occupants.clear();
} else
stderr.printf("MUC State not changed %s : %s\n",old_state.to_string(), description);
}
@@ -94,7 +100,7 @@
public Conference(ModuleMuc module, string jid) {
this.module = module;
var section = "muc "+jid;
- this.desired_nick = module.cfg[section,"nick"];
+ this.desired_nick = module.cfg.get_default(section,"nick",module.cfg.get_default("muc","nick",Random.next_int().to_string()));
this.nick = this.desired_nick;
this.jid = jid;
this._state = State.DISCONNECTED;
@@ -108,7 +114,7 @@
prs.node.add_child("x",null).set_attribute("xmlns","http://jabber.org/protocol/muc");
module.conn.cn.send(prs);
nick = desired_nick;
- _change_state(State.CONNECTING, "requested to join");
+ _change_state(State.CONNECTING, "requested to join: "+desc);
}
}
@@ -123,41 +129,51 @@
case "unavailable":
if (from.length==2) {
var statuses = new Gee.HashSet<int>();
+ var occupant = occupants[from[1]];
+ var affil = Affiliation.NONE;
+ var role = Role.NONE;
+ string prs_nick = null;
- var x = node.get_child("x");
- var child = x!=null ? x.children : null;
- while (child != null) {
- stdout.printf("Child %s %s\n", child.name, child.get_attribute("code"));
- if (child.name == "status") {
- var code = child.get_attribute("code");
- if (code!=null)
- statuses.add(code.to_int());
+ var chn = node.children;
+ while (chn != null) {
+ switch (chn.name) {
+
+ case "x":
+ switch (chn.get_attribute("xmlns")) {
+ case NS_MUC_USER:
+ var child = chn.children;
+ while (child != null) {
+ stdout.printf("Child %s %s\n", child.name, child.get_attribute("code"));
+ if (child.name == "status") {
+ var code = child.get_attribute("code");
+ if (code!=null)
+ statuses.add(code.to_int());
+ }
+ child = child.next;
+ }
+ var item = chn.get_child("item");
+ if (item == null)
+ log("Muc", LogLevelFlags.LEVEL_ERROR, "Your MUC server is shit. No role and affiliation info in presences: %s", node.to_string());
+ affil = affil_from_string(item.get_attribute("affiliation"));
+ role = role_from_string(item.get_attribute("role"));
+ prs_nick = item.get_attribute("nick");
+ break;
+ }
+ break;
}
- child = child.next;
+ chn = chn.next;
}
if (statuses.contains(110) && (_state == State.CONNECTED))
log("Muc", LogLevelFlags.LEVEL_INFO, "Joined a room which I was already in: %s", from[0]);
- var occupant = occupants[from[1]];
- var item = x != null ? x.get_child("item") : null;
- var affil = Affiliation.NONE;
- var role = Role.NONE;
- string nick = null;
- if (item != null) {
- affil = affil_from_string(item.get_attribute("affiliation"));
- role = role_from_string(item.get_attribute("role"));
- nick = item.get_attribute("nick");
- } else
- log("Muc", LogLevelFlags.LEVEL_ERROR, "Your MUC server is shit. No role and affiliation info in presences: %s", node.to_string());
if (occupant != null) {
if (role == Role.NONE) {
occupants.unset(from[1]);
log("Muc", LogLevelFlags.LEVEL_INFO, "MUC<%s> %s has parted.", this.jid, from[1]);
module.on_part(this, occupant);
- if (from[1]==this.nick) {
+ if (occupant.isme) {
_change_state(State.DISCONNECTED, "we became unavailable");
- occupants.clear();
}
} else {
if (affil != occupant.affil) {
@@ -170,10 +186,10 @@
occupant.role = role;
module.on_role(this, occupant, prev);
}
- if (statuses.contains(303) && (nick!=null)) {
- occupants[nick] = occupant;
+ if (statuses.contains(303) && (prs_nick!=null)) {
+ occupants[prs_nick] = occupant;
occupants.unset(from[1]);
- occupant.nick = nick;
+ occupant.nick = prs_nick;
module.on_nick(this, occupant, from[1]);
}
}
@@ -186,8 +202,10 @@
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());
- if (statuses.contains(110))
+ if (statuses.contains(110)) {
+ this.nick = from[1];
_change_state(State.CONNECTED, "got own presence. we are "+this.nick);
+ }
module.on_join(this, occupant);
}
@@ -214,11 +232,27 @@
this.subject = subj;
module.on_subject(this);
}
+ } else {
+ var occupant = (from.length > 1) ? occupants[from[1]] : null;
+ var body = node.find_child("body");
+ module.on_message(this, occupant, node, (body!=null) ? body.get_value() : null);
}
}
return Lm.HandlerResult.ALLOW_MORE_HANDLERS;
}
public void part(string desc) {
+ if (_state != State.DISCONNECTED) {
+ var prs = new Lm.Message(jid+"/"+desired_nick, Lm.MessageType.PRESENCE);
+ presence_join_id = jid+"_"+Random.next_int().to_string();
+ prs.node.set_attribute("type","unavailable");
+ prs.node.add_child("x",null).set_attribute("xmlns","http://jabber.org/protocol/muc");
+ module.conn.cn.send(prs);
+ nick = desired_nick;
+ }
+ }
+
+ public void connection_lost() {
+ _change_state(State.DISCONNECTED, "connection lost");
}
}
@@ -241,15 +275,37 @@
}
return Lm.HandlerResult.ALLOW_MORE_HANDLERS;
}, null);
+ var names = cfg.get_default("muc","mucs","").split(" ");
+ foreach (var name in names) {
+ var room = new Conference(this, name); //, "Ζαλυπα");
+ //room.join("Oh hai");
+ room.enabled = true;
+ this.rooms[room.jid] = room;
+ }
conn.cn.register_message_handler(muc_handler, Lm.MessageType.MESSAGE, Lm.HandlerPriority.NORMAL);
conn.cn.register_message_handler(muc_handler, Lm.MessageType.PRESENCE, Lm.HandlerPriority.NORMAL);
conn.cn.register_message_handler(muc_handler, Lm.MessageType.IQ, Lm.HandlerPriority.NORMAL);
conn.state_changed.connect( (olds, news, desc) => {
- if (news == Connection.State.CONNECTED) {
- var room = new Conference(this, "говнохост@conference.blasux.ru"); //, "Ζαλυπα");
- room.join("Oh hai");
- this.rooms[room.jid] = room;
+ switch (news) {
+ case Connection.State.CONNECTED:
+ break;
+ case Connection.State.DISCONNECTED:
+ foreach(var room in rooms.values)
+ room.connection_lost();
+ break;
}
});
+ conn.check_time.connect( () => {
+ if (conn.state == Connection.State.CONNECTED)
+ foreach (var room in rooms.values) {
+ if (room.enabled) {
+ if (room.state == State.DISCONNECTED)
+ room.join("Reconnect");
+ } else {
+ if (room.state == State.CONNECTED)
+ room.part("Disabled");
+ }
+ }
+ });
}
}