How do i program a simple IRC bot in python?

69,571

Solution 1

It'd probably be easiest to base it on twisted's implementation of the IRC protocol. Take a look at : http://github.com/brosner/bosnobot for inspiration.

Solution 2

To connect to an IRC channel, you must send certain IRC protocol specific commands to the IRC server before you can do it.

When you connect to the server you must wait until the server has sent all data (MOTD and whatnot), then you must send the PASS command.

PASS <some_secret_password>

What follows is the NICK command.

NICK <username>

Then you must send the USER command.

USER <username> <hostname> <servername> :<realname>

Both are mandatory.

Then you're likely to see the PING message from server, you must reply to the server with PONG command every time the server sends PING message to you. The server might ask for PONG between NICK and USER commands too.

PING :12345678

Reply with the exact same text after "PING" with PONG command:

PONG :12345678

What's after PING is unique to every server I believe so make sure you reply with the value that the server sent you.

Now you can join a channel with JOIN command:

JOIN <#channel>

Now you can send messages to channels and users with PRIVMSG command:

PRIVMSG <#channel>|<nick> :<message>

Quit with

QUIT :<optional_quit_msg>

Experiment with Telnet! Start with

telnet irc.example.com 6667

See the IRC RFC for more commands and options.

Hope this helps!

Solution 3

I used this as the MAIN IRC code:

import socket
import sys

server = "server"       #settings
channel = "#channel"
botnick = "botname"

irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #defines the socket
print "connecting to:"+server
irc.connect((server, 6667))                                                         #connects to the server
irc.send("USER "+ botnick +" "+ botnick +" "+ botnick +" :This is a fun bot!\n") #user authentication
irc.send("NICK "+ botnick +"\n")                            #sets nick
irc.send("PRIVMSG nickserv :iNOOPE\r\n")    #auth
irc.send("JOIN "+ channel +"\n")        #join the chan

while 1:    #puts it in a loop
   text=irc.recv(2040)  #receive the text
   print text   #print text to console

   if text.find('PING') != -1:                          #check if 'PING' is found
      irc.send('PONG ' + text.split() [1] + '\r\n') #returnes 'PONG' back to the server (prevents pinging out!)

Then, you can start setting commands like: !hi <nick>

if text.find(':!hi') !=-1: #you can change !hi to whatever you want
    t = text.split(':!hi') #you can change t and to :)
    to = t[1].strip() #this code is for getting the first word after !hi
    irc.send('PRIVMSG '+channel+' :Hello '+str(to)+'! \r\n')

Note that all irc.send texts must start with PRIVMSG or NOTICE + channel/user and the text should start with a : !

Solution 4

This is an extension of MichaelvdNet's Post, which supports a few additional things:

  • Uses SSL wrapper for socket
  • Uses server password authentication
  • Uses nickserv password authentication
  • Uses nonblocking sockets, to allow other events to trigger
  • Logs changes to text files to channel

    #!/usr/local/bin/python
    
    import socket
    import ssl
    import time
    
    ## Settings
    ### IRC
    server = "chat.freenode.net"
    port = 6697
    channel = "#meLon"
    botnick = "meLon-Test"
    password = "YOURPASSWORD"
    
    ### Tail
    tail_files = [
        '/tmp/file-to-tail.txt'
    ]
    
    irc_C = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #defines the socket
    irc = ssl.wrap_socket(irc_C)
    
    print "Establishing connection to [%s]" % (server)
    # Connect
    irc.connect((server, port))
    irc.setblocking(False)
    irc.send("PASS %s\n" % (password))
    irc.send("USER "+ botnick +" "+ botnick +" "+ botnick +" :meLon-Test\n")
    irc.send("NICK "+ botnick +"\n")
    irc.send("PRIVMSG nickserv :identify %s %s\r\n" % (botnick, password))
    irc.send("JOIN "+ channel +"\n")
    
    
    tail_line = []
    for i, tail in enumerate(tail_files):
        tail_line.append('')
    
    
    while True:
        time.sleep(2)
    
        # Tail Files
        for i, tail in enumerate(tail_files):
            try:
                f = open(tail, 'r')
                line = f.readlines()[-1]
                f.close()
                if tail_line[i] != line:
                    tail_line[i] = line
                    irc.send("PRIVMSG %s :%s" % (channel, line))
            except Exception as e:
                print "Error with file %s" % (tail)
                print e
    
        try:
            text=irc.recv(2040)
            print text
    
            # Prevent Timeout
            if text.find('PING') != -1:
                irc.send('PONG ' + text.split() [1] + '\r\n')
        except Exception:
            continue
    
Share:
69,571

Related videos on Youtube

Jake
Author by

Jake

Updated on July 09, 2022

Comments

  • Jake
    Jake almost 2 years

    I need help writing a basic IRC bot that just connects to a channel.. is anyone able to explain me this? I have managed to get it to connect to the IRC server but i am unable to join a channel and log on. The code i have thus far is:

    import sockethost = 'irc.freenode.org'
    port = 6667
    join_sock = socket.socket()
    join_sock.connect((host, port))
    <code here> 
    

    Any help would be greatly appreciated.

    • jamessan
      jamessan almost 14 years
      Why reinvent the wheel? There are plenty of IRC bots written in Python already.
    • Eric Palakovich Carr
      Eric Palakovich Carr almost 14 years
      @jamessan To learn, of course :)
    • Joe DF
      Joe DF over 10 years
      @eric I love that response :D
  • Jake
    Jake almost 14 years
    Thanks, this is GREAT! Especially the tip about telnet.. Didn't even think of it :) Thanks.. I might have a few more questions.. Let me try out the telnet thing then i will get back!
  • Jake
    Jake almost 14 years
    This is my session: NOTICE AUTH :*** Processing connection to irc.mzima.net NOTICE AUTH :*** Looking up your hostname... NOTICE AUTH :*** Checking Ident NOTICE AUTH :*** Found your hostname NOTICE AUTH :*** No Ident response NICK PYIRC\r\n USER PYIRC PYIRC PYIRC :Python\r\n JOIN #pytest\r\n :irc.mzima.net 451 * :You have not registered It seems to be the registration.. How do i regisster? Or do you know an IRC server that does not require that? i am lost................
  • TheMagician
    TheMagician almost 14 years
    I don't think you can send the commands simultaneously like that. Try sending them separately, because the server might send you something in between the commands, thus you get the notice on registration, that actually refers to connection registration. Apparently there is a PASS <some_password> command you must also send before NICK/USER, I have never had to use that command myself before, so try that, I updated my post.
  • Jake
    Jake almost 14 years
    I see. I am sorry for the sloppy session paste. I was sending them one at a time.. eg: NICK Test\r\n USER ....\r\n and so on. I wonder how to find the password..
  • Jake
    Jake almost 14 years
    How to i register my connection??
  • TheMagician
    TheMagician almost 14 years
    Jake, the password can be anything. You register the connection by sending the PASS, NICK and USER commands to the server. Try it with telnet, irc.quakenet.org 6667 works fine.
  • Jake
    Jake almost 14 years
    Yeah the telnet connection works fine. So at least i got a bit further. But the problem is, if i try to do the same in python. it doesnt work. Maybe python isnt the best language to do this in. though my first though was "python can do this!". It seems perl might be more appropriate for this task, but i really want to use python. But thank you because now i can use IRC with telnet!:b Which is very nice as well. it seems like there is a step missing (maybe the ping pong?) when i try to recreate it in python it goes wrong. If i were to post my new python code would you be willing to look at it?
  • TheMagician
    TheMagician almost 14 years
    Jake, last time I did anything with Python was a couple of years ago. You basically want to have an infinite loop that reads from the server after you have connected. And the first thing you always want to check for is the PING. And make sure you "continue" in the loop after every command or you might miss PINGs or other data that must be read before you can send another command. Try creating a simple server and client script first on your machine and then modify the client script.
  • Jake
    Jake almost 14 years
    Thanks alot. You have helped me greatly :)
  • ffledgling
    ffledgling over 10 years
    The telnet tip is awesome. +1. Going to read the RFC for the full list of Commands!
  • OozeMeister
    OozeMeister over 10 years
    Hey @Jake, if this answer helped you that much, why not select his answer as correct?
  • earthmeLon
    earthmeLon about 10 years
    This is great, but I can only get the while loop to trigger if irc.recv(2040) returns something.
  • earthmeLon
    earthmeLon about 10 years
    You can set irc.setblocking(False) after irc.connect(), but be sure to add a time.sleep() to your while loop unless you want to use your processor to warm your home.
  • freeforall tousez
    freeforall tousez about 9 years
    where does it say that we must wait till the server send all the data? this answer say otherwise