SHOW:
|
|
- or go back to the newest paste.
1 | #!/usr/bin/env python | |
2 | ||
3 | """Charitum.py: an extensible IRC bot""" | |
4 | ||
5 | - | # ---------------------------------------------------------------------------- |
5 | + | |
6 | - | # "THE BEER-WARE LICENSE" (Revision 42): |
6 | + | |
7 | - | # <s0lll0s@blinkenshell.org> wrote this file. As long as you retain this notice you |
7 | + | |
8 | - | # can do whatever you want with this stuff. If we meet some day, and you think |
8 | + | __version__ = "1.4.2" |
9 | - | # this stuff is worth it, you can buy me a beer in return. S0lll0s |
9 | + | |
10 | - | # ---------------------------------------------------------------------------- |
10 | + | |
11 | import sys | |
12 | import signal | |
13 | import time | |
14 | from ircutils import bot, format, protocol | |
15 | - | __version__ = "1.4.4" |
15 | + | |
16 | ############################## EVENTS ############################### | |
17 | ||
18 | # event handling seems to be broken | |
19 | ||
20 | def callback_shutdown( signal, frame ): | |
21 | - | import urllib2 |
21 | + | |
22 | - | import urllib |
22 | + | |
23 | sys.exit( 0 ) | |
24 | ||
25 | ############################# UTILS ################################# | |
26 | ||
27 | def format_command( command, received ): | |
28 | """ Returns the fitting 'command' based on 'received'. | |
29 | received is either channel or private""" | |
30 | if received == "channel": | |
31 | return "!" + command.lower() | |
32 | return command.upper() | |
33 | ||
34 | ############################# COMMANDS ############################## | |
35 | ||
36 | def cmd_exec( self, command, params, event, received="channel" ): | |
37 | """ {0}!X!- Execute an IRC command: | |
38 | {0} <COMMAND> <[PARAMS]>!X!- Execute the IRC command <COMMAND> with parameters <PARAMS>""" | |
39 | ||
40 | self.execute( params[0].upper(), ' '.join( params[1:] ).strip() ) | |
41 | if received == "private": | |
42 | self.send_message( event.source, "Executed" + format.bold( params[0].upper() + ' '.join( params[1:] ) ) ) | |
43 | ||
44 | def cmd_say( self, command, params, event, received="channel" ): | |
45 | """ {0}!X!- Say a Text: | |
46 | - | """ {0}!X!- Execute an IRC command |
46 | + | |
47 | {0} <CHANNEL> <TEXT>!X!- Say <TEXT> in channel <CHANNEL> (/msg only)""" | |
48 | ||
49 | if received == "private": | |
50 | self.send_message( params[0], ' '.join( params[1:] ).strip() ) | |
51 | else: | |
52 | self.send_message( event.target, ' '.join( params ).strip() ) | |
53 | ||
54 | - | """ {0}!X!- Say a Text |
54 | + | |
55 | """ {0}!X!- Update the Voice/HOP/OP info manually: | |
56 | {0}!X!- Update the Voice/HOP/OP info manually""" | |
57 | ||
58 | self.execute( "NAMES", event.target ) | |
59 | ||
60 | def cmd_help( self, command, params, event, received="channel" ): | |
61 | """ {0}!X!- Help for commands: | |
62 | {0}!X!- List commands | |
63 | {0} <COMMAND>!X!- Help for <COMMAND>""" | |
64 | - | """ {0}!X!- Update the Voice/HOP/OP info manually |
64 | + | |
65 | if len( params ) < 1: | |
66 | self.send_message( event.source, "List of commands:" ) | |
67 | for cmd in self.commands: | |
68 | self.send_message( event.source, format.color( "## ", format.LIME_GREEN ) + '{:<20} {}'.format( *self.commands[ cmd ][1].__doc__.format( format.bold( format_command( cmd, received ) ) ).splitlines()[0].strip().split( "!X!", 1 ) ) ) # split and justify | |
69 | return | |
70 | - | """ {0}!X!- Help for commands |
70 | + | |
71 | self.send_message( event.source, "Usage info for command {0}:".format( format.bold( params[0] ) ) ) | |
72 | for line in self.commands[ params[0].lower() ][1].__doc__.format( *[ format.bold( format_command( c, received ) ) for c in params ] ).splitlines(): | |
73 | self.send_message( event.source, format.color( "## ", format.LIME_GREEN ) + '{:<35} {}'.format( *line.strip().split( "!X!", 1 ) ) ) # split and justify | |
74 | else: | |
75 | self.send_message( event.source, "Unkown Command {0}.".format( format.bold( params[0] ) ) ) | |
76 | ||
77 | def cmd_shout( self, command, params, event, received="channel" ): | |
78 | """ {0}!X!- Shout a Text: | |
79 | {0} <TEXT>!X!- Shout <TEXT> in current channel | |
80 | {0} <CHANNEL> <TEXT>!X!- Shout <TEXT> in channel <CHANNEL> (/msg only)""" | |
81 | ||
82 | colors = [ format.GREEN, format.RED, format.AQUA, format.YELLOW, format.PINK, format.PURPLE, format.TEAL, format.LIGHT_GRAY ] | |
83 | if received == "private": | |
84 | for color, bg in [(x,y) for x in colors for y in colors]: | |
85 | self.send_message( params[0], format.color( ' '.join( params[1:] ).strip(), color, bg ) ) | |
86 | time.sleep( 0.5 ) | |
87 | - | """ {0}!X!- Shout a Text |
87 | + | |
88 | for color, bg in [(x,y) for x in colors for y in colors]: | |
89 | self.send_message( event.target, format.color( ' '.join( params ).strip() , color, bg ) ) | |
90 | time.sleep( 0.5 ) | |
91 | ||
92 | def cmd_op( self, command, params, event, received="channel" ): | |
93 | """{0}!X!- Make an user OP: | |
94 | {0}!X!- Get OP yourself | |
95 | {0} <USER>!X!- Make <USER> OP | |
96 | {0} <CHANNEL>!X!- Get OP yourself (/msg) | |
97 | {0} <CHANNEL> <USER>!X!- Make <USER> OP (/msg)""" | |
98 | ||
99 | user = event.source | |
100 | if received == "private": | |
101 | if len( params ) > 1: | |
102 | - | """{0}!X!- Make an user OP |
102 | + | |
103 | self.execute( "OP", params[0] + " " + user ) | |
104 | else: | |
105 | if len( params ) > 0: | |
106 | user = params[0] | |
107 | self.execute( "OP", event.target + " " + user ) | |
108 | ||
109 | def cmd_kick( self, command, params, event, received="channel" ): | |
110 | """{0}!X!- Kick an user: | |
111 | {0} <USER>!X!- Kick <USER> | |
112 | - | self.execute( "MODE", params[0], "+o:", user ) |
112 | + | |
113 | ||
114 | if len( params ) < 1 or [0] == "Charitum": | |
115 | return | |
116 | - | self.execute( "MODE", event.target, "+o:", user ) |
116 | + | |
117 | channel = event.target | |
118 | if len( params ) > 1: | |
119 | - | """{0}!X!- Kick an user |
119 | + | |
120 | self.execute( "KICK", channel + " " + params[0] ) | |
121 | ||
122 | ############################### BOT ################################# | |
123 | - | if len( params ) < 1 or params[0] == "Charitum": |
123 | + | |
124 | class Charitum( bot.SimpleBot ): | |
125 | commands = {} | |
126 | channelusers = {} | |
127 | access = dict( ( ([ '', '+', '%', '@', '&', '~' ])[num] , num ) for num in range( 6 ) ) | |
128 | ||
129 | - | self.execute( "KICK", channel, " ", params[0] ) |
129 | + | |
130 | """ Adds a new command. command and short are names for | |
131 | the command, used as ![command/short] and [COMMAND/SHORT]. | |
132 | - | def cmd_banner( self, command, params, event, received="channel" ): |
132 | + | |
133 | - | """{0}!X!- Print an ASCII Banner |
133 | + | |
134 | - | {0} <BANNER>!X!- Print <BANNER> |
134 | + | |
135 | - | {0} <BANNER> <CHANNEL>!X!- Print <BANNER> in <CHANNEL>""" |
135 | + | |
136 | specifically targetting the command. Format your docstring | |
137 | - | rec = event.target |
137 | + | |
138 | - | if received == "private": |
138 | + | |
139 | - | rec = event.source |
139 | + | |
140 | - | if len( params ) > 1: |
140 | + | |
141 | - | rec = params[1] |
141 | + | |
142 | if short is not None: | |
143 | - | banner = None |
143 | + | |
144 | - | if params[0] == "text": |
144 | + | print "Added commmand", command, ", level", level, ", func", func.__name__ |
145 | - | banner = ( format.BLUE, urllib2.urlopen( "https://artii.herokuapp.com/make?text=" + urllib.quote( " ".join( params[2:] ) ) ).read().splitlines() ) |
145 | + | |
146 | - | print banner |
146 | + | |
147 | - | print "https://artii.herokuapp.com/make?text=" + " ".join(params[2:]) |
147 | + | |
148 | - | elif params[0] == "graffiti": |
148 | + | |
149 | - | banner = ( format.BLUE, urllib2.urlopen( "https://artii.herokuapp.com/make?text=" + urllib.quote( " ".join( params[2:] ) ) + "&font=graffiti" ).read().splitlines() ) |
149 | + | |
150 | - | print "graf" |
150 | + | |
151 | - | elif params[0] in banners: |
151 | + | |
152 | - | banner = banners[params[0]] |
152 | + | |
153 | - | print "file" |
153 | + | |
154 | - | else: |
154 | + | |
155 | - | self.send_message( rec, format.color( "ERROR:", format.RED ) + " Banner not found" ) |
155 | + | |
156 | - | print "none" |
156 | + | |
157 | - | return |
157 | + | |
158 | message = event.message.split() | |
159 | - | for line in banner[1]: |
159 | + | |
160 | - | self.send_message( rec, format.color( format.bold( line ), banner[0], format.BLACK ) ) |
160 | + | |
161 | - | time.sleep( 0.5 ) |
161 | + | |
162 | if len( command ) == 1: # skip single !'s and stuff | |
163 | return | |
164 | ||
165 | if command[0] == "!": # only handle commands directed to us... | |
166 | command = command[1:].lower() | |
167 | if command in self.commands: # ... that exist | |
168 | self.execute( "NAMES", event.target ) # update permissions | |
169 | ( level, func ) = self.commands[ command ] | |
170 | ||
171 | for name in self.channelusers[ event.target ]: | |
172 | if protocol.strip_name_symbol( name ) == event.source: break # name is now event.target's name | |
173 | ||
174 | ulevel = 0 | |
175 | if name[0] in self.access: # do not handle 'empty' users | |
176 | ulevel = self.access[ name[0] ] | |
177 | ||
178 | if ulevel < self.access[ level ]: | |
179 | self.send_message( event.target, format.color( "ERROR:", format.RED ) + " You are not allowed to use the " + format.bold( command ) + " Command" ) | |
180 | return | |
181 | func( self, command, params, event ) | |
182 | else: | |
183 | self.send_message( event.target, format.color( "ERROR:", format.RED ) + " Command " + format.bold( command ) +" not found" ) | |
184 | ||
185 | - | print "Added commmand " + command + ", level " + level + ", func " + func.__name__ |
185 | + | |
186 | def on_private_message( self, event ): | |
187 | message = event.message.split() | |
188 | command = message[0].upper() | |
189 | params = message[1:] | |
190 | ||
191 | if command.lower() in self.commands: | |
192 | self.execute( "NAMES", "#ltfu" ) # update permissions | |
193 | ( level, func ) = self.commands[ command.lower() ] | |
194 | ||
195 | for name in self.channelusers[ "#ltfu" ]: | |
196 | if protocol.strip_name_symbol( name ) == event.source: break # name is now event.target's name | |
197 | ||
198 | ulevel = 0 | |
199 | if name[0] in self.access: # do not handle 'empty' users | |
200 | ulevel = self.access[ name[0] ] | |
201 | ||
202 | if ulevel < self.access[ level ]: | |
203 | self.send_message( event.source, format.color( "ERROR:", format.RED ) + " You are not allowed to use the " + format.bold( command ) + " Command" ) | |
204 | return | |
205 | func( self, command, params, event, received="private" ) # tell the function this was a private message and call it | |
206 | else: | |
207 | self.send_message( event.source, format.color( "ERROR:", format.RED ) + " Command " + format.bold( command ) +" not found" ) | |
208 | ||
209 | ############################### RUN ################################# | |
210 | ||
211 | if __name__ == "__main__": | |
212 | charitum = Charitum( "DudelZ" ) | |
213 | charitum.connect( "irc.freenode.net", channel=["#ltfu"] ) | |
214 | ||
215 | ||
216 | charitum.add_command( "execute", "~", cmd_exec, short="exec" ) | |
217 | charitum.add_command( "say", "@", cmd_say, "!" ) | |
218 | charitum.add_command( "shout", "@", cmd_shout, "!!" ) | |
219 | charitum.add_command( "update", "", cmd_update, "upd" ) | |
220 | #charitum.add_command( "kick", "@", cmd_kick ) | |
221 | #charitum.add_command( "op", "@", cmd_op ) | |
222 | charitum.add_command( "help", "", cmd_help ) | |
223 | ||
224 | signal.signal( signal.SIGINT, callback_shutdown ) # register graceful shutdown here | |
225 | ||
226 | charitum.start() |