tools

- collection of tools for supernets sysadmins
git clone git://git.acid.vegas/tools.git
Log | Files | Refs | Archive

hateserv.py (8378B)

      1 #!/usr/bin/env python
      2 # hateserv irc bot - developed by acidvegas in python (https://git.acid.vegas/hateserv)
      3 
      4 import re
      5 import socket
      6 import ssl
      7 import time
      8 import urllib.request
      9 
     10 import commands
     11 
     12 # Config
     13 admin             = 'acidvegas!~stillfree@most.dangerous.motherfuck'
     14 server            = 'irc.supernets.org'
     15 channel           = '#dev'
     16 nickname          = '[dev]HateServ'
     17 username          = 'H'
     18 realname          = 'SuperNETs HATE Services'
     19 nickserv_password = 'simps0nsfan22'
     20 operator_password = 'EatMYsh0rts39'
     21 
     22 # Colors & Control Characters
     23 bold        = '\x02'
     24 underline   = '\x1F'
     25 reset       = '\x0f'
     26 white       = '00'
     27 black       = '01'
     28 blue        = '02'
     29 green       = '03'
     30 red         = '04'
     31 brown       = '05'
     32 purple      = '06'
     33 orange      = '07'
     34 yellow      = '08'
     35 light_green = '09'
     36 cyan        = '10'
     37 light_cyan  = '11'
     38 light_blue  = '12'
     39 pink        = '13'
     40 grey        = '14'
     41 light_grey  = '15'
     42 
     43 def color(msg, foreground, background=None):
     44     return f'\x03{foreground},{background}{msg}{reset}' if background else f'\x03{foreground}{msg}{reset}'
     45 
     46 def debug(data):
     47 	print('{0} | [~] - {1}'.format(time.strftime('%I:%M:%S'), data))
     48 
     49 def error(data, reason=None):
     50 	print('{0} | [!] - {1} ({2})'.format(time.strftime('%I:%M:%S'), data, str(reason))) if reason else print('{0} | [!] - {1}'.format(time.strftime('%I:%M:%S'), data))
     51 
     52 def irc_error(chan, data, reason=None):
     53 	sendmsg(chan, '[{0}] {1}'.format(color('error', red), data, color(f'({reason})', grey))) if reason else sendmsg(chan, '[{0}] {1}'.format(color('error', red), data))
     54 
     55 def raw(msg):
     56 	msg = msg.replace('\r\n',' ')
     57 	sock.send(bytes(msg[:510] + '\r\n', 'utf-8'))
     58 
     59 def sendmsg(target, msg):
     60 	raw(f'PRIVMSG {target} :{msg}')
     61 
     62 def trim(data, max_length):
     63 	return data[:max_length] + '...' if len(data) > max_length else data
     64 
     65 def urlcheck(msg):
     66 	url = re.compile('(?:http[s]?:\/\/|http[s]?:\/\/www.)(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.IGNORECASE).findall(msg)
     67 	if url:
     68 		url = url[0]
     69 		try:
     70 			if (check := re.match('^.*?github.com\/([0-9A-Za-z]+\/[0-9A-Za-z]+).*?', url, re.IGNORECASE)):
     71 				data = commands.github('repo', check.group(1))
     72 				if data:
     73 					if not data['description']:
     74 						data['description'] = 'no description available'
     75 					sendmsg(channel, '{0} {1} {2} [{3}:{4}|{5}:{6}|{7}:{8}]'.format(color(' GitHub ', black, grey), data['full_name'], color('('+data['description']+')', grey), color('Stars', purple), data['stargazers_count'], color('Watch', purple), data['watchers'], color('Forks', purple), data['forks']))
     76 			elif (check := re.match('^.*?github.com\/([0-9A-Za-z]+)', url, re.IGNORECASE)):
     77 				data = commands.github('user', check.group(1))
     78 				if data:
     79 					data['bio'] = data['bio'].replace('\r\n','') if data['bio'] else ''
     80 					sendmsg(channel, '{0} {1} {2} {3} [{4}:{5}|{6}:{7}]'.format(color(' GitHub ', black, grey), data['login'], color('('+data['name']+')', grey), data['bio'], color('Repos', purple), data['public_repos'], color('Followers', purple), data['followers']))
     81 			elif (check := re.match('^.*?reddit.com\/r\/(.*?)\/comments\/([0-9A-Za-z]+).*$', url, re.IGNORECASE)):
     82 				data = commands.reddit('post', check.group(1), check.group(2))
     83 				sendmsg(channel, '[{0}] - {1} [{2}/{3}|{4}]'.format(color('reddit', cyan), color(trim(data['title'], 300), white), color('+' + str(data['ups']), green), color('-' + str(data['downs']), red), color(str(data['num_comments']), white)))
     84 			elif (check := re.match('^.*?youtu(be)?\.([a-z])+\/(watch(.*?)(\?|\&)v=)?(.*?)(&(.)*)*$', url, re.IGNORECASE)):
     85 				pass
     86 			else:
     87 				source = urllib.request.urlopen(url, timeout=10)
     88 				title = re.compile(r'<title.*?>(.+?)</title>', re.I | re.M | re.S | re.U).search(source.read().decode('utf-8'))
     89 				if title:
     90 					title = title.group(1).replace('\n',' ')
     91 					if len(title) > 100:
     92 						title = title[:100] + '...'
     93 					type = source.info().get_content_type()
     94 					sendmsg(channel, f'[{type}] {title}')
     95 		except Exception as ex:
     96 			error('failed to get parse url title', ex)
     97 
     98 def event_message(chan, nick, ident, msg):
     99 	args = msg.split()
    100 	if not msg.startswith('.'):
    101 		urlcheck(msg)
    102 		if msg == '@hateserv':
    103 			sendmsg(channel, 'hateserv irc bot for supernets - developed by acidvegas in python (https://git.acid.vegas/hateserv)')
    104 		elif msg in ('melp','.melp','melp?','.melp?'):
    105 			sendmsg(chan, '\x01ACTION explodes\x01')
    106 	else:
    107 		if ident == admin:
    108 			if msg == '.massjoin':
    109 				raw('WHO * n%nc')
    110 		if args[0] in ('.g','.s'):
    111 			query   = ' '.join(args[1:])
    112 			results = commands.librex(query)
    113 			if results:
    114 				for item in results:
    115 					sendmsg(chan, '[{0}] {1}'.format(color(str(results.index(item)+1).zfill(2), pink), trim(item['title'], 300)))
    116 					sendmsg(chan, ' '*5 + underline + color(item['link'], light_blue))
    117 			else:
    118 				irc_error(chan, 'no results found')
    119 		elif args[0] == '.cve':
    120 			data = commands.cve_search(' '.join(args[1:]))
    121 			for item in data['vulnerabilities']:
    122 				id = item['cve']['id']
    123 				desc = item['cve']['descriptions'][0]['value']
    124 				sendmsg(chan, '[{0}] {1} - {2}'.format(color(str(data['vulnerabilities'].index(item)+1).zfill(2), pink), color(id, cyan), trim(desc, 300)))
    125 		elif args[0] == '.ip':
    126 			data = commands.geoip(args[1])
    127 			location = '{0}, {1}, {2}'.format(data['location']['city'], data['location']['state'], data['location']['country_code'])
    128 			asn = 'AS{0} ({1})'.format(data['asn']['asn'], data['asn']['descr'])
    129 			sendmsg(chan, '[{0}] {1} under {2} controlled by {3}'.format(color('geoip', light_blue), color(location, yellow), color(asn, cyan), color(data['rir'], pink)))
    130 		elif args[0] == '.gh':
    131 			query = ' '.join(args[1:]).replace(' ','%20')
    132 			results = commands.github('search',query)
    133 			if results:
    134 				for item in results:
    135 					if not item['description']:
    136 						item['description'] = 'no description'
    137 					sendmsg(chan, '[{0}] {1}/{2}{3}{4} {5}'.format(color(str(results.index(item)+1).zfill(2), pink), item['owner']['login'], bold, item['name'], reset, color('('+item['description']+')', grey)))
    138 					sendmsg(chan, ' '*5 + underline + color(item['html_url'], light_blue))
    139 		elif args[0] == '.r' and len(args) == 2:
    140 			query   = args[1]
    141 			results = commands.reddit('subreddit', query)
    142 			if results:
    143 				for item in results:
    144 					sendmsg(chan, '[{0}] {1} [{2}/{3}|{4}]'.format(color(str(results.index(item)+1).zfill(2), pink), trim(item['title'], 300), color('+' + str(item['ups']), green), color('-' + str(item['downs']), red), color(item['num_comments'], white)))
    145 					sendmsg(chan, ' '*5 + underline + color(item['url'], light_blue))
    146 			else:
    147 				irc_error(chan, 'no results found')
    148 
    149 while True:
    150 	#try:
    151 		#sock = ssl.wrap_socket(socket.socket())
    152 		sock = socket.socket()
    153 		sock.connect((server, 6667))
    154 		raw(f'USER {username} 0 * :{realname}')
    155 		raw('NICK ' + nickname)
    156 		while True:
    157 			try:
    158 				data = sock.recv(1024).decode('utf-8')
    159 				for line in (line for line in data.split('\r\n') if len(line.split()) >= 2):
    160 					debug(line)
    161 					args = line.split()
    162 					if line.startswith('ERROR :Closing Link:'):
    163 						raise Exception('Connection has closed.')
    164 					elif args[0] == 'PING':
    165 						raw('PONG ' + args[1][1:])
    166 					elif args[1] == '001': #RPL_WELCOME
    167 						raw(f'MODE {nickname} +B')
    168 						raw(f'PRIVMSG NickServ IDENTIFY {nickname} {nickserv_password}')
    169 						raw(f'OPER hates {operator_password}')
    170 						raw('JOIN ' + channel)
    171 						last = 5
    172 					elif args[1] == '354' and len(args) == 5: #RPL_WHOSPCRPL
    173 						nick = args[4]
    174 						if nick not in (nickname,'AI','BLACKHOLE','BotServ','ChanServ','EliManning','fraud','Global','HostServ','IRCCEX','NickServ','OperServ','THEGAME'):
    175 							raw(f'SAJOIN {nick} {channel}')
    176 					elif args[1] == 'JOIN' and len(args) == 3:
    177 						nick = args[0].split('!')[0][1:]
    178 						chan = args[2][1:]
    179 					elif args[1] == 'PRIVMSG' and len(args) >= 4:
    180 						ident  = args[0][1:]
    181 						chan   = args[2]
    182 						nick   = args[0].split('!')[0][1:].lower()
    183 						msg    = ' '.join(args[3:])[1:]
    184 						if chan == channel:
    185 							#try:
    186 								event_message(chan, nick, ident, msg)
    187 							#except Exception as ex:
    188 							#	irc_error(chan, 'unknown error occured', ex)
    189 						elif chan == nickname and ident == admin and msg.startswith('.raw '):
    190 							raw(msg[5:])
    191 			except (UnicodeDecodeError, UnicodeEncodeError):
    192 				pass
    193 	#except Exception as ex:
    194 	#	error('fatal error occured', ex)
    195 	#	sock.close()
    196 	#finally:
    197 	#	time.sleep(15)