Home Upgrade Search Memberlist Extras Hacker Tools Award Goals Help Wiki Contact

Python 

IRC Simple Bot in Python 3

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
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)) 
SRPP Discord Server

I am a professional network/cloud security architect.
My Old Tutorials
(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!
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.

I love this user <3
Spoiler (Click to View)
(Aug 18, 2016 02:24 PM)Black‌jack 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!
Nice work man, this was well detailed and explained


Possibly Related Threads...
Thread / Author Replies Views Last Post
[Python] by Bass_ReevesAug 20, 2023 01:44 AM 9 631 Aug 20, 2023 01:44 AM
Last Post: Lucky4L
[C#] by gigajewJun 20, 2018 07:26 AM 2 291 Jun 20, 2018 07:26 AM
Last Post: JustNothing
[Python] by maslenFeb 20, 2016 12:09 AM 11 1,062 Feb 20, 2016 12:09 AM
Last Post: emadaldin1