# HG changeset patch # User Stiletto # Date 1352145284 -14400 # Node ID d3e36b368fc5637bf5f210968e5a545bb23286e3 # Parent 0f0cf428409fc08f348a6073da76a59bf7f99bb1 iq, commands, makefile up diff -r 0f0cf428409f -r d3e36b368fc5 .hgignore --- a/.hgignore Mon Nov 05 23:53:52 2012 +0400 +++ b/.hgignore Mon Nov 05 23:54:44 2012 +0400 @@ -1,4 +1,7 @@ ^config.ini$ ^iswydt-bot$ -.swp$ +.sw[op]$ ^cfiles/ +^logs/.*.html$ +^test/ +^version.vala$ diff -r 0f0cf428409f -r d3e36b368fc5 Makefile --- a/Makefile Mon Nov 05 23:53:52 2012 +0400 +++ b/Makefile Mon Nov 05 23:54:44 2012 +0400 @@ -5,11 +5,14 @@ VALAONLYLIBS := posix VALALIBS := $(patsubst %, --pkg %, $(LIBS) $(VALAONLYLIBS)) VFLAGS = -g +SOURCES = iswydt.vala config.vala simple_iq.vala muc.vala muc_log.vala muc_commands.vala version.vala -iswydt-bot: iswydt.vala config.vala muc.vala muc_log.vala +version.vala: . + echo "static const string IswydtVersion = \"$$(hg id -bnit)\";" > version.vala +iswydt-bot: $(SOURCES) $(VALAC) $(VFLAGS) $(VALALIBS) -o $@ $^ -cfiles: iswydt.vala config.vala muc.vala muc_log.vala +cfiles: $(SOURCES) $(VALAC) $(VFLAGS) $(VALALIBS) -C $^ mkdir -p cfiles mv *.c cfiles/ diff -r 0f0cf428409f -r d3e36b368fc5 iswydt.vala --- a/iswydt.vala Mon Nov 05 23:53:52 2012 +0400 +++ b/iswydt.vala Mon Nov 05 23:54:44 2012 +0400 @@ -167,7 +167,9 @@ }); checktimer.attach(loop.get_context()); + account.add_module(new ModuleIq(cfg, account)); account.add_module(new ModuleMuc(cfg, account)); + account.add_module(new ModuleMucCommands(cfg, account)); account.add_module(new ModuleMucLog(cfg, account)); Posix.sigaction_t action = Posix.sigaction_t(); diff -r 0f0cf428409f -r d3e36b368fc5 muc_commands.vala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/muc_commands.vala Mon Nov 05 23:54:44 2012 +0400 @@ -0,0 +1,94 @@ +using Gee; + +class ModuleMucCommands : Module { + protected weak ModuleMuc muc; + public delegate void CommandHandler(ModuleMuc.Conference conf, ModuleMuc.Occupant user, string command, string? arguments); + public class Command : Object { + public weak Module mod; + public CommandHandler hnd; + } + protected HashMap commands; + + public string getconf(string jid, string key, string? def) { + var res = cfg["muc "+jid, key]; + if (res==null) res = cfg["muc", key]; + if (res==null) res = def; + return res; + } + public bool register(string command, Module mod, CommandHandler handler) { + var cmd = new Command(); + cmd.mod = mod; /* this will cause "copying delegates is discouraged" warning. that's okay, this delegate's data needs no destroy notify */ + cmd.hnd = handler; + if (commands.has_key(command)) + log("muc_commands", LogLevelFlags.LEVEL_WARNING, "Command '%s' defined by '%s' was redefined by '%s'.", + command, commands[command].mod.name(), mod.name()); + commands[command] = cmd; + return true; + } + public bool unregister(string command) { + return commands.unset(command); + } + + protected void hnd_modules(ModuleMuc.Conference conf, ModuleMuc.Occupant user, string command, string? arguments) { + var sb = new StringBuilder(); + sb.append("Loaded modules:"); + muc.name(); + foreach (var mod in conn.modules) + sb.append(" "+mod.name()); + user.public_message(sb.str); + } + + protected void hnd_status(ModuleMuc.Conference conf, ModuleMuc.Occupant user, string command, string? arguments) { + var sb = new StringBuilder(); + sb.append("Status:"); + foreach (var room in muc.rooms.values) { + sb.append(" "); + sb.append(room.jid.split("@",2)[0]); + sb.append("["); + sb.append(room.enabled ? "EN":"DIS"); + sb.append(":"); + switch (room.state) { + case ModuleMuc.State.CONNECTED: sb.append("C"); break; + case ModuleMuc.State.DISCOVERING: sb.append("DS"); break; + case ModuleMuc.State.CONNECTING: sb.append(">C"); break; + case ModuleMuc.State.DISCONNECTING: sb.append(">D"); break; + case ModuleMuc.State.DISCONNECTED: sb.append("D"); break; + } + sb.append("]"); + } + user.public_message(sb.str); + } + + public ModuleMucCommands(Config cfg, Connection conn) { + base(cfg, conn); + commands = new HashMap(); + foreach (var module in conn.modules) { + if (module.name()=="muc") + muc = (ModuleMuc)module; + } + if (muc==null) + log("muc_log", LogLevelFlags.LEVEL_ERROR, "Module 'muc' is not loaded"); + + muc.on_message.connect( (conf, user, message, body) => { + if ((user!=null)&&(body!=null)&&(message.get_child("delay")==null)) { + if (getconf(conf.jid, "commands", "no")!="yes") + return; + if (body.has_prefix(conf.nick)) { + var txt = body[conf.nick.length:body.length]; + if (txt.has_prefix(": ")||txt.has_prefix(", ")) { + var command_n_args = txt[2:txt.length].split(" ",2); + var command = commands[command_n_args[0]]; + if (command!=null) + command.hnd(conf, user, command_n_args[0], (command_n_args.length > 1) ? command_n_args[1] : null); + } + } + } + }); + + register("modules", this, hnd_modules); + register("status", this, hnd_status); + } + public override string name() { + return "muc_commands"; + } +} diff -r 0f0cf428409f -r d3e36b368fc5 muc_log.vala --- a/muc_log.vala Mon Nov 05 23:53:52 2012 +0400 +++ b/muc_log.vala Mon Nov 05 23:54:44 2012 +0400 @@ -35,12 +35,26 @@ } return ((sum ^ m)+l)%10; } + + protected void real_write(Time time, string _class, string nick, string str) { + var id = getid(time); + var times = time.format("%H:%M:%S"); + var nicklass = (_class=="message") ? (" nick%u".printf(nick_hash(nick))) : ""; + + file.printf("%s", id, _class, id, id, times); + file.printf("%s%s\n", nicklass, nick, str); + file.flush(); + } + public void write(Time time, string _class, string nick, string str) { - if ((lastday != time.day)||(lastmonth != time.month)||(lastyear!=time.year)) { var fname = time.format(logpath).replace("",jid); log("muc_log", LogLevelFlags.LEVEL_INFO, "Switching log file '%s' to '%s'", filename, fname); - if (file!=null) file.flush(); + bool wasntnull = false; + if (file!=null) { + wasntnull = true; + real_write(time, "logstop", "", "Log stopped. See you in the next episode."); + } //try { file = FileStream.open(fname,"a"); if (file==null) { @@ -79,15 +93,11 @@ } filename = fname; lastyear = time.year; lastmonth = time.month; lastday = time.day; + if (wasntnull) + real_write(time, "logstart", "", "Log started. This soap opera will never end."); } - - var id = getid(time); - var times = time.format("%H:%M:%S"); - var nicklass = (_class=="message") ? (" nick%u".printf(nick_hash(nick))) : ""; - file.printf("%s", id, _class, id, id, times); - file.printf("%s%s\n", nicklass, nick, str); - file.flush(); + real_write(time, _class, nick, str); } } diff -r 0f0cf428409f -r d3e36b368fc5 simple_iq.vala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/simple_iq.vala Mon Nov 05 23:54:44 2012 +0400 @@ -0,0 +1,41 @@ +using Gee, Lm; + +class ModuleIq : Module { + const string NS_IQ_VERSION = "jabber:iq:version"; + public static delegate void Callback(string id, MessageNode request, MessageNode response); + protected HashMap callbacks; + public ModuleIq(Config cfg, Connection conn) { + base(cfg, conn); + var iq_handler = new Lm.MessageHandler((handler, connection, message) => { + var node = message.node; + + var query = node.get_child("query"); + if (query == null) return Lm.HandlerResult.ALLOW_MORE_HANDLERS; + + var from = node.get_attribute("from"); + var id = node.get_attribute("id"); + + var response = new Lm.Message(from, Lm.MessageType.IQ); + response.node.set_attribute("type","result"); + if (id!=null) + response.node.set_attribute("id",id); + var rquery = response.node.add_child("query",null); + + switch (query.get_attribute("xmlns")) { + case NS_IQ_VERSION: + rquery.set_attribute("xmlns", NS_IQ_VERSION); + rquery.add_child("name", "iswydt"); + rquery.add_child("version", IswydtVersion); + stderr.printf("RQ: %s\n",rquery.to_string()); + stderr.printf("RS: %s\n",response.node.to_string()); + this.conn.cn.send(response); + return Lm.HandlerResult.REMOVE_MESSAGE; + } + return Lm.HandlerResult.ALLOW_MORE_HANDLERS; + }, null); + conn.cn.register_message_handler(iq_handler, Lm.MessageType.IQ, Lm.HandlerPriority.NORMAL); + } + public override string name() { + return "iq"; + } +}