cinch 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +24 -1
- data/examples/hello.rb +13 -0
- data/examples/join_part.rb +26 -0
- data/examples/msg.rb +14 -0
- data/examples/named-param-types.rb +19 -0
- data/examples/seen.rb +41 -0
- data/lib/cinch.rb +2 -1
- data/lib/cinch/base.rb +83 -47
- data/lib/cinch/irc/parser.rb +1 -1
- data/lib/cinch/irc/socket.rb +5 -2
- data/lib/cinch/rules.rb +161 -0
- data/spec/base_spec.rb +107 -0
- data/spec/rules_spec.rb +109 -0
- metadata +11 -3
data/README.rdoc
CHANGED
@@ -10,7 +10,11 @@ plugin, defining a rule, and watching your profits flourish.
|
|
10
10
|
Cinch will do all of the hard work for you, so you can spend time creating cool plugins
|
11
11
|
and extensions to wow your internet peers.
|
12
12
|
|
13
|
+
Cinch is not a fully fledged IRC framework, its base is extremely small. If you're looking
|
14
|
+
for a more controlled library check out {silverplatter-irc}[http://github.com/apeiros/silverplatter-irc].
|
15
|
+
|
13
16
|
== Installation
|
17
|
+
The latest version of Cinch is 0.2
|
14
18
|
|
15
19
|
=== RubyGems
|
16
20
|
You can install the latest version of Cinch using RubyGems
|
@@ -95,9 +99,28 @@ the rules given, for example if we want to reply only if the nick sending the me
|
|
95
99
|
could pass the 'nick' option to the hash.
|
96
100
|
|
97
101
|
bot.plugin("join :channel", :nick => 'injekt') do |m|
|
98
|
-
|
102
|
+
bot.join #{m.args[:channel]}
|
103
|
+
end
|
104
|
+
|
105
|
+
== Named Parameter Types
|
106
|
+
Since version 0.2, Cinch supports named parameter types. Although at the moment you're constrained
|
107
|
+
to the <i>digit</i>, <i>string</i> and <i>word</i> types. It means stuff like the this works:
|
108
|
+
|
109
|
+
bot.plugin("say :n-digit :text") do |m|
|
110
|
+
m.args[:n].to_i.times {
|
111
|
+
m.reply m.args[:text]
|
112
|
+
end
|
99
113
|
end
|
100
114
|
|
115
|
+
This would provide the following output on IRC
|
116
|
+
|
117
|
+
injekt> !say foo bar
|
118
|
+
injekt> !say 2 foo bar
|
119
|
+
Cinch> foo bar
|
120
|
+
Cinch> foo bar
|
121
|
+
|
122
|
+
* See Cinch::Base#compile for more information
|
123
|
+
|
101
124
|
== Authors
|
102
125
|
Just me at the moment, sad poor lonely me...
|
103
126
|
* {Lee Jarvis}[http://blog.injekt.net]
|
data/examples/hello.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'cinch'
|
2
|
+
|
3
|
+
bot = Cinch.setup do
|
4
|
+
server "irc.freenode.org"
|
5
|
+
nick "CinchBot"
|
6
|
+
channels %w( #cinch )
|
7
|
+
end
|
8
|
+
|
9
|
+
# Who should be able to access these plugins
|
10
|
+
admin = 'injekt'
|
11
|
+
|
12
|
+
bot.plugin "join :channel", :nick => admin do |m|
|
13
|
+
bot.join m.args[:channel]
|
14
|
+
end
|
15
|
+
|
16
|
+
bot.plugin "part :channel", :nick => admin do |m|
|
17
|
+
bot.part m.args[:channel]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Part current channel if none is given
|
21
|
+
bot.plugin "part", :nick => admin do |m|
|
22
|
+
bot.part m.channel
|
23
|
+
end
|
24
|
+
|
25
|
+
bot.run
|
26
|
+
|
data/examples/msg.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'cinch'
|
2
|
+
|
3
|
+
bot = Cinch.setup do
|
4
|
+
server "irc.freenode.org"
|
5
|
+
channels %w( #cinch )
|
6
|
+
end
|
7
|
+
|
8
|
+
bot.plugin("say :n-digit :text") do |m|
|
9
|
+
m.args[:n].to_i.times {
|
10
|
+
m.reply m.args[:text]
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
bot.plugin("say :text-word :rest") do |m|
|
15
|
+
stuff = [m.args[:text], m.args[:rest]].join(' ')
|
16
|
+
m.reply stuff
|
17
|
+
end
|
18
|
+
|
19
|
+
bot.run
|
data/examples/seen.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'cinch'
|
2
|
+
|
3
|
+
users = {}
|
4
|
+
|
5
|
+
class Seen < Struct.new(:who, :where, :what, :time)
|
6
|
+
def to_s
|
7
|
+
"[#{time.asctime}] #{who} was seen in #{where} saying #{what}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
bot = Cinch.setup(
|
12
|
+
:server => 'irc.freenode.org',
|
13
|
+
:channels => ['#cinch'],
|
14
|
+
:prefix => '!',
|
15
|
+
:verbose => true,
|
16
|
+
)
|
17
|
+
|
18
|
+
# Only log a PRIVMSG
|
19
|
+
bot.on :privmsg do |m|
|
20
|
+
# Dont record a private message
|
21
|
+
unless m.private?
|
22
|
+
users[m.nick] = Seen.new(m.nick, m.channel, m.text, Time.new)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
bot.plugin("seen :nick foo") do |m|
|
27
|
+
nick = m.args[:nick]
|
28
|
+
|
29
|
+
if nick == bot.nick
|
30
|
+
m.reply "That's me!"
|
31
|
+
elsif nick == m.nick
|
32
|
+
m.reply "That's you!"
|
33
|
+
elsif users.key?(nick)
|
34
|
+
m.reply users[nick].to_s
|
35
|
+
else
|
36
|
+
m.reply "I haven't seen #{nick}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
bot.run
|
41
|
+
|
data/lib/cinch.rb
CHANGED
@@ -5,10 +5,11 @@ require 'ostruct'
|
|
5
5
|
require 'optparse'
|
6
6
|
|
7
7
|
require 'cinch/irc'
|
8
|
+
require 'cinch/rules'
|
8
9
|
require 'cinch/base'
|
9
10
|
|
10
11
|
module Cinch
|
11
|
-
VERSION = '0.
|
12
|
+
VERSION = '0.2'
|
12
13
|
|
13
14
|
# Setup bot options and return a new Cinch::Base instance
|
14
15
|
def self.setup(ops={}, &blk)
|
data/lib/cinch/base.rb
CHANGED
@@ -60,7 +60,7 @@ module Cinch
|
|
60
60
|
options = DEFAULTS.merge(ops).merge(Options.new(&blk))
|
61
61
|
@options = OpenStruct.new(options.merge(cli_ops))
|
62
62
|
|
63
|
-
@rules =
|
63
|
+
@rules = Rules.new
|
64
64
|
@listeners = {}
|
65
65
|
|
66
66
|
@irc = IRC::Socket.new(options[:server], options[:port])
|
@@ -85,12 +85,15 @@ module Cinch
|
|
85
85
|
op.on("-n nick") {|v| options[:nick] = v }
|
86
86
|
op.on("-c command_prefix") {|v| options[:prefix] = v }
|
87
87
|
op.on("-v", "--verbose", "Enable verbose mode") {|v| options[:verbose] = true }
|
88
|
-
op.on("-
|
88
|
+
op.on("-C", "--channels x,y,z", Array, "Autojoin channels") {|v|
|
89
89
|
options[:channels] = v.map {|c| %w(# + &).include?(c[0].chr) ? c : c.insert(0, '#') }
|
90
90
|
}
|
91
91
|
end.parse(ARGV)
|
92
92
|
rescue OptionParser::MissingArgument => err
|
93
|
-
|
93
|
+
warn "Missing values for options: #{err.args.join(', ')}\nFalling back to default"
|
94
|
+
rescue OptionParser::InvalidOption => err
|
95
|
+
warn err.message
|
96
|
+
exit
|
94
97
|
end
|
95
98
|
end
|
96
99
|
options
|
@@ -104,7 +107,13 @@ module Cinch
|
|
104
107
|
# end
|
105
108
|
def plugin(rule, options={}, &blk)
|
106
109
|
rule, keys = compile(rule)
|
107
|
-
|
110
|
+
|
111
|
+
if @rules.has_rule?(rule)
|
112
|
+
@rules.add_callback(rule, blk)
|
113
|
+
@rules.merge_options(rule, options)
|
114
|
+
else
|
115
|
+
@rules.add_rule(rule, keys, options, blk)
|
116
|
+
end
|
108
117
|
end
|
109
118
|
|
110
119
|
# Add new listeners
|
@@ -123,35 +132,80 @@ module Cinch
|
|
123
132
|
end
|
124
133
|
end
|
125
134
|
|
126
|
-
#
|
135
|
+
# This method builds a regular expression from your rule
|
136
|
+
# and defines all named parameters, as well as dealing with
|
137
|
+
# types.
|
138
|
+
#
|
139
|
+
# So far 3 types are supported:
|
140
|
+
#
|
141
|
+
# * word - matches [a-zA-Z]+
|
142
|
+
# * string - matches \w+
|
143
|
+
# * digit - matches \d+
|
144
|
+
#
|
145
|
+
# == Examples
|
146
|
+
# For capturing individual words
|
147
|
+
# bot.plugin("say :text-word")
|
148
|
+
# * Does match !say foo
|
149
|
+
# * Does not match !say foo bar baz
|
150
|
+
#
|
151
|
+
# For capturing digits
|
152
|
+
# bot.plugin("say :text-digit")
|
153
|
+
# * Does match !say 3
|
154
|
+
# * Does not match !say 3 4
|
155
|
+
# * Does not match !say foo
|
156
|
+
#
|
157
|
+
# For both
|
158
|
+
# bot.plugin("say :n-digit :text-word")
|
159
|
+
# * Does match !say 3 foo
|
160
|
+
# * Does not match !say 3 foo bar
|
161
|
+
#
|
162
|
+
# For capturing until the end of the line
|
163
|
+
# bot.plugin("say :text")
|
164
|
+
# * Does match !say foo
|
165
|
+
# * Does match !say foo bar
|
166
|
+
#
|
167
|
+
# Or mix them all
|
168
|
+
# bot.plugin("say :n-digit :who-word :text")
|
169
|
+
#
|
170
|
+
# Using "!say 3 injekt some text here" would provide
|
171
|
+
# the following attributes
|
172
|
+
# m.args[:n] => 3
|
173
|
+
# m.args[:who] => injekt
|
174
|
+
# m.args[:text] => some text here
|
127
175
|
def compile(rule)
|
128
|
-
return [rule []] if rule.is_a?(Regexp)
|
176
|
+
return [rule, []] if rule.is_a?(Regexp)
|
129
177
|
keys = []
|
130
178
|
special_chars = %w{. + ( )}
|
131
179
|
|
132
|
-
pattern = rule.to_s.gsub(/((
|
180
|
+
pattern = rule.to_s.gsub(/((:[\w\-]+)|[\*#{special_chars.join}])/) do |match|
|
133
181
|
case match
|
134
182
|
when *special_chars
|
135
183
|
Regexp.escape(match)
|
136
184
|
else
|
137
|
-
|
138
|
-
|
185
|
+
k = $2
|
186
|
+
if k =~ /\-(\w+)$/
|
187
|
+
key, type = k.split('-')
|
188
|
+
keys << key[1..-1]
|
189
|
+
|
190
|
+
case type
|
191
|
+
when 'digit'; "(\\d+?)"
|
192
|
+
when 'word'; "([a-zA-Z]+?)"
|
193
|
+
when 'string'; "(\\w+?)"
|
194
|
+
else
|
195
|
+
"([^\x00\r\n]+?)"
|
196
|
+
end
|
197
|
+
else
|
198
|
+
keys << k[1..-1]
|
199
|
+
"([^\x00\r\n]+?)"
|
200
|
+
end
|
139
201
|
end
|
140
202
|
end
|
141
203
|
["^#{pattern}$", keys]
|
142
204
|
end
|
143
205
|
|
144
|
-
# Add a new rule, or add to an existing one if it
|
145
|
-
# already exists
|
146
|
-
def add_rule(rule, keys, options={}, &blk)
|
147
|
-
unless @rules.key?(rule)
|
148
|
-
@rules[rule] = [rule, keys, options, blk]
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
206
|
# Run run run
|
153
|
-
def run
|
154
|
-
@irc.connect
|
207
|
+
def run
|
208
|
+
@irc.connect options.server, options.port
|
155
209
|
@irc.nick options.nick
|
156
210
|
@irc.user options.username, options.usermode, '*', options.realname
|
157
211
|
|
@@ -166,6 +220,7 @@ module Cinch
|
|
166
220
|
|
167
221
|
# Process the next line read from the server
|
168
222
|
def process(line)
|
223
|
+
return unless line
|
169
224
|
message = @parser.parse(line)
|
170
225
|
message.irc = @irc
|
171
226
|
puts message if options.verbose
|
@@ -175,40 +230,21 @@ module Cinch
|
|
175
230
|
end
|
176
231
|
|
177
232
|
if [:privmsg].include?(message.symbol)
|
178
|
-
rules.
|
179
|
-
rule
|
180
|
-
|
181
|
-
|
182
|
-
unless ops.has_key?(:prefix) || options.prefix == false
|
183
|
-
rule.insert(1, options.prefix) unless rule[1].chr == options.prefix
|
233
|
+
rules.each do |rule|
|
234
|
+
unless rule.options.key?(:prefix) || options.prefix == false
|
235
|
+
rule.to_s.insert(1, options.prefix) unless rule.to_s[1].chr == options.prefix
|
184
236
|
end
|
185
237
|
|
186
|
-
if message.text && mdata = message.text.match(Regexp.new(rule))
|
187
|
-
unless keys.empty? || mdata.captures.empty?
|
188
|
-
args = Hash[keys.map {|k| k.to_sym}.zip(mdata.captures)]
|
238
|
+
if message.text && mdata = message.text.match(Regexp.new(rule.to_s))
|
239
|
+
unless rule.keys.empty? || mdata.captures.empty?
|
240
|
+
args = Hash[rule.keys.map {|k| k.to_sym}.zip(mdata.captures)]
|
189
241
|
message.args = args
|
190
|
-
end
|
191
|
-
|
192
|
-
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
# Execute a rule
|
198
|
-
def execute_rule(message, ops, blk)
|
199
|
-
ops.keys.each do |k|
|
200
|
-
case k
|
201
|
-
when :nick; return unless ops[:nick] == message.nick
|
202
|
-
when :user; return unless ops[:user] == message.user
|
203
|
-
when :host; return unless ops[:host] == message.host
|
204
|
-
when :channel
|
205
|
-
if message.channel
|
206
|
-
return unless ops[:channel] == message.channel
|
242
|
+
end
|
243
|
+
# execute rule
|
244
|
+
rule.execute(message)
|
207
245
|
end
|
208
246
|
end
|
209
247
|
end
|
210
|
-
|
211
|
-
blk.call(message)
|
212
248
|
end
|
213
249
|
|
214
250
|
# Catch methods
|
data/lib/cinch/irc/parser.rb
CHANGED
@@ -80,7 +80,7 @@ module Cinch
|
|
80
80
|
# Parse the incoming raw IRC string and return
|
81
81
|
# a nicely formatted IRC::Message
|
82
82
|
def parse_servermessage(raw)
|
83
|
-
raise ArgumentError, raw unless matches = raw.match(pattern(:message))
|
83
|
+
raise ArgumentError, raw unless raw && matches = raw.match(pattern(:message))
|
84
84
|
|
85
85
|
prefix, command, parameters = matches.captures
|
86
86
|
|
data/lib/cinch/irc/socket.rb
CHANGED
@@ -87,8 +87,11 @@ module Cinch
|
|
87
87
|
|
88
88
|
# Connect to an IRC server, returns true on a successful connection, or
|
89
89
|
# raises otherwise
|
90
|
-
def connect
|
91
|
-
@
|
90
|
+
def connect(server=nil, port=nil)
|
91
|
+
@server = server if server
|
92
|
+
@port = port if port
|
93
|
+
|
94
|
+
@socket = TCPSocket.new(@server, @port)
|
92
95
|
rescue Interrupt
|
93
96
|
raise
|
94
97
|
rescue Exception
|
data/lib/cinch/rules.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
module Cinch
|
2
|
+
|
3
|
+
# == Author
|
4
|
+
# * Lee Jarvis - ljjarvis@gmail.com
|
5
|
+
#
|
6
|
+
# == Description
|
7
|
+
# Every rule defined through the Cinch::Base#plugin method becomes an instance
|
8
|
+
# of this class. Each rule consists of keys used for named parameters, a hash
|
9
|
+
# of options, and an Array of callbacks.
|
10
|
+
#
|
11
|
+
# When a rule matches an IRC message, all options with be checked, then all
|
12
|
+
# callbacks will be invoked.
|
13
|
+
class Rule < Struct.new(:rule, :keys, :options, :callbacks)
|
14
|
+
def initialize(rule, keys, options, callback)
|
15
|
+
callbacks = [callback]
|
16
|
+
super(rule, keys, options, callbacks)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Execute all callbacks, passing an Cinch::IRC::Message to them
|
20
|
+
def execute(message)
|
21
|
+
options.keys.each do |key|
|
22
|
+
case key
|
23
|
+
when :nick
|
24
|
+
return unless options[:nick] == message.nick
|
25
|
+
when :host
|
26
|
+
return unless options[:host] == message.host
|
27
|
+
when :user
|
28
|
+
return unless options[:user] == message.user
|
29
|
+
when :channel
|
30
|
+
if message.channel
|
31
|
+
return unless options[:channel] == message.channel
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
callbacks.each do |blk|
|
37
|
+
blk.call(message)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# The rule as a String
|
42
|
+
def to_s
|
43
|
+
rule
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# == Author
|
48
|
+
# * Lee Jarvis - ljjarvis@gmail.com
|
49
|
+
#
|
50
|
+
# == Description
|
51
|
+
# This class provides an interface to manage rules. A rule should only ever be
|
52
|
+
# added using the Rules#add_rule method and retrieved using the Rules#get_rule
|
53
|
+
# method, or an alias of these.
|
54
|
+
#
|
55
|
+
# This class provides an easy way to add options or callbacks to an existing
|
56
|
+
# rule.
|
57
|
+
#
|
58
|
+
# Essentially the add_callback, add_option, and merge_options methods are just sugar
|
59
|
+
# so you don't have to edit Rule attributes directly
|
60
|
+
#
|
61
|
+
# == Example
|
62
|
+
# rules = Cinch::Rules.new
|
63
|
+
#
|
64
|
+
# rules.add('foo', [], {}, Proc.new{})
|
65
|
+
#
|
66
|
+
# rules.add_callback('foo', Proc.new{})
|
67
|
+
# rules['foo'].callbacks #=> [#<Proc:0x9f1e110@(main):100>, #<Proc:0x9f1e0f4@(main):150>]
|
68
|
+
#
|
69
|
+
# # Or assign directly
|
70
|
+
# rules.get('foo').callbacks << Proc.new {}
|
71
|
+
#
|
72
|
+
# rules['foo'].options #=> {}
|
73
|
+
# rules.add_option('foo', :nick, 'injekt')
|
74
|
+
# rules['foo'].options #=> {:nick => 'injekt'}
|
75
|
+
#
|
76
|
+
# # Or retrieve the rule first and assign directly
|
77
|
+
# rules.get_rule('foo')
|
78
|
+
# rules.options = {:foo => 'bar'}
|
79
|
+
# rules.options[:bar] = 'baz'
|
80
|
+
class Rules
|
81
|
+
def initialize
|
82
|
+
@rules = {}
|
83
|
+
end
|
84
|
+
|
85
|
+
# Add a new rule, overwrites an already existing rule
|
86
|
+
def add_rule(rule, keys, options, callback)
|
87
|
+
@rules[rule] = Rule.new(rule, keys, options, callback)
|
88
|
+
end
|
89
|
+
alias :add :add_rule
|
90
|
+
|
91
|
+
# Return a Cinch::Rule by its rule, or nil it one does not exist
|
92
|
+
def get_rule(rule)
|
93
|
+
@rules[rule]
|
94
|
+
end
|
95
|
+
alias :get :get_rule
|
96
|
+
alias :[] :get_rule
|
97
|
+
|
98
|
+
# Remove a rule
|
99
|
+
def remove_rule(rule)
|
100
|
+
@rules.delete(rule)
|
101
|
+
end
|
102
|
+
alias :remove :remove_rule
|
103
|
+
|
104
|
+
# Check if a rule exists
|
105
|
+
def include?(rule)
|
106
|
+
@rules.key?(rule)
|
107
|
+
end
|
108
|
+
alias :has_rule? :include?
|
109
|
+
|
110
|
+
# Add a callback for an already existing rule
|
111
|
+
def add_callback(rule, blk)
|
112
|
+
return unless include?(rule)
|
113
|
+
@rules[rule].callbacks << blk
|
114
|
+
end
|
115
|
+
|
116
|
+
# Add an option for an already existing rule
|
117
|
+
def add_option(rule, key, value)
|
118
|
+
return unless include?(rule)
|
119
|
+
@rules[rule].options[key] = value
|
120
|
+
end
|
121
|
+
|
122
|
+
# Merge rule options
|
123
|
+
def merge_options(rule, ops={})
|
124
|
+
return unless include?(rule)
|
125
|
+
@rules[rule].options.merge!(ops)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Iterate over the rules
|
129
|
+
def each
|
130
|
+
@rules.each {|rule, obj| yield obj }
|
131
|
+
end
|
132
|
+
|
133
|
+
# Remove all rules
|
134
|
+
def clear
|
135
|
+
@rules.clear
|
136
|
+
end
|
137
|
+
|
138
|
+
# Check if any rules exist
|
139
|
+
def empty?
|
140
|
+
@rules.empty?
|
141
|
+
end
|
142
|
+
|
143
|
+
# Return how many rules exist
|
144
|
+
def count
|
145
|
+
@rules.size
|
146
|
+
end
|
147
|
+
alias :size :count
|
148
|
+
|
149
|
+
# Return the hash of rules
|
150
|
+
def all
|
151
|
+
@rules
|
152
|
+
end
|
153
|
+
|
154
|
+
# Return an Array of rules
|
155
|
+
def to_a
|
156
|
+
@rules.keys
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
describe "Cinch::Base" do
|
4
|
+
before do
|
5
|
+
@base = Cinch::Base.new
|
6
|
+
|
7
|
+
@full = Cinch::Base.new(
|
8
|
+
:server => 'irc.freenode.org',
|
9
|
+
:nick => 'CinchBot',
|
10
|
+
:channels => ['#cinch']
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "::new" do
|
15
|
+
it "should add a default ping listener" do
|
16
|
+
@base.listeners.should include :ping
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should add a 376 listener, only if channels are set" do
|
20
|
+
@base.listeners.should_not include :'376'
|
21
|
+
@full.listeners.should include :'376'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#plugin" do
|
26
|
+
it "should compile and add a rule" do
|
27
|
+
@base.plugin('foo')
|
28
|
+
@base.rules.include?("^foo$").should == true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should add options to an existing rule" do
|
32
|
+
@base.plugin('foo') { }
|
33
|
+
@base.plugin('foo', :bar => 'baz') { }
|
34
|
+
rule = @base.rules.get('^foo$')
|
35
|
+
rule.options.should include :bar
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should add its block to an existing rule" do
|
39
|
+
@base.plugin('foo') { }
|
40
|
+
@base.plugin('foo') { }
|
41
|
+
rule = @base.rules.get_rule('^foo$')
|
42
|
+
rule.callbacks.size.should == 2
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#on" do
|
47
|
+
it "should save a listener" do
|
48
|
+
@base.on(:foo) {}
|
49
|
+
@base.listeners.should include :foo
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should store listener blocks in an Array" do
|
53
|
+
@base.listeners[:ping].should be_kind_of Array
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#compile" do
|
58
|
+
it "should return an Array of 2 values" do
|
59
|
+
ret = @base.compile("foo")
|
60
|
+
ret.should be_kind_of(Array)
|
61
|
+
ret.size.should == 2
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return an empty set of keys if no named parameters are labeled" do
|
65
|
+
rule, keys = @base.compile("foo")
|
66
|
+
keys.should be_empty
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should return a key for each named parameter labeled" do
|
70
|
+
rule, keys = @base.compile("foo :bar :baz")
|
71
|
+
keys.size.should == 2
|
72
|
+
keys.should include "bar"
|
73
|
+
keys.should include "baz"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return a rule of type String, unless Regexp is given" do
|
77
|
+
rule, keys = @base.compile(:foo)
|
78
|
+
rule.should be_kind_of(String)
|
79
|
+
|
80
|
+
rule, keys = @base.compile(/foo/)
|
81
|
+
rule.should be_kind_of(Regexp)
|
82
|
+
keys.should be_empty
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should convert a digit type" do
|
86
|
+
rule, keys = @base.compile(":foo-digit")
|
87
|
+
rule.should == "^(\\d+?)$"
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should convert a string type" do
|
91
|
+
rule, keys = @base.compile(":foo-string")
|
92
|
+
rule.should == "^(\\w+?)$"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should convert a word type" do
|
96
|
+
rule, keys = @base.compile(":foo-word")
|
97
|
+
rule.should == "^([a-zA-Z]+?)$"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should automatically add start and end anchors" do
|
101
|
+
rule, keys = @base.compile("foo bar baz")
|
102
|
+
rule[0].chr.should == "^"
|
103
|
+
rule[-1].chr.should == "$"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
data/spec/rules_spec.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
describe "Cinch::Rules" do
|
4
|
+
before do
|
5
|
+
@rules = Cinch::Rules.new
|
6
|
+
@rules.add_rule('foo', [], {}, Proc.new{})
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "::new" do
|
10
|
+
it "should define an empty set of rules" do
|
11
|
+
Cinch::Rules.new.empty?.should == true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#add_rule" do
|
16
|
+
it "should add a new rule" do
|
17
|
+
@rules.add_rule('bar', [], {}, Proc.new{})
|
18
|
+
@rules.all.should include 'foo'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should replace an existing rule" do
|
22
|
+
@rules.add_rule('foo', [], {}, Proc.new{})
|
23
|
+
@rules.count.should == 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#get_rule" do
|
28
|
+
it "should return a Cinch::Rule" do
|
29
|
+
@rules.get_rule('foo').should be_kind_of Cinch::Rule
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#remove_rule" do
|
34
|
+
it "should remove a rule" do
|
35
|
+
@rules.remove_rule('foo')
|
36
|
+
@rules.include?('foo').should == false
|
37
|
+
@rules.count.should == 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#add_callback" do
|
42
|
+
it "should add a callback for a rule" do
|
43
|
+
@rules.add_callback('foo', Proc.new{})
|
44
|
+
rule = @rules.get_rule('foo')
|
45
|
+
rule.callbacks.size.should == 2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#add_option" do
|
50
|
+
it "should add an option for a rule" do
|
51
|
+
@rules.add_option('foo', :nick, 'injekt')
|
52
|
+
rule = @rules.get('foo')
|
53
|
+
rule.options.should include :nick
|
54
|
+
rule.options[:nick].should == 'injekt'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#merge_options" do
|
59
|
+
it "should merge rule options" do
|
60
|
+
@rules.merge_options('foo', {:bar => 'baz'})
|
61
|
+
rule = @rules['foo']
|
62
|
+
rule.options.should == {:bar => 'baz'}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#include?" do
|
67
|
+
it "should check if a rule exists" do
|
68
|
+
@rules.include?('foo').should == true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#clear" do
|
73
|
+
it "should clear all rules" do
|
74
|
+
@rules.clear
|
75
|
+
@rules.empty?.should == true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#empty?" do
|
80
|
+
it "should check if any rules exist" do
|
81
|
+
@rules.empty?.should == false
|
82
|
+
@rules.clear
|
83
|
+
@rules.empty?.should == true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#count" do
|
88
|
+
it "should show how many rules exist" do
|
89
|
+
@rules.count.should == 1
|
90
|
+
@rules.add_rule('bar', [], {}, Proc.new{})
|
91
|
+
@rules.count.should == 2
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#all" do
|
96
|
+
it "should return a Hash of all rules" do
|
97
|
+
@rules.all.should be_kind_of Hash
|
98
|
+
@rules.all.should include 'foo'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#to_a" do
|
103
|
+
it "should return an Array of rules" do
|
104
|
+
@rules.to_a.should be_kind_of Array
|
105
|
+
@rules.to_a.include?('foo').should == true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
metadata
CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
version: "0.
|
7
|
+
- 2
|
8
|
+
version: "0.2"
|
9
9
|
platform: ruby
|
10
10
|
authors:
|
11
11
|
- Lee 'injekt' Jarvis
|
@@ -13,7 +13,7 @@ autorequire:
|
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
15
|
|
16
|
-
date: 2010-04-
|
16
|
+
date: 2010-04-26 00:00:00 +01:00
|
17
17
|
default_executable:
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
@@ -41,18 +41,26 @@ extra_rdoc_files:
|
|
41
41
|
files:
|
42
42
|
- README.rdoc
|
43
43
|
- Rakefile
|
44
|
+
- spec/base_spec.rb
|
44
45
|
- spec/irc/socket_spec.rb
|
45
46
|
- spec/irc/helper.rb
|
46
47
|
- spec/irc/message_spec.rb
|
47
48
|
- spec/irc/parser_spec.rb
|
48
49
|
- spec/helper.rb
|
50
|
+
- spec/rules_spec.rb
|
49
51
|
- spec/options_spec.rb
|
50
52
|
- lib/cinch.rb
|
51
53
|
- lib/cinch/base.rb
|
52
54
|
- lib/cinch/irc/message.rb
|
53
55
|
- lib/cinch/irc/socket.rb
|
54
56
|
- lib/cinch/irc/parser.rb
|
57
|
+
- lib/cinch/rules.rb
|
55
58
|
- lib/cinch/irc.rb
|
59
|
+
- examples/join_part.rb
|
60
|
+
- examples/msg.rb
|
61
|
+
- examples/seen.rb
|
62
|
+
- examples/hello.rb
|
63
|
+
- examples/named-param-types.rb
|
56
64
|
has_rdoc: true
|
57
65
|
homepage: http://rdoc.injekt.net/cinch
|
58
66
|
licenses: []
|