Project

beerbot

0.0
No commit activity in last 3 years
No release in over 3 years
["Out of the box you get an irc bot, but beerbot could be so much more...", ["Daniel Bush"]]
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0
>= 0

Runtime

= 0.1.6
>= 0
 Project Readme

BeerBot

"...the number of BeerBot installations has grown to 1, with more expected..." -- BeerBot Labs

BeerBot is an irc bot written in ruby 2.0 and some bits of thread.

  • Uses ruby 2.0
  • includes IRC
  • Structured to be independent of IRC, the bot itself is agnostic
    • you know, if you want to make BeerBot do xmpp, please do so and let me know :D
  • Uses pry as a repl for administering the bot while running
  • Contains a scheduler based on CronR gem; this should make it easy to get BeerBot to do recurring tasks like reminders

I wrote it partly in frustration with another ruby irc bot and partly for an internal irc server.

Status

  • Started building this in the last week of 27-Nov-2013 .
  • Be careful about using this on a public network.

Batteries sold separately

BeerBot will run and connect to an irc server out of the box but not much else.

A bunch of useful modules can be found here:

This version of beerbot is 0.2.x and should work with similarly versioned bot modules. Look for similar/matching tags/branches in the beerbot-modules git repo :).

Layout

  • lib/ contains the core bot code
  • conf/ example configuration file here; some settings are mandatory, take a look at it
  • bin/ contains beerbot-run-irc.rb

Installing

Install the gem

  gem install 'beerbot'
  type beerbot-run-irc.rb
  # => beerbot-run-irc.rb is hashed (/home/danb/.rvm/gems/ruby-2.0.0-p247/bin/beerbot-run-irc.rb)

Or, if you want the code...

Git clone this code (using your git-fu).

Then do bundle install.

Configure / Setup

First, take a look at the example configuration file in conf/. Hopefully that is mostly self-explanatory.

You want something like this:

  cd somewhere
  mkdir beerbot
  mkdir beerbot/conf
  mkdir beerbot/code
  mkdir beerbot/data
  mkdir beerbot/modules

where...

  • conf/
    • Put your conf file(s) in here
  • code/
    • Bot code can go here (if you're cloning from here, not using the gem)
  • modules/
  • data/
    • This is the datadir in conf.
    • It can be used to store data generated by your modules, see BeerBot::Config#module_data .

Running

If you installed the gem, with a bit of luck, all you need to do (once you've done the above preparatory stuff) is...

  beerbot-run-irc.rb path/to/conf.json

Your path/to/conf.json should be a json file that specifies things like a moduledir and a datadir and some other things - see conf/ for example.

If you're working with the code (not a gem), then you'll probably want to do something like this:

  ruby -Ip/t/b/lib p/t/b/bin/beerbot-run-irc.rb path/to/conf.json

where p/t/b = path/to/beerbot

The -I will force 'require' used in the modules and possibly elsewhere to use the code-based beerbot and not the gem if you installed it. (If you don't, you may get "constant already defined" errors.

You should see some irc lines whizz by on your terminal.

Amongst these you should see some some scary numbers like 001 (that means the irc server likes the cut of our gib), and 353 / 366... you'll get those if you specified any channels in your conf that beerbot will have joined.

Repl

Yeh, repl is cool. Way cool. If you got beerbot running, you already have one once those lines go whizzing by. Hit enter a couple of times and you should see the pry repl prompt

  pry>

Before you go too much further, it's a bit of a pain, using the repl when every now and then a bunch of stuff gets logged into there too. So do this:

  pry> echo
  => false  # suppress other logging
  pry> echo
  => true   # unsuppress

Pry is running inside the BeerBot::Kernel class in lib/kernel.rb . There are some convenience methods in this class for making the bot do things.

  pry> join '#chan1'
  pry> say '#chan1','howdy!'
  pry> action '#chan1','departs the channel hastily'
  pry> leave '#chan1'

You get the idea.

Try typing:

  pry> @scheduler
  pry> @bot
  pry> @config
  pry> @conn
  pry> @conn.connection.closed?

Note, that @bot is just an array of bot modules. Neat. Those are the bot modules that beerbot will run when responding to commands, overhearing messages / actions or receiving events.

@scheduler is an instance of CronR::Cron which is also an array. You can add jobs to it from this repl if you feel so inclined. See the CronR gem.

  pry> @scheduler.time

... will give you the current time for the configured timezone you have. See the CronR documentation.

Talking to the bot (on irc)

On irc, the cmd_prefix you specified in your conf can be used as a shortcut to address the bot.

You can say:

  beerbot: help

or just

  ,help

where , is the cmd_prefix.

If you do this on a channel, beerbot will tell you that it is messaging you directly with help.

Doing... stuff

pry> @bot

should give you access to the core of the bot.

It's an array of BeerBot::BotModule instances which are just hashes (h). h[:mod] should reference the actual bot module.

Ok, so to give you a taste, try this:

pry> mod = Object.new
pry> def mod.cmd msg,**kargs; [to:kargs[:to],msg:"yo"]; end
pry> @bot.push({mod:mod,status:true})

Now, say something to the bot in irc:

irc> ,yo
beerbot> yo

Or on the repl:

pry> @bot.cmd 'hey!'
pry> [{:to=>nil, :msg=>"yo"}]

No irc here. None whatsoever.

Cool no?

Ordinarily, modules are loaded from files using a particular format, but here we just dynamically put one in.

You'll be wanting to be head over to https://github.com/danielbush/beerbot-modules . There you will learn the gentle art of beerbot. There are several different bot methods you'll need to know about besides cmd eg hear, event etc

Going modal

Alright. Advanced topic here. Because we just showed you how to create a rudimentary bot mod on the fly in the above section, we're gonna show you how to suppress that.

pry> @bot.set_cmd{nil} 

Now try talking to the bot.

To get it back:

pry> @bot.set_cmd

So what's the point of that?

Well, if you want to suppress beerbot's normal set of responses as dictated by the modules loaded in @bot, then, well, this is what you want to do.

What you're really doing is setting another module.

pry> mod2 = Object.new
pry> def mod2.cmd msg,**kargs; [to:kargs[:to],msg:"yarp!"]; end
pry> @bot.set_cmd{|msg,**kargs|mod2.cmd(msg,**kargs)}
pry> @bot.set_cmd  # to revert to normal functioning

See?

Or how about, suppress normal beerbot function, and then get him to do something else:

pry> @bot.set_cmd {nil}
pry> ann = lambda {
  @config.out << [to:'#chan1',msg:"This is an announcement..."]
  sleep 1.5
  @config.out << [to:'#chan1',action:"starts drum roll ..."]
  sleep 2.5
  @config.out << [to:'#chan1',msg:"I'm not sentient!"]
}
pry> ann.call
pry> @bot.set_cmd

The bit after the '<<' is what we'll call a botmsg.

We could have also said:

  @config.out << {to:'#chan1',msg:"This is an announcement..."}

A botmsg is a hash, usually with to and msg keys. But it can be an array of these, and arrays allow us to return several lines. Also, it can be a Proc that returns either of the above.

Actually, since we're in the pry repl, we have access to BeerBot's writeq as well, so we could have said this:

  @conn.writeq << IRC.encode([to:'#chan1',msg:"This is an announcement..."])

or even

  @conn.writeq << IRC.msg('#chan1',"This is an announcement...")

But you wouldn't want to or be able to do that in modules loaded normally.

Bit weird isn't it, the whole @config.out thing?

Well, think of @config as something we will be injecting into things like bot modules. It's the config, so it may contain information your modules might want to know about, and because we're a bit cheap, we threw in an out-queue in there too.

Modules like mod and mod2 above often don't have to worry about queues or even the config, they just need to return a generic message (called a botmsg) when responding to something coming over the wire.

But in the event that you want to say something that is not triggered by an input from the irc server, you'll need the out queue. Your mod should receive kargs[:config] with this config instance for that purpose.

https://github.com/danielbush/beerbot-modules for more exciting details.

Array return format

Actually bot modules can return in another more general format:

[bool, botmsg]

where bool is true or false and botmsg is a botmsg (array, hash).

If bool is false, this is interpreted by the bot as meaning "don't process any more bot modules after this one".

See the Bot class which is essentially an array of bot modules that are run in order.

Scheduling

You can grab the CronR scheduler in a more official way like this:

  scheduler = BeerBot::Scheduler.instance
  # Cron parameters: 5 = 'friday', 0,16 = 4pm 
  cronargs = [0,16,true,true,5]
  # Add a job...
  scheduler.suspend {|arr|
    arr << CronR::CronJob.new('timesheet',*cronargs) {
      [to:'#chan',msg:"OMG! it's like 4pm friday..."]
    }
  }

Testing

Tests are in spec/ .

The tests should do a require_relative for the lib/ directory.

So you should be able to run them like: rspec Or rspec spec You could also do rspec -Ilib spec to ensure you're using the checked out code.

Developer

Broadly speaking:


Kernel

  • instantiated with an instance of Config
  • TODO: this is essentially the kernel and should be reusable (if we did xmpp). So we should inject objects like BeerBot::IRCConnection and BeerBot::Codecs::IRC .
  • sets up and knows about all the other parts
    • irc connection
    • dispatcher
    • scheduler
    • the bot and its modules

IRCConnection

  • connects, receives and sends out irc messages

IRC codec

  • encodes and decodes irc messages
  • TODO: I'd probably rename this to encode/decode => returns generic format: [event, *args]

Dispatcher#receive(event, args)

  • has an instance of Bot
  • may call Bot#cmd|hear|action|event
  • which will call instances of BotModule => returns a botmsg