Source

zedify / zedify / weechat.py

#!/usr/bin/env python2

import time

import zmq

from weechat import buffer_get_string as get, config_get_plugin as cfg
import weechat

from zedify.config import config


__author__ = 'codekoala'
__version__ = '0.0.5'
__descr__ = 'Deliver message notifications to remote machines'

weechat.register('zedifier', __author__, __version__, 'GPL3',
                 __descr__, 'close', '')


OK = weechat.WEECHAT_RC_OK
ERR = weechat.WEECHAT_RC_ERROR

MODE_LOCAL = 0
MODE_REMOTE = 1
MSG_TAGS = {'irc_privmsg', 'notify_message'}

MODE_MAP = {
    'local': MODE_LOCAL,
    'remote': MODE_REMOTE
}

ctx = zmq.Context()


def buffer_name(buf):
    return get(buf, 'short_name') or get(buf, 'name')


def window_name(win):
    return 'win_%s' % weechat.window_get_integer(win, 'number')


class Zedifier(object):

    SETTINGS = {
        'notify_in_channel': ''
    }

    def __init__(self):
        self.configure()
        self.last_msg = None
        self.last_time = None

        self.pub = ctx.socket(zmq.PUSH)
        self.connect()

        # handle weechat events
        weechat.hook_print('', 'irc_privmsg', '', 1, 'notify', '')
        weechat.hook_signal('input_text_changed', 'typing', '')
        weechat.hook_signal('buffer_switch', 'buffer_switch', '')
        weechat.hook_signal('window_switch', 'window_switch', '')
        #weechat.hook_config('plugins.var.python.tray_notify.host',
        #                    'connect', '')

    def configure(self):
        """Update the default configuration options"""

        for option, default in Zedifier.SETTINGS.items():
            if cfg(option) == "":
                weechat.config_set_plugin(option, default)

    def connect(self):
        """Connect to services"""

        if self.mode == MODE_LOCAL:
            self.pub.bind(config.zedifier.pub)
        else:
            self.pub.connect(config.zedifier.push)

    def notify(self, data, buf, date, tags, displayed, hilight, prefix, msg):
        """Send a message notification"""

        if not MSG_TAGS and set(tags):
            return

        chat = buffer_name(buf)
        send = False
        event = None

        if get(buf, 'localvar_type') == 'private':
            event = 'pm'
            send = chat == prefix
        elif hilight == "1":
            event = 'mention'
            send = True
        elif 'notify_message' in tags:
            track = weechat.config_get_plugin('notify_in_channel').split(',')
            event = 'message'
            send = chat in track

        if send:
            self.send({
                'event': event,
                'user': prefix,
                'chat': chat,
                'msg': msg,
            })

        return OK

    def typing(self, data, signal, buf):
        name = buffer_name(buf)
        self.send({
            'event': 'typing',
            'in_buffer': name,
        })

        return OK

    def buffer_switch(self, data, signal, buf):
        name = buffer_name(buf)
        self.send({
            'event': 'buffer_switch',
            'to_buffer': name,
        })

        return OK

    def window_switch(self, data, signal, win):
        name = window_name(win)
        self.send({
            'event': 'window_switch',
            'to_window': name,
        })

        return OK

    def send(self, obj):
        """
        Only send the message if it's changed or been more than 15 seconds
        since the last message.
        """

        now = time.time()

        if obj != self.last_msg or \
                self.last_time is None or \
                now - self.last_time > 15:
            self.pub.send_json(obj)

        self.last_msg = obj
        self.last_time = now

    def close(self):
        """Clean up connections"""

        rc = OK
        try:
            self.pub.close()
        except:
            weechat.prnt('', 'Failed to close channel')
            rc = ERR

        return rc

    @property
    def mode(self):
        mode = MODE_MAP.get(config.zedifier.mode, MODE_LOCAL)

        return mode


app = Zedifier()
notify = app.notify
typing = app.typing
buffer_switch = app.buffer_switch
window_switch = app.window_switch
close = app.close