Browse Source

* Initial working implementation

master
Erik Hollensbe 13 years ago
commit
6f7ad32d6a
6 changed files with 221 additions and 0 deletions
  1. +10
    -0
      bin/dbot.rb
  2. +13
    -0
      dbottest.yml
  3. +53
    -0
      lib/dbot.rb
  4. +60
    -0
      lib/dbot/basebot.rb
  5. +45
    -0
      lib/dbot/command.rb
  6. +40
    -0
      lib/dbot/config.rb

+ 10
- 0
bin/dbot.rb View File

@ -0,0 +1,10 @@
#!/usr/bin/env ruby
require 'dbot'
unless ARGV[0]
STDERR.puts "usage: $0 <yaml config>"
exit 1
end
DBot.new(ARGV[0]).run

+ 13
- 0
dbottest.yml View File

@ -0,0 +1,13 @@
delicious_username: "nogoodshits"
delicious_password: "0poopie"
server: "irc.barelylegalbovines.com"
channels:
- "#test"
username: "yummy"
realname: "!help for information."
nicknames:
- "yummy"
- "tasty"
- "delicious"
loud: true
welcome_text: "hello, there!"

+ 53
- 0
lib/dbot.rb View File

@ -0,0 +1,53 @@
begin
require 'rubygems'
gem 'net-yail'
rescue LoadError => e
end
require 'net/yail'
$:.unshift(File.dirname(File.expand_path(__FILE__)))
require 'dbot/config'
require 'dbot/command'
require 'dbot/basebot'
class DBot
def initialize(config_path)
@config = DBot::Config.new(config_path)
load_features
end
def load_features
features = @config.features || []
features.each do |feature|
require feature
end
end
def run
@bot = DBot::BaseBot.new(@config)
if @config.daemonize
fork do
$stdout.reopen('/dev/null')
$stderr.reopen('/dev/null')
$stdin.reopen('/dev/null')
Process.setsid
bot_loop
end
else
bot_loop
end
end
def bot_loop
@bot.connect_socket
@bot.start_listening
@bot.irc_loop
end
end

+ 60
- 0
lib/dbot/basebot.rb View File

@ -0,0 +1,60 @@
begin
require 'rubygems'
gem 'net-yail'
rescue LoadError
end
require 'net/yail'
require 'net/yail/IRCBot'
class DBot
class BaseBot < IRCBot
def initialize(config)
raise "Cannot construct bot; invalid args" if config.nil?
@config = config
@command = DBot::Commands
super(@config.yail_args)
end
def add_custom_handlers
@irc.prepend_handler :incoming_msg, method(:handle_incoming)
end
private
def handle_incoming(hostinfo, nick, channel, text)
out = case channel
when @irc.me
nick
else
channel
end
tokens = text.split(/\s+/)
command = tokens.shift
@commands.handle_command(
@irc,
command,
out,
tokens,
{
:hostinfo => hostinfo,
:nick => nick,
:channel => channel,
:text => text
}
)
end
def welcome(text, args)
welcome_text = @config.welcome_text
@channels.each do |channel|
@irc.join(channel)
msg(channel, welcome_text) if welcome_text
end
end
end
end

+ 45
- 0
lib/dbot/command.rb View File

@ -0,0 +1,45 @@
class DBot
module Commands
@commands = []
def self.register_commandset(commandset)
@commandsets.push(commandset)
end
def self.handle_command(irc, command_str, *args)
@commands.collect do |commandset|
if commandset.handles? command_str
commandset.handle(irc, command_str, *args)
else
nil
end
end.reject { |x| x.nil? }
end
end
class CommandSet
def initialize(valid_commands, leader="!")
@valid_commands = valid_commands || []
@leader = leader
end
def handles?(string)
@valid_commands.include?(strip_leader(string))
end
def handle(irc, command_str, *args)
raise "This command does not handle #{command_str}" unless self.handles?(command_str)
self.send(strip_leader(string).to_sym, *args)
end
protected
def strip_leader(string)
if string[0..(@leader.length-1)] == @leader
string[1..-1]
else
string.dup
end
end
end
end

+ 40
- 0
lib/dbot/config.rb View File

@ -0,0 +1,40 @@
require 'yaml'
require 'delegate'
class DBot
class Config < DelegateClass(Hash)
def initialize(filename)
@config = YAML.load_file(filename)
if @config.nil?
raise "Invalid config: couldn't load file #{filename}."
elsif !@config.kind_of?(Hash)
raise "Invalid config: not a hash"
end
super(@config)
end
# just an override to prefer #duping the result.
def [](x)
@config[x].dup rescue @config[x]
end
# produces the args needed by Net::YAIL's constructor.
def yail_args
{
:irc_network => self["server"],
:channels => self["channels"],
:username => self["username"],
:realname => self["realname"],
:nicknames => self["nicknames"],
:loud => self["loud"],
}
end
# read-only struct-like behavior.
def method_missing(method, *args)
self[method.to_s]
end
end
end

Loading…
Cancel
Save