Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IRC bot in python won't send messages

Tags:

python

irc

I'm using Phredds Irc bot because I am trying to make a bot for my twitch chat. It connects and responds to pings fine but it won't respond to anything else. I seem to be doing exactly what he did in the pastebin so what is wrong with this?

import socket #imports module allowing connection to IRC
import threading #imports module allowing timing functions

#sets variables for connection to twitch chat
bot_owner = 'TwitchPlaysFightingGames'
nick = 'MagicalCakeBot'
channel = '#TwitchPlaysFightingGames'
server = 'irc.twitch.tv'
password = 'oauth:~redacted~'

queue = 0 #sets variable for anti-spam queue functionality

irc = socket.socket()
irc.connect((server, 6667)) #connects to the server

#sends variables for connection to twitch chat
irc.send('PASS ' + password + '\r\n')
irc.send('USER ' + nick + ' 0 * :' + bot_owner + '\r\n')
irc.send('NICK ' + nick + '\r\n')
irc.send('JOIN ' + channel + '\r\n') 

def message(msg): #function for sending messages to the IRC chat
    global queue
    queue = queue + 1
    print queue
    if queue < 20: #ensures does not send >20 msgs per 30 seconds.
        irc.send('PRIVMSG ' + channel + ' :' + msg + '\r\n')
    else:
        print 'Message deleted'

def queuetimer(): #function for resetting the queue every 30 seconds
    global queue
    print 'queue reset'
    queue = 0
    threading.Timer(30,queuetimer).start()
queuetimer()

while True:
    data = irc.recv(1204) #gets output from IRC server
    user = data.split(':')[1]
    user = user.split('!')[0] #determines the sender of the messages
    print data

    if data.find('PING') != -1:
        irc.send(data.replace('PING', 'PONG')) #responds to PINGS from the server
    if data.find('!test') != -1: #!test command
        message('Hi')
like image 291
TheMagicalCake Avatar asked Feb 21 '14 06:02

TheMagicalCake


1 Answers

I glanced over your implementation and it looks like it should work (in most practical cases) now that you have edited it to contain the message function definition. I briefly tested the implementation you posted after your edit and it worked for me during two test runs.

Although it worked for me, I would not say that it is completely foolproof as is. When I tested it, I tested it in a quiet channel that was not flooding the socket with a high volume of data. Judging by the name of the channel you included in your code ("#TwitchPlaysFightingGames"), I suspect that you may be joining this rudimentary Twitch IRC client into a channel that is continuously pushing a high volume of data. The case I am about to describe touches on why this might be an issue for you.

Divided Message Issue

The one obvious problem I see involves how you are handling the data you are receiving from your call to socket.recv(). Your code receives a hard-coded finite amount of data per call to the socket receive function and then assumes that it will always contain one full "message", so to speak. In your case, the "message" you are interested in is "!test" Depending on various factors including the latency between calls to socket.recv() and the received packet length(s), it is possible for your "message"-inspection logic to fail when a single "message" is divided across two calls to socket.recv().

In the following simplified snippet of code, consider what would happen if the socket's buffer contained the data "[x][y:1]":

while True:
  response = socket.recv(5)
  if response.find("[y:1]") != -1:
    print("success")

During the first iteration, response would be equal to "[x][y". During the second iteration, response would be equal to ":1]". Neither of these iterations would contain the message "[y:1]". In this example, "success" would never be printed. This is a significantly scaled down version of the problem I described above.

That said, if you wanted to create a completely foolproof implementation, you may consider building a separate buffer to house unparsed pieces of "messages". For instance, in the example above, if you parse the message "[x]" and keep the remainder of the receive buffer ("[y") in a separate unparsed message buffer, you can later join the content of the next receive buffer with the unparsed message buffer to yield the full "message" (in this case, "[y:1]").

Potential IndexError Exception Issue

Another issue is that you are performing string split operations and immediately attempting to access an index of a list that may not contain any elements. You would know when this happens, because the attempt would raise an IndexError exception. I am guessing this is not happening to you, because you did not mention any exceptions.

Advice For Debugging Your Issue

Because I could not easily reproduce your issue, it may help to have more information about your situation. I would start by testing the code in a quiet channel. Next, you should consider saving a second copy of the code and simplifying it so that you can narrow down the issue, if it still persists.

Consider removing the following code to simplify your problem:

  • remove the call to queuetimer() as well as its function definition and any other references to the queue variable
  • simplify the message() function so that it only calls irc.send()
  • remove the data.split() and user.split() lines, since you are not using them

If you still cannot figure out what the problem is, post back to this thread with any additional information you uncover.

An Additional Twitch.TV IRC Client Example

I figured it might help for you to see an example of what it may entail to take some steps toward parsing more of the Twitch.TV IRC protocol; so, I uploaded a quick demonstration application to GitHub with this in mind: see https://github.com/jwilges/twitchtvircclient for the demonstration code.

like image 159
Jeffrey Wilges Avatar answered Nov 16 '22 05:11

Jeffrey Wilges