cinch 0.3.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +192 -0
  3. data/Rakefile +53 -43
  4. data/examples/basic/autovoice.rb +32 -0
  5. data/examples/basic/google.rb +35 -0
  6. data/examples/basic/hello.rb +15 -0
  7. data/examples/basic/join_part.rb +38 -0
  8. data/examples/basic/memo.rb +39 -0
  9. data/examples/basic/msg.rb +16 -0
  10. data/examples/basic/seen.rb +36 -0
  11. data/examples/basic/urban_dict.rb +35 -0
  12. data/examples/basic/url_shorten.rb +35 -0
  13. data/examples/plugins/autovoice.rb +40 -0
  14. data/examples/plugins/custom_prefix.rb +23 -0
  15. data/examples/plugins/google.rb +37 -0
  16. data/examples/plugins/hello.rb +22 -0
  17. data/examples/plugins/join_part.rb +42 -0
  18. data/examples/plugins/memo.rb +50 -0
  19. data/examples/plugins/msg.rb +22 -0
  20. data/examples/plugins/multiple_matches.rb +41 -0
  21. data/examples/plugins/seen.rb +45 -0
  22. data/examples/plugins/urban_dict.rb +30 -0
  23. data/examples/plugins/url_shorten.rb +32 -0
  24. data/lib/cinch.rb +7 -20
  25. data/lib/cinch/ban.rb +41 -0
  26. data/lib/cinch/bot.rb +479 -0
  27. data/lib/cinch/callback.rb +11 -0
  28. data/lib/cinch/channel.rb +419 -0
  29. data/lib/cinch/constants.rb +369 -0
  30. data/lib/cinch/exceptions.rb +25 -0
  31. data/lib/cinch/helpers.rb +21 -0
  32. data/lib/cinch/irc.rb +344 -38
  33. data/lib/cinch/isupport.rb +96 -0
  34. data/lib/cinch/logger/formatted_logger.rb +80 -0
  35. data/lib/cinch/logger/logger.rb +44 -0
  36. data/lib/cinch/logger/null_logger.rb +18 -0
  37. data/lib/cinch/mask.rb +46 -0
  38. data/lib/cinch/message.rb +183 -0
  39. data/lib/cinch/message_queue.rb +62 -0
  40. data/lib/cinch/plugin.rb +205 -0
  41. data/lib/cinch/rubyext/infinity.rb +1 -0
  42. data/lib/cinch/rubyext/module.rb +18 -0
  43. data/lib/cinch/rubyext/queue.rb +19 -0
  44. data/lib/cinch/rubyext/string.rb +24 -0
  45. data/lib/cinch/syncable.rb +55 -0
  46. data/lib/cinch/user.rb +325 -0
  47. data/spec/bot_spec.rb +5 -0
  48. data/spec/channel_spec.rb +5 -0
  49. data/spec/cinch_spec.rb +5 -0
  50. data/spec/irc_spec.rb +5 -0
  51. data/spec/message_spec.rb +5 -0
  52. data/spec/plugin_spec.rb +5 -0
  53. data/spec/{helper.rb → spec_helper.rb} +0 -0
  54. data/spec/user_spec.rb +5 -0
  55. metadata +69 -51
  56. data/README.rdoc +0 -195
  57. data/examples/autovoice.rb +0 -32
  58. data/examples/custom_patterns.rb +0 -19
  59. data/examples/custom_prefix.rb +0 -25
  60. data/examples/google.rb +0 -31
  61. data/examples/hello.rb +0 -13
  62. data/examples/join_part.rb +0 -26
  63. data/examples/memo.rb +0 -40
  64. data/examples/msg.rb +0 -14
  65. data/examples/named-param-types.rb +0 -19
  66. data/examples/seen.rb +0 -41
  67. data/examples/urban_dict.rb +0 -31
  68. data/examples/url_shorten.rb +0 -34
  69. data/lib/cinch/base.rb +0 -368
  70. data/lib/cinch/irc/message.rb +0 -135
  71. data/lib/cinch/irc/parser.rb +0 -141
  72. data/lib/cinch/irc/socket.rb +0 -329
  73. data/lib/cinch/names.rb +0 -54
  74. data/lib/cinch/rules.rb +0 -171
  75. data/spec/base_spec.rb +0 -94
  76. data/spec/irc/helper.rb +0 -8
  77. data/spec/irc/message_spec.rb +0 -61
  78. data/spec/irc/parser_spec.rb +0 -103
  79. data/spec/irc/socket_spec.rb +0 -90
  80. data/spec/names_spec.rb +0 -393
  81. data/spec/options_spec.rb +0 -45
  82. data/spec/rules_spec.rb +0 -109
@@ -1,54 +0,0 @@
1
- module Cinch
2
- module Names
3
- attr_reader :channel_names
4
-
5
- def tracking_names?
6
- !!@tracking_names
7
- end
8
-
9
- def track_names
10
- return if tracking_names?
11
-
12
- @tracking_names = true
13
-
14
- @channel_names = {}
15
-
16
- on(:join) do |m|
17
- if m.nick == nick
18
- names(m.channel)
19
- else
20
- channel_names[m.channel] ||= []
21
- channel_names[m.channel].push m.nick
22
- end
23
- end
24
-
25
- on(353) do |m|
26
- channel = m.params.detect { |c| c.match(/^#/) }
27
- names = m.text.split.collect { |n| n.sub(/^@/, '') }
28
- channel_names[channel] ||= []
29
- channel_names[channel] += names
30
- end
31
-
32
- on(:part) do |m|
33
- if m.nick == nick
34
- channel_names.delete(m.channel)
35
- else
36
- channel_names[m.channel] ||= []
37
- channel_names[m.channel].delete m.nick
38
- end
39
- end
40
-
41
- on(:quit, :kill) do |m|
42
- channel_names.each_value { |names| names.delete m.nick }
43
- end
44
-
45
- on(:nick) do |m|
46
- channel_names.each_value { |names| names.push m.recipient if names.delete m.nick }
47
- end
48
- end
49
- end
50
- end
51
-
52
- class Cinch::Base
53
- include Cinch::Names
54
- end
@@ -1,171 +0,0 @@
1
- module Cinch
2
-
3
- # == Description
4
- # Every rule defined through the Cinch::Base#plugin method becomes an instance
5
- # of this class. Each rule consists of keys used for named parameters, a hash
6
- # of options, and an Array of callbacks.
7
- #
8
- # When a rule matches an IRC message, all options with be checked, then all
9
- # callbacks will be invoked.
10
- #
11
- # == Author
12
- # * Lee Jarvis - ljjarvis@gmail.com
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 a Cinch::IRC::Message to them
20
- def execute(message)
21
- options.keys.each do |key|
22
- case key
23
- when :nick, :nicks
24
- return unless validate(options[:nick] || options[:nicks], message.nick)
25
- when :host, :hosts
26
- return unless validate(options[:host] || options[:hosts], message.host)
27
- when :user, :users
28
- return unless validate(options[:user] || options[:users], message.user)
29
- when :channel, :channels
30
- if message.channel
31
- return unless validate(options[:channel] || options[:channels], message.channel)
32
- end
33
- end
34
- end
35
-
36
- callbacks.each do |blk|
37
- blk.call(message)
38
- end
39
- end
40
-
41
- # Validate rule attributes
42
- def validate(option, attr)
43
- if option.is_a?(Array)
44
- return unless option.any?{|o| o == attr }
45
- else
46
- return unless option.to_s == attr
47
- end
48
- true
49
- end
50
-
51
- # The rule as a String
52
- def to_s
53
- rule
54
- end
55
- end
56
-
57
- # == Description
58
- # This class provides an interface to manage rules. A rule should only ever be
59
- # added using the Rules#add_rule method and retrieved using the Rules#get_rule
60
- # method, or an alias of these.
61
- #
62
- # This class provides an easy way to add options or callbacks to an existing
63
- # rule.
64
- #
65
- # Essentially the add_callback, add_option, and merge_options methods are just sugar
66
- # so you don't have to edit Rule attributes directly
67
- #
68
- # == Example
69
- # rules = Cinch::Rules.new
70
- #
71
- # rules.add('foo', [], {}, Proc.new{})
72
- #
73
- # rules.add_callback('foo', Proc.new{})
74
- # rules['foo'].callbacks #=> [#<Proc:0x9f1e110@(main):100>, #<Proc:0x9f1e0f4@(main):150>]
75
- #
76
- # # Or assign directly
77
- # rules.get('foo').callbacks << Proc.new {}
78
- #
79
- # rules['foo'].options #=> {}
80
- # rules.add_option('foo', :nick, 'injekt')
81
- # rules['foo'].options #=> {:nick => 'injekt'}
82
- #
83
- # # Or retrieve the rule first and assign directly
84
- # rules.get_rule('foo')
85
- # rules.options = {:foo => 'bar'}
86
- # rules.options[:bar] = 'baz'
87
- #
88
- # == Author
89
- # * Lee Jarvis - ljjarvis@gmail.com
90
- class Rules
91
- def initialize
92
- @rules = {}
93
- end
94
-
95
- # Add a new rule, overwrites an already existing rule
96
- def add_rule(rule, keys, options, callback)
97
- @rules[rule] = Rule.new(rule, keys, options, callback)
98
- end
99
- alias :add :add_rule
100
-
101
- # Return a Cinch::Rule by its rule, or nil it one does not exist
102
- def get_rule(rule)
103
- @rules[rule]
104
- end
105
- alias :get :get_rule
106
- alias :[] :get_rule
107
-
108
- # Remove a rule
109
- def remove_rule(rule)
110
- @rules.delete(rule)
111
- end
112
- alias :remove :remove_rule
113
-
114
- # Check if a rule exists
115
- def include?(rule)
116
- @rules.key?(rule)
117
- end
118
- alias :has_rule? :include?
119
-
120
- # Add a callback for an already existing rule
121
- def add_callback(rule, blk)
122
- return unless include?(rule)
123
- @rules[rule].callbacks << blk
124
- end
125
-
126
- # Add an option for an already existing rule
127
- def add_option(rule, key, value)
128
- return unless include?(rule)
129
- @rules[rule].options[key] = value
130
- end
131
-
132
- # Merge rule options
133
- def merge_options(rule, ops={})
134
- return unless include?(rule)
135
- @rules[rule].options.merge!(ops)
136
- end
137
-
138
- # Iterate over the rules
139
- def each
140
- @rules.each {|rule, obj| yield obj }
141
- end
142
-
143
- # Remove all rules
144
- def clear
145
- @rules.clear
146
- end
147
-
148
- # Check if any rules exist
149
- def empty?
150
- @rules.empty?
151
- end
152
-
153
- # Return how many rules exist
154
- def count
155
- @rules.size
156
- end
157
- alias :size :count
158
-
159
- # Return the hash of rules
160
- def all
161
- @rules
162
- end
163
-
164
- # Return an Array of rules
165
- def to_a
166
- @rules.keys
167
- end
168
- end
169
-
170
- end
171
-
@@ -1,94 +0,0 @@
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 ctcp version listener" do
16
- @base.listeners.should include :ctcp
17
- @base.listeners[:ctcp].should include :version
18
- end
19
- end
20
-
21
- describe "#plugin" do
22
- it "should compile and add a rule" do
23
- @base.plugin('foo')
24
- @base.rules.include?("^foo$").should == true
25
- end
26
-
27
- it "should add options to an existing rule" do
28
- @base.plugin('foo') { }
29
- @base.plugin('foo', :bar => 'baz') { }
30
- rule = @base.rules.get('^foo$')
31
- rule.options.should include :bar
32
- end
33
-
34
- it "should add its block to an existing rule" do
35
- @base.plugin('foo') { }
36
- @base.plugin('foo') { }
37
- rule = @base.rules.get_rule('^foo$')
38
- rule.callbacks.size.should == 2
39
- end
40
- end
41
-
42
- describe "#on" do
43
- it "should save a listener" do
44
- @base.on(:foo) {}
45
- @base.listeners.should include :foo
46
- end
47
-
48
- it "should store listener blocks in an Array" do
49
- @base.listeners[:ping].should be_kind_of Array
50
- end
51
- end
52
-
53
- describe "#compile" do
54
- it "should return an Array of 2 values" do
55
- ret = @base.compile("foo")
56
- ret.should be_kind_of(Array)
57
- ret.size.should == 2
58
- end
59
-
60
- it "should return an empty set of keys if no named parameters are labeled" do
61
- rule, keys = @base.compile("foo")
62
- keys.should be_empty
63
- end
64
-
65
- it "should return a key for each named parameter labeled" do
66
- rule, keys = @base.compile("foo :bar :baz")
67
- keys.size.should == 2
68
- keys.should include "bar"
69
- keys.should include "baz"
70
- end
71
-
72
- it "should return a rule of type String, unless Regexp is given" do
73
- rule, keys = @base.compile(:foo)
74
- rule.should be_kind_of(String)
75
-
76
- rule, keys = @base.compile(/foo/)
77
- rule.should be_kind_of(Regexp)
78
- keys.should be_empty
79
- end
80
-
81
- it "should convert a custom pattern" do
82
- @base.add_custom_pattern(:people, "foo|bar|baz")
83
- rule, keys = @base.compile(":foo-people")
84
- rule.should == "^(foo|bar|baz)$"
85
- end
86
-
87
- it "should automatically add start and end anchors" do
88
- rule, keys = @base.compile("foo bar baz")
89
- rule[0].chr.should == "^"
90
- rule[-1].chr.should == "$"
91
- end
92
- end
93
- end
94
-
@@ -1,8 +0,0 @@
1
- spec = File.dirname(__FILE__)
2
- $LOAD_PATH.unshift(spec) unless $LOAD_PATH.include?(spec)
3
-
4
- lib = File.dirname(__FILE__) + '../../lib/'
5
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
-
7
- require 'cinch/irc'
8
-
@@ -1,61 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- describe "IRC::Message" do
4
- before do
5
- @message = Cinch::IRC::Message.new('rawline', 'prefix', 'COMMAND', ['#chan', 'hello world'])
6
- end
7
-
8
- describe "#add, #[]=" do
9
- it "should add an attribute" do
10
- @message.add(:custom, 'something')
11
- @message.data.should include :custom
12
- @message.data[:custom].should == "something"
13
- end
14
- end
15
-
16
- describe "#delete" do
17
- it "should remove an attribute" do
18
- @message.add(:custom, 'something')
19
- @message.delete(:custom)
20
- @message.data.should_not include :custom
21
- end
22
- end
23
-
24
- describe "#to_s" do
25
- it "should return the raw IRC message" do
26
- @message.to_s.should == @message.raw
27
- end
28
- end
29
-
30
- describe "#method_missing" do
31
- it "should return an attribute if it exists" do
32
- @message.add(:custom, 'something')
33
- @message.custom.should == 'something'
34
- end
35
-
36
- it "should return nil if no attribute exists" do
37
- @message.foobar.should == nil
38
- end
39
- end
40
-
41
- describe "default attributes" do
42
- it "should contain a prefix" do
43
- @message.prefix.should == 'prefix'
44
- end
45
-
46
- it "should contain a command" do
47
- @message.command.should == "COMMAND"
48
- end
49
-
50
- it "should contain params" do
51
- @message.params.should be_kind_of(Array)
52
- @message.params.size.should == 2
53
- end
54
-
55
- it "should contain a symbolized command" do
56
- @message.symbol.should == :command
57
- end
58
- end
59
-
60
- end
61
-
@@ -1,103 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- # Common commands
4
- commands = {
5
- :ping => "PING :foobar",
6
- :nick => ":foo!~baz@host.com NICK Baz",
7
- :join => ":foo!~bar@host.com JOIN #baz",
8
- :ctcp => ":foo!~bar@host.com PRIVMSG Baz :\001VERSION\001",
9
-
10
- :privmsg => {
11
- "to a channel" => ":foo!~bar@host.com PRIVMSG #baz :hello world",
12
- "to a user" => ":foo!~bar@host.com PRIVMSG Baz :hello world",
13
- },
14
-
15
- :notice => {
16
- "to a channel" => ":foo!~bar@host.com NOTICE #baz :hello world",
17
- "to a user" => ":foo!~bar@host.com NOTICE Baz :hello world",
18
- },
19
-
20
- :part => {
21
- "without a message" => ":foo!~bar@host.com PART #baz",
22
- "with a message" => ":foo!~bar@host.com PART #baz :beer",
23
- },
24
-
25
- :quit => {
26
- "without a message" => ":foo!~bar@host.com QUIT",
27
- "with a message" => ":foo!~bar@host.com QUIT :baz"
28
- }
29
- }
30
-
31
- describe "IRC::Parser" do
32
- before do
33
- @parser = Cinch::IRC::Parser.new
34
- end
35
-
36
- describe "#add_pattern" do
37
- it "should add a pattern" do
38
- @parser.add_pattern(:custom, /foo/)
39
- @parser.patterns.key?(:custom)
40
- end
41
- end
42
-
43
- describe "#remove_pattern" do
44
- it "should remove a pattern" do
45
- @parser.add_pattern(:custom, /foo/)
46
- @parser.remove_pattern(:custom)
47
- @parser.patterns.keys.should_not include(:custom)
48
- end
49
-
50
- it "should return nil if a pattern doesn't exist" do
51
- @parser.remove_pattern(:foo).should be nil
52
- end
53
- end
54
-
55
- describe "#parse" do
56
- it "should return an IRC::Message" do
57
- @parser.parse("foo :bar").should be_kind_of(Cinch::IRC::Message)
58
- end
59
-
60
- it "should raise if given an invalid message" do
61
- lambda { @parser.parse("#") }.should raise_error(ArgumentError)
62
- end
63
-
64
- commands.each do |cmd, passes|
65
- if passes.is_a?(Hash)
66
- passes.each do |extra, pass|
67
- it "should parse a #{cmd.to_s.upcase} command #{extra}" do
68
- m = @parser.parse(pass)
69
- m.symbol.should == cmd
70
- end
71
- end
72
- else
73
- it "should parse a #{cmd.to_s.upcase} command" do
74
- m = @parser.parse(passes)
75
- m.symbol.should == cmd
76
- end
77
- end
78
- end
79
-
80
- end
81
-
82
- describe "#parse_userhost" do
83
- it "should return an Array" do
84
- @parser.parse_userhost(":foo!bar@baz").should be_kind_of(Array)
85
- end
86
-
87
- it "should return 3 values" do
88
- @parser.parse_userhost(":foo!bar@baz").size.should be 3
89
- end
90
- end
91
-
92
- describe "#valid_channel?" do
93
- it "should return true with a valid channel name" do
94
- @parser.valid_channel?("#foo").should be true
95
- end
96
-
97
- it "should return false with an invalid channel name" do
98
- @parser.valid_channel?("foo").should be false
99
- end
100
- end
101
-
102
- end
103
-