scamp 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  .rvmrc
2
+ Gemfile.lock
2
3
  pkg/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/README.md CHANGED
@@ -14,11 +14,11 @@ Ruby >= 1.9.2 (At least for the named captures)
14
14
 
15
15
  Matchers are tested in order and all that satisfy the match and conditions will be run. Careful, Scamp listens to itself, you could easily create an infinite loop. Look in the examples dir for more.
16
16
 
17
- require 'Scamp'
17
+ require 'scamp'
18
18
 
19
- scamp = Scamp.new(:api_key => "YOUR API KEY")
19
+ scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "yoursubdomain")
20
20
 
21
- Scamp.behaviour do
21
+ scamp.behaviour do
22
22
  #
23
23
  # Simple matching based on regex or string:
24
24
  #
@@ -69,8 +69,24 @@ Matchers are tested in order and all that satisfy the match and conditions will
69
69
  say "#{user} said something in channel #{channel}", "System Administration"
70
70
  end
71
71
 
72
- # Connect and join some channels
73
- scamp.connect!([293788, "Monitoring"])
72
+ #
73
+ # A list of commands is available as command_list this matcher uses it
74
+ # to format a help text
75
+ #
76
+ match "help" do
77
+ max_command_length = command_list.map{|cl| cl.first.to_s }.max_by(&:size).size
78
+ format_string = "%#{max_command_length + 1}s"
79
+ formatted_commands = command_list.map{|action, conds| "#{sprintf(format_string, action)} | #{conds.size == 0 ? '' : conds.inspect}"}
80
+ say <<-EOS
81
+ #{sprintf("%-#{max_command_length + 1}s", "Command match")} | Conditions
82
+ --------------------------------------------------------------------------------
83
+ #{formatted_commands.join("\n")}
84
+ EOS
85
+ end
86
+ end
87
+
88
+ # Connect and join some channels
89
+ scamp.connect!([293788, "Monitoring"])
74
90
 
75
91
  In the channel/user conditions you can use the name, regex or ID of a user or channel, in say you can ise a string or ID, eg:
76
92
 
@@ -87,15 +103,16 @@ In the channel/user conditions you can use the name, regex or ID of a user or ch
87
103
 
88
104
  ## TODO
89
105
 
90
- * Write the tests
106
+ * Write more tests
91
107
  * Allow multiple values for conditions, eg: :conditions => {:channel => [/someregex/, "Some channel"]}
92
- * Remove debugging output
93
- * Add support for a logger
108
+ * Add paste/play support
109
+ * Add option to stop bot responding to itself
94
110
 
95
111
  ## Known issues
96
112
 
97
- * Bot doesn't detect that it's been kicked out of a channel and recommect
113
+ * Bot doesn't detect that it's been kicked out of a channel and reconnect
98
114
  * Bot tends to crash when it encounters an error.
115
+ * When encountering a problem straming (Couldn't stream channel 401839 at url https://streaming.campfirenow.com/room/<channel_id>/live.json) no attempt is made to re-connect
99
116
 
100
117
  ## How to contribute
101
118
 
@@ -132,4 +149,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
132
149
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
133
150
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
134
151
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
135
- THE SOFTWARE.
152
+ THE SOFTWARE.
data/Rakefile CHANGED
@@ -1 +1,13 @@
1
1
  require 'bundler/gem_tasks'
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ rescue LoadError => e
7
+ task "spec" do
8
+ puts "RSpec not loaded - make sure it's installed and you're using bundle exec"
9
+ exit 1
10
+ end
11
+ end
12
+
13
+ task :default => :spec
data/examples/bot.rb CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  $:.unshift File.join(File.dirname(__FILE__), '../lib')
4
4
 
5
- require 'Scamp'
5
+ require 'scamp'
6
6
 
7
- scamp = Scamp.new(:api_key => "YOUR API KEY")
7
+ scamp = Scamp.new(:api_key => "YOUR API KEY", :subdomain => "37s")
8
8
 
9
- Scamp.behaviour do
9
+ scamp.behaviour do
10
10
  # Match some regex limited to a channel condition based on a channel id
11
11
  match /^channel id (.+)$/, :conditions => {:channel => 401839} do
12
12
  # Reply in the current channel
@@ -73,4 +73,4 @@ Scamp.behaviour do
73
73
  end
74
74
 
75
75
  # FIXME: this does if the channel doesn't exist. Need a better error.
76
- scamp.connect!([293788, "Monitoring"])
76
+ scamp.connect!([293788, "Monitoring"])
data/lib/scamp/action.rb CHANGED
@@ -9,7 +9,7 @@
9
9
  class Scamp
10
10
  class Action
11
11
 
12
- attr :matches, :bot
12
+ attr_accessor :matches, :bot
13
13
 
14
14
  def initialize(bot, action, message)
15
15
  @bot = bot
@@ -24,12 +24,11 @@ class Scamp
24
24
  self.class.send :define_method, name_s do
25
25
  match[name_s]
26
26
  end
27
- end
27
+ end if match.respond_to?(:names) # 1.8 doesn't support named captures
28
28
  end
29
29
 
30
30
  def channel
31
- puts "Need the real channel name at #{__FILE__}:#{__LINE__}"
32
- @message[:room_id]
31
+ bot.channel_name_for @message[:room_id]
33
32
  end
34
33
 
35
34
  def user
@@ -50,8 +49,12 @@ class Scamp
50
49
 
51
50
  private
52
51
 
52
+ def command_list
53
+ bot.command_list
54
+ end
55
+
53
56
  def say(msg, channel_id_or_name = channel)
54
57
  bot.say(msg, channel_id_or_name)
55
58
  end
56
59
  end
57
- end
60
+ end
@@ -7,10 +7,10 @@ class Scamp
7
7
 
8
8
  # curl -vvv -H 'Content-Type: application/json' -d '{"message":{"body":"Yeeeeeaaaaaahh", "type":"Textmessage"}}' -u API_KEY:X https://37s.campfirenow.com/room/293788/speak.json
9
9
  def say(message, channel)
10
- url = "https://37s.campfirenow.com/room/#{channel_id(channel)}/speak.json"
10
+ url = "https://#{subdomain}.campfirenow.com/room/#{channel_id(channel)}/speak.json"
11
11
  http = EventMachine::HttpRequest.new(url).post :head => {'Content-Type' => 'application/json', 'authorization' => [api_key, 'X']}, :body => Yajl::Encoder.encode({:message => {:body => message, :type => "Textmessage"}})
12
12
 
13
- http.errback { STDERR.puts "Error speaking: '#{message}' to #{channel_id(channel)}" }
13
+ http.errback { logger.error "Error speaking: '#{message}' to #{channel_id(channel)}" }
14
14
  end
15
15
 
16
16
  def paste(text, channel)
@@ -20,10 +20,11 @@ class Scamp
20
20
  end
21
21
 
22
22
  def join(channel_id)
23
- url = "https://37s.campfirenow.com/room/#{channel_id}/join.json"
23
+ logger.info "Joining channel #{channel_id}"
24
+ url = "https://#{subdomain}.campfirenow.com/room/#{channel_id}/join.json"
24
25
  http = EventMachine::HttpRequest.new(url).post :head => {'Content-Type' => 'application/json', 'authorization' => [api_key, 'X']}
25
26
 
26
- http.errback { STDERR.puts "Error joining channel: #{channel_id}" }
27
+ http.errback { logger.error "Error joining channel: #{channel_id}" }
27
28
  http.callback {
28
29
  yield if block_given?
29
30
  }
@@ -52,9 +53,9 @@ class Scamp
52
53
  end
53
54
 
54
55
  def populate_channel_list
55
- url = "https://37s.campfirenow.com/rooms.json"
56
+ url = "https://#{subdomain}.campfirenow.com/rooms.json"
56
57
  http = EventMachine::HttpRequest.new(url).get :head => {'authorization' => [api_key, 'X']}
57
- http.errback { puts http.status }
58
+ http.errback { logger.error "Error populating the channel list: #{http.status.inspect}" }
58
59
  http.callback {
59
60
  new_channels = {}
60
61
  Yajl::Parser.parse(http.response)['rooms'].each do |c|
@@ -69,12 +70,12 @@ class Scamp
69
70
  end
70
71
 
71
72
  def fetch_channel_data(channel_id)
72
- STDERR.puts "Fetching channel data for #{channel_id}"
73
- url = "https://37s.campfirenow.com/room/#{channel_id}.json"
73
+ logger.debug "Fetching channel data for #{channel_id}"
74
+ url = "https://#{subdomain}.campfirenow.com/room/#{channel_id}.json"
74
75
  http = EventMachine::HttpRequest.new(url).get :head => {'authorization' => [api_key, 'X']}
75
- http.errback { STDERR.puts "Couldn't get data for channel #{channel_id} at url #{url}" }
76
+ http.errback { logger.error "Couldn't get data for channel #{channel_id} at url #{url}" }
76
77
  http.callback {
77
- puts "Fetched channel data for #{channel_id}"
78
+ logger.debug "Fetched channel data for #{channel_id}"
78
79
  room = Yajl::Parser.parse(http.response)['room']
79
80
  channel_cache[room["id"]] = room
80
81
  room['users'].each do |u|
@@ -83,19 +84,28 @@ class Scamp
83
84
  }
84
85
  end
85
86
 
87
+ def join_and_stream(id)
88
+ join(id) do
89
+ logger.info "Joined channel #{id} successfully"
90
+ fetch_channel_data(id)
91
+ stream(id)
92
+ end
93
+ end
94
+
86
95
  def stream(channel_id)
87
96
  json_parser = Yajl::Parser.new :symbolize_keys => true
88
97
  json_parser.on_parse_complete = method(:process_message)
89
98
 
90
99
  url = "https://streaming.campfirenow.com/room/#{channel_id}/live.json"
91
100
  http = EventMachine::HttpRequest.new(url).get :head => {'authorization' => [api_key, 'X']}
92
- http.errback { STDERR.puts "Couldn't stream channel #{channel_id} at url #{url}" }
101
+ http.errback { logger.error "Couldn't stream channel #{channel_id} at url #{url}" }
102
+ http.callback { logger.error "Disconnected from #{url}" }
93
103
  http.stream {|chunk| json_parser << chunk }
94
104
  end
95
105
 
96
106
  def channel_id_from_channel_name(channel_name)
97
- puts "Looking for channel id for #{channel_name}"
107
+ logger.debug "Looking for channel id for #{channel_name}"
98
108
  channels[channel_name]["id"]
99
109
  end
100
110
  end
101
- end #class
111
+ end
@@ -7,15 +7,11 @@ class Scamp
7
7
  # Ideally populate_channel_list would block, but I can't see an easy way to do this, so a hacky callback it is.
8
8
  populate_channel_list do
9
9
  channels_to_join.map{|c| channel_id(c) }.each do |id|
10
- puts "Joining channel #{id}"
11
- join(id) do
12
- fetch_channel_data(id)
13
- stream(id)
14
- end
10
+ join_and_stream(id)
15
11
  end
16
12
  end
17
13
  end
18
14
  end
19
15
 
20
- end #module
21
- end #class
16
+ end
17
+ end
data/lib/scamp/matcher.rb CHANGED
@@ -31,7 +31,7 @@ class Scamp
31
31
  elsif trigger.is_a? Regexp
32
32
  return trigger.match message_text
33
33
  else
34
- STDERR.puts "Don't know what to do with #{trigger.inspect} at #{__FILE__}:#{__LINE__}"
34
+ bot.logger.warn "Don't know what to do with #{trigger.inspect} at #{__FILE__}:#{__LINE__}"
35
35
  end
36
36
  false
37
37
  end
@@ -43,7 +43,8 @@ class Scamp
43
43
  end
44
44
 
45
45
  def conditions_satisfied_by(msg)
46
- # STDERR.puts "Need to take into account nick, channel and regexps at #{__FILE__}:#{__LINE__}"
46
+ # bot.logger.warn "Need to take into account nick, channel and regexps at #{__FILE__}:#{__LINE__}"
47
+ bot.logger.info "Checking message against #{conditions.inspect}"
47
48
 
48
49
  # nick
49
50
  # channel name
@@ -55,10 +56,10 @@ class Scamp
55
56
  # item will be :nick or :channel
56
57
  # cond is the regex, int or string value.
57
58
  conditions.each do |item, cond|
58
- STDERR.puts "Checking #{item} against #{cond}"
59
- puts "msg is #{msg.inspect}"
59
+ bot.logger.debug "Checking #{item} against #{cond}"
60
+ bot.logger.debug "msg is #{msg.inspect}"
60
61
  if cond.is_a? Integer
61
- # puts "item is #{msg[{:channel => :room_id, :user => :user_id}[item]]}"
62
+ # bot.logger.debug "item is #{msg[{:channel => :room_id, :user => :user_id}[item]]}"
62
63
  return false unless msg[{:channel => :room_id, :user => :user_id}[item]] == cond
63
64
  elsif cond.is_a? String
64
65
  case item
@@ -67,7 +68,7 @@ class Scamp
67
68
  when :user
68
69
  return false unless bot.username_for(msg[:user_id]) == cond
69
70
  end
70
- STDERR.puts "Don't know how to deal with a match item of #{item}, cond #{cond}"
71
+ bot.logger.error "Don't know how to deal with a match item of #{item}, cond #{cond}"
71
72
  elsif cond.is_a? Regexp
72
73
  return false
73
74
  return false unless msg[item].match(cond)
@@ -76,4 +77,4 @@ class Scamp
76
77
  true
77
78
  end
78
79
  end
79
- end
80
+ end
data/lib/scamp/users.rb CHANGED
@@ -22,23 +22,20 @@ class Scamp
22
22
  private
23
23
 
24
24
  def fetch_data_for(user_id)
25
- url = "https://37s.campfirenow.com/users/#{user_id}.json"
25
+ url = "https://#{subdomain}.campfirenow.com/users/#{user_id}.json"
26
26
  http = EventMachine::HttpRequest.new(url).get(:head => {'authorization' => [api_key, 'X'], "Content-Type" => "application/json"})
27
- puts http.inspect
27
+ logger.debug http.inspect
28
28
  http.callback do
29
- STDERR.puts "Got the data for #{user_id}"
29
+ logger.debug "Got the data for #{user_id}"
30
30
  update_user_cache_with(user_id, Yajl::Parser.parse(http.response)['user'])
31
31
  end
32
32
  http.errback do
33
- STDERR.puts "Couldn't fetch user data for #{user_id} with url #{url}"
34
- STDERR.puts http.response_header.status
35
- STDERR.puts http.response_header.inspect
36
- STDERR.puts http.response.inspect
33
+ logger.error "Couldn't fetch user data for #{user_id} with url #{url}\n#{http.response_header.status.inspect}\n#{http.response_header.inspect}\n#{http.response.inspect}"
37
34
  end
38
35
  end
39
36
 
40
37
  def update_user_cache_with(user_id, data)
41
- STDERR.puts "Updated user cache for #{data['name']}"
38
+ logger.debug "Updated user cache for #{data['name']}"
42
39
  user_cache[user_id] = data
43
40
  end
44
41
  end
data/lib/scamp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Scamp
2
- VERSION = "0.0.1"
1
+ class Scamp
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/scamp.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'eventmachine'
2
2
  require 'em-http-request'
3
3
  require 'yajl'
4
+ require "logger"
4
5
 
5
6
  require "scamp/version"
6
7
  require 'scamp/connection'
@@ -13,15 +14,23 @@ class Scamp
13
14
  include Connection
14
15
  include Channels
15
16
  include Users
16
-
17
- attr_accessor :channels, :user_cache, :channel_cache
18
- attr :matchers, :api_key
17
+
18
+ attr_accessor :channels, :user_cache, :channel_cache, :matchers, :api_key, :subdomain, :logger, :verbose, :first_match_only
19
19
 
20
20
  def initialize(options = {})
21
21
  options ||= {}
22
22
  raise ArgumentError, "You must pass an API key" unless options[:api_key]
23
-
24
- @api_key = options[:api_key]
23
+ raise ArgumentError, "You must pass a subdomain" unless options[:subdomain]
24
+
25
+ options.each do |k,v|
26
+ s = "#{k}="
27
+ if respond_to?(s)
28
+ send(s, v)
29
+ else
30
+ logger.warn "Scamp initialized with #{k.inspect} => #{v.inspect} but NO UNDERSTAND!"
31
+ end
32
+ end
33
+
25
34
  @channels = {}
26
35
  @user_cache = {}
27
36
  @channel_cache = {}
@@ -33,19 +42,43 @@ class Scamp
33
42
  end
34
43
 
35
44
  def connect!(channel_list)
45
+ logger.info "Starting up"
36
46
  connect(api_key, channel_list)
37
47
  end
38
48
 
49
+ def command_list
50
+ matchers.map{|m| [m.trigger, m.conditions] }
51
+ end
52
+
53
+ def logger
54
+ unless @logger
55
+ @logger = Logger.new(STDOUT)
56
+ @logger.level = (verbose ? Logger::DEBUG : Logger::INFO)
57
+ end
58
+ @logger
59
+ end
60
+
61
+ def verbose
62
+ @verbose = false if @verbose == nil
63
+ @verbose
64
+ end
65
+
66
+ def first_match_only
67
+ @first_match_only = false if @first_match_only == nil
68
+ @first_match_only
69
+ end
70
+
39
71
  private
40
-
72
+
41
73
  def match trigger, params={}, &block
42
74
  params ||= {}
43
75
  matchers << Matcher.new(self, {:trigger => trigger, :action => block, :conditions => params[:conditions]})
44
76
  end
45
77
 
46
78
  def process_message(msg)
79
+ logger.debug "Received message #{msg.inspect}"
47
80
  matchers.each do |matcher|
48
- matcher.attempt(msg)
81
+ break if first_match_only & matcher.attempt(msg)
49
82
  end
50
83
  end
51
84
  end
data/scamp.gemspec CHANGED
@@ -19,4 +19,6 @@ Gem::Specification.new do |s|
19
19
  s.add_dependency('eventmachine', '~> 0.12.10')
20
20
  s.add_dependency('yajl-ruby', '~> 0.8.3')
21
21
  s.add_dependency('em-http-request', '~> 0.3.0')
22
+
23
+ s.add_development_dependency "rspec", "~> 2.6.0"
22
24
  end
@@ -0,0 +1,112 @@
1
+ require "spec_helper"
2
+
3
+ describe Scamp do
4
+ before do
5
+ @valid_params = {:api_key => "6124d98749365e3db2c9e5b27ca04db6", :subdomain => "oxygen"}
6
+ end
7
+
8
+ describe "#initialize" do
9
+ it "should work with valid params" do
10
+ a(Scamp).should be_a(Scamp)
11
+ end
12
+ it "should warn if given an option it doesn't know" do
13
+ mock_logger
14
+
15
+ a(Scamp, :fred => "estaire").should be_a(Scamp)
16
+
17
+ logger_output.should =~ /WARN.*Scamp initialized with :fred => "estaire" but NO UNDERSTAND!/
18
+ end
19
+ end
20
+
21
+ describe "#verbose" do
22
+ it "should default to false" do
23
+ a(Scamp).verbose.should be_false
24
+ end
25
+ it "should be overridable at initialization" do
26
+ a(Scamp, :verbose => true).verbose.should be_true
27
+ end
28
+ end
29
+
30
+ describe "#logger" do
31
+ context "default logger" do
32
+ before { @bot = a Scamp }
33
+ it { @bot.logger.should be_a(Logger) }
34
+ it { @bot.logger.level.should be == Logger::INFO }
35
+ end
36
+ context "default logger in verbose mode" do
37
+ before { @bot = a Scamp, :verbose => true }
38
+ it { @bot.logger.level.should be == Logger::DEBUG }
39
+ end
40
+ context "overriding default" do
41
+ before do
42
+ @custom_logger = Logger.new("/dev/null")
43
+ @bot = a Scamp, :logger => @custom_logger
44
+ end
45
+ it { @bot.logger.should be == @custom_logger }
46
+ end
47
+ end
48
+
49
+ describe "#first_match_only" do
50
+ it "should default to false" do
51
+ a(Scamp).first_match_only.should be_false
52
+ end
53
+ it "should be settable" do
54
+ a(Scamp, :first_match_only => true).first_match_only.should be_true
55
+ end
56
+ end
57
+
58
+ describe "private methods" do
59
+
60
+ describe "#process_message" do
61
+ before do
62
+ @bot = a Scamp
63
+ $attempts = 0 # Yes, I hate it too. Works though.
64
+ @message = {:body => "my message here"}
65
+
66
+ @bot.behaviour do
67
+ 2.times { match(/.*/) { $attempts += 1 } }
68
+ end
69
+ end
70
+ after { $attempts = nil }
71
+ context "with first_match_only not set" do
72
+ before { @bot.first_match_only.should be_false }
73
+ it "should process all matchers which attempt the message" do
74
+ @bot.send(:process_message, @message)
75
+ $attempts.should be == 2
76
+ end
77
+ end
78
+ context "with first_match_only set" do
79
+ before do
80
+ @bot.first_match_only = true
81
+ @bot.first_match_only.should be_true
82
+ end
83
+ it "should only process the first matcher which attempts the message" do
84
+ @bot.send(:process_message, @message)
85
+ $attempts.should be == 1
86
+ end
87
+ end
88
+ end
89
+
90
+
91
+ end
92
+
93
+ def a klass, params={}
94
+ params ||= {}
95
+ params = @valid_params.merge(params) if klass == Scamp
96
+ klass.new(params)
97
+ end
98
+
99
+ # Urg
100
+ def mock_logger
101
+ @logger_string = StringIO.new
102
+ @fake_logger = Logger.new(@logger_string)
103
+ Scamp.any_instance.should_receive(:logger).and_return(@fake_logger)
104
+ end
105
+
106
+ # Bleurgh
107
+ def logger_output
108
+ str = @logger_string.dup
109
+ str.rewind
110
+ str.read
111
+ end
112
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path("../lib/scamp", File.dirname(__FILE__))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scamp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-12 00:00:00.000000000 +01:00
13
- default_executable:
12
+ date: 2011-09-17 00:00:00.000000000Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: eventmachine
17
- requirement: &2165823060 !ruby/object:Gem::Requirement
16
+ requirement: &70244078916620 !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ~>
@@ -22,10 +21,10 @@ dependencies:
22
21
  version: 0.12.10
23
22
  type: :runtime
24
23
  prerelease: false
25
- version_requirements: *2165823060
24
+ version_requirements: *70244078916620
26
25
  - !ruby/object:Gem::Dependency
27
26
  name: yajl-ruby
28
- requirement: &2165822560 !ruby/object:Gem::Requirement
27
+ requirement: &70244078916120 !ruby/object:Gem::Requirement
29
28
  none: false
30
29
  requirements:
31
30
  - - ~>
@@ -33,10 +32,10 @@ dependencies:
33
32
  version: 0.8.3
34
33
  type: :runtime
35
34
  prerelease: false
36
- version_requirements: *2165822560
35
+ version_requirements: *70244078916120
37
36
  - !ruby/object:Gem::Dependency
38
37
  name: em-http-request
39
- requirement: &2165822100 !ruby/object:Gem::Requirement
38
+ requirement: &70244078915660 !ruby/object:Gem::Requirement
40
39
  none: false
41
40
  requirements:
42
41
  - - ~>
@@ -44,7 +43,18 @@ dependencies:
44
43
  version: 0.3.0
45
44
  type: :runtime
46
45
  prerelease: false
47
- version_requirements: *2165822100
46
+ version_requirements: *70244078915660
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &70244078915200 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.6.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70244078915200
48
58
  description: Eventmachine based Campfire bot framework
49
59
  email:
50
60
  - will@willj.net
@@ -53,6 +63,7 @@ extensions: []
53
63
  extra_rdoc_files: []
54
64
  files:
55
65
  - .gitignore
66
+ - .rspec
56
67
  - Gemfile
57
68
  - README.md
58
69
  - Rakefile
@@ -65,7 +76,8 @@ files:
65
76
  - lib/scamp/users.rb
66
77
  - lib/scamp/version.rb
67
78
  - scamp.gemspec
68
- has_rdoc: true
79
+ - spec/lib/scamp_spec.rb
80
+ - spec/spec_helper.rb
69
81
  homepage: ''
70
82
  licenses: []
71
83
  post_install_message:
@@ -86,8 +98,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
98
  version: '0'
87
99
  requirements: []
88
100
  rubyforge_project:
89
- rubygems_version: 1.6.2
101
+ rubygems_version: 1.8.10
90
102
  signing_key:
91
103
  specification_version: 3
92
104
  summary: Eventmachine based Campfire bot framework
93
- test_files: []
105
+ test_files:
106
+ - spec/lib/scamp_spec.rb
107
+ - spec/spec_helper.rb