h1. Marvin Marvin is a simple IRC Framework for Rails suitable for building things such as simple IRC bots. Extracted from real use - we'd originally used a heavily modified version of MatzBot - it's been built to service a particular need. h2. Background The library is designed to be event driven in that it: # Uses the EventMachine library for all network connections # It uses an architecture based on event listeners - called 'handlers' It's been heavily influenced by rack in terms of design, making it easy to do things like chain handlers, write your own functionality and most of all making it easy to implement. h2. Getting Started The easiest way to get started with Marvin is by installing the Marvin gem. To do this, make sure Github is added to your gem sources (and you are using rubygems >= 1.2.0) (by default, substitute username for Sutto): $ gem sources -a http://gems.github.com $ sudo gem install username-marvin Once you have installed the gem, you should have access to the "marvin" command: $ marvin --help You can create a new marvin folder: $ marvin create my_marvin_project Then simply edit your settings in the +config/settings.yml+ default: name: Marvin use_logging: false datastore_location: tmp/datastore.json development: user: MarvinBot name: MarvinBot nick: Marvin You can use the defaults or configure it. The datastore location specifies a relative path where a simple json-backed key value store will store persistent information for your client (if chosen). Once that's been done, you'll want to setup some connections by editing +config/connections.yml+, using the following format: "server-address": post: 6667 # Defaults to 6667 channels: - "#marvin-testing" - "#relayrelay" nicks: - List - Of - Alternative - Nicks "another-server-address": post: 6667 # Defaults to 6667 channels: - "#helloworld" Which will let marvin connect to multiple servers - autojoining the specific rooms. Next, to get started you can simply type: $ ./script/client The bot should join the specified channel and will respond to some simple commands by default: *YourName*: MarvinBot3000: hello *MarvinBot3000*: YourName: Hola! As defined in handlers/hello_world.rb h2. Marvin::Base - A handler starting point The first, Marvin::Base provides a base set of methods (e.g. say, reply etc etc.) which make writing a client easier. You can simply inherit from Marvin::Base, write some logic and then use the class method on_event to define responses to events. The passed in meta data for each event is then usable via options.attribute_name - an openstruct version of the details. e.g. class NinjaStuff < Marvin::Base on_event :incoming_message do do_something end def do_something reply options.message # Will echo back the message end end Or the like. Also, the halt! method can be called in any subclass to halt the handler callback chain. You also get access to the class method +on_numeric+ which makes it relatively easy to respond to a specific numeric reply. h2. Marvin::CommandHandler - Ridiculously easy Bots With Marvin::CommandHandler, you get to define seriously simple classes which can act as a simple bot. It takes great inspiration from "MatzBot":http://github.com/defunkt/matzbot/tree/master to make it as easy as possible to make a simple bot To write a CommandHandler, you simply create a subclass (ala ActiveRecord::Base), define a few methods and then just use the "exposes" class method. e.g. class MySecondExample < Marvin::CommandHandler exposes :hello def hello(data) reply "Hello!" end end Where data is an array of parameters. exposed methods will be called when they match the following pattern: Botname: *exposed-method* *space-seperated-list-meaning-data* i.e., the above handler could be called in IRC as such: YourBotsName: hello or, even easier, by PM'ing the bot with: hello h2. Marvin::MiddleMan - Introducing middleware Marvin::MiddleMan lets you insert middleware between handlers and you're client - letting you do things such as translating all messages on the fly. It's build to be extensible and is relatively simple to use. On any Marvin::Base subclass (baring the MiddleMan itself), using a middle man is easy - you simply call the register! class method with an option argument. e.g: HelloWorld.register! Marvin::MiddleMan h2. Marvin::DataStore - A dead simple persistent hash store Want to save data between when you stop and start your IRC Client? With Marvin, it's really, really simple - Marvin::DataStore offers a simple syntax for persistent data stores. New datastores can be created with Marvin::DataStore.new("global-store-key"). From there, you have a hash to do whatever the hell you want. Just make sure the data you store is JSON-serializable. When you start - stop a server (via Marvin::Loader.run! and Marvin::Loader.stop!) you're data will be loaded from and written to disk accordingly. If you're inside a Marvin::Base subclass it's even easier. You can get a cattr_access style accessor for free - just use the "uses_datastore" method. e.g: class X < Marvin::Base uses_datastore "datastore-global-key", :something end Then, self.something will point to the data store - letting you do things like: def hello(data) (self.something[from] ||= 0) += 1 end which will persist the count between each session.