Plugins

Ratchet has a powerful plugin system allowing on the fly loading/unloading/configuration, the ability for plugins to add their commands to /help's output and the ability to define what variables they'd like configured and expose those to the user via a GUI.

Ratchet currently bundles 4 plugins:

Writing a plugin

Ratchet's plugins consist of combinations of 3 actions, adding a method, adding a callback and adding a callback after a method has been called. In theory you could add a callback and a method anywhere in Ratchet's code, but usually there are only 4 places where it is useful to do so: commands, events, replies and buffer formatting. Ratchet looks for methods/callbacks beginning with cmd_, event_, reply_ and buffer_ both for inserted functions and callbacks. The callback system is similar to GTK+s system where if the callback returns true, subsequent callback/method execution is terminated.

ALL plugins must be objects that directly inherit from the class Plugin and they must place all the code they wish executed in the load function. An unload function is also called when the plugin is unloaded, but this is only needed if you need to do additional cleanups. Plugins can also optionally implement a configure function that returns an array of hashes detailing the config options, their description, type, tooltip, etc. Ratchet uses this information to create a dialog window to allow GUI configuration of the plugin.

As an example, here's a sample plugin that I whipped up...

#a l33tify plugin (because its damn easy to do)

class L33tify < Plugin
    #define a method to mangle strings
    def l33tify(string)
        string.gsub!(/s/i, '5')
        string.gsub!(/e/i, '3')
        string.gsub!(/i/i, '1')
        string.gsub!(/o/i, '0')
        string.gsub!(/a/i, '4')#you get the idea
        string
    end

    #the method called when the plugin is loaded
    def load
        #set some config variables, use ||= to prevent clobbering existing values
        @@main.config['autol33t'] ||= false
        
        #document the command
        help :cmd_l33t, '"l33tify" the outgoing message'
        add_method(self, Main, 'cmd_l33t') do |arguments, target|
            #mangle the string and pass it to the message command
            cmd_message(l33tify(arguments), target)
        end
        
        add_callback(self, Main, 'cmd_message') do |arguments, target|
            #if autol33t is set, mangle the output of messages
            arguments = l33tify(arguments) if @@main.config['autol33t']
            #return the arguments so they can be passed to the real method
            [arguments, target]
        end
        
        #don't use a callback_after, it'd have too much XML crap in it we might screw up
        add_callback(self, Buffer, 'buffer_message') do |line, pattern, username, users, insert_location|
            #don't try to escape XHTML-IM messages, too lazy
            if line[MSG]
                line[MSG] = l33tify(line[MSG])
            end
            #again, return the data back to the real method
            [line, pattern, username, users, insert_location]
        end
    end

    def configure
        [{'type'=> TrueClass, 'name'=>'autol33t', 'value'=>@@main.config['autol33t'],
            'description'=>'automatically l33tify outgoing messages?'}]
    end
end

#create an instance of the plugin and register it
l33tify = L33tify.new
Plugin.register(l33tify)

I've removed the scoping wtf, now all method and callback blocks are evaluated in their calling scope, and if something can't be resolved it looks up the plugin (or tries to, its possible it will find the wrong plugin right now, so unique method/var names would be a good idea).

I've also added command_missing, the function called if a command cannot be found, you can also all callbacks to this to implement dynamic methods (see numberswitcher plugin for details).

Clients/Ratchet/Plugins (last edited 2009-03-15 22:42:39 by localhost)