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 | - | # <[email protected]> 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() |