You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
4.1 KiB
Python

import socket, argparse, sys, time, re
def split_irc(message):
message = re.sub("(?<=[0-9A-Fa-fI]):(?=[0-9A-Fa-fI])", "[..]", message)
if ":" in message:
first, second = message.split(":", 1)
return first.rstrip().split(" ") + [second]
else:
return message.split(" ")
parser = argparse.ArgumentParser(description='Connects to an IRC network and executes a rakill.')
parser.add_argument('-H', dest='hostname', action='store', required=True,
help='server to connect to')
parser.add_argument('-o', dest='port', action='store', required=True,
help='port* to connect to')
parser.add_argument('-u', dest='username', action='store', required=True,
help='oper username')
parser.add_argument('-p', dest='password', action='store', required=True,
help='oper password')
parser.add_argument('-r', dest='regex', action='store', required=True,
help='regex to match')
parser.add_argument('-d', dest='duration', action='store', default="30d",
help='gline duration')
parser.add_argument('-m', dest='message', action='store', default="You were banned during an automated bot kill. If this is in error, contact an operator.",
help='gline/kill message')
parser.add_argument('--list', dest='action_list', action='store_true',
help='list all matching users')
parser.add_argument('--gline', dest='action_gline', action='store_true',
help='gline all matching users')
parser.add_argument('--kill', dest='action_kill', action='store_true',
help='kill all matching users')
parser.add_argument('--unrealircd', dest='ircd_unreal', action='store_true',
help='assume UnrealIRCd')
parser.add_argument('--inspircd', dest='ircd_insp', action='store_true',
help='assume InspIRCd')
args = parser.parse_args()
options = vars(args)
if options['ircd_unreal'] == False and options['ircd_insp'] == False:
print "You did not specify an IRCd. Try again with --inspircd or --unrealircd switch."
exit(1)
print "Connecting...",
sock = socket.socket()
sock.connect((options['hostname'], int(options['port'])))
readbuffer = ""
print "connected"
sock.send("NICK botkill\r\n")
sock.send("USER botkill %s 0 :rakill.py\r\n" % options['hostname'])
print "Registered."
while True:
readbuffer = readbuffer + sock.recv(1024)
lines = readbuffer.split("\n")
readbuffer = lines.pop()
for line in lines:
if line.startswith(":"):
line = line.split(" ", 1)[1]
line = line.rstrip()
parts = split_irc(line)
if parts[0] == "PING":
sock.send("PONG %s\r\n" % parts[1])
print "Completed connection challenge."
elif parts[0] == "001":
sock.send("OPER %s %s\r\n" % (options['username'], options['password']))
elif parts[0] == "381":
print "Authenticated as oper."
if options['ircd_insp'] == True:
# InspIRCd
sock.send("WHO ** h\r\n")
elif options['ircd_unreal'] == True:
# UnrealIRCd
sock.send("WHO +hR **\r\n")
print "Requested userlist."
elif parts[0] == "352":
try:
ident = parts[3]
host = parts[4].replace("[..]", ":")
leaf = parts[5]
nick = parts[6]
realname = parts[8][3:]
if re.match(options['regex'], nick):
if options['action_gline']:
sock.send("GLINE *@%s %s :[%s] %s\r\n" % (host, options['duration'], nick, options['message']))
print "Glined *@%s" % host
if options['action_kill']:
sock.send("KILL %s :%s\r\n" % (nick, options['message']))
print "Killed %s" % nick
if options['action_list']:
print "Matched user: %s!%s@%s" % (nick, ident, host)
except IndexError:
print "WARNING: Ignored user due to parsing error."
elif parts[0] == "315":
print "All users checked, exiting..."
sock.send("QUIT :rakill.py bot killer\r\n")
time.sleep(1)
exit(0)
elif parts[0] == "491":
print "Invalid oper credentials given."
exit(1)
time.sleep(0.005)