raibo 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/bin/raibo +14 -0
- data/example/example_module.rb +25 -0
- data/lib/raibo.rb +2 -0
- data/lib/raibo/bot.rb +66 -0
- data/lib/raibo/connection.rb +20 -9
- data/lib/raibo/message.rb +63 -0
- data/lib/raibo/version.rb +1 -1
- data/spec/message_spec.rb +46 -0
- data/spec/spec_helper.rb +2 -0
- metadata +14 -18
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/bin/raibo
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'raibo'
|
5
|
+
|
6
|
+
botfile = ARGV.shift || 'Botfile'
|
7
|
+
|
8
|
+
if Dir[botfile].empty?
|
9
|
+
puts "Usage: raibo [botfile]"
|
10
|
+
end
|
11
|
+
|
12
|
+
b = Raibo::Bot.new('irc.he.net', :nick => 'raibot', :port => 6667, :verbose => true)
|
13
|
+
b.instance_eval(File.read(botfile))
|
14
|
+
b.run
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# This is a simple example of a module that could be used with Raibo.
|
2
|
+
# An associated Botfile might look like this:
|
3
|
+
#
|
4
|
+
# require_relative 'example/test_module'
|
5
|
+
# use ExampleModule.new(/hello/, 'goodbye')
|
6
|
+
# use ExampleModule.new(/goodbye/, 'hello')
|
7
|
+
#
|
8
|
+
# This will run a bot that responds to a message containing "hello"
|
9
|
+
# by saying "goodbye", and vice versa.
|
10
|
+
#
|
11
|
+
# Bots can maintain whatever state they want to. The only requirement
|
12
|
+
# is that they respond to a #call method with a Raibo::Connection as
|
13
|
+
# the first parameter and Raibo::Message as the second.
|
14
|
+
|
15
|
+
class ExampleModule
|
16
|
+
def initialize(regexp, response)
|
17
|
+
@regexp, @response = regexp, response
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(c, message)
|
21
|
+
if message.body =~ @regexp
|
22
|
+
c.say @response
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/raibo.rb
CHANGED
data/lib/raibo/bot.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Raibo
|
2
|
+
class Bot
|
3
|
+
def initialize(*args)
|
4
|
+
@handlers = []
|
5
|
+
|
6
|
+
if args.first.is_a?(Raibo::Connection)
|
7
|
+
@connection = args.shift
|
8
|
+
else
|
9
|
+
@connection = Raibo::Connection.new(*args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def use(handler=nil, &block)
|
14
|
+
@handlers.push(handler || block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def match(regexp, &block)
|
18
|
+
use do |msg|
|
19
|
+
if msg.body =~ regexp
|
20
|
+
exec_with_var_arity($~, msg, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def run(async=false)
|
26
|
+
if async
|
27
|
+
@thread = Thread.new { run_sync }
|
28
|
+
@thread.abort_on_exception = true
|
29
|
+
else
|
30
|
+
run_sync
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def stop
|
35
|
+
@thread.kill if @thread
|
36
|
+
@connection.close
|
37
|
+
end
|
38
|
+
|
39
|
+
def alive?
|
40
|
+
@thread.alive? if @thread
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def run_sync
|
45
|
+
@connection.open
|
46
|
+
@connection.handle_lines do |line|
|
47
|
+
begin
|
48
|
+
message = Raibo::Message.new(line)
|
49
|
+
rescue => e
|
50
|
+
if @connection.verbose
|
51
|
+
puts "Error parsing line:"
|
52
|
+
puts " #{line}"
|
53
|
+
puts " #{e.backtrace}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@handlers.each do |handler|
|
57
|
+
if handler.is_a?(Proc)
|
58
|
+
break if @connection.instance_exec(message, &handler)
|
59
|
+
else
|
60
|
+
break if handler.call(@connection, message)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/raibo/connection.rb
CHANGED
@@ -3,23 +3,23 @@ module Raibo
|
|
3
3
|
attr_accessor :server, :port, :nick, :channel
|
4
4
|
|
5
5
|
def initialize(server, opts={})
|
6
|
-
@server
|
7
|
-
@port
|
8
|
-
@nick
|
9
|
-
@channel
|
10
|
-
@verbose
|
6
|
+
@server = server
|
7
|
+
@port = opts[:port] || 6667
|
8
|
+
@nick = opts[:nick] || 'Raibo'
|
9
|
+
@channel = opts[:channel] || '#raibo'
|
10
|
+
@verbose = !!opts[:verbose]
|
11
11
|
end
|
12
12
|
|
13
13
|
def open
|
14
14
|
@connection = TCPSocket.new(@server, @port)
|
15
|
-
send "USER #{@nick} 0 * :
|
15
|
+
send "USER #{@nick} 0 * :Hello"
|
16
16
|
nick @nick
|
17
17
|
|
18
18
|
handle_lines do |line|
|
19
19
|
case line
|
20
|
-
when /:Nickname is already in use
|
21
|
-
@
|
22
|
-
|
20
|
+
when /:Nickname is already in use/
|
21
|
+
@connection.close
|
22
|
+
raise "Connection error: Nickname is already in use."
|
23
23
|
when /001/
|
24
24
|
join @channel
|
25
25
|
break
|
@@ -41,6 +41,8 @@ module Raibo
|
|
41
41
|
yield line
|
42
42
|
end
|
43
43
|
end
|
44
|
+
rescue IOError
|
45
|
+
close
|
44
46
|
end
|
45
47
|
|
46
48
|
def nick(nick)
|
@@ -67,5 +69,14 @@ module Raibo
|
|
67
69
|
puts "<-- #{str}" if @verbose
|
68
70
|
@connection.puts(str)
|
69
71
|
end
|
72
|
+
|
73
|
+
def exec_with_var_arity(*args, &block)
|
74
|
+
arity = block.arity
|
75
|
+
if arity <= 0
|
76
|
+
instance_eval(&block)
|
77
|
+
else
|
78
|
+
instance_exec(*args.take(block.arity), &block)
|
79
|
+
end
|
80
|
+
end
|
70
81
|
end
|
71
82
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Raibo
|
2
|
+
class Message
|
3
|
+
# Readers for the components of the actual IRC protocol line.
|
4
|
+
attr_reader :prefix, :type, :middle, :trailing
|
5
|
+
|
6
|
+
# Readers for higher-level attributes of the message.
|
7
|
+
attr_reader :kind, :from, :to, :body
|
8
|
+
|
9
|
+
def initialize(line)
|
10
|
+
@prefix, @type, @middle, @trailing = parse_line(line)
|
11
|
+
|
12
|
+
@kind = get_kind
|
13
|
+
@from = get_from
|
14
|
+
@to = get_to
|
15
|
+
@body = get_body
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def parse_line(line)
|
20
|
+
prefix, type, params = line.match(/:(\S+) (\S+) (.*)/).captures
|
21
|
+
if params
|
22
|
+
middle, _, trailing = params.partition(':')
|
23
|
+
middle = middle.split
|
24
|
+
trailing.chomp!
|
25
|
+
end
|
26
|
+
[prefix, type, middle, trailing]
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_kind
|
30
|
+
case type
|
31
|
+
when 'PRIVMSG'
|
32
|
+
if trailing =~ /^\001ACTION/
|
33
|
+
:emote
|
34
|
+
else
|
35
|
+
:message
|
36
|
+
end
|
37
|
+
when 'JOIN'
|
38
|
+
:join
|
39
|
+
when 'PART'
|
40
|
+
:part
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_from
|
45
|
+
prefix[/^([^!@ ]*)/, 1]
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_to
|
49
|
+
if [:message, :emote].include?(kind)
|
50
|
+
middle.first
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_body
|
55
|
+
case kind
|
56
|
+
when :message
|
57
|
+
trailing
|
58
|
+
when :emote
|
59
|
+
trailing[/\001ACTION ([^\001]*)/, 1]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/raibo/version.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Raibo
|
4
|
+
describe Message do
|
5
|
+
it 'parses a message' do
|
6
|
+
m = Raibo::Message.new(":someone!someone@Nightstar-251832d1.snfc22.example.com PRIVMSG #raibo :foo bar baz")
|
7
|
+
|
8
|
+
m.kind.should == :message
|
9
|
+
m.from.should == 'someone'
|
10
|
+
m.to.should == '#raibo'
|
11
|
+
m.body.should == 'foo bar baz'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'parses an emote' do
|
15
|
+
m = Raibo::Message.new(":someone!someone@Nightstar-251832d1.snfc22.example.com PRIVMSG #raibo :\001ACTION foo bar baz\001")
|
16
|
+
|
17
|
+
m.kind.should == :emote
|
18
|
+
m.from.should == 'someone'
|
19
|
+
m.to.should == '#raibo'
|
20
|
+
m.body.should == 'foo bar baz'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'parses a join' do
|
24
|
+
m = Raibo::Message.new(":someone!someone@Nightstar-251832d1.snfc22.example.com JOIN :#raibo")
|
25
|
+
|
26
|
+
m.kind.should == :join
|
27
|
+
m.from.should == 'someone'
|
28
|
+
m.to.should == nil
|
29
|
+
m.body.should == nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'parses a part' do
|
33
|
+
m = Raibo::Message.new(":someone!someone@Nightstar-251832d1.snfc22.example.com PART #raibo")
|
34
|
+
|
35
|
+
m.kind.should == :part
|
36
|
+
m.from.should == 'someone'
|
37
|
+
m.to.should == nil
|
38
|
+
m.body.should == nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'parses an arbitrary line' do
|
42
|
+
m = Raibo::Message.new(":Deepthought.NY.US.Nightstar.Net 255 Raibo :I have 83 clients and 1 servers")
|
43
|
+
m.kind.should == nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: raibo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 29
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 1
|
10
|
-
version: 0.0.1
|
5
|
+
version: 0.0.2
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Ryan Fitzgerald
|
@@ -15,15 +10,15 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-07-
|
13
|
+
date: 2011-07-17 00:00:00 -07:00
|
19
14
|
default_executable:
|
20
15
|
dependencies: []
|
21
16
|
|
22
17
|
description: ""
|
23
18
|
email:
|
24
19
|
- rwfitzge@gmail.com
|
25
|
-
executables:
|
26
|
-
|
20
|
+
executables:
|
21
|
+
- raibo
|
27
22
|
extensions: []
|
28
23
|
|
29
24
|
extra_rdoc_files: []
|
@@ -32,10 +27,16 @@ files:
|
|
32
27
|
- .gitignore
|
33
28
|
- Gemfile
|
34
29
|
- Rakefile
|
30
|
+
- bin/raibo
|
31
|
+
- example/example_module.rb
|
35
32
|
- lib/raibo.rb
|
33
|
+
- lib/raibo/bot.rb
|
36
34
|
- lib/raibo/connection.rb
|
35
|
+
- lib/raibo/message.rb
|
37
36
|
- lib/raibo/version.rb
|
38
37
|
- raibo.gemspec
|
38
|
+
- spec/message_spec.rb
|
39
|
+
- spec/spec_helper.rb
|
39
40
|
has_rdoc: true
|
40
41
|
homepage: ""
|
41
42
|
licenses: []
|
@@ -50,25 +51,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
51
|
requirements:
|
51
52
|
- - ">="
|
52
53
|
- !ruby/object:Gem::Version
|
53
|
-
hash: 3
|
54
|
-
segments:
|
55
|
-
- 0
|
56
54
|
version: "0"
|
57
55
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
56
|
none: false
|
59
57
|
requirements:
|
60
58
|
- - ">="
|
61
59
|
- !ruby/object:Gem::Version
|
62
|
-
hash: 3
|
63
|
-
segments:
|
64
|
-
- 0
|
65
60
|
version: "0"
|
66
61
|
requirements: []
|
67
62
|
|
68
63
|
rubyforge_project: raibo
|
69
|
-
rubygems_version: 1.5.
|
64
|
+
rubygems_version: 1.5.2
|
70
65
|
signing_key:
|
71
66
|
specification_version: 3
|
72
67
|
summary: A simple IRC library
|
73
|
-
test_files:
|
74
|
-
|
68
|
+
test_files:
|
69
|
+
- spec/message_spec.rb
|
70
|
+
- spec/spec_helper.rb
|