- A fairly awful user experience.
- Confusing to new users.
I additionally don’t like this idea since it requires us to have commands for all the common tasks you’d want to do in an auto-perform (or support sending absolutely raw messages to the server, which we actually do already in the /quote command). Essentially what I just described is writing our own scripting language…that seems pointless (and frankly, I have better things to do). I’m hoping to convince you with this post (and maybe a series of posts) that auto-performs aren’t necessary and a trivial restartless extension can replace them.
Initially I tried to do this by making the IRC account into an XPCOM component (well it is one already, it’s an prplIAccount, but I meant an IRC specific one: implementing ircIAccount, if you will). Unfortunately, this seemed to have a lot of overhead and got complicated extremely quickly. Anything I’d want to touch from a message handler (wait, wait…what’s a handler?! I’ll get back to that) would need to have methods written and exposed to access internal data of the account…does that sound very extensible to you? Well, it doesn’t to me…
- IRC itself (i.e. RFC 1459 / RFC 2812 / various numeric extensions)
- CTCP (the Client-to-Client Protocol),embedded in PRIVMSG commands of IRC
- DCC (Direct Client-to-Client), a subprotocol of CTCP
- ISUPPORT (also known as Numeric 005), a method of negotiating capabilities between a client and server
- And finally, handling of IRC Services (there’s a lot of them and no specification, but we treat them specially)
Briefly what happens when we receive a raw message over the wire, we create an ircMessage object out of it using a variety of regular expressions. This object has a variety of fields (see the link for details), including the command, who sent the message and the parameters.
If the message is identified as a CTCP message, we then morph the ircMessage into a CTCPMessage, which can be morphed into a DCCMessage. Additionally, a 005 reply can be parsed into a isupportMessage. And last, but not least, a received PRIVMSG can also be parsed into a ServiceMessage. Each of these extends the IRC message without destroying information. (Yes, I’m realizing now that my choice of whether to use capitals is all messed up…)
Well, why do we care…? By preparsing the strings into objects (as defined by any “specifications” that exist), we keep extensions from having to parse messages over and over again from strings.
A handler is simply what I call the object that contains the methods to deal with an incoming message. Pretty much, you get to say “Only send me ISUPPORT messages!” or “Only send me CTCP messages!” and voila, you only get that type of message. Each message type has a field that is used to choose the method to run (for the IRC messages, the “command”, for CTCP the “CTCP command”, ISUPPORT the “parameter”, etc.) This sounds a lot more complicated than it is, I think a brief example is in order:
Just like that we’ve designed a handler! Whenever the 001 method is received from the server, this function will run and attempt to identify with the NickServ (of course this could use a bit more security on it, but it’s to demonstrate the possibilities). (The sendMessage function takes the command to send and an array of parameters to send.)
As this is already a long post, I think I’ll cut this off now and continue this at another time, but I hope I’m beginning to convince you that allowing directy access to the account and protocol implementation is a more powerful (and even simpler in many ways, in my opinion) alternative to “auto-performs”. The one major downside I see to this, is that it requires a bit more understanding of the actual protocol level implementation, I don’t feel that knowing you need to use “PRIVMSG” as a command instead of /msg is a huge issue, however.