awaitself.handle(data.decode('utf-8').strip())# Handle the data received from the IRC server
exceptExceptionasex:
logging.error(f'failed to connect to {self.server} ({ex})')
finally:
awaitasyncio.sleep(30)# Wait 30 seconds before reconnecting
asyncdefhandle(self,data:str):
'''
HandlethedatareceivedfromtheIRCserver.
:paramdata:ThedatareceivedfromtheIRCserver.
'''
try:
args=data.split()
ifdata.startswith('ERROR :Closing Link:'):
raiseException('BANNED')
ifargs[0]=='PING':
awaitself.raw('PONG '+args[1])# Respond to the server's PING request with a PONG to prevent ping timeout
elifargs[1]=='001':# RPL_WELCOME
awaitself.raw(f'MODE {self.nickname} +B')# Set user mode +B (Bot)
awaitself.sendmsg('NickServ','IDENTIFY {self.nickname} simps0nsfan420')# Identify to NickServ
awaitself.raw('OPER MrSysadmin fartsimps0n1337')# Oper up
awaitasyncio.sleep(10)# Wait 10 seconds before joining the channel (required by some IRCds to wait before JOIN)
awaitself.raw(f'JOIN {args.channel}{args.key}')# Join the channel (if no key was provided, this will still work as the key will default to an empty string)
elifargs[1]=='433':# ERR_NICKNAMEINUSE
self.nickname+='_'# If the nickname is already in use, append an underscore to the end of it
awaitself.raw('NICK '+self.nickname)# Send the new nickname to the server
elifargs[1]=='KICK':
chan=args[2]
kicked=args[3]
ifkicked==self.nickname:
awaitasyncio.sleep(3)
awaitself.raw(f'JOIN {chan}')
elifargs[1]=='PRIVMSG':
ident=args[0][1:]
nick=args[0].split('!')[0][1:]
target=args[2]
msg=''.join(args[3:])[1:]
iftarget==self.nickname:
pass# Handle private messages here
iftarget.startswith('#'):# Channel message
ifmsg.startswith('!'):
ifmsg=='!hello':
self.sendmsg(chan,f'Hello {nick}!')
except(UnicodeDecodeError,UnicodeEncodeError):
pass# Some IRCds allow invalid UTF-8 characters, this is a very important exception to catch
exceptExceptionasex:
logging.exception(f'Unknown error has occured! ({ex})')
fh=logging.handlers.RotatingFileHandler(log_filename+'.log',maxBytes=250000,backupCount=3,encoding='utf-8')# Max size of 250KB, 3 backups
fh.setFormatter(logging.Formatter('%(asctime)s | %(levelname)9s | %(filename)s.%(funcName)s.%(lineno)d | %(message)s','%Y-%m-%d%I:%M %p'))# We can be more verbose in the log file