/[shmookey]/killbot/killbot.py


UCC Code Repository

Contents of /killbot/killbot.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 123 - (hide annotations) (download) (as text)
Wed Nov 11 02:41:36 2009 UTC (12 years ago) by shmookey
File MIME type: text/x-python
File size: 5460 byte(s)
Unicode support from [DJA]

1 shmookey 121 #!/usr/bin/python
2     ''' killbot.py
3     Kicks users from an IRC channel when they send banned expressions.
4    
5     Written by Luke Williams <[email protected]>
6     Distributed under an MIT-style license - see the LICENSE file for details.
7     '''
8    
9 shmookey 122 import re, os, sys
10     import conf, easybot
11 shmookey 123 import unicodedata
12 shmookey 121
13 shmookey 122 BOT_NAME = conf.username
14 shmookey 121
15 shmookey 122 patterns = {}
16 shmookey 121
17 shmookey 122 def load_channel (channel):
18     patterns[channel] = []
19     if os.access ("channels/" + channel, os.F_OK | os.R_OK):
20     pattern_file = open ("channels/" + channel, "r")
21     for line in pattern_file.read().split("\n"):
22     if (not line == "") and (not line[0] == ";"):
23 shmookey 123 patterns[channel].append( (line,re.compile(line, re.IGNORECASE | re.UNICODE)) )
24 shmookey 122 pattern_file.close ()
25     else:
26     os.mknod ("channels/" + channel)
27     pattern_file = open ("channels/" + channel, "w+")
28     pattern_file.write ("; Autogenerated by killbot")
29     pattern_file.close ()
30    
31 shmookey 121 def msg (chobj, channel, msg_from, msg, is_oper):
32     words = msg.split (":")
33     if len (words) > 1:
34     if words [0] == BOT_NAME:
35 shmookey 122 responses = process_command (words[1], channel, msg_from, is_oper, chobj)
36 shmookey 121 for response in responses:
37     chobj.privmsg (channel, response)
38     return
39 shmookey 123
40     # strip out all but alphanumeric (Ll, Lu, Nd) and spacing (Zs) characters.
41     # punctuation is deliberately stripped out so as people cannot evade kicks by padding their message
42     safe_chars = [ 'Lu', 'Ll', 'Zs', 'Nd' ]
43     clean_msg = ''.join(c for c in msg.decode('utf-8') if unicodedata.category(c) in safe_chars)
44 shmookey 121
45 shmookey 122 for pattern in patterns[channel]:
46 shmookey 123 if re.search (pattern[1], clean_msg):
47 shmookey 121 print "Kicking " + msg_from + " for violating kickable expression (\"" + pattern[0] + "\")"
48     chobj.kick (channel, msg_from, "Violating kickable expression (\"" + pattern[0] + "\")")
49    
50 shmookey 122 def process_command (cmd, channel, msg_from, is_oper, connection):
51 shmookey 121 words = cmd [1:].split (" ", 1)
52     try:
53     if words[0] == "help":
54     responses = ["I kick people when they act like idiots! Channel operators can define what idiotic behaviour looks like with Python-style regex by telling me:"]
55     responses.append (BOT_NAME + ": add kickable_pattern_here")
56 shmookey 123 responses.append ("I ignore everything except letters, numbers and whitespace when processing the regex.")
57 shmookey 121 responses.append ("Anyone can get the list of kickable expressions by asking me with \"" + BOT_NAME + ": show\"")
58     responses.append ("Channel operators can remove expressions from the kicklist with \"" + BOT_NAME + ": remove list_index\"")
59     responses.append ("I was originally written in 2009 by shmookey for #ucc on irc.ucc.asn.au")
60     return responses
61     if words[0] == "show":
62     responses = ["Kickable Expressions:"]
63 shmookey 122 for i, pattern in enumerate (patterns[channel]):
64 shmookey 121 responses.append (str(i) + ". " + pattern[0])
65     return responses
66     elif words[0] == "add" and len (words) > 1:
67     if not is_oper:
68     responses = [msg_from + ": I only obey channel operators."]
69     return responses
70     pattern = words[1]
71     try:
72 shmookey 122 patterns[channel].append ( (pattern,re.compile (pattern, re.IGNORECASE)) )
73 shmookey 121 except:
74     responses = ["There was a problem compiling your expression."]
75     return responses
76 shmookey 122 pattern_file = open ("channels/" + channel, "a+")
77     pattern_file.write ("\n" + pattern)
78     pattern_file.close ()
79 shmookey 121 responses = ["Added \"" + pattern + "\" to the list of kickable expressions."]
80 shmookey 123 responses.append ("Use \"" + BOT_NAME + ": remove " + str (len (patterns[channel])-1) + "\" to remove.")
81 shmookey 121 return responses
82     elif words[0] == "remove" and len(words) > 1:
83     if not is_oper:
84     responses = [msg_from + ": I only obey channel operators."]
85     return responses
86     pnum = int (words[1])
87 shmookey 122 pattern = patterns[channel] [pnum]
88     patterns[channel].pop (pnum)
89     pattern_file = open ("channels/" + channel, "r")
90     new_content = "\n".join ([line for line in pattern_file.read().split("\n") if not line == pattern[0]])
91     pattern_file = open ("channels/" + channel, "w")
92     pattern_file.write (new_content)
93     pattern_file.close ()
94 shmookey 121 responses = ["Removed pattern " + str (pnum) + " (\"" + pattern[0] + "\") from kicklist."]
95     return responses
96 shmookey 122 elif words[0] == "join" and len(words) > 1:
97     if not is_oper:
98     responses = [msg_from + ": I only obey channel operators."]
99     return responses
100     new_channel = words[1]
101     load_channel (new_channel)
102     channel_file = open ("channels.conf", "a+")
103     channel_file.write ("\n" + new_channel)
104     channel_file.close ()
105     connection.join (new_channel)
106     responses = ["OK!"]
107     return responses
108     elif words[0] == "leave":
109     if not is_oper:
110     responses = [msg_from + ": I only obey channel operators."]
111     return responses
112     channel_file = open ("channels.conf", "r")
113     new_content = "\n".join([line for line in channel_file.read().split("\n") if not line == channel])
114     print new_content
115     channel_file.close ()
116     channel_file = open ("channels.conf", "w")
117     channel_file.write (new_content)
118     channel_file.close ()
119     connection.part (channel)
120     return []
121 shmookey 121 else:
122     responses = [msg_from + ": I don't understand."]
123     return responses
124     except:
125     responses = [msg_from + ": What?"]
126     return responses
127    
128 shmookey 122 def on_welcome (c):
129     for channel in patterns:
130     c.join (channel)
131 shmookey 121
132 shmookey 122 channel_file = open ("channels.conf", "r")
133     for line in channel_file.read().split("\n"):
134     if (not line == "") and (not line[0] == ";"):
135     load_channel (line)
136     channel_file.close ()
137     bot = easybot.EasyBot (BOT_NAME, conf.server, port=conf.port)
138 shmookey 121 bot.message_hook = msg
139 shmookey 122 bot.welcome_hook = on_welcome
140 shmookey 121 bot.start ()

Managed by UCC Webmasters ViewVC Help
Powered by ViewVC 1.1.26