Class | Net::YAIL |
In: |
lib/net/yail.rb
lib/net/yail/message_parser.rb |
Parent: | Object |
This library is based on the initial release of IRCSocket with a tiny bit of plagarism of Ruby-IRC.
My aim here is to build something that is still fairly simple to use, but powerful enough to build a decent IRC program.
This is far from complete, but it does successfully power a relatively complicated bot, so I believe it‘s solid and "good enough" for basic tasks.
Current list of incoming events and the parameters sent to the handler:
Common parameter elements:
Generally speaking, you won‘t need these very often, but they‘re here for the edge cases all the same. Note that the socket output cannot be skipped (see "Return value from events" below), so this is truly just to allow modifying things before they go out (filtering speech, converting or stripping markup, etc) or just general stats-type logic.
Note that in all cases below, the client is about to perform an action. Text can be filtered, things can be logged, but keep in mind that the action has not yet happened.
Events:
Note that a single output call can hit multiple handlers, so you must plan carefully. A call to act() will hit the act handler, then ctcp (since act is a type of ctcp message), then privmsg.
Yes, you can register your own wacky event handlers if you like, and have your code call them. Just register a handler with some funky name of your own design (avoid the prefixes :incoming and :outgoing for obvious reasons), and so long as something calls that handler, your handler method will get its data.
This isn‘t likely useful for a simple program, but for a subclass or wrapper of the IRC class, having the ability to give its users new events without mucking up this class can be helpful. For instance, see IRCBot#irc_loop and the :irc_loop event. If one wants their bot to do something regularly, they just handle that event and get frequent calls.
The return can be critical - a true value tells the handlers to stop their chain (true = "yes, I handled this event, stay the frak away you other, lesser handlers!), so no other handlers will be called.
Note that critical handlers (incoming ping, welcome, and nick change) cannot be overwritten as they actually run before user-defined handlers, and output handlers are just for filtering and cannot stop the socket from sending its data. If you want to change that low-level stuff, you should subclass, modify the code directly, monkey-patch, or just write your own library.
When should you return false from an event? Generally any time you have a handler that really needs to report itself. Unless you have multiple layers of handlers for a given event, there‘s little reason to worry about breaking the chain of events. Since handlers are prepended to the list, anybody subclassing your code can override your events, not the other way around. The main use is if you have multiple handlers for a single complex event, where you want each handler to do its own set process and pass on the event if it isn‘t resposible for that particular situation. Allows complex interactions to be made a bit cleaner, theoretically.
For a program to do anything useful, it must instantiate an object with useful data and register some handlers:
require 'rubygems' require 'net/yail' irc = Net::YAIL.new( :address => 'irc.someplace.co.uk', :username => 'Frakking Bot', :realname => 'John Botfrakker', :nicknames => ['bot1', 'bot2', 'bot3'] ) irc.prepend_handler :incoming_welcome, proc {|text, args| irc.join('#foo') return false } irc.start_listening while irc.dead_socket == false # Avoid major CPU overuse by taking a very short nap sleep 0.05 end
Now we‘ve built a simple IRC listener that will connect to a (probably invalid) network, identify itself, and sit around waiting for the welcome message. After this has occurred, we join a channel and return false.
One could also define a method instead of a proc:
require 'rubygems' require 'net/yail' def welcome(text, args) @irc.join('#channel') return false end irc = Net::YAIL.new( :address => 'irc.someplace.co.uk', :username => 'Frakking Bot', :realname => 'John Botfrakker', :nicknames => ['bot1', 'bot2', 'bot3'] ) irc.prepend_handler :incoming_welcome, method(:welcome) irc.start_listening while irc.dead_socket == false # Avoid major CPU overuse by taking a very short nap sleep 0.05 end
See the included logger bot (under the examples directory of this project) for use of the IRCBot base class. It‘s a fully working bot example with real-world use.
VERSION | = | '1.3.2' |
dead_socket | [R] | |
loud | [RW] | |
me | [R] | |
nicknames | [R] | |
registered | [R] | |
silent | [RW] | |
socket | [R] | |
throttle_seconds | [RW] |
Makes a new instance, obviously.
Note: I haven‘t done this everywhere, but for the constructor, I felt it needed to have hash-based args. It‘s just cleaner to me when you‘re taking this many args.
Options:
Handles the given event (if it‘s in the @handlers array) with the arguments specified.
The @handlers must be a hash where key = event to handle and value is a Proc object (via Class.method(:name) or just proc {…}). This should be fine if you‘re setting up handlers with the prepend_handler method, but if you get "clever," you‘re on your own.
Since numerics are so many and so varied, this method will auto-fallback to a simple report if no handler was defined.
Event handler hook. Kinda hacky. Calls your event(s) before the default event. Default stuff will happen if your handler doesn‘t return true.
Reports may not get printed in the proper order since I scrubbed the IRCSocket report capturing, but this is way more straightforward to me.
Starts listening for input and builds the perma-threads that check for input, output, and privmsg buffering.