dragoon 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +27 -0
- data/Rakefile +1 -0
- data/TODO +48 -0
- data/bin/dragoon +10 -0
- data/config/config.yml +4 -0
- data/config/config.yml.example +4 -0
- data/dragoon.gemspec +23 -0
- data/lib/dragoon.rb +106 -0
- data/lib/dragoon/color.rb +38 -0
- data/lib/dragoon/commands.rb +31 -0
- data/lib/dragoon/core_ext.rb +3 -0
- data/lib/dragoon/event.rb +43 -0
- data/lib/dragoon/event_manager.rb +20 -0
- data/lib/dragoon/version.rb +3 -0
- data/spec/colors_spec.rb +99 -0
- data/spec/event_manager_spec.rb +46 -0
- data/spec/event_spec.rb +64 -0
- data/spec/spec_helper.rb +4 -0
- metadata +117 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Dragoon
|
2
|
+
============
|
3
|
+
|
4
|
+
An IRC bot that notifies you of keyword occurences in your favorite chatrooms. You can listen to multiple channels but right now, i've only tested it on freenode.net. Support for multiple networks will be done soon.
|
5
|
+
|
6
|
+
|
7
|
+
Dependencies
|
8
|
+
-----------
|
9
|
+
|
10
|
+
- growl
|
11
|
+
- growlnotify
|
12
|
+
|
13
|
+
P.S. You can still run the program even without growl, you'll only see the keywords being highlighted and there won't be any growl notificaiton, that's all.
|
14
|
+
|
15
|
+
Usage
|
16
|
+
-----
|
17
|
+
|
18
|
+
1. `git clone git://github.com/redgetan/dragoon.git`
|
19
|
+
2. Create a configuration file under config/ directory and name it "config.yml". See "config.yml.example" for reference.
|
20
|
+
3. If you have growl support, make sure it's turned on
|
21
|
+
4. To start the program, type `./bin/dragoon`
|
22
|
+
|
23
|
+
P.S. will gemify this soon so you only have to do 'gem install dragoon', then 'dragoon'
|
24
|
+
|
25
|
+
Screenshot
|
26
|
+
---------
|
27
|
+
http://farm8.staticflickr.com/7027/6733543233_6f354d61d0_b.jpg
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/TODO
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
TODO
|
2
|
+
----------
|
3
|
+
- [x] config.yml.example
|
4
|
+
- [x] network: irc.freenode.net
|
5
|
+
- [x] channels: #ubuntu, #ruby, #ffmpeg
|
6
|
+
- [x] keywords: and, how, why, help
|
7
|
+
- [x] connect to network
|
8
|
+
- [ ] - multiple networks
|
9
|
+
- [x] login
|
10
|
+
- [x] join channels
|
11
|
+
- [x] Event Parsing
|
12
|
+
- [x] during msg events (PRIVMSG)
|
13
|
+
- [x] - parse message
|
14
|
+
- [x] - highligh keywords
|
15
|
+
- [x] - feature
|
16
|
+
- [ ] - add ignore case
|
17
|
+
- [x] - tests
|
18
|
+
- [x] - colorize channel
|
19
|
+
- [x] - feature
|
20
|
+
- [x] - tests
|
21
|
+
- [ ] channel view
|
22
|
+
- [ ] - enter a command (i.e view #ubuntu)
|
23
|
+
- [ ] - shows only messages belonging to a specific channel
|
24
|
+
- [ ] command line options
|
25
|
+
- [ ] - help
|
26
|
+
- [ ] - verbose mode (list all msgs sent to me msgs that i send to server)
|
27
|
+
|
28
|
+
|
29
|
+
Problems encountered
|
30
|
+
--------------
|
31
|
+
Cannot join certain channels
|
32
|
+
- :calvino.freenode.net 477 pacman23 ##java :Cannot join channel (+r) - you need to be identified with services
|
33
|
+
|
34
|
+
Helpful links
|
35
|
+
-------------
|
36
|
+
- http://www.irchelp.org/irchelp/rfc/
|
37
|
+
- http://www.irchelp.org/irchelp/misc/ccosmos.html (Advanced IRC Guide)
|
38
|
+
- http://www.irchelp.org/irchelp/text/rfc1459.txt
|
39
|
+
- http://www.devarticles.com/c/a/Delphi-Kylix/Building-an-IRC-Client/
|
40
|
+
- http://www.jibble.org/pircbot.php
|
41
|
+
- http://www.scribd.com/doc/28253878/EventMachine-scalable-non-blocking-i-o-in-ruby
|
42
|
+
- http://www.paperplanes.de/2011/4/25/eventmachine-how-does-it-work.html (EM vs lower level socket prog, ie select, poll)
|
43
|
+
- http://cia.vc/doc/
|
44
|
+
|
45
|
+
Existing IRC clients/bots to get ideas from
|
46
|
+
-------------------------------------------
|
47
|
+
- https://github.com/cinchrb/cinch
|
48
|
+
- https://github.com/RISCFuture/autumn
|
data/bin/dragoon
ADDED
data/config/config.yml
ADDED
data/dragoon.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dragoon/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dragoon"
|
7
|
+
s.version = Dragoon::VERSION
|
8
|
+
s.authors = ["Reginald Tan"]
|
9
|
+
s.email = ["redge.tan@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/redgetan/dragoon"
|
11
|
+
s.summary = %q{IRC bot for keyword notification }
|
12
|
+
s.description = %q{An IRC bot that alerts you whenever certain keywords appear in your favorite channels }
|
13
|
+
|
14
|
+
s.rubyforge_project = "dragoon"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_runtime_dependency "term/ansicolor"
|
23
|
+
end
|
data/lib/dragoon.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'forwardable'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
require 'term/ansicolor'
|
7
|
+
|
8
|
+
require 'dragoon/commands'
|
9
|
+
require 'dragoon/event'
|
10
|
+
require 'dragoon/event_manager'
|
11
|
+
require 'dragoon/color'
|
12
|
+
require 'dragoon/core_ext'
|
13
|
+
|
14
|
+
|
15
|
+
module Dragoon
|
16
|
+
class Bot
|
17
|
+
extend Forwardable
|
18
|
+
|
19
|
+
include Commands
|
20
|
+
include Color
|
21
|
+
|
22
|
+
attr_accessor :nickname, :networks, :channels, :keywords
|
23
|
+
|
24
|
+
def_delegators :@event_manager, :on, :dispatch
|
25
|
+
|
26
|
+
DEFAULT_PORT = 6667
|
27
|
+
|
28
|
+
def initialize(&blk)
|
29
|
+
@event_manager = EventManager.new
|
30
|
+
load_config
|
31
|
+
init_callbacks
|
32
|
+
end
|
33
|
+
|
34
|
+
def load_config
|
35
|
+
begin
|
36
|
+
config = YAML.load_file(File.expand_path(File.join(File.dirname(__FILE__), "./../config/config.yml")))
|
37
|
+
rescue => e
|
38
|
+
$stderr.puts e.message
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
@nickname = config["nickname"]
|
42
|
+
@networks = config["networks"]
|
43
|
+
@channels = config["channels"]
|
44
|
+
@keywords = config["keywords"]
|
45
|
+
end
|
46
|
+
|
47
|
+
def init_callbacks
|
48
|
+
on :startup do |msg|
|
49
|
+
puts msg.text
|
50
|
+
if msg.text =~ /.*Found your hostname.*/
|
51
|
+
# login
|
52
|
+
user(self.nickname)
|
53
|
+
nick(self.nickname)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
on :ping do |msg|
|
58
|
+
pong(msg.server) # keep alive
|
59
|
+
end
|
60
|
+
|
61
|
+
on :mode do |msg|
|
62
|
+
puts "*** Logged in as #{@nickname}"
|
63
|
+
join_channels
|
64
|
+
end
|
65
|
+
|
66
|
+
on :join do |msg|
|
67
|
+
puts "*** Listening on channel #{colorize(msg.channel)}" if self.nickname == msg.nickname
|
68
|
+
end
|
69
|
+
|
70
|
+
on :err do |msg|
|
71
|
+
puts "err: #{msg.text}" unless msg.error_code == '470' # channel forwarding
|
72
|
+
end
|
73
|
+
|
74
|
+
on :privmsg do |msg|
|
75
|
+
if system("which growlnotify > /dev/null")
|
76
|
+
if keyword = self.keywords.detect { |keyword| msg.text.include?(keyword) }
|
77
|
+
system("growlnotify " +
|
78
|
+
"-t \"#{keyword}\" " +
|
79
|
+
"-m \"#{escape_double_quotes(msg.privmsg)}\"")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
puts "#{colorize(msg.channel)} <#{msg.nickname}> #{highlight_keywords(msg.privmsg,self.keywords)}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def run
|
87
|
+
@socket = connect
|
88
|
+
while line = @socket.gets
|
89
|
+
@event = Event.parse(line)
|
90
|
+
dispatch(@event)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def connect
|
95
|
+
puts "*** Connecting to #{@networks.first} on port #{DEFAULT_PORT}"
|
96
|
+
TCPSocket.new(@networks.first, DEFAULT_PORT)
|
97
|
+
end
|
98
|
+
|
99
|
+
def escape_double_quotes(text)
|
100
|
+
text.gsub("\"", "\\\"")
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
#http://www.nightmare.com/medusa/async_sockets.html
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Dragoon
|
2
|
+
module Color
|
3
|
+
|
4
|
+
# borrowed from Term::ANSIColors
|
5
|
+
COLORED_REGEXP = /\e\[(?:(?:[349]|10)[0-7]|[0-9])?m/
|
6
|
+
# :yellow is reserved for highlight keywords
|
7
|
+
@@color_list = [:red, :green, :blue, :magenta, :cyan, :white]
|
8
|
+
|
9
|
+
def colorize(text)
|
10
|
+
@c_table ||= {}
|
11
|
+
color = @c_table.fetch(text) rescue @c_table[text] = next_color
|
12
|
+
text.send color
|
13
|
+
end
|
14
|
+
|
15
|
+
def next_color
|
16
|
+
@@color_list.push(@@color_list.shift).first
|
17
|
+
end
|
18
|
+
|
19
|
+
def highlight_keywords(text,keywords)
|
20
|
+
keywords.sort_by(&:length).reverse.inject(text) do |result, keyword|
|
21
|
+
result.gsub(keyword) { |word|
|
22
|
+
to_left_of_word, to_right_of_word = $`, $'
|
23
|
+
|
24
|
+
# check if inside exisitng highlighted word via ANSI ESCAPE
|
25
|
+
if to_left_of_word =~ /#{COLORED_REGEXP}\S+$/ && to_right_of_word =~ /^\S+#{COLORED_REGEXP}/
|
26
|
+
word
|
27
|
+
else
|
28
|
+
highlight(word)
|
29
|
+
end
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def highlight(word)
|
35
|
+
word.black.on_yellow
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Dragoon
|
2
|
+
module Commands
|
3
|
+
|
4
|
+
def nick(text)
|
5
|
+
write "NICK #{text}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def user(text)
|
9
|
+
write "USER #{text} #{text} #{text} #{text}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def pong(text)
|
13
|
+
write "PONG #{text}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def join(text)
|
17
|
+
write "JOIN #{text}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def join_channels
|
21
|
+
@channels.each { |channel| join(channel) }
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def write(text)
|
27
|
+
@socket.write "#{text}\r\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Dragoon
|
2
|
+
class Event
|
3
|
+
|
4
|
+
class Message < OpenStruct
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :name, :message
|
8
|
+
|
9
|
+
def initialize(name, message)
|
10
|
+
@name = name
|
11
|
+
@message = message
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.parse(line)
|
15
|
+
case line
|
16
|
+
when /^:\S+ NOTICE \* :\*{3} .*/
|
17
|
+
self.new(:startup, Message.new(:text => line))
|
18
|
+
when /^PING :(\S+)/
|
19
|
+
self.new(:ping, Message.new(:text => line, :server => $1))
|
20
|
+
when /^:\S+ MODE \S+ :.*/
|
21
|
+
self.new(:mode, Message.new(:text => line))
|
22
|
+
when /^:(\S+)!(\S+)@(\S+) JOIN (\S+)/
|
23
|
+
self.new(:join, Message.new(:text => line,
|
24
|
+
:nickname => $1,
|
25
|
+
:user => $2,
|
26
|
+
:hostname => $3,
|
27
|
+
:channel => $4))
|
28
|
+
when /^:(\S+)!(\S+)@(\S+) PRIVMSG (\S+) :(.+)/
|
29
|
+
self.new(:privmsg, Message.new(:text => line,
|
30
|
+
:nickname => $1,
|
31
|
+
:user => $2,
|
32
|
+
:hostname => $3,
|
33
|
+
:channel => $4,
|
34
|
+
:privmsg => $5))
|
35
|
+
when /^:\S+ (4\d{2}|5\d{2}) .*/
|
36
|
+
self.new(:err, Message.new(:text => line, :error_code => $1))
|
37
|
+
else
|
38
|
+
self.new(:unknown, Message.new(:text => line))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Dragoon
|
2
|
+
class EventManager
|
3
|
+
|
4
|
+
attr_reader :handlers
|
5
|
+
|
6
|
+
def dispatch(event)
|
7
|
+
if @handlers.include?(event.name) && event.name != :unknown
|
8
|
+
@handlers[event.name].call(event.message)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# register callbacks for certain events
|
13
|
+
# valid events are found on constant VALID_EVENTS
|
14
|
+
def on(event_name, &callback)
|
15
|
+
@handlers = {} if @handlers.nil?
|
16
|
+
@handlers[event_name] = callback
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
data/spec/colors_spec.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# borrowed from Term::ANSIColors
|
4
|
+
COLORED_REGEXP = /\e\[(?:(?:[349]|10)[0-7]|[0-9])?m/
|
5
|
+
|
6
|
+
describe Dragoon::Color do
|
7
|
+
before(:each) do
|
8
|
+
class Client
|
9
|
+
include Dragoon::Color
|
10
|
+
end
|
11
|
+
@client = Client.new
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#colorize" do
|
15
|
+
context "single word" do
|
16
|
+
before(:each) do
|
17
|
+
@text = "#scala"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should assign text a permanent color" do
|
21
|
+
colored = @client.colorize(@text)
|
22
|
+
colored.should match COLORED_REGEXP
|
23
|
+
3.times { colored.should == @client.colorize(@text) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "multiple words" do
|
28
|
+
before(:each) do
|
29
|
+
@words = %w[ #ruby #java #scala #c #c++ #music #movies #video #opencv #webgl #webkit #processingjs #coffee]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should assign text a permanent color" do
|
33
|
+
@words.each do |text|
|
34
|
+
colored = @client.colorize(text)
|
35
|
+
colored.should match COLORED_REGEXP
|
36
|
+
3.times { colored.should == @client.colorize(text) }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#highlight" do
|
43
|
+
context "a keyword overlaps with another" do
|
44
|
+
context "on the TAIL" do
|
45
|
+
before(:each) do
|
46
|
+
@text = "Should I use textmate or vim?"
|
47
|
+
@keywords = %w[ textmate ate ]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should highlight only longest keyword" do
|
51
|
+
result = @client.highlight_keywords(@text, @keywords)
|
52
|
+
result.should ==
|
53
|
+
"Should I use #{@client.highlight('textmate')} or vim?"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "on the HEAD" do
|
58
|
+
before(:each) do
|
59
|
+
@text = "I'll be surprised if he believes in it."
|
60
|
+
@keywords = %w[ be believe ]
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should highlight only longest keyword" do
|
64
|
+
result = @client.highlight_keywords(@text, @keywords)
|
65
|
+
result.should ==
|
66
|
+
"I'll #{@client.highlight("be")} surprised if " +
|
67
|
+
"he #{@client.highlight("believe")}s in it."
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "on the MIDDLE" do
|
73
|
+
before(:each) do
|
74
|
+
@keywords = %w[ computer put ]
|
75
|
+
@text = "Please put the computer down"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should highlight only longest keyword" do
|
79
|
+
result = @client.highlight_keywords(@text, @keywords)
|
80
|
+
result.should ==
|
81
|
+
"Please #{@client.highlight("put")} the " +
|
82
|
+
"#{@client.highlight("computer")} down"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "no keyword overlaps" do
|
88
|
+
before(:each) do
|
89
|
+
@keywords = %w[ game linux need ]
|
90
|
+
@text = "I basically need to simulate the game port."
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should highlight keywords" do
|
94
|
+
@client.highlight_keywords(@text, @keywords).should ==
|
95
|
+
"I basically \e[43m\e[30mneed\e[0m\e[0m to simulate the \e[43m\e[30mgame\e[0m\e[0m port."
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dragoon::EventManager do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@event_manager = Dragoon::EventManager.new
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#dispatch" do
|
10
|
+
context "event is unknown" do
|
11
|
+
it "should not do anything" do
|
12
|
+
pending "help from other people"
|
13
|
+
#@event_manager.dispatch(:unknown, ":adams.freenode.net 372 felix21 :- portrayed in his uniquely British irony. He is sorely missed")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "no handler for an event" do
|
18
|
+
it "should not do anything" do
|
19
|
+
pending "help from other people"
|
20
|
+
#@event_manager.dispatch(:mode, ":felix21 MODE felix21 :+i")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "callback exists for an event" do
|
25
|
+
before(:each) do
|
26
|
+
@callback = lambda { puts "hello world" }
|
27
|
+
@event = Dragoon::Event.parse(":felix21 MODE felix21 :+i")
|
28
|
+
@event_manager.on @event.name, &@callback
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should run the corresponding callback" do
|
32
|
+
@callback.should_receive(:call)
|
33
|
+
@event_manager.dispatch(@event)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#on" do
|
39
|
+
it "should register that event" do
|
40
|
+
callback = lambda { puts "this is a callback" }
|
41
|
+
@event_manager.on(:mode, &callback)
|
42
|
+
@event_manager.handlers[:mode].should == callback
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/spec/event_spec.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dragoon::Event do
|
4
|
+
|
5
|
+
describe "#get_event" do
|
6
|
+
it "should process startup event" do
|
7
|
+
msg = ":zelazny.freenode.net NOTICE * :*** Found your hostname"
|
8
|
+
event = Dragoon::Event.parse(msg)
|
9
|
+
event.name.should == :startup
|
10
|
+
event.message.text.should == msg
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should process ping event" do
|
14
|
+
msg = "PING :zelazny.freenode.net"
|
15
|
+
event = Dragoon::Event.parse(msg)
|
16
|
+
event.name.should == :ping
|
17
|
+
event.message.text.should == "PING :zelazny.freenode.net"
|
18
|
+
event.message.server.should == "zelazny.freenode.net"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should process mode event" do
|
22
|
+
msg = ":favor212 MODE favor212 :+i"
|
23
|
+
event = Dragoon::Event.parse(msg)
|
24
|
+
event.name.should == :mode
|
25
|
+
event.message.text.should == ":favor212 MODE favor212 :+i"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should process join event" do
|
29
|
+
msg = ":zigcat_Fox!~zigcat_fox@hostname JOIN #time_to_show_off"
|
30
|
+
event = Dragoon::Event.parse(msg)
|
31
|
+
event.name.should == :join
|
32
|
+
event.message.text.should == ":zigcat_Fox!~zigcat_fox@hostname JOIN #time_to_show_off"
|
33
|
+
event.message.nickname.should == "zigcat_Fox"
|
34
|
+
event.message.user.should == "~zigcat_fox"
|
35
|
+
event.message.hostname.should == "hostname"
|
36
|
+
event.message.channel.should == "#time_to_show_off"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should process privmsg event" do
|
40
|
+
msg = ":nick!~user@hostname PRIVMSG #ruby :array << 0 if array.size.odd?"
|
41
|
+
event = Dragoon::Event.parse(msg)
|
42
|
+
event.name.should == :privmsg
|
43
|
+
event.message.text.should == ":nick!~user@hostname PRIVMSG #ruby :array << 0 if array.size.odd?"
|
44
|
+
event.message.nickname.should == "nick"
|
45
|
+
event.message.user.should == "~user"
|
46
|
+
event.message.hostname.should == "hostname"
|
47
|
+
event.message.channel.should == "#ruby"
|
48
|
+
event.message.privmsg.should == "array << 0 if array.size.odd?"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should process error reply event" do
|
52
|
+
msg1 = ":asimov.freenode.net 477 zigcat_Fox ##java :Cannot join channel (+r) - you need to be identified with services"
|
53
|
+
msg2 = ":kornbluth.freenode.net 461 fenix45 USER :Not enough parameters"
|
54
|
+
event = Dragoon::Event.parse(msg1)
|
55
|
+
event.name.should == :err
|
56
|
+
event.message.error_code.should == '477'
|
57
|
+
event = Dragoon::Event.parse(msg2)
|
58
|
+
event.name.should == :err
|
59
|
+
event.message.error_code.should == '461'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dragoon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Reginald Tan
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-01-22 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: term/ansicolor
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
description: "An IRC bot that alerts you whenever certain keywords appear in your favorite channels "
|
49
|
+
email:
|
50
|
+
- redge.tan@gmail.com
|
51
|
+
executables:
|
52
|
+
- dragoon
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- .gitignore
|
59
|
+
- Gemfile
|
60
|
+
- Gemfile.lock
|
61
|
+
- README.md
|
62
|
+
- Rakefile
|
63
|
+
- TODO
|
64
|
+
- bin/dragoon
|
65
|
+
- config/config.yml
|
66
|
+
- config/config.yml.example
|
67
|
+
- dragoon.gemspec
|
68
|
+
- lib/dragoon.rb
|
69
|
+
- lib/dragoon/color.rb
|
70
|
+
- lib/dragoon/commands.rb
|
71
|
+
- lib/dragoon/core_ext.rb
|
72
|
+
- lib/dragoon/event.rb
|
73
|
+
- lib/dragoon/event_manager.rb
|
74
|
+
- lib/dragoon/version.rb
|
75
|
+
- spec/colors_spec.rb
|
76
|
+
- spec/event_manager_spec.rb
|
77
|
+
- spec/event_spec.rb
|
78
|
+
- spec/spec_helper.rb
|
79
|
+
homepage: https://github.com/redgetan/dragoon
|
80
|
+
licenses: []
|
81
|
+
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
hash: 3
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
version: "0"
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
hash: 3
|
102
|
+
segments:
|
103
|
+
- 0
|
104
|
+
version: "0"
|
105
|
+
requirements: []
|
106
|
+
|
107
|
+
rubyforge_project: dragoon
|
108
|
+
rubygems_version: 1.8.10
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: IRC bot for keyword notification
|
112
|
+
test_files:
|
113
|
+
- spec/colors_spec.rb
|
114
|
+
- spec/event_manager_spec.rb
|
115
|
+
- spec/event_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
has_rdoc:
|