IRC Simple Bot in Python 3 - lulzabar - Aug 15, 2016
Hi everyone! New to the forums and coding, just picked up on python about two hours ago. Posting on here to get some constructive criticism, help/tips, and any advise, which is really all the same thing in 3 different ways of saying it 😏
Anywho, here is my first program in python from scratch 🤩
Bot features: Auto op on owner joins, channel idling, commands.
Bot commands: !op, !deop, !voice, !devoice, !kick, !ban, !unban, !lockdown, !unlockdown, !topic
(lockdown is just +m or moderated channel making users have to have +v or higher to speak.)
Things I know I need to work on: Multiple channels, owners, better way to handle commands.
P.s. Made it simple if you want to use it/Test. Edit the things ONLY in #bot settings (ex. HOST, NICK, owner, bot_chan) After that just launch the code! #Basic commands is a decent skeleton if you want to implement your own like !ban, !say, etc into the bot.
Code #importing extra modules for future updates
import os
import sys
import time
import socket
import string
import fnmatch
#----------------------------------------------------------------------
#bot settings
HOST = ("irc.freenode.net", 6667) #server and port we're connecting to
NICK = "BBB0t" #Bots nickname
IDENT = "v v v :Testing" #First/Middle/Last Name: description/info
owner = "lulzabar" #Owner/Operator of the bot
bot_chan = "#testchanpls" #channel where commands can be used (ex: !op, !kick)
#-----------------------------------------------------------------------
#Creating/Connecting the socket
s = socket.socket()
s.connect(HOST)
#------------------------------------------------------------------------
#Sending our info through socket
nick_send = ("NICK " +NICK+ " \r\n")
s.sendall(bytes(str(nick_send).encode()))
ident_send = ("USER " +IDENT+ " \r\n")
s.sendall(bytes(str(ident_send).encode()))
bot_join = ("JOIN " +bot_chan+ " \r\n")
s.sendall(bytes(str(bot_join).encode()))
#------------------------------------------------------------------------
#Grabbing what the server is sending us
while 1:
data = s.recv(4096).decode()
msg = str.split(data)
#replying to pings so we dont time out
if (msg[0] == "PING"):
PONG = "PONG " + msg[1] + " \r\n"
s.sendall(bytes(str(PONG).encode()))
#------------------------------------------------------------------------
#making sure that the owner only can give commands
#checks if the vHost matches owners/returns True if matches
vHost = msg[0]
oHost = fnmatch.fnmatch(vHost, ":"+owner+"*")
#-----------------------------------------------------------------------
#basic commands
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!deop"):
deopMsg = (("MODE {0} -o "+msg[4]+" \r\n").format(bot_chan))
s.sendall(bytes(str(deopMsg).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!op"):
opMsg = (("MODE {0} +o "+msg[4]+" \r\n").format(bot_chan))
s.sendall(bytes(str(opMsg).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!voice"):
vUser = (("MODE {0} +v "+msg[4]+" \r\n").format(bot_chan))
s.sendall(bytes(str(vUser).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!devoice"):
dvUser = (("MODE {0} -v "+msg[4]+" \r\n").format(bot_chan))
s.sendall(bytes(str(dvUser).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!kick"):
kickUser = (("KICK {0} " + msg[4] + " \r\n").format(bot_chan))
s.sendall(bytes(str(kickUser).encode()))
if oHost == True:
if (msg[1] == "JOIN"):
if (msg[2] == bot_chan):
opMsg = (("MODE {0} +o {1} \r\n").format(bot_chan, owner))
s.sendall(bytes(str(opMsg).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!topic"):
topic = (("TOPIC {0} " + str(msg[4]) + " \r\n").format(bot_chan))
s.sendall(bytes(str(topic).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!ban"):
ban = (("MODE {0} +b " + msg[4] + " \r\n").format(bot_chan))
s.sendall(bytes(str(ban).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!unban"):
unban = (("MODE {0} -b " + msg[4] + " \r\n").format(bot_chan))
s.sendall(bytes(str(unban).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!lockdown"):
lockdown = (("MODE {0} +m \r\n").format(bot_chan))
s.sendall(bytes(str(lockdown).encode()))
if oHost == True:
if (msg[1] == "PRIVMSG"):
if (msg[2] == bot_chan):
if(msg[3] == ":!unlockdown"):
unlockdown = (("MODE {0} -m \r\n").format(bot_chan))
s.sendall(bytes(str(unlockdown).encode()))
print(data) #printing what the server is sending us to console
* - Goodies - Aug 15, 2016
You should get familiar with basic programming concepts and guidelines. For example, you have TONS of code re-use opportunities here.
Without changing the functionality at all, you can rewrite all of those if statements as a far more simplified version:
PHP Code
<?php if oHost == True: if (msg[1] == "PRIVMSG"): if (msg[2] == bot_chan): response = None if(msg[3] == ":!deop"): response = (("MODE {0} -o "+msg[4]+" \r\n").format(bot_chan)) if(msg[3] == ":!op"): response = (("MODE {0} +o "+msg[4]+" \r\n").format(bot_chan)) if(msg[3] == ":!voice"): response = (("MODE {0} +v "+msg[4]+" \r\n").format(bot_chan)) if(msg[3] == ":!devoice"): response = (("MODE {0} -v "+msg[4]+" \r\n").format(bot_chan)) if(msg[3] == ":!kick"): response = (("KICK {0} " + msg[4] + " \r\n").format(bot_chan)) if(msg[3] == ":!topic"): response = (("TOPIC {0} " + str(msg[4]) + " \r\n").format(bot_chan)) if(msg[3] == ":!ban"): response = (("MODE {0} +b " + msg[4] + " \r\n").format(bot_chan)) if(msg[3] == ":!unban"): response = (("MODE {0} -b " + msg[4] + " \r\n").format(bot_chan)) if(msg[3] == ":!lockdown"): response = (("MODE {0} +m \r\n").format(bot_chan)) if(msg[3] == ":!unlockdown"): response = (("MODE {0} -m \r\n").format(bot_chan)) if response is not None: s.sendall(bytes(str(response).encode())) if (msg[1] == "JOIN"): if (msg[2] == bot_chan): response = (("MODE {0} +o {1} \r\n").format(bot_chan, owner))
* - lulzabar - Aug 16, 2016
(Aug 15, 2016 10:27 PM)Goodies Wrote: You should get familiar with basic programming concepts and guidelines. For example, you have TONS of code re-use opportunities here.
Without changing the functionality at all, you can rewrite all of those if statements as a far more simplified version:
PHP Code
<?php if oHost == True: if (msg[1] == "PRIVMSG"): if (msg[2] == bot_chan): response = None if(msg[3] == ":!deop"): response = (("MODE {0} -o "+msg[4]+" \r\n").format(bot_chan)) if(msg[3] == ":!op"): response = (("MODE {0} +o "+msg[4]+" \r\n").format(bot_chan)) if(msg[3] == ":!voice"): response = (("MODE {0} +v "+msg[4]+" \r\n").format(bot_chan)) if(msg[3] == ":!devoice"): response = (("MODE {0} -v "+msg[4]+" \r\n").format(bot_chan)) if(msg[3] == ":!kick"): response = (("KICK {0} " + msg[4] + " \r\n").format(bot_chan)) if(msg[3] == ":!topic"): response = (("TOPIC {0} " + str(msg[4]) + " \r\n").format(bot_chan)) if(msg[3] == ":!ban"): response = (("MODE {0} +b " + msg[4] + " \r\n").format(bot_chan)) if(msg[3] == ":!unban"): response = (("MODE {0} -b " + msg[4] + " \r\n").format(bot_chan)) if(msg[3] == ":!lockdown"): response = (("MODE {0} +m \r\n").format(bot_chan)) if(msg[3] == ":!unlockdown"): response = (("MODE {0} -m \r\n").format(bot_chan)) if response is not None: s.sendall(bytes(str(response).encode())) if (msg[1] == "JOIN"): if (msg[2] == bot_chan): response = (("MODE {0} +o {1} \r\n").format(bot_chan, owner))
That looks really clean. Thanks for the feedback, I'll definitely look into the concepts. Im sure its all over youtube!
* - Blackjack - Aug 18, 2016
Keep something in mind: socket.recv() is not guaranteed to only receive one line. It could receive half a line, or 2 lines, etc. You want to read your data into a buffer and then read lines from that buffer.
* - lulzabar - Aug 18, 2016
(Aug 18, 2016 02:24 PM)Blackjack Wrote: Keep something in mind: socket.recv() is not guaranteed to only receive one line. It could receive half a line, or 2 lines, etc. You want to read your data into a buffer and then read lines from that buffer.
Thanks for this heads up. I haven't had any problems (luckily) using it for irc shenanigans but ill definitely start implementing a buffering system to handle the data!
* - Sleeky - Sep 16, 2016
Nice work man, this was well detailed and explained
|