Skip to content

Instantly share code, notes, and snippets.

@williamjacksn
Created January 31, 2018 19:55
Show Gist options
  • Save williamjacksn/60718d30138ed501bf72f30043313932 to your computer and use it in GitHub Desktop.
Save williamjacksn/60718d30138ed501bf72f30043313932 to your computer and use it in GitHub Desktop.
Class-based IRC bot
import socket
# change these
HOST = 'irc.undernet.org'
PORT = 6667
NICK = 'rex'
CHAN = '#dashin'
ADMIN = 'Humphrey'
class IRCBot:
def __init__(self, host: str, port: int, nick: str, chan: str, admin: str):
self.socket = socket.socket()
self.host = host
self.port = port
self.nick = nick
self.chan = chan
self.admin = admin
self.buff = b''
# this is where I do my work
def run(self):
self.socket.connect((self.host, self.port))
print(f'** connected to {self.host}')
# identify myself to the IRC server
self.send_line(f'NICK {self.nick}')
self.send_line(f'USER {self.nick} {self.host} x :{self.nick}')
while True:
# receive what the server has sent me
self.buff = self.buff + self.socket.recv(4096)
# split it into lines
lines = self.buff.split(b'\n')
# the last line might be incomplete, put it back in the buffer
self.buff = lines.pop()
# handle each of the lines that the server sent me
for line in lines:
self.handle_line(line)
# this is the function I will use when I want to send a message to the IRC server
def send_line(self, line: str):
print(f'=> {line}')
# add \r\n to the end of the line and convert it from string to bytes, then send
self.socket.send(f'{line}\r\n'.encode())
# this is the function I will use when I want to process a message I received from the IRC server
def handle_line(self, line: bytes):
# convert line from bytes to string, and remove leading and trailing whitespace
line = line.decode().strip()
print(f'<= {line}')
# split the line on whitespace into a list of tokens
tokens = line.split()
if tokens[0] == 'PING':
self.handle_ping(tokens[1])
elif tokens[1] in ('376', '422'):
# 376 means the server has finished sending the message of the day
# 422 means there is no message of the day to send
self.handle_server_connect_done()
elif tokens[1] == 'PRIVMSG' and tokens[2] == self.nick:
self.handle_private_message(tokens)
elif tokens[1] == 'PRIVMSG' and tokens[2] == self.chan:
self.handle_public_message(tokens)
def handle_ping(self, message):
# when the server sends PING, I automatically reply with PONG
self.send_line(f'PONG {message}')
def handle_server_connect_done(self):
# when the server connection and introduction is complete, join my channel
self.send_line(f'JOIN {self.chan}')
def handle_private_message(self, tokens):
# when I get a message sent directly to me, not the channel
sender = self.get_nick(tokens[0])
command = tokens[3]
if command == ':!changename' and sender == self.admin:
self.nick = tokens[4]
print(f'COMMAND: Change nickname to {self.nick}')
self.send_line(f'NICK {self.nick}')
def handle_public_message(self, tokens):
# when I get a message sent to the channel
sender = self.get_nick(tokens[0])
command = tokens[3]
if command == ':!jump':
print('COMMAND: Jump')
self.send_line(f'PRIVMSG {self.chan} :\x01ACTION does jumping jacks!')
@staticmethod
def get_nick(prefix: str):
# ':nick!user@host' => 'nick'
prefix = prefix.lstrip(':')
nick = prefix.split('!')[0]
return nick
def main():
irc = IRCBot(HOST, PORT, NICK, CHAN, ADMIN)
irc.run()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment