IRC Reading Sockets

可紊 提交于 2019-12-25 05:25:19

问题


I am making a bot and have most everything ready except input. I want to have something like this: "!test word" and have it output something like "word2". Here is the code that I am using to output data. I would also like to find out my username (opername). Sorry if the indenting is off on the page; it's just fine on my end.

while True:

    data = irc.recv ( 4096 )
    if data.find ('PING' ) != -1:
      irc.send ('PONG ' + data.split() [ 1 ] + '\r\n' )

    if data.find ('!quit') != -1:
      irc.send ('QUIT\r\n')

    if data.find ('!enc %s\r\n' % werd) != -1:
      irc.send ("PRIVMSG %s :%s\r\n" % (channel,werd))

回答1:


There's a fundamental flaw in your code that has to be fixed before you can get any further.

IRC is a line-based protocol, but you're not reading line by line. Instead, you're reading up to 4096 bytes at a time. That could return the first half of a line, or the middle third of a line, or the last third of a line followed by two complete lines and the first two characters of the fourth.

If you don't understand why this is a problem: Imagine that one read returns something ending in '\r\nPI', and the next one returns something starting with 'NG foo\r\n'. Neither of those will match your find('PING'), so you'll miss the command.

The easiest way around this is to change your loop to something like this:

for line in irc.makefile():

As a minor note, you probably want '!quit' in data rather than data.find ('!quit') != -1.

Finally, I don't think this is what you actually want (although I could be wrong):

if data.find ('!enc %s\r\n' % werd) != -1:
    irc.send ("PRIVMSG %s :%s\r\n" % (channel,werd))

This will work if werd is a static string that came from somewhere else, but from your description, it sounds like you want to be able to catch any command !enc foo\r\n and return PRIVMSG #chan: foo\r\n, and also catch !enc bar\r\n and return PRIVMSG #chan: bar\r\n, and so on for any other possibility that someone might type. For that, you may want a regular expression, or you may just want slightly more complicated string-processing code (e.g., split data by whitespace, and if any element matches '!enc', the next element is the word to send back).

Here's an example of one way to do something that may or may not be like what you're trying to do:

m = re.search(r'!enc (.*)\r\n', line)
if m:
    irc.send('PRIVMSG %s: %s\r\n' % (channel, m.group(1)))

I want to have something like this: "!test word" and have it output something like "word2"

OK, so how does it figure out that you want "word2" when given "word"? Whatever the rule is, you obviously have to code that rule up somewhere. Or, if you need help coding it up, you have to describe it to us.

From the comments:

I just want "!test x". The user enters "!test x", I do stuff to "x" and output the changes

I'm assuming you're using x here as a metavariable, not a literal—that is, if the user does "!test x" you do stuff to "x", if the user does "!test y" you do stuff to "y", etc. If I'm wrong, please let me know.

Obviously the code above isn't going to catch that, because it's searching for "enc" rather than "test". But that's a trivial change:

m = re.search(r'!test (.*)\r\n', line)

And as for "do stuff" to x before outputting it, m.group(1) is the x above, so:

if m:
    irc.send('PRIVMSG %s: %s\r\n' % (channel, do_stuff_to(m.group(1))))

If you're not sure what you're sending, receiving, and parsing, you can always add a print statement to test things out:

m = re.search(r'!test (.*)\r\n', line)
print m, m.groups() if m else ''
if m:
    print 'got %s, sending %s' % (m.group(1), do_stuff_to(m.group(1))))
    irc.send('PRIVMSG %s: %s\r\n' % (channel, do_stuff_to(m.group(1))))

If you want to watch what's going over the socket, there are two ways to do that: Install wireshark and use it to spy on the messages on the wire, or set up a fake server using netcat. I won't explain the former, because there's too much to explain, and there are already good tutorials. But for the latter, it's as simple as this: Open a terminal and run nc -kl 8888. Then have your bot connect to localhost:8888 instead of the remote server. Watch what the bot sends to you, and type or paste the replies into the terminal window. (On almost any platform but Windows, nc comes built in; on Windows you need to get netcat or ncat from somewhere, but I'm pretty sure the Wikipedia page has links.) If you need to do a lot of debugging, you can set netcat up as a proxy that just forwards messages back and forth between your bot and the real server and prints out everything that passes through.



来源:https://stackoverflow.com/questions/13059547/irc-reading-sockets

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!