-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcirca.py
115 lines (95 loc) · 3.3 KB
/
circa.py
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
import logging
import client
import importlib
import modules
import sys
import time
from util.nick import nicklower
from util.mask import match
from version import version as v
class Circa(client.Client):
version = "circa {0} http://github.com/sammdot/circa".format(".".join(map(str, v)))
def __init__(self, conf):
conf["autoconn"] = False
for setting in "server nick username realname admins".split():
if setting not in conf or conf[setting] is None:
logging.error("Required setting %s not present", setting)
logging.info("See %s for details", conf["log"])
exit(1)
self.cwd = conf["cwd"]
self.modules = {}
client.Client.__init__(self, **conf)
self.conf["admins"] = set(map(nicklower, self.conf["admins"]))
logging.info("Registering callbacks")
self.add_listener("registered", self.registered)
self.add_listener("invite", self.invited)
self.add_listener("ctcp.version", self.ctcp_version)
self.add_listener("message", self.handle_cmd)
logging.info("Loading modules")
sys.path.append(self.cwd)
for module in "chan module".split() + conf["modules"]:
self.load_module(module)
self.connect()
def handle_cmd(self, fr, to, text, m):
if text.startswith(self.conf["prefix"]):
cmd = text.split(" ")[0]
cmdname = "$" if cmd == self.conf["prefix"] else cmd[1:]
self.emit("cmd." + cmdname, fr, fr if to == self.nick else to,
" ".join(text.split(" ")[1:]), m)
def say(self, to, msg):
lines = msg.replace("\x07", "").splitlines()
limit = self.conf["linelimit"]
for line in lines[:limit]:
client.Client.say(self, to, line)
if len(lines) > limit:
diff = len(lines) - limit
client.Client.say(self, to, "[... {0} more line{1}]".format(diff, "s" if diff > 1 else ""))
def notice(self, to, msg):
msg = msg.replace("\x07", "")
for line in msg.splitlines():
client.Client.notice(self, to, line)
def registered(self, nick, m):
self.send("MODE", nick, "+B")
self.send("MODE", nick, "-x")
for chan in self.conf["channels"]:
self.join("#" + chan)
self.server.admins = set(map(nicklower, self.conf["admins"]))
def invited(self, chan, by, m):
self.join(chan)
def ctcp_version(self, fr, to):
self.ctcp_notice(fr, "VERSION " + self.version)
def close(self):
self.send("QUIT")
self.sock.close()
def is_admin(self, prefix):
return any(match(mask, prefix) for mask in self.server.admins)
def load_module(self, name):
if name in self.modules:
return "{0} already loaded".format(name)
try:
mod = importlib.import_module("modules." + name)
# if it's been imported before, make sure we get the latest version
importlib.reload(mod)
m = mod.module
if hasattr(m, "require"):
for mod in m.require.split():
if mod == "cmd":
continue
self.load_module(mod)
self.modules[name] = module = m(self)
for event, listeners in module.events.items():
for listener in listeners:
self.add_listener(event, listener)
logging.info("Loaded {0}".format(name))
return 0
except Exception as e:
return "Cannot import {0}: {1}".format(name, e)
def unload_module(self, name):
if name not in self.modules:
return
module = self.modules[name]
for event, listeners in module.events.items():
for listener in listeners:
self.remove_listener(event, listener)
del self.modules[name]
logging.info("Unloaded {0}".format(name))