cinch 0.2.9 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,8 +1,7 @@
1
- = Cinch: The IRC Microframework
1
+ = Cinch: The IRC Bot Building Framework
2
2
 
3
3
  == Description
4
-
5
- Cinch is an IRC Microframework for quickly creating IRC bots
4
+ Cinch is an IRC Bot Building Framework for quickly creating IRC bots
6
5
  in Ruby with minimal effort.
7
6
  It provides a minimal interface based on plugins and rules. It's as simple as creating a
8
7
  plugin, defining a rule, and watching your profits flourish.
@@ -14,7 +13,6 @@ If you'd like to test your own Cinch experiments you can do so in the cinch IRC
14
13
  on {irc.freenode.org}[irc://irc.freenode.org/cinch]. Support is also welcome here.
15
14
 
16
15
  == Installation
17
- The latest version of Cinch is 0.2
18
16
 
19
17
  === RubyGems
20
18
  You can install the latest version of Cinch using RubyGems
@@ -25,7 +23,6 @@ Alternatively you can check out the latest code directly from Github
25
23
  git clone http://github.com/injekt/cinch.git
26
24
 
27
25
  == Example
28
-
29
26
  Your typical <em>Hello, World</em> application would go something like this:
30
27
 
31
28
  require 'cinch'
@@ -62,17 +59,18 @@ other Ruby script.
62
59
 
63
60
  ruby hello.rb
64
61
 
65
- Cinch also parses the command line for options, to save you having to configure options within your script.
62
+ Cinch also parses the command line for options, to save you having to configure
63
+ options within your script.
66
64
 
67
65
  ruby hello.rb -s irc.freenode.org -n Coolbot
68
- ruby hello.rb --channels foo,bar
66
+ ruby hello.rb -C foo,bar
69
67
 
70
- Doing a <b>ruby hello.rb -h</b> provides all possible command line options. When using the <em>--channels</em>
71
- option, the channel prefix is option, and if none is given the channel will be prefixed with a hash (#)
68
+ Doing a <b>ruby hello.rb -h</b> provides all possible command line options. When using the <em>-C</em>
69
+ or <em>--channels</em> option, the channel prefix is option, and if none is given the channel
70
+ will be prefixed with a hash (#)
72
71
  character
73
72
 
74
73
  == Plugins
75
-
76
74
  Plugins are invoked using the command prefix character (which by default is set to <b>!</b>). You can
77
75
  also tell Cinch to ignore any command prefix and instead use the bots username. This would provide
78
76
  a result similar to this:
@@ -172,8 +170,7 @@ before sending me a pull request. Alternatively paste the example and inform me
172
170
  channel or by email
173
171
 
174
172
  == Authors
175
- Just me at the moment, sad poor lonely me...
176
- * {Lee Jarvis}[http://blog.injekt.net]
173
+ * {Lee Jarvis}[http://injekt.net]
177
174
 
178
175
  == Notes
179
176
  * RDoc API documentation is available {here}[http://rdoc.injekt.net/cinch]
@@ -189,5 +186,4 @@ request once one patch has been submitted. Any contribution is welcome and appre
189
186
  == TODO
190
187
  * More specs
191
188
  * More documentation
192
- * More examples
193
189
 
data/Rakefile CHANGED
@@ -1,14 +1,19 @@
1
1
  require "rake"
2
2
  require "rake/clean"
3
3
  require "rake/gempackagetask"
4
- require "rake/rdoctask"
5
4
  require "spec/rake/spectask"
6
5
 
6
+ begin
7
+ require 'hanna/rdoctask'
8
+ rescue LoadError
9
+ require 'rake/rdoctask'
10
+ end
11
+
7
12
  require 'lib/cinch'
8
13
 
9
14
  NAME = 'cinch'
10
15
  VERSION = Cinch::VERSION
11
- TITLE = "Cinch: The IRC Microframework"
16
+ TITLE = "Cinch: The IRC Bot Building Framework"
12
17
  CLEAN.include ["*.gem", "rdoc"]
13
18
  RDOC_OPTS = [
14
19
  "-U", "--title", TITLE,
data/lib/cinch.rb CHANGED
@@ -9,7 +9,7 @@ require 'cinch/rules'
9
9
  require 'cinch/base'
10
10
 
11
11
  module Cinch
12
- VERSION = '0.2.9'
12
+ VERSION = '0.3.0'
13
13
 
14
14
  # Setup bot options and return a new Cinch::Base instance
15
15
  def self.setup(ops={}, &blk)
data/lib/cinch/base.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  module Cinch
2
2
 
3
- # == Author
4
- # * Lee Jarvis - ljjarvis@gmail.com
5
- #
6
3
  # == Description
7
4
  # The base for an IRC connection
8
5
  # TODO: More documentation
@@ -17,6 +14,9 @@ module Cinch
17
14
  # bot.plugin "say :text" do |m|
18
15
  # m.reply m.args[:text]
19
16
  # end
17
+ #
18
+ # == Author
19
+ # * Lee Jarvis - ljjarvis@gmail.com
20
20
  class Base
21
21
 
22
22
  # A Hash holding rules and attributes
@@ -28,6 +28,12 @@ module Cinch
28
28
  # An OpenStruct holding all configuration options
29
29
  attr_reader :options
30
30
 
31
+ # Hash of custom rule patterns
32
+ attr_reader :custom_patterns
33
+
34
+ # Our IRC::Socket instance
35
+ attr_reader :irc
36
+
31
37
  # Default options hash
32
38
  DEFAULTS = {
33
39
  :port => 6667,
@@ -64,7 +70,14 @@ module Cinch
64
70
 
65
71
  @rules = Rules.new
66
72
  @listeners = {}
67
- @custom_patterns = {}
73
+
74
+ @custom_patterns = {
75
+ 'digit' => "(\\d+?)",
76
+ 'word' => "([a-zA-Z_]+?)",
77
+ 'string' => "(\\w+?)",
78
+ 'upper' => "([A-Z]+?)",
79
+ 'lower' => "([a-z]+?)",
80
+ }
68
81
 
69
82
  @irc = IRC::Socket.new(options[:server], options[:port])
70
83
  @parser = IRC::Parser.new
@@ -78,7 +91,7 @@ module Cinch
78
91
  end
79
92
 
80
93
  if @options.respond_to?(:channels)
81
- on(376) { @options.channels.each {|c| @irc.join(c) } }
94
+ on("004") { @options.channels.each {|c| @irc.join(c) } }
82
95
  end
83
96
  end
84
97
 
@@ -123,6 +136,7 @@ module Cinch
123
136
  @rules.add_rule(rule, keys, options, blk)
124
137
  end
125
138
  end
139
+ alias :rule :plugin
126
140
 
127
141
  # Add new listeners
128
142
  #
@@ -130,6 +144,11 @@ module Cinch
130
144
  # on(376) do |m|
131
145
  # m.join "#mychan"
132
146
  # end
147
+ #
148
+ # Note that when adding listeners for numberic IRC replies which
149
+ # begin with a 0 (digit), make sure you define the command as a
150
+ # String and not Integer. This is because 001.to_s == "1" so the
151
+ # command will not work as expected.
133
152
  def on(*commands, &blk)
134
153
  commands.map {|x| x.to_s.downcase.to_sym }.each do |cmd|
135
154
  if @listeners.key?(cmd)
@@ -153,28 +172,28 @@ module Cinch
153
172
  # * upper - matches [A-Z]+
154
173
  #
155
174
  # == Examples
156
- # For capturing individual words
175
+ # === Capturing individual words
157
176
  # bot.plugin("say :text-word")
158
177
  # * Does match !say foo
159
178
  # * Does not match !say foo bar baz
160
179
  #
161
- # For capturing digits
180
+ # === Capturing digits
162
181
  # bot.plugin("say :text-digit")
163
182
  # * Does match !say 3
164
183
  # * Does not match !say 3 4
165
184
  # * Does not match !say foo
166
185
  #
167
- # For both
186
+ # === Both digit and word
168
187
  # bot.plugin("say :n-digit :text-word")
169
188
  # * Does match !say 3 foo
170
189
  # * Does not match !say 3 foo bar
171
190
  #
172
- # For capturing until the end of the line
191
+ # === Capturing until the end of the line
173
192
  # bot.plugin("say :text")
174
193
  # * Does match !say foo
175
194
  # * Does match !say foo bar
176
195
  #
177
- # Or mix them all
196
+ # === Or mix them all
178
197
  # bot.plugin("say :n-digit :who-word :text")
179
198
  #
180
199
  # Using "!say 3 injekt some text here" would provide
@@ -193,22 +212,14 @@ module Cinch
193
212
  Regexp.escape(match)
194
213
  else
195
214
  k = $2
196
- if k =~ /\-(\w+)$/
215
+ if k =~ /\-\w+$/
197
216
  key, type = k.split('-')
198
217
  keys << key[1..-1]
199
-
200
- case type
201
- when 'digit'; "(\\d+?)"
202
- when 'word'; "([a-zA-Z_]+?)"
203
- when 'string'; "(\\w+?)"
204
- when 'upper'; "([A-Z]+?)"
205
- when 'lower'; "([a-z]+?)"
218
+
219
+ if @custom_patterns.include?(type)
220
+ @custom_patterns[type]
206
221
  else
207
- if @custom_patterns.include?(type)
208
- @custom_patterns[type]
209
- else
210
- "([^\x00\r\n]+?)"
211
- end
222
+ "([^\x00\r\n]+?)"
212
223
  end
213
224
  else
214
225
  keys << k[1..-1]
@@ -222,20 +233,19 @@ module Cinch
222
233
  # Add a custom 'type', for rule validation
223
234
  #
224
235
  # == Example
225
- # bot = Cinch.setup do
226
- # server 'irc.freenode.org'
227
- # port 6667
228
- # end
236
+ # bot = Cinch.setup do
237
+ # server 'irc.freenode.org'
238
+ # port 6667
239
+ # end
229
240
  #
230
- # bot.add_custom_pattern(:number, "[0-9]")
241
+ # bot.add_custom_pattern(:number, "[0-9]")
231
242
  #
232
- # bot.plugin("getnum :foo-number") do |m|
233
- # m.reply "Your number was: #{m.args[:foo]}"
234
- # end
243
+ # bot.plugin("getnum :foo-number") do |m|
244
+ # m.reply "Your number was: #{m.args[:foo]}"
245
+ # end
235
246
  def add_custom_pattern(name, pattern)
236
247
  @custom_patterns[name.to_s] = "(#{pattern.to_s})"
237
248
  end
238
- alias :add_custom_type :add_custom_pattern # backwards
239
249
  alias :add_pattern :add_custom_pattern
240
250
 
241
251
  # Run run run
data/lib/cinch/irc.rb CHANGED
@@ -8,9 +8,7 @@ require 'irc/message'
8
8
  require 'irc/socket'
9
9
 
10
10
  module Cinch
11
- # == Author
12
- # * Lee Jarvis - ljjarvis@gmail.com
13
- #
11
+
14
12
  # == Description
15
13
  # Cinch::IRC provides tools to interact with an IRC server, this
16
14
  # includes reading/writing/parsing and building a message response.
@@ -38,6 +36,8 @@ module Cinch
38
36
  # end
39
37
  # end
40
38
  #
39
+ # == Author
40
+ # * Lee Jarvis - ljjarvis@gmail.com
41
41
  module IRC
42
42
 
43
43
  end
@@ -1,18 +1,17 @@
1
1
  module Cinch
2
2
  module IRC
3
3
 
4
- # == Author
5
- # * Lee Jarvis - ljjarvis@gmail.com
6
- #
7
4
  # == Description
8
- # IRC::Message is a nicely encapsulated IRC message object. Used directly by
9
- # IRC::Parser#parse_servermessage and sent to every plugin defined. It does
10
- # not do any parsing of itself, that's all down to the parser
11
- #
12
- # == See
13
- # * Cinch::IRC::Parser#parse_servermessage
5
+ # IRC::Message provies a nicely encapsulated IRC message object. Used directly by
6
+ # IRC::Parser#parse and sent to any plugin or listener defined.
14
7
  #
15
8
  # TODO: Add more documentation
9
+ #
10
+ # == See Also
11
+ # * Cinch::IRC::Parser#parse
12
+ #
13
+ # == Author
14
+ # * Lee Jarvis - ljjarvis@gmail.com
16
15
  class Message
17
16
 
18
17
  # Message prefix
@@ -74,16 +73,21 @@ module Cinch
74
73
  @data.delete(var)
75
74
  end
76
75
 
76
+ # Alter an attribute
77
+ def alter(var, val)
78
+ if @data.key?(var)
79
+ @data[var] = val
80
+ end
81
+ end
82
+
77
83
  # Check if our message was sent privately
78
84
  def private?
79
85
  !@data[:channel]
80
86
  end
81
87
 
82
- # Add the nick/user/host attributes
83
- def apply_user(nick, user, host)
84
- @data[:nick] = nick
85
- @data[:user] = user
86
- @data[:host] = host
88
+ # Check if our message was sent publicly (in a channel)
89
+ def public?
90
+ !private?
87
91
  end
88
92
 
89
93
  # Reply to a channel or user, probably the most commonly used helper
@@ -1,9 +1,6 @@
1
1
  module Cinch
2
2
  module IRC
3
3
 
4
- # == Author
5
- # * Lee Jarvis - ljjarvis@gmail.com
6
- #
7
4
  # == Description
8
5
  # Parse incoming IRC lines and extract data, returning a nicely
9
6
  # encapsulated Cinch::IRC::Message
@@ -19,6 +16,9 @@ module Cinch
19
16
  # message.nick #=> foo
20
17
  # message.channel #=> #mychan
21
18
  # message.text #=> ding dong!
19
+ #
20
+ # == Author
21
+ # * Lee Jarvis - ljjarvis@gmail.com
22
22
  class Parser
23
23
 
24
24
  # A hash holding all of our patterns
@@ -79,7 +79,7 @@ module Cinch
79
79
 
80
80
  # Parse the incoming raw IRC string and return
81
81
  # a nicely formatted IRC::Message
82
- def parse_servermessage(raw)
82
+ def parse(raw)
83
83
  raise ArgumentError, raw unless raw && matches = raw.match(pattern(:message))
84
84
 
85
85
  prefix, command, parameters = matches.captures
@@ -90,17 +90,19 @@ module Cinch
90
90
  m = IRC::Message.new(raw, prefix, command, params)
91
91
 
92
92
  if prefix && userhost = parse_userhost(prefix)
93
- m.apply_user(*userhost)
93
+ nick, user, host = userhost
94
+ m.add(:nick, nick)
95
+ m.add(:user, user)
96
+ m.add(:host, host)
94
97
 
95
98
  unless m.params.empty?
96
- m[:recipient] = m.params.first
97
- m[:channel] = m[:recipient] if valid_channel?(m[:recipient])
99
+ m.add(:recipient, m.params.first)
100
+ m.add(:channel, m.recipient) if valid_channel?(m.recipient)
98
101
  end
99
102
  end
100
103
 
101
104
  m # Return our IRC::Message
102
105
  end
103
- alias :parse :parse_servermessage
104
106
 
105
107
  # Parse the prefix returned from the server
106
108
  # and return an Array of [nick, user, host] or
@@ -1,10 +1,8 @@
1
1
  module Cinch
2
2
  module IRC
3
- # == Author
4
- # * Lee Jarvis - ljjarvis@gmail.com
5
- #
3
+
6
4
  # == Description
7
- # This class has been directly take from the irc-socket library. Original documentation
5
+ # This class has been directly taken from the irc-socket library. Original documentation
8
6
  # for this class can be found {here}[http://rdoc.injekt.net/irc-socket].
9
7
  #
10
8
  # IRCSocket is an IRC wrapper around a TCPSocket. It implements all of the major
@@ -37,6 +35,9 @@ module Cinch
37
35
  #
38
36
  # puts irc.read
39
37
  # end
38
+ #
39
+ # == Author
40
+ # * Lee Jarvis - ljjarvis@gmail.com
40
41
  class Socket
41
42
 
42
43
  # The server our socket is connected to
@@ -166,7 +167,7 @@ module Cinch
166
167
 
167
168
  # Send JOIN command - Join a channel with given password
168
169
  def join(channel, password=nil)
169
- write("JOIN #{channel}")
170
+ write_optional("JOIN #{channel}", password)
170
171
  end
171
172
 
172
173
  # Send PART command
data/lib/cinch/rules.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  module Cinch
2
2
 
3
- # == Author
4
- # * Lee Jarvis - ljjarvis@gmail.com
5
- #
6
3
  # == Description
7
4
  # Every rule defined through the Cinch::Base#plugin method becomes an instance
8
5
  # of this class. Each rule consists of keys used for named parameters, a hash
@@ -10,25 +7,28 @@ module Cinch
10
7
  #
11
8
  # When a rule matches an IRC message, all options with be checked, then all
12
9
  # callbacks will be invoked.
10
+ #
11
+ # == Author
12
+ # * Lee Jarvis - ljjarvis@gmail.com
13
13
  class Rule < Struct.new(:rule, :keys, :options, :callbacks)
14
14
  def initialize(rule, keys, options, callback)
15
15
  callbacks = [callback]
16
16
  super(rule, keys, options, callbacks)
17
17
  end
18
18
 
19
- # Execute all callbacks, passing an Cinch::IRC::Message to them
19
+ # Execute all callbacks, passing a Cinch::IRC::Message to them
20
20
  def execute(message)
21
21
  options.keys.each do |key|
22
22
  case key
23
23
  when :nick, :nicks
24
- return unless validate(options[:nick], message.nick)
24
+ return unless validate(options[:nick] || options[:nicks], message.nick)
25
25
  when :host, :hosts
26
- return unless validate(options[:host], message.host)
26
+ return unless validate(options[:host] || options[:hosts], message.host)
27
27
  when :user, :users
28
- return unless validate(options[:user], message.user)
28
+ return unless validate(options[:user] || options[:users], message.user)
29
29
  when :channel, :channels
30
30
  if message.channel
31
- return unless validate(options[:channel], message.channel)
31
+ return unless validate(options[:channel] || options[:channels], message.channel)
32
32
  end
33
33
  end
34
34
  end
@@ -43,7 +43,7 @@ module Cinch
43
43
  if option.is_a?(Array)
44
44
  return unless option.any?{|o| o == attr }
45
45
  else
46
- return unless options.to_s == attr
46
+ return unless option.to_s == attr
47
47
  end
48
48
  true
49
49
  end
@@ -54,9 +54,6 @@ module Cinch
54
54
  end
55
55
  end
56
56
 
57
- # == Author
58
- # * Lee Jarvis - ljjarvis@gmail.com
59
- #
60
57
  # == Description
61
58
  # This class provides an interface to manage rules. A rule should only ever be
62
59
  # added using the Rules#add_rule method and retrieved using the Rules#get_rule
@@ -87,6 +84,9 @@ module Cinch
87
84
  # rules.get_rule('foo')
88
85
  # rules.options = {:foo => 'bar'}
89
86
  # rules.options[:bar] = 'baz'
87
+ #
88
+ # == Author
89
+ # * Lee Jarvis - ljjarvis@gmail.com
90
90
  class Rules
91
91
  def initialize
92
92
  @rules = {}
data/spec/base_spec.rb CHANGED
@@ -20,9 +20,19 @@ describe "Cinch::Base" do
20
20
  @base.listeners.should include :"433"
21
21
  end
22
22
 
23
- it "should add a 376 listener, only if channels are set" do
24
- @base.listeners.should_not include :'376'
25
- @full.listeners.should include :'376'
23
+ it "should add a 004 listener, only if channels are set" do
24
+ @base.listeners.should_not include :'004'
25
+ @full.listeners.should include :'004'
26
+ end
27
+
28
+ it "should add a 433 nick taken listener" do
29
+ @base.listeners.should include :'433'
30
+ end
31
+
32
+ it "should add default custom_patterns" do
33
+ [:digit, :word, :string, :upper, :lower].each do |l|
34
+ @base.custom_patterns.should include l.to_s
35
+ end
26
36
  end
27
37
  end
28
38
 
@@ -56,7 +56,7 @@ describe "IRC::Parser" do
56
56
  end
57
57
  end
58
58
 
59
- describe "#parse_servermessage" do
59
+ describe "#parse" do
60
60
  it "should return an IRC::Message" do
61
61
  @parser.parse("foo :bar").should be_kind_of(Cinch::IRC::Message)
62
62
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
- - 9
9
- version: 0.2.9
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Lee 'injekt' Jarvis
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-07 00:00:00 +01:00
17
+ date: 2010-05-18 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -31,7 +31,7 @@ dependencies:
31
31
  version: 1.3.0
32
32
  type: :development
33
33
  version_requirements: *id001
34
- description: An IRC Microframework
34
+ description: An IRC Bot Building Framework
35
35
  email: ljjarvis@gmail.com
36
36
  executables: []
37
37
 
@@ -77,7 +77,7 @@ post_install_message:
77
77
  rdoc_options:
78
78
  - --quiet
79
79
  - --title
80
- - "Cinch: The IRC Microframework"
80
+ - "Cinch: The IRC Bot Building Framework"
81
81
  - --main
82
82
  - README.rdoc
83
83
  require_paths:
@@ -104,6 +104,6 @@ rubyforge_project:
104
104
  rubygems_version: 1.3.6
105
105
  signing_key:
106
106
  specification_version: 3
107
- summary: An IRC Microframework
107
+ summary: An IRC Bot Building Framework
108
108
  test_files: []
109
109