em-campfire 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ em-campfire (0.0.1)
5
+ em-http-request (~> 1.0.0.beta.4)
6
+ eventmachine (~> 1.0.0.beta.4)
7
+ yajl-ruby (~> 0.8.3)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ addressable (2.2.6)
13
+ cookiejar (0.3.0)
14
+ crack (0.3.1)
15
+ diff-lcs (1.1.3)
16
+ em-http-request (1.0.1)
17
+ addressable (>= 2.2.3)
18
+ cookiejar
19
+ em-socksify
20
+ eventmachine (>= 1.0.0.beta.4)
21
+ http_parser.rb (>= 0.5.3)
22
+ em-socksify (0.1.0)
23
+ eventmachine
24
+ eventmachine (1.0.0.beta.4)
25
+ http_parser.rb (0.5.3)
26
+ metaclass (0.0.1)
27
+ mocha (0.10.0)
28
+ metaclass (~> 0.0.1)
29
+ rake (0.9.2.2)
30
+ rspec (2.6.0)
31
+ rspec-core (~> 2.6.0)
32
+ rspec-expectations (~> 2.6.0)
33
+ rspec-mocks (~> 2.6.0)
34
+ rspec-core (2.6.4)
35
+ rspec-expectations (2.6.0)
36
+ diff-lcs (~> 1.1.2)
37
+ rspec-mocks (2.6.0)
38
+ webmock (1.7.10)
39
+ addressable (~> 2.2, > 2.2.5)
40
+ crack (>= 0.1.7)
41
+ yajl-ruby (0.8.3)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ em-campfire!
48
+ mocha (~> 0.10.0)
49
+ rake (~> 0.9.2)
50
+ rspec (~> 2.6.0)
51
+ webmock (~> 1.7.6)
data/LICENSE.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2011 by Will Jessop
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,6 @@
1
+
2
+ This isn't ready for production use yet, so don't use it!
3
+
4
+ ## Example
5
+
6
+ See examples/simple.rb
data/Rakefile ADDED
@@ -0,0 +1,13 @@
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
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "em-campfire/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "em-campfire"
7
+ s.version = EventMachine::Campfire::VERSION
8
+ s.authors = ["Will Jessop"]
9
+ s.email = ["will@willj.net"]
10
+ s.homepage = "https://github.com/wjessop/em-campfire"
11
+ s.summary = %q{Eventmachine campfire API lib}
12
+ s.description = %q{Eventmachine campfire API lib}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency('eventmachine', '~> 1.0.0.beta.4')
20
+ s.add_dependency('yajl-ruby', '~> 0.8.3')
21
+ s.add_dependency('em-http-request', '~> 1.0.0.beta.4')
22
+
23
+ s.add_development_dependency "rake", "~> 0.9.2"
24
+ s.add_development_dependency "rspec", "~> 2.6.0"
25
+ s.add_development_dependency "mocha", "~> 0.10.0"
26
+ s.add_development_dependency "webmock", "~> 1.7.6"
27
+ end
@@ -0,0 +1,19 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '../lib')
2
+
3
+ require 'em-campfire'
4
+
5
+ EM.run {
6
+ connection = EM::Campfire.new(:subdomain => "foo", :api_key => "foo")
7
+ connection.join 293788 # Robot Army
8
+ connection.join 401839 # Monitoring
9
+
10
+ connection.on_message do |msg|
11
+ puts msg.inspect
12
+ end
13
+
14
+ # Give lib a chance to connect
15
+ EM::Timer.new(10) do
16
+ # Say something on a specific channel
17
+ connection.say "foofoofoo", "Robot Army"
18
+ end
19
+ }
@@ -0,0 +1,28 @@
1
+ module EventMachine
2
+ class Campfire
3
+ module Connection
4
+
5
+ attr_accessor :ignore_self
6
+
7
+ def on_message &blk
8
+ @on_message_block = blk
9
+ end
10
+
11
+ private
12
+
13
+ attr_accessor :on_message_block
14
+
15
+ def process_message(msg)
16
+ logger.debug "Received message #{msg.inspect}"
17
+ return false if ignore_self && is_me?(msg[:user_id])
18
+ if on_message_block
19
+ logger.debug "on_message callback exists, calling it #{msg.inspect}"
20
+ on_message_block.call(msg)
21
+ else
22
+ logger.debug "on_message callback does not exist"
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ module EventMachine
2
+ class Campfire
3
+ module Messages
4
+ def say(message, room_id_or_name)
5
+ send_message(room_id_or_name, message, "Textmessage")
6
+ end
7
+
8
+ def paste(message, room_id_or_name)
9
+ send_message(room_id_or_name, message, "PasteMessage")
10
+ end
11
+
12
+ def play(sound, room_id_or_name)
13
+ send_message(room_id_or_name, sound, "SoundMessage")
14
+ end
15
+
16
+ private
17
+
18
+ # curl -vvv -H 'Content-Type: application/json' -d '{"message":{"body":"Yeeeeeaaaaaahh", "type":"Textmessage"}}' -u API_KEY:X https://something.campfirenow.com/room/2345678/speak.json
19
+ def send_message(room_id_or_name, payload, type)
20
+ if room_cache.size < 1
21
+ logger.error "Couldn't post message \"#{payload}\" to room #{room_id_or_name} as no rooms have been joined"
22
+ return
23
+ end
24
+
25
+ room_id = room_id(room_id_or_name)
26
+ url = "https://#{subdomain}.campfirenow.com/room/#{room_id}/speak.json"
27
+ http = EventMachine::HttpRequest.new(url).post :head => {'Content-Type' => 'application/json', 'authorization' => [api_key, 'X']}, :body => Yajl::Encoder.encode({:message => {:body => payload, :type => type}})
28
+ http.errback { logger.error "Couldn't connect to #{url} to post message \"#{payload}\" to room #{room_id}" }
29
+ http.callback {
30
+ if [200,201].include? http.response_header.status
31
+ logger.debug "Posted #{type} \"#{payload}\" to room #{room_id}"
32
+ else
33
+ logger.error "Couldn't post message \"#{payload}\" to room #{room_id} using url #{url}, http response from the API was #{http.response_header.status}"
34
+ end
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,122 @@
1
+ module EventMachine
2
+ class Campfire
3
+ module Rooms
4
+
5
+ # attr_accessor :rooms
6
+ attr_accessor :room_cache
7
+
8
+ def join(room, &blk)
9
+ id = room_id(room)
10
+ # logger.info "Joining room #{id}"
11
+ if id
12
+ url = "https://#{subdomain}.campfirenow.com/room/#{id}/join.json"
13
+ http = EventMachine::HttpRequest.new(url).post :head => {'Content-Type' => 'application/json', 'authorization' => [api_key, 'X']}
14
+ http.errback { logger.error "Error joining room: #{id}" }
15
+ http.callback {
16
+ if http.response_header.status == 200
17
+ logger.info "Joined room #{id} successfully"
18
+ # fetch_room_data(id)
19
+ stream(id)
20
+ else
21
+ logger.error "Error joining room: #{id}"
22
+ end
23
+ }
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ attr_accessor :populating_room_list
30
+
31
+ def stream(room_id)
32
+ json_parser = Yajl::Parser.new :symbolize_keys => true
33
+ json_parser.on_parse_complete = method(:process_message)
34
+
35
+ url = "https://streaming.campfirenow.com/room/#{room_id}/live.json"
36
+ # Timeout per https://github.com/igrigorik/em-http-request/wiki/Redirects-and-Timeouts
37
+ http = EventMachine::HttpRequest.new(url, :connect_timeout => 20, :inactivity_timeout => 0).get :head => {'authorization' => [api_key, 'X']}
38
+ http.errback { logger.error "Couldn't stream room #{room_id} at url #{url}" }
39
+ http.callback { logger.info "Disconnected from #{url}"; join(room_id) if rooms[room_id] }
40
+ http.stream {|chunk| json_parser << chunk }
41
+ end
42
+
43
+
44
+ def room_id(room_id_or_name)
45
+ if room_id_or_name.is_a? Integer
46
+ return room_id_or_name
47
+ else
48
+ return room_id_from_room_name(room_id_or_name)
49
+ end
50
+ end
51
+
52
+ def room_id_from_room_name(room_name)
53
+ logger.debug "Looking for room id for #{room_name}"
54
+
55
+ if room_cache.has_key? room_name
56
+ return room_cache[room_name]["id"]
57
+ else
58
+ logger.warn "Attempted to join #{room_name} but could not find an ID for it"
59
+ return false
60
+ end
61
+ end
62
+
63
+ # curl -vvv -H 'Content-Type: application/json' -u API_KEY:X https://something.campfirenow.com/rooms.json
64
+ def populate_room_list
65
+ url = "https://#{subdomain}.campfirenow.com/rooms.json"
66
+ http = EventMachine::HttpRequest.new(url).get :head => {'authorization' => [api_key, 'X']}
67
+ http.errback { logger.error "Couldn't connect to url #{url} to fetch room list"; puts http.inspect }
68
+ http.callback {
69
+ if http.response_header.status == 200
70
+ logger.debug "Fetched room list"
71
+ new_rooms = {}
72
+ Yajl::Parser.parse(http.response)['rooms'].each do |c|
73
+ new_rooms[c["name"]] = c
74
+ end
75
+ @room_cache = new_rooms # replace existing room list
76
+ else
77
+ logger.error "Couldn't fetch room list with url #{url}, http response from API was #{http.response_header.status}"
78
+ end
79
+ }
80
+ end
81
+
82
+ # def fetch_room_data(room_id)
83
+ # url = "https://#{subdomain}.campfirenow.com/room/#{room_id}.json"
84
+ # http = EventMachine::HttpRequest.new(url).get :head => {'authorization' => [api_key, 'X']}
85
+ # http.errback { logger.error "Couldn't connect to #{url} to fetch room data for room #{room_id}" }
86
+ # http.callback {
87
+ # if http.response_header.status == 200
88
+ # logger.debug "Fetched room data for #{room_id}"
89
+ # room = Yajl::Parser.parse(http.response)['room']
90
+ # room_cache[room["id"]] = room
91
+ #
92
+ # room['users'].each do |u|
93
+ # update_user_cache_with(u["id"], u)
94
+ # end
95
+ # else
96
+ # logger.error "Couldn't fetch room data for room #{room_id} with url #{url}, http response from API was #{http.response_header.status}"
97
+ # end
98
+ # }
99
+ # end
100
+
101
+ def fetch_room_data(room_id)
102
+ url = "https://#{subdomain}.campfirenow.com/room/#{room_id}.json"
103
+ http = EventMachine::HttpRequest.new(url).get :head => {'authorization' => [api_key, 'X']}
104
+ http.errback { logger.error "Couldn't connect to #{url} to fetch room data for room #{room_id}" }
105
+ http.callback {
106
+ if http.response_header.status == 200
107
+ logger.debug "Fetched room data for #{room_id}"
108
+ room = Yajl::Parser.parse(http.response)['room']
109
+ room_cache[room["id"]] = room
110
+
111
+ room['users'].each do |u|
112
+ update_user_cache_with(u["id"], u)
113
+ end
114
+ else
115
+ logger.error "Couldn't fetch room data for room #{room_id} with url #{url}, http response from API was #{http.response_header.status}"
116
+ end
117
+ }
118
+ end
119
+
120
+ end # Rooms
121
+ end # Campfire
122
+ end # EventMachine
@@ -0,0 +1,56 @@
1
+ module EventMachine
2
+ class Campfire
3
+ module Users
4
+
5
+ # attr_accessor :user_cache
6
+
7
+ private
8
+
9
+ # Return the user_id if we haven't got the real name and
10
+ # kick off a user data fetch
11
+ def username_for(user_id)
12
+ # if cached_user?(user_id)
13
+ # user_cache[user_id]["name"]
14
+ # else
15
+ fetch_data_for(user_id)
16
+ # user_id.to_s
17
+ # end
18
+ end
19
+
20
+ # def is_me?(user_id)
21
+ # if user_cache['me']
22
+ # user_cache['me']['id'] == user_id
23
+ # else
24
+ # fetch_data_for('me')
25
+ # false
26
+ # end
27
+ # end
28
+ #
29
+ # def cached_user? user_id
30
+ # user_cache[user_id] != nil
31
+ # end
32
+
33
+ def fetch_data_for(user_id)
34
+ return unless user_id
35
+ url = "https://#{subdomain}.campfirenow.com/users/#{user_id}.json"
36
+ http = EventMachine::HttpRequest.new(url).get(:head => {'authorization' => [api_key, 'X'], "Content-Type" => "application/json"})
37
+ http.callback do
38
+ if http.response_header.status == 200
39
+ logger.debug "Got the data for #{user_id}"
40
+ update_user_cache_with(user_id, Yajl::Parser.parse(http.response)['user'])
41
+ else
42
+ logger.error "Couldn't fetch user data for user #{user_id} with url #{url}, http response from API was #{http.response_header.status}"
43
+ end
44
+ end
45
+ http.errback do
46
+ logger.error "Couldn't connect to #{url} to fetch user data for user #{user_id}"
47
+ end
48
+ end
49
+
50
+ # def update_user_cache_with(user_id, data)
51
+ # logger.debug "Updated user cache for #{data['name']}"
52
+ # user_cache[user_id] = data
53
+ # end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,5 @@
1
+ module EventMachine
2
+ class Campfire
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,57 @@
1
+ require 'eventmachine'
2
+ require 'em-http-request'
3
+ require 'yajl'
4
+ require "logger"
5
+
6
+ require "em-campfire/version"
7
+ require "em-campfire/connection"
8
+ require "em-campfire/rooms"
9
+ require "em-campfire/users"
10
+ require "em-campfire/messages"
11
+
12
+ module EventMachine
13
+ class Campfire
14
+ attr_accessor :logger, :verbose, :subdomain, :api_key
15
+
16
+ include Connection
17
+ include Rooms
18
+ include Users
19
+ include Messages
20
+
21
+ def initialize(options = {})
22
+ raise ArgumentError, "You must pass an API key" unless 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 "em-campfire initialized with #{k.inspect} => #{v.inspect} but NO UNDERSTAND!"
31
+ end
32
+ end
33
+
34
+ # @rooms = {}
35
+ # @user_cache = {}
36
+ @room_cache = {}
37
+
38
+ populate_room_list
39
+
40
+ # # populate bot data separately, in case we are ignoring ourselves
41
+ # fetch_data_for('me')
42
+ end
43
+
44
+ def logger
45
+ unless @logger
46
+ @logger = Logger.new(STDOUT)
47
+ @logger.level = (verbose ? Logger::DEBUG : Logger::INFO)
48
+ end
49
+ @logger
50
+ end
51
+
52
+ def verbose=(is_verbose)
53
+ @verbose = is_verbose
54
+ logger.level = Logger::DEBUG if is_verbose
55
+ end
56
+ end # Campfire
57
+ end # EventMachine
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ describe EventMachine::Campfire::Connection do
4
+
5
+ context "#on_message" do
6
+ before :each do
7
+ EM.run_block { @adaptor = a EM::Campfire }
8
+ end
9
+
10
+ it "run a block when it receives a message"
11
+ end
12
+ end
@@ -0,0 +1,253 @@
1
+ require "spec_helper"
2
+
3
+ describe EventMachine::Campfire do
4
+
5
+ before :each do
6
+ stub_rooms_data_request
7
+ end
8
+
9
+ describe "#initialize" do
10
+ it "should work with valid params" do
11
+ EM.run_block { a(EM::Campfire).should be_a(EM::Campfire) }
12
+ end
13
+
14
+ it "should warn if given an option it doesn't know" do
15
+ mock_logger
16
+ EM.run_block { a(EM::Campfire, :fred => "estaire").should be_a(EM::Campfire) }
17
+ logger_output.should =~ /WARN.*em-campfire initialized with :fred => "estaire" but NO UNDERSTAND!/
18
+ end
19
+
20
+ it "should require essential parameters" do
21
+ lambda { EM::Campfire.new }.should raise_error(ArgumentError, "You must pass an API key")
22
+ lambda { EM::Campfire.new(:api_key => "foo") }.should raise_error(ArgumentError, "You must pass a subdomain")
23
+ end
24
+ end
25
+
26
+ describe "#verbose" do
27
+ it "should default to false" do
28
+ EM.run_block { a(EM::Campfire).verbose.should be_false }
29
+ end
30
+
31
+ it "should be overridable at initialization" do
32
+ EM.run_block { a(EM::Campfire, :verbose => true).verbose.should be_true }
33
+ end
34
+ end
35
+
36
+ describe "#logger" do
37
+ context "default logger" do
38
+ before { EM.run_block { @adaptor = a EM::Campfire } }
39
+
40
+ it { @adaptor.logger.should be_a(Logger) }
41
+ it { @adaptor.logger.level.should be == Logger::INFO }
42
+ end
43
+
44
+ context "default logger in verbose mode" do
45
+ before { EM.run_block { @adaptor = a EM::Campfire, :verbose => true } }
46
+
47
+ it { @adaptor.logger.level.should be == Logger::DEBUG }
48
+ end
49
+
50
+ context "overriding default" do
51
+ before do
52
+ @custom_logger = Logger.new("/dev/null")
53
+ EM.run_block { @adaptor = a EM::Campfire, :logger => @custom_logger }
54
+ end
55
+
56
+ it { @adaptor.logger.should be == @custom_logger }
57
+ end
58
+
59
+
60
+
61
+ #
62
+ # it "should handle HTTP errors fetching individual room data" do
63
+ # mock_logger
64
+ # bot = a Scamp
65
+ #
66
+ # EM.run_block {
67
+ # stub_request(:post, @message_post_url).
68
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type' => 'application/json'}).
69
+ # to_return(:status => 502, :body => "", :headers => {'Content-Type'=>'text/html'})
70
+ # lambda {bot.send(:send_message, 123, "Hi", "Textmessage")}.should_not raise_error
71
+ # }
72
+ # logger_output.should =~ /ERROR.*Couldn't post message "Hi" to room 123 using url #{@message_post_url}, http response from the API was 502/
73
+ # end
74
+ #
75
+ # it "should handle network errors fetching individual room data" do
76
+ # mock_logger
77
+ # bot = a Scamp
78
+ #
79
+ # EM.run_block {
80
+ # stub_request(:post, @message_post_url).
81
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type' => 'application/json'}).to_timeout
82
+ # lambda {bot.send(:send_message, 123, "Hi", "Textmessage")}.should_not raise_error
83
+ # }
84
+ # logger_output.should =~ /ERROR.*Couldn't connect to #{@message_post_url} to post message "Hi" to room 123/
85
+ # end
86
+ #
87
+
88
+
89
+
90
+ # context "user operations" do
91
+ # it "should fetch user data" do
92
+ # adaptor = a EM::Campfire
93
+ #
94
+ # EM.run_block {
95
+ # stub_request(:get, "https://#{valid_params[:subdomain]}.campfirenow.com/users/123.json").
96
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type'=>'application/json'}).
97
+ # to_return(:status => 200, :body => Yajl::Encoder.encode(:user => valid_user_cache_data[123]), :headers => {})
98
+ # adaptor.send(:username_for, 123)
99
+ # stub.should have_been_requested
100
+ # }
101
+ # end
102
+
103
+ # it "should handle HTTP errors fetching user data" do
104
+ # mock_logger
105
+ # bot = a EM::Campfire
106
+ #
107
+ # url = "https://#{valid_params[:subdomain]}.campfirenow.com/users/123.json"
108
+ # EM.run_block {
109
+ # stub_request(:get, url).
110
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type'=>'application/json'}).
111
+ # to_return(:status => 502, :body => "", :headers => {'Content-Type'=>'text/html'})
112
+ # lambda {bot.username_for(123)}.should_not raise_error
113
+ # }
114
+ # logger_output.should =~ /ERROR.*Couldn't fetch user data for user 123 with url #{url}, http response from API was 502/
115
+ # end
116
+ #
117
+ # it "should handle network errors fetching user data" do
118
+ # mock_logger
119
+ # bot = a EM::Campfire
120
+ #
121
+ # url = "https://#{valid_params[:subdomain]}.campfirenow.com/users/123.json"
122
+ # EM.run_block {
123
+ # stub_request(:get, url).
124
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type'=>'application/json'}).to_timeout
125
+ # lambda {bot.username_for(123)}.should_not raise_error
126
+ # }
127
+ # logger_output.should =~ /ERROR.*Couldn't connect to #{url} to fetch user data for user 123/
128
+ # end
129
+ end
130
+
131
+ context "room operations" do
132
+ before do
133
+ @room_list_url = "https://#{valid_params[:subdomain]}.campfirenow.com/rooms.json"
134
+ @me_list_url = "https://#{valid_params[:subdomain]}.campfirenow.com/users/me.json"
135
+ @room_url = "https://#{valid_params[:subdomain]}.campfirenow.com/room/123.json"
136
+ @stream_url = "https://streaming.campfirenow.com/room/123/live.json"
137
+ end
138
+
139
+ # it "should fetch a room list" do
140
+ # mock_logger
141
+ # bot = a EM::Campfire
142
+ #
143
+ # EM.run_block {
144
+ # stub_request(:get, @room_list_url).
145
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X']}).
146
+ # to_return(:status => 200, :body => Yajl::Encoder.encode(:rooms => valid_room_cache_data.values), :headers => {})
147
+ # bot.send(:populate_room_list)
148
+ # stub.should have_been_requested
149
+ # }
150
+ # logger_output.should =~ /DEBUG.*Fetched room list/
151
+ # end
152
+
153
+ # it "should invoke the post connection callback" do
154
+ # mock_logger
155
+ # bot = a EM::Campfire
156
+ #
157
+ # invoked_cb = false
158
+ #
159
+ # EM.run_block {
160
+ # stub_request(:get, @room_list_url).
161
+ # with(:headers => {
162
+ # 'Authorization'=>[valid_params[:api_key], 'X'],
163
+ # 'Content-Type' => 'application/json'
164
+ # }).
165
+ # to_return(:status => 200, :body => Yajl::Encoder.encode(:rooms => valid_room_cache_data.values), :headers => {})
166
+ #
167
+ # stub_request(:get, @room_list_url).
168
+ # with(:headers => {
169
+ # 'Authorization'=>[valid_params[:api_key], 'X']
170
+ # }).
171
+ # to_return(:status => 200, :body => Yajl::Encoder.encode(:rooms => valid_room_cache_data.values), :headers => {})
172
+ #
173
+ # # Disable fetch_data_for, not important to this test.
174
+ # EM::Campfire.any_instance.expects(:fetch_data_for).returns(nil)
175
+ #
176
+ # bot.send(:connect!, [valid_room_cache_data.keys.first]) do
177
+ # invoked_cb = true
178
+ # end
179
+ # }
180
+ # invoked_cb.should be_true
181
+ # end
182
+ #
183
+ # it "should handle HTTP errors fetching the room list" do
184
+ # mock_logger
185
+ # bot = a EM::Campfire
186
+ #
187
+ # EM.run_block {
188
+ # # stub_request(:get, url).
189
+ # # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type'=>'application/json'}).
190
+ # # to_return(:status => 502, :body => "", :headers => {'Content-Type'=>'text/html'})
191
+ # stub_request(:get, @room_list_url).
192
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X']}).
193
+ # to_return(:status => 502, :body => "", :headers => {'Content-Type'=>'text/html'})
194
+ # lambda {bot.send(:populate_room_list)}.should_not raise_error
195
+ # }
196
+ # logger_output.should =~ /ERROR.*Couldn't fetch room list with url #{@room_list_url}, http response from API was 502/
197
+ # end
198
+ #
199
+ # it "should handle network errors fetching the room list" do
200
+ # mock_logger
201
+ # bot = a EM::Campfire
202
+ # EM.run_block {
203
+ # stub_request(:get, @room_list_url).
204
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X']}).to_timeout
205
+ # lambda {bot.send(:populate_room_list)}.should_not raise_error
206
+ # }
207
+ # logger_output.should =~ /ERROR.*Couldn't connect to url #{@room_list_url} to fetch room list/
208
+ # end
209
+ #
210
+ # it "should fetch individual room data" do
211
+ # mock_logger
212
+ # bot = a EM::Campfire
213
+ #
214
+ # EM.run_block {
215
+ # stub_request(:get, @room_url).
216
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X']}).
217
+ # to_return(:status => 200, :body => Yajl::Encoder.encode(:room => valid_room_cache_data[123]), :headers => {})
218
+ # bot.room_name_for(123)
219
+ # }
220
+ # logger_output.should =~ /DEBUG.*Fetched room data for 123/
221
+ # end
222
+ #
223
+ # it "should handle HTTP errors fetching individual room data" do
224
+ # mock_logger
225
+ # bot = a EM::Campfire
226
+ #
227
+ # EM.run_block {
228
+ # stub_request(:get, @room_url).
229
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X']}).
230
+ # to_return(:status => 502, :body => "", :headers => {'Content-Type'=>'text/html'})
231
+ # lambda {bot.room_name_for(123)}.should_not raise_error
232
+ # }
233
+ # logger_output.should =~ /ERROR.*Couldn't fetch room data for room 123 with url #{@room_url}, http response from API was 502/
234
+ # end
235
+ #
236
+ # it "should handle network errors fetching individual room data" do
237
+ # mock_logger
238
+ # bot = a EM::Campfire
239
+ #
240
+ # EM.run_block {
241
+ # stub_request(:get, @room_url).
242
+ # with(:headers => {'Authorization'=>[valid_params[:api_key], 'X']}).to_timeout
243
+ # lambda {bot.room_name_for(123)}.should_not raise_error
244
+ # }
245
+ # logger_output.should =~ /ERROR.*Couldn't connect to #{@room_url} to fetch room data for room 123/
246
+ # end
247
+ #
248
+ # it "should stream a room"
249
+ # it "should handle HTTP errors streaming a room"
250
+ # it "should handle network errors streaming a room"
251
+ end
252
+ end
253
+
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ describe EventMachine::Campfire::Messages do
4
+
5
+ before :each do
6
+ stub_rooms_data_request
7
+ stub_join_room_request(123)
8
+ stub_stream_room_request(123)
9
+ EM.run_block { @adaptor = a(EM::Campfire) }
10
+ end
11
+
12
+ it "should say a message" do
13
+ mock_logger
14
+ stub = stub_message_post_request
15
+
16
+ EM.run_block {
17
+ @adaptor.join 123
18
+ @adaptor.say "Hi", 123
19
+ }
20
+ stub.should have_been_requested
21
+ logger_output.should =~ /DEBUG.*Posted Textmessage "Hi" to room 123/
22
+ end
23
+
24
+ it "should paste a message" do
25
+ mock_logger
26
+ stub = stub_message_post_request
27
+
28
+ EM.run_block {
29
+ @adaptor.join 123
30
+ @adaptor.paste "Hi", 123
31
+ }
32
+ stub.should have_been_requested
33
+ logger_output.should =~ /DEBUG.*Posted PasteMessage "Hi" to room 123/
34
+ end
35
+
36
+ it "should play a sound" do
37
+ mock_logger
38
+ stub = stub_message_post_request
39
+
40
+ EM.run_block {
41
+ @adaptor.join 123
42
+ @adaptor.play "nyan", 123
43
+ }
44
+ stub.should have_been_requested
45
+ logger_output.should =~ /DEBUG.*Posted SoundMessage "nyan" to room 123/
46
+ end
47
+ end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ describe EventMachine::Campfire::Rooms do
4
+
5
+ before :each do
6
+ @message_post_url = "https://#{valid_params[:subdomain]}.campfirenow.com/room/123/speak.json"
7
+ stub_rooms_data_request
8
+ EM.run_block { @adaptor = a(EM::Campfire) }
9
+ end
10
+
11
+ context "#join" do
12
+ before :each do
13
+ EM.run_block { @adaptor = a EM::Campfire }
14
+ end
15
+
16
+ it "should allow joining by id" do
17
+ mock_logger
18
+
19
+ join_stub = stub_join_room_request(123)
20
+ stream_stub = stub_stream_room_request(123)
21
+ EM.run_block { @adaptor.join(123) }
22
+ logger_output.should =~ /INFO.*Joined room 123 successfully/
23
+ join_stub.should have_been_requested
24
+ end
25
+
26
+ it "should allow joining by name" do
27
+ join_stub = stub_join_room_request(123)
28
+ stream_stub = stub_stream_room_request(123)
29
+ EM.run_block { @adaptor.join("foo") }
30
+ join_stub.should have_been_requested
31
+ end
32
+
33
+ it "should not be able to join an invalid room" do
34
+ mock_logger
35
+ stream_stub = stub_stream_room_request(9999999999999999)
36
+ url = "https://#{valid_params[:subdomain]}.campfirenow.com/room/9999999999999999/join.json"
37
+ join_stub = stub_request(:post, url).
38
+ with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type'=>'application/json'}).
39
+ to_return(:status => 302, :body => "", :headers => {})
40
+
41
+ EM.run_block { @adaptor.join(9999999999999999) }
42
+ logger_output.should =~ /Error joining room: 9999999999999999/
43
+ join_stub.should have_been_requested
44
+ stream_stub.should_not have_been_requested
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,78 @@
1
+ require File.expand_path("../lib/em-campfire", File.dirname(__FILE__))
2
+
3
+ require 'mocha'
4
+ require 'webmock/rspec'
5
+
6
+ RSpec.configure do |config|
7
+ config.color_enabled = true
8
+ config.mock_framework = :mocha
9
+ end
10
+
11
+ def a klass, params={}
12
+ params ||= {}
13
+ params = valid_params.merge(params) if klass == EM::Campfire
14
+ klass.new(params)
15
+ end
16
+
17
+ # Urg
18
+ def mock_logger
19
+ @logger_string = StringIO.new
20
+ @fake_logger = Logger.new(@logger_string)
21
+ EM::Campfire.any_instance.expects(:logger).at_least(1).returns(@fake_logger)
22
+ end
23
+
24
+ # Bleurgh
25
+ def logger_output
26
+ str = @logger_string.dup
27
+ str.rewind
28
+ str.read
29
+ end
30
+
31
+ def valid_user_cache_data
32
+ {123 => {"name" => "foo"}, 456 => {"name" => "bar"}, 'me' => {"name" => "bot", "id" => 123}}
33
+ end
34
+
35
+ def valid_room_cache_data
36
+ {
37
+ 123 => {
38
+ "id" => 123,
39
+ "name" => "foo",
40
+ "users" => []
41
+ },
42
+ 456 => {
43
+ "id" => 456,
44
+ "name" => "bar",
45
+ "users" => []
46
+ }
47
+ }
48
+ end
49
+
50
+ def valid_params
51
+ {:api_key => "6124d98749365e3db2c9e5b27ca04db6", :subdomain => "oxygen"}
52
+ end
53
+
54
+ def stub_join_room_request(room)
55
+ url = "https://#{valid_params[:subdomain]}.campfirenow.com/room/#{room}/join.json"
56
+ stub_request(:post, url).
57
+ with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type'=>'application/json'}).
58
+ to_return(:status => 200, :body => "", :headers => {})
59
+ end
60
+
61
+ def stub_rooms_data_request
62
+ stub_request(:get, "https://#{valid_params[:subdomain]}.campfirenow.com/rooms.json").
63
+ with(:headers => {'Authorization'=>['6124d98749365e3db2c9e5b27ca04db6', 'X']}).
64
+ to_return(:status => 200, :body => Yajl::Encoder.encode(:rooms => valid_room_cache_data.values), :headers => {})
65
+ end
66
+
67
+ def stub_message_post_request
68
+ message_post_url = "https://#{valid_params[:subdomain]}.campfirenow.com/room/123/speak.json"
69
+ stub_request(:post, message_post_url).
70
+ with(:headers => {'Authorization'=>[valid_params[:api_key], 'X'], 'Content-Type' => 'application/json'}).
71
+ to_return(:status => 201, :body => "", :headers => {})
72
+ end
73
+
74
+ def stub_stream_room_request(room)
75
+ stub_request(:get, "https://streaming.campfirenow.com/room/#{room}/live.json").
76
+ with(:headers => {'Authorization'=>[valid_params[:api_key], 'X']}).
77
+ to_return(:status => 200, :body => "", :headers => {})
78
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: em-campfire
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Will Jessop
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: eventmachine
16
+ requirement: &70274674754820 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.0.beta.4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70274674754820
25
+ - !ruby/object:Gem::Dependency
26
+ name: yajl-ruby
27
+ requirement: &70274674754280 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.8.3
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70274674754280
36
+ - !ruby/object:Gem::Dependency
37
+ name: em-http-request
38
+ requirement: &70274674753780 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.0.beta.4
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70274674753780
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: &70274674753320 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.2
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70274674753320
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &70274674752720 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 2.6.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70274674752720
69
+ - !ruby/object:Gem::Dependency
70
+ name: mocha
71
+ requirement: &70274674751940 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 0.10.0
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70274674751940
80
+ - !ruby/object:Gem::Dependency
81
+ name: webmock
82
+ requirement: &70274674751460 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 1.7.6
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70274674751460
91
+ description: Eventmachine campfire API lib
92
+ email:
93
+ - will@willj.net
94
+ executables: []
95
+ extensions: []
96
+ extra_rdoc_files: []
97
+ files:
98
+ - Gemfile
99
+ - Gemfile.lock
100
+ - LICENSE.md
101
+ - README.md
102
+ - Rakefile
103
+ - em-campfire.gemspec
104
+ - examples/simple.rb
105
+ - lib/em-campfire.rb
106
+ - lib/em-campfire/connection.rb
107
+ - lib/em-campfire/messages.rb
108
+ - lib/em-campfire/rooms.rb
109
+ - lib/em-campfire/users.rb
110
+ - lib/em-campfire/version.rb
111
+ - spec/lib/connection_spec.rb
112
+ - spec/lib/em-campfire_spec.rb
113
+ - spec/lib/messages_spec.rb
114
+ - spec/lib/rooms_spec.rb
115
+ - spec/spec_helper.rb
116
+ homepage: https://github.com/wjessop/em-campfire
117
+ licenses: []
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 1.8.10
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: Eventmachine campfire API lib
140
+ test_files:
141
+ - spec/lib/connection_spec.rb
142
+ - spec/lib/em-campfire_spec.rb
143
+ - spec/lib/messages_spec.rb
144
+ - spec/lib/rooms_spec.rb
145
+ - spec/spec_helper.rb