Skip to content
This repository was archived by the owner on Nov 10, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions lib/isaac/bot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
module Isaac
VERSION = '0.2.1'

Config = Struct.new(:server, :port, :ssl, :password, :nick, :realname, :version, :environment, :verbose, :encoding)
Config = Struct.new(:server, :port, :ssl, :password, :nick, :realname, :version, :environment, :verbose, :encoding, :channels)

class Bot
attr_accessor :config, :irc, :nick, :channel, :message, :user, :host, :match,
:error

def initialize(&b)
@events = {}
@config = Config.new("localhost", 6667, false, nil, "isaac", "Isaac", 'isaac', :production, false, "utf-8")
@config = Config.new("localhost", 6667, false, nil, "isaac", "Isaac", 'isaac', :production, false, "utf-8", [])

instance_eval(&b) if block_given?
end
Expand All @@ -20,6 +20,12 @@ def configure(&b)
b.call(@config)
end

def configure_from(file)
cfgfile = ::File.read(file)
cfgfile.sub!(/^__END__\n.*/, '')
instance_eval( cfgfile )
end

def on(event, match=//, &block)
match = match.to_s if match.is_a? Integer
(@events[event] ||= []) << [Regexp.new(match), block]
Expand Down Expand Up @@ -71,7 +77,7 @@ def quit(message=nil)
end

def start
puts "Connecting to #{@config.server}:#{@config.port}" unless @config.environment == :test
$stdout.puts "Connecting to #{@config.server}:#{@config.port}" unless @config.environment == :test
@irc = IRC.connect(self, @config)
end

Expand Down Expand Up @@ -118,9 +124,11 @@ def invoke(block)

class IRC < EventMachine::Connection
def self.connect(bot, config)
EventMachine.connect(config.server, config.port, self, bot, config)
EventMachine.connect(config.server, config.port, IRCClient, bot, config)
end
end

module IRCClient
def initialize(bot, config)
@bot, @config = bot, config
@transfered = 0
Expand All @@ -147,14 +155,15 @@ def receive_data(data)
end

def parse(input)
puts "<< #{input}" if @bot.config.verbose
$stdout.puts "<< #{input}" if @bot.config.verbose
msg = Message.new(input)

if ("001".."004").include? msg.command
@registration << msg.command
if registered?
@queue.unlock
@bot.dispatch(:connect)
@bot.join(*@bot.config.channels) unless @bot.config.channels.empty?
end
elsif msg.command == "PRIVMSG"
if msg.params.last == "\001VERSION\001"
Expand Down
165 changes: 105 additions & 60 deletions test/helper.rb
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,60 +1,105 @@
$LOAD_PATH.unshift 'lib'
require 'isaac'
require 'rubygems'
require 'test/unit'
require 'contest'
require 'rr'
require 'timeout'
begin
require 'ruby-debug'
rescue LoadError; end

module Test::Unit::Assertions
def assert_empty_buffer(io)
assert_raise(Errno::EAGAIN) { io.read_nonblock 1 }
end
end

class MockSocket
def self.pipe
socket1, socket2 = new, new
socket1.in, socket2.out = IO.pipe
socket2.in, socket1.out = IO.pipe
[socket1, socket2]
end

attr_accessor :in, :out
def gets()
Timeout.timeout(1) {@in.gets}
end
def puts(m) @out.puts(m) end
def print(m) @out.print(m) end
def eof?() @in.eof? end
def empty?
begin
@in.read_nonblock(1)
false
rescue Errno::EAGAIN
true
end
end
end

class Test::Unit::TestCase
include RR::Adapters::TestUnit

def mock_bot(&b)
@socket, @server = MockSocket.pipe
stub(TCPSocket).open(anything, anything) {@socket}
bot = Isaac::Bot.new(&b)
bot.config.environment = :test
Thread.start { bot.start }
bot
end

def bot_is_connected
assert_equal "NICK isaac\r\n", @server.gets
assert_equal "USER isaac 0 * :Isaac\r\n", @server.gets
1.upto(4) {|i| @server.print ":localhost 00#{i}\r\n"}
end
end
$LOAD_PATH.unshift 'lib'
require 'isaac/bot'
require 'rubygems'
require 'test/unit'
require 'contest'
require 'rr'
require 'timeout'
begin
require 'ruby-debug'
rescue LoadError; end

class MockSocket
def self.pipe
socket1, socket2 = new, new
socket1.in, socket2.out = IO.pipe
socket2.in, socket1.out = IO.pipe
[socket1, socket2]
end

attr_accessor :in, :out
def gets()
Timeout.timeout(1) {@in.gets}
end
def puts(m) @out.puts(m) end
def print(m) @out.print(m) end
def eof?() @in.eof? end
def empty?
begin
@in.read_nonblock(1)
false
rescue Errno::EAGAIN
true
end
end
end


class FakeReactor

def poll(io, &blk)
(@polls ||= {})[io] = lambda {
blk.call(io.read_nonblock(1))
}
end

def react!
@polls.each do |_, proc|
loop do
begin
proc.call
rescue Errno::EAGAIN
break
end
end
end
end

end


class StubIRCClient
include Isaac::IRCClient

attr_accessor :socket

def send_data data
@socket.print data
end

end


class Test::Unit::TestCase
include RR::Adapters::TestUnit

def mock_bot(bot=nil, &b)
@socket, @server = MockSocket.pipe
bot ||= Isaac::Bot.new(&b)
@r = FakeReactor.new
stub(Isaac::IRC).connect(anything, anything) do
conn = StubIRCClient.new(bot, bot.config)
conn.socket = @socket
conn.post_init
@r.poll(@socket.in) { |data| conn.receive_data data }
conn
end
bot.config.environment = :test
bot.start
bot
end

def bot_is_connected
assert_equal "NICK isaac\r\n", @server.gets
assert_equal "USER isaac 0 * :Isaac\r\n", @server.gets
1.upto(4) {|i| @server.print ":localhost 00#{i}\r\n" }
react!
end

def react!
@r.react!
end

end


40 changes: 40 additions & 0 deletions test/test_configure_from.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require 'helper'
require 'tempfile'

class TestConfigureFrom < Test::Unit::TestCase
include Isaac

def setup
@file = Tempfile.open('config') do |f|
f.write(
<<__EOF__
config.server = "irc.foo.com"
config.nick = "foo"
config.realname = "Bar"
__EOF__
)
f
end
end

def teardown
@file.unlink
end

test "config is loaded from specified file" do
bot = Bot.new

bot.configure_from(@file.path)
assert_equal "irc.foo.com", bot.config.server
assert_equal "foo", bot.config.nick
assert_equal "Bar", bot.config.realname
end

test "default config is not changed" do
bot = Bot.new

bot.configure_from(@file.path)
assert_equal 6667, bot.config.port
end

end
1 change: 1 addition & 0 deletions test/test_events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,5 @@ def dispatch(type, env)

assert_equal "foo\r\n", @server.gets
end

end
4 changes: 3 additions & 1 deletion test/test_irc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ class TestIrc < Test::Unit::TestCase
bot = mock_bot {
configure {|c| c.password = "foo"}
}

assert_equal "PASS foo\r\n", @server.gets
end

test "no messages are sent when registration isn't complete" do
bot = mock_bot {
on(:connect) {raw "Connected!"}
}

2.times { @server.gets } # NICK / USER
bot.dispatch :connect

Expand All @@ -32,7 +34,7 @@ class TestIrc < Test::Unit::TestCase
2.times { @server.gets } # NICK / USER
bot.dispatch :connect

1.upto(4) {|i| @server.puts ":localhost 00#{i}"}
1.upto(4) {|i| @server.puts ":localhost 00#{i}"}; react!
assert_equal "Connected!\r\n", @server.gets
end
end
Loading