muc_log.vala
author Stiletto <blasux@blasux.ru>
Wed, 24 Oct 2012 00:37:04 +0400
changeset 6 0d97b0d61ed2
parent 4 8785de25b6bd
child 8 dfd274c668f9
permissions -rw-r--r--
Log error if failed to load config file

using Gee;

class ModuleMucLog : Module {
    protected weak ModuleMuc muc;
    protected HashMap<string,RoomLog> rooms;
    class RoomLog : Object {
        public string jid;
        public string logpath;
        public string filename;
        protected weak ModuleMucLog muclog;
        protected FileStream file;
        public string getid(Time time) {
            return time.format("%s");
        }
        protected int lastday;
        protected int lastyear;
        protected int lastmonth;

        public RoomLog(ModuleMucLog muclog, string jid) {
            this.jid = jid;
            this.muclog = muclog;
            logpath = muclog.getconf(jid, "log-path", null);
            filename = null;
            write(Time.local(new time_t()), "logstart", "", "Log started");
        }
        ~RoomLog() {
            write(Time.local(new time_t()), "logstop", "", "Log stopped");
        }
        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("<muc>",jid);
                log("muc_log", LogLevelFlags.LEVEL_INFO, "Switching log file '%s' to '%s'", filename, fname);
                if (file!=null) file.flush();
                //try {
                    file = FileStream.open(fname,"a");
                if (file==null) {
                    int start = 0;
                    int length = fname.length;
                    while (true) {
                        var pos = fname.index_of("/", start);
                        if (pos==-1)
                            break;
                        stderr.printf("--------------------- %s\n", fname[0:pos]);
                        Posix.mkdir(fname[0:pos],0777);
                        start = pos+1;
                    } 

                    file = FileStream.open(fname,"a");
                    if (file == null) {
                        log("muc_log", LogLevelFlags.LEVEL_WARNING, "Failed to create log file '%s'", fname);
                        return;
                    }
                }

                if (file.tell()==0) {
                    var loghead = muclog.getconf(jid, "log-head",null);
                    if (loghead!="null") {
                        try {
                            var headfile = new IOChannel.file(loghead,"r");
                            string head;
                            size_t length;
                            headfile.read_to_end(out head, out length);
                            headfile.shutdown(false);
                            file.printf("%s\n", head.replace("<muc>",jid).replace("<date>",time.format("%d.%m.%Y")));
                        } catch (FileError fe) {
                            log("muc_log", LogLevelFlags.LEVEL_WARNING, "Failed to read head");
                        }
                    }
                }
                filename = fname;
                lastyear = time.year; lastmonth = time.month; lastday = time.day;
            }
            
            var id = getid(time);
            var times = time.format("%H:%M:%S");
            file.printf("<tr id='l_%s' class='%s'><td class='time'><a id='i_%s' href='#i_%s'>%s</a></td>", id, _class, id, id, times);
            file.printf("<td class='nick'>%s</td><td class='text'>%s</td></tr>\n", nick, str);
            file.flush();
        }
            
    }
    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 ModuleMucLog(Config cfg, Connection conn) {
        base(cfg, conn);
        rooms = new HashMap<string,RoomLog>();
        muc = null;
        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.state_changed.connect( (conf, olds, news, desc) => {
            switch (news) {
                case ModuleMuc.State.CONNECTED:
                    if (getconf(conf.jid, "log", "no")=="yes") {
                        rooms[conf.jid] = new RoomLog(this, conf.jid);
                    }
                    break;
                case ModuleMuc.State.DISCONNECTED:
                    rooms.unset(conf.jid);
                    break;
            }
        });
        muc.on_message.connect( (conf, user, message, body) => {
            if ((user!=null)&&(body!=null)&&(message.get_child("delay")==null)) {
                var room = rooms[conf.jid];
                if (room!=null) {
                    var nick = Markup.escape_text(user.nick).replace(" ","&nbsp;");
                    room.write(Time.local(new time_t()), "message", nick, Markup.escape_text(body).replace("\n","<br/>"));
                }
            }
        });
    }
    public override string name() {
        return "muc_log";
    }
}