1

I have an IRC bot written in Python that works fairly well. I think the issue is with my limited knowledge of the IRC protocol, so IRC gurus are particularly welcome here :D

When you first connect to an IRC network, a MOTD usually gets displayed. The network will not accept any commands until the MOTD is finished. So with my bot, I have to have a loop that checks for the end of the MOTD. This isn't particularly modular at all, as in my experience not all servers end their MOTD's the same way. Is there a way to tell the server to not send the MOTD, or indeed a better way to wait for the end of the MOTD to tell the server what channel I wish to connect to?

My current code for waiting for the end of MOTD consists of a while loop reading the input buffer and parsing each full command into a list. It takes this list and searches each string object for a certain string that appears at the end of FreeNode's MOTD, if it is found, the loop ends and a command to join a channel is sent before going into the main loop.

Is there a better way to handle the MOTD's? I can't help but feel that this way is rather clumsy.

LiamMeron
  • 13
  • 6

2 Answers2

2

Is there a way to tell the server to not send the MOTD, or indeed a better way to wait for the end of the MOTD to tell the server what channel I wish to connect to

No, there isn't a way to turn off the MOTD. However, it shouldn't even be necessary, because your assumption that "The network will not accept any commands until the MOTD is finished" is not true in the first place.

All networks start accepting commands immediately as soon as you register (i.e. send NICK and USER) โ€“ some of them merely delay acting on those commands by a second or two. It is perfectly valid to start sending commands as soon as you can.


In any case, you wouldn't need to delay the main loop to achieve this โ€“ indeed, all received input should be handled by the same loop. Instead, you would just keep track of whether you have already seen an "end of MOTD" line, and send the JOINs the first time you see it.

Also, from your description, it does sound like you're using a somewhat unreliable method to detect the end of MOTD. If you're looking for the "End of /MOTD" string โ€“ don't. Instead, parse the entire line as specified in RFC 1459 ยง 2.3.1 (here's a not-particularly-Pythonic parser) and check the command in each line, since the descriptive text can vary between different IRC daemons. You should also check for the "no /MOTD" message.

For example, you would have:

# raw input is ":leguin.freenode.net 376 grawity :End of /MOTD.\r\n"
# split input is [":leguin.freenode.net", "376", "grawity", "End of /MOTD."]
# parsed input is {"prefix":  "leguin.freenode.net",
#                  "command": "376",
#                  "args":    ["grawity", "End of /MOTD."]}

RPL_WELCOME = "001" RPL_ENDOFMOTD = "376" ERR_NOMOTD = "422"

if not sent_initial_join: if command in {RPL_WELCOME, RPL_ENDOFMOTD, ERR_NOMOTD}: conn.send("JOIN %s\r\n" % ",".join(channels)) sent_initial_join = True

But as said above, this should never be necessary. Just send the JOINs immediately after NICK, USER, and things like CAP END.

And by the gods, do not use something as silly as a 10 second timeout for this.

grawity
  • 501,077
0

What I do is wait until I get an 376 or 422 numeric then I send the commands to join channels, setup notify list, etc.

if split_line[1] == '376' or split_line[1] == "422":
    # End of /motd # keep track if it is the first motd 
    # (on connect) or already connected.
    if not socket_data.state[client_socket]['connected']:
        socket_data.state[client_socket]['connected'] = time()
        # Join channels now

An irc server sends messages starting with an number either as the first word or the second word following ":irc.server.com". I just check if the first character of the line is not ':' then I add an empty string to the split_line. If the second word is an digit then it is an numeric. Different numbers mean different things, in this case, just looking for 422 will tell you there is no MOTD file, and 376 says end of MOTD and 375 is the content of the MOTD. https://www.tg007.net/raws lists many raw numeric codes.