summaryrefslogtreecommitdiff
path: root/subbot.py
blob: 7e90c562c91678b03352b1d3b2f3db7aa00904c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env python

import irc.bot
import irc.buffer
import irc.client
import json, time
import urllib2
import sys
import contextlib
import signal
import settings
import select
import errno

svcpw = settings.bot_svcpw

import bot_backend
def reload_backend(signum, frame):
    try:
        reload(bot_backend)
    except Exception:
        print >>sys.stderr, "Error reloading bot backend:"
        sys.excepthook(*sys.exc_info())
    else:
        print >>sys.stderr, "Reloaded backend."
signal.signal(signal.SIGUSR1, reload_backend)

class PermissiveDecodingLineBuffer(irc.buffer.DecodingLineBuffer):
    errors = 'replace'
irc.client.ServerConnection.buffer_class = PermissiveDecodingLineBuffer

class TestBot(irc.bot.SingleServerIRCBot):
    def __init__(self, channel, nickname, server, port=6667):
        self.nickname_base = nickname
        self.status = 'closed'
        self.update_nick(False)

        irc.bot.SingleServerIRCBot.__init__(self, [(server, port)], self.nickname, self.nickname)
        self.channel = channel

    def start(self):
        self._connect()
        while True:
            try:
                self.ircobj.process_forever(30)
            except select.error, e:
                if e.args[0] == errno.EINTR:
                    continue
                raise

    def on_nicknameinuse(self, c, e):
        self.nickname_base += '_'
        self.update_nick()

    def on_welcome(self, c, e):
        c.privmsg('NickServ', 'identify %s %s' % (self.nickname, svcpw))
        self.refresh()
        c.join(self.channel)

    def on_pubmsg(self, c, e):
        try:
            bot_backend.on_pubmsg(self, c, e)
        except Exception:
            print >>sys.stderr, "Error in backend processing message:"
            sys.excepthook(*sys.exc_info())

    def update_nick(self, server_interaction=True):
        """Set new nickname from nickname base and current status"""
        wantnick = self.nickname_base + '|' + self.status

        if not server_interaction:
            self.nickname = wantnick
            return

        curtime = time.time()
        c = self.connection
        havenick = c.get_nickname()

        if wantnick != havenick:
            print int(curtime), 'nick:', havenick, '->', wantnick
            c.privmsg('NickServ', 'ghost %s %s' % (wantnick, svcpw))
            c.privmsg('NickServ', 'release %s %s' % (wantnick, svcpw))
            c.nick(wantnick)
            self.nickname = wantnick

    def refresh(self):
        curtime = time.time()
        try:
            with contextlib.closing(urllib2.urlopen('http://argonaut.local.sublab.org/subcan.json')) as json_stream:
                sdata = json.load(json_stream)
            door = sdata[u'door.lock']

            if door[u'ts'] < curtime - 120:
                self.status = 'error'
            elif door[u'text'] == u'closed':
                self.status = 'closed'
            elif door[u'text'] == u'open':
                self.status = 'open'
            else:
                self.status = 'error'
        except Exception, e:
            print >>sys.stderr, "Error in door status retrieval:"
            sys.excepthook(*sys.exc_info())
            self.status = 'error'

        self.update_nick()
        self.ircobj.execute_delayed(5, self.refresh)

def main(nickname, channel):
    bot = TestBot(channel, nickname, 'irc.hackint.org', 6667)
    bot.start()

if __name__ == "__main__":
    if sys.argv[0] == 'subbot.py':
        nickname = 'sublab'
        channel = '#sublab'
    else:
        nickname = 'sublab2'
        channel = '#sublab2'
    main(nickname, channel)