summaryrefslogtreecommitdiff
path: root/ircapp.py
blob: 3bc444fb5f5dfa8ab9f2359c3ba0d0aeebaeb6f4 (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
121
122
123
124
125
#!/usr/bin/python
import os
import re
import time
import signal
import sys
import irc
import modjson
import readline
import rlcompleter
import types
import code

nonaddontypes = (types.ModuleType, types.MethodType,
                 types.FunctionType, types.TypeType, irc.Connection)


class IRCApplication:

    def __init__(self, conffile=None):
        self._quitting = False
        self.conffile = conffile
        self.termcaught = False
        self.confdecoder = modjson.ModJSONDecoder()
        self.confencoder = modjson.ModJSONEncoder(indent=3)
        signal.signal(signal.SIGTERM, self.sigterm)
        self.namespace = {}
        if conffile and os.path.isfile(conffile):
            with open(conffile, "r") as f:
                pyirc = self.confdecoder.decode(f.read())
            if "addons" in pyirc.keys():
                self.namespace.update(pyirc["addons"])
            if "networks" in pyirc.keys():
                self.namespace.update(pyirc["networks"])
        self.shell = code.InteractiveConsole(locals=self.namespace)
        self.namespace["quit"] = self.quit
        self.namespace["save"] = self.save
        # self.namespace["exit"]=self.exit
        self.namespace["irc"] = irc

    def quit(self, quitmsg="Goodbye!"):
        networks = [
            o for o in self.namespace.values() if type(o) == irc.Connection]
        for context in networks:
            if type(context) == irc.Connection and context.isAlive():
                context.quit(quitmsg)
        for context in networks:
            if type(context) == irc.Connection:
                with context._disconnecting:
                    while context.connected:
                        context._disconnecting.wait(30)
                    if context._recvhandlerthread:
                        context._recvhandlerthread.join()
                    if context._sendhandlerthread:
                        context._sendhandlerthread.join()

    def complete(self, text, state):
        raise NotImplemented

    def start(self):
        sys.ps1 = "(ircapp) "
        sys.ps2 = "........ "
        readline.parse_and_bind("tab: complete")
        completer = rlcompleter.Completer(self.namespace)
        readline.set_completer(completer.complete)
        for o in self.namespace.values():
            if type(o) == irc.Connection:
                o.connect()
        while True:
            try:
                self.shell.interact(banner="Welcome to pyIRC!")
            except SystemExit, quitmsg:
                if not self._quitting:
                    if quitmsg.message:
                        self.quit(quitmsg.message)
                    else:
                        self.quit()
                break
            # In case CTRL+D is accidentally sent to the console.
            print "Ooops... Did you mean to do that?"

    def sigterm(self, signum, frame):
        if not self.termcaught:
            self.termcaught = True
            self.exit("Caught SIGTERM")

    def save(self, conffile=None):
        addons = {key: o for (key, o) in self.namespace.items()
                  if not isinstance(o, nonaddontypes) and not key.startswith("_")}
        extraaddons = []
        networks = {key: o for (key, o) in self.namespace.items() if type(
            o) == irc.Connection and not key.startswith("_")}
        if not conffile:
            conffile = self.conffile
        with open(conffile, "w") as f:
            print >>f, self.confencoder.encode(
                dict(addons=addons, networks=networks))

    def exit(self, quitmsg="Goodbye!"):
        self.quit(quitmsg)
        addons = [o for (key, o) in self.namespace.items()
                  if not isinstance(o, nonaddontypes) and not key.startswith("_")]
        networks = [o for (key, o) in self.namespace.items() if type(
            o) == irc.Connection and not key.startswith("_")]
        for context in networks:
            for conf in list(context.addons):
                addon = conf.addon if type(conf) == irc.Config else conf
                context.rmAddon(addon)
                if addon not in addons:
                    addons.append(addon)
        for addon in addons:
            if "stop" in dir(addon) and callable(addon.stop) and "isAlive" in dir(addon) and callable(addon.isAlive) and addon.isAlive():
                try:
                    addon.stop()
                except:
                    pass
        print "Quit: {quitmsg}".format(**vars())
        self._quitting = True
        sys.exit()

if __name__ == "__main__":
    ircapp = IRCApplication(
        sys.argv[1] if len(sys.argv) > 1 else "ircapp.conf")
    ircapp.start()
    ircapp.exit()