campy 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +19 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +16 -0
- data/Guardfile +5 -0
- data/LICENSE +22 -0
- data/README.md +99 -0
- data/Rakefile +12 -0
- data/bin/campy +38 -0
- data/campy.gemspec +22 -0
- data/lib/campy.rb +6 -0
- data/lib/campy/room.rb +186 -0
- data/lib/campy/version.rb +4 -0
- data/spec/campy/room_spec.rb +166 -0
- data/spec/fixtures/webmock_no_rooms.txt +4 -0
- data/spec/fixtures/webmock_rooms.txt +22 -0
- data/spec/fixtures/webmock_speak.txt +11 -0
- metadata +106 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in campy.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem 'rake', '~> 0.9'
|
8
|
+
|
9
|
+
gem 'growl'
|
10
|
+
gem 'guard'
|
11
|
+
gem 'guard-minitest'
|
12
|
+
end
|
13
|
+
|
14
|
+
platforms :jruby do
|
15
|
+
gem 'jruby-openssl'
|
16
|
+
end
|
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Fletcher Nichol
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# <a name="title"></a> Campy [](http://travis-ci.org/fnichol/campy)
|
2
|
+
|
3
|
+
Tiny Campfire client so you can get on with it. It's implemented on top of
|
4
|
+
`Net::HTTP` and only requires the `multi_json` gem for Ruby compatibilities.
|
5
|
+
|
6
|
+
## <a name="installation"></a> Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'campy'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
```bash
|
17
|
+
$ bundle
|
18
|
+
```
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
```
|
23
|
+
$ gem install campy
|
24
|
+
```
|
25
|
+
|
26
|
+
## <a name="usage"></a> Usage
|
27
|
+
|
28
|
+
First create a `campfire.yml` file in your home directory:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
$ cat <<CAMPFIRE_YAML > $HOME/.campfire.yml
|
32
|
+
:account: mysubdomain
|
33
|
+
:token: mytoken123
|
34
|
+
:room: House of Hubot
|
35
|
+
CAMPFIRE_YAML
|
36
|
+
```
|
37
|
+
|
38
|
+
### <a name="usage-bin"></a> campy Command
|
39
|
+
|
40
|
+
Campy comes with the `campy` command so you can send messages from the
|
41
|
+
command line:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
$ campy speak "Campy says yello"
|
45
|
+
$ campy play ohmy
|
46
|
+
```
|
47
|
+
|
48
|
+
### <a name="usage-ruby"></a> Ruby Library
|
49
|
+
|
50
|
+
There's not much to the API; create a `Campy::Room` and go:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
require 'campy'
|
54
|
+
|
55
|
+
campy = Campy::Room.new(:account => "mysubdomain", :token => "mytoken123",
|
56
|
+
:room => "House of Hubot")
|
57
|
+
campy.speak "Campy says yello"
|
58
|
+
campy.play "ohmy"
|
59
|
+
```
|
60
|
+
|
61
|
+
Why not use the `campfire.yml` config? Let's do that:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
require 'campy'
|
65
|
+
require 'yaml'
|
66
|
+
|
67
|
+
campy = Campy::Room.new(YAML.load_file(File.expand_path("~/.campfire.yml")))
|
68
|
+
campy.speak "Campy says yello"
|
69
|
+
campy.play "ohmy"
|
70
|
+
```
|
71
|
+
|
72
|
+
## <a name="development"></a> Development
|
73
|
+
|
74
|
+
* Source hosted at [GitHub][repo]
|
75
|
+
* Report issues/questions/feature requests on [GitHub Issues][issues]
|
76
|
+
|
77
|
+
Pull requests are very welcome! Make sure your patches are well tested.
|
78
|
+
Ideally create a topic branch for every separate change you make. For
|
79
|
+
example:
|
80
|
+
|
81
|
+
1. Fork the repo
|
82
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
83
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
84
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
85
|
+
5. Create new Pull Request
|
86
|
+
|
87
|
+
## <a name="authors"></a> Authors
|
88
|
+
|
89
|
+
Created and maintained by [Fletcher Nichol][fnichol] (<fnichol@nichol.ca>)
|
90
|
+
|
91
|
+
## <a name="license"></a> License
|
92
|
+
|
93
|
+
MIT (see [LICENSE][license])
|
94
|
+
|
95
|
+
[license]: https://github.com/fnichol/campy/blob/master/LICENSE
|
96
|
+
[fnichol]: https://github.com/fnichol
|
97
|
+
[repo]: https://github.com/fnichol/campy
|
98
|
+
[issues]: https://github.com/fnichol/campy/issues
|
99
|
+
[contributors]: https://github.com/fnichol/campy/contributors
|
data/Rakefile
ADDED
data/bin/campy
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
4
|
+
require 'campy'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
def options
|
8
|
+
yaml_file = File.expand_path(ENV['CAMPFIRE_YAML_FILE'] || '~/.campfire.yml')
|
9
|
+
if !File.exists?(yaml_file)
|
10
|
+
abort "File '#{yaml_file}' does not exist with campfire configuration."
|
11
|
+
end
|
12
|
+
YAML.load_file(yaml_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
def usage
|
16
|
+
<<-USAGE.gsub(/^ {4}/, '')
|
17
|
+
|
18
|
+
Usage
|
19
|
+
|
20
|
+
campy <action> <message>
|
21
|
+
|
22
|
+
Actions
|
23
|
+
|
24
|
+
help - Display CLI help (this output)
|
25
|
+
speak - Speak a message into the campfire room
|
26
|
+
play - Play a sound into the campfire room
|
27
|
+
|
28
|
+
USAGE
|
29
|
+
end
|
30
|
+
|
31
|
+
if ARGV.first == "help"
|
32
|
+
puts usage
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
abort usage if ARGV.empty? || !%w{speak play}.include?(ARGV.first)
|
37
|
+
|
38
|
+
Campy::Room.new(options).send(ARGV.shift, ARGV.shift)
|
data/campy.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/campy/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Fletcher Nichol"]
|
6
|
+
gem.email = ["fnichol@nichol.ca"]
|
7
|
+
gem.description = %q{Small Campfire client using Net::HTTP.}
|
8
|
+
gem.summary = gem.description
|
9
|
+
gem.homepage = "http://fnichol.github.com/campy/"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "campy"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Campy::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency "multi_json", "~> 1.0"
|
19
|
+
|
20
|
+
gem.add_development_dependency "minitest", "~> 2.12.0"
|
21
|
+
gem.add_development_dependency "webmock", "~> 1.8.5"
|
22
|
+
end
|
data/lib/campy.rb
ADDED
data/lib/campy/room.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'net/https'
|
3
|
+
require 'multi_json'
|
4
|
+
|
5
|
+
module Campy
|
6
|
+
class Room
|
7
|
+
# Public: Error class raised when a room ID cannot be found with a
|
8
|
+
# given name.
|
9
|
+
class NotFound < RuntimeError ; end
|
10
|
+
|
11
|
+
# Public: Error class raised when an HTTP error has occured.
|
12
|
+
class ConnectionError < RuntimeError ; end
|
13
|
+
|
14
|
+
# Public: Returns the String account name.
|
15
|
+
attr_reader :account
|
16
|
+
|
17
|
+
# Public: Returns the String room name.
|
18
|
+
attr_reader :room
|
19
|
+
|
20
|
+
# Public: Returns the API token String for a user.
|
21
|
+
attr_reader :ssl
|
22
|
+
|
23
|
+
# Public: Initializes a Room from a Hash of configuration options.
|
24
|
+
#
|
25
|
+
# options - A Hash of options to set up the Room (default: {}):
|
26
|
+
# :account - The String account/subdomain name.
|
27
|
+
# :room - The String room name, not the room ID.
|
28
|
+
# :token - The API token String for a user.
|
29
|
+
# :ssl - A truthy object which is true when SSL is
|
30
|
+
# required (default: true).
|
31
|
+
def initialize(options = {})
|
32
|
+
options = { :ssl => true }.merge(options)
|
33
|
+
|
34
|
+
[:account, :room, :token, :ssl].each do |option|
|
35
|
+
instance_variable_set "@#{option}", options[option]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Public: Returns the Integer room ID of the Campfire room.
|
40
|
+
#
|
41
|
+
# Returns the Integer room ID.
|
42
|
+
# Raises NotFound if a room cannot be found for the given name.
|
43
|
+
# Raises ConnectionError if an HTTP error occurs.
|
44
|
+
def room_id
|
45
|
+
@room_id ||= fetch_room_id
|
46
|
+
end
|
47
|
+
|
48
|
+
# Public: Posts a message into the campfire room.
|
49
|
+
#
|
50
|
+
# msg - A String message.
|
51
|
+
#
|
52
|
+
# Returns true if message is delivered.
|
53
|
+
# Raises ConnectionError if an HTTP error occurs.
|
54
|
+
def speak(msg)
|
55
|
+
send_message(msg)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Plays a sound into the campfire room.
|
59
|
+
#
|
60
|
+
# sound - A String representing the sound.
|
61
|
+
#
|
62
|
+
# Returns true if message is delivered.
|
63
|
+
# Raises ConnectionError if an HTTP error occurs.
|
64
|
+
def play(msg)
|
65
|
+
send_message(msg, 'SoundMessage')
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# Internal: Array of errors that will be wrapped when using Net::HTTP.
|
71
|
+
HTTP_ERRORS = [Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
|
72
|
+
EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
73
|
+
Net::ProtocolError, SocketError, OpenSSL::SSL::SSLError,
|
74
|
+
Errno::ECONNREFUSED]
|
75
|
+
|
76
|
+
# Internal: Returns the API token String for a user.
|
77
|
+
attr_reader :token
|
78
|
+
|
79
|
+
# Internal: Returns the campfire hostname with subdomain.
|
80
|
+
def host
|
81
|
+
"#{account}.campfirenow.com"
|
82
|
+
end
|
83
|
+
|
84
|
+
# Internal: Returns the Integer HTTP port number to connect with.
|
85
|
+
def port
|
86
|
+
ssl ? 443 : 80
|
87
|
+
end
|
88
|
+
|
89
|
+
# Internal: Returns the Integer number of the room.
|
90
|
+
#
|
91
|
+
# Returns the Integer room number.
|
92
|
+
# Raises NotFound if a room cannot be found for the given name.
|
93
|
+
# Raises ConnectionError if an HTTP error occurs.
|
94
|
+
def fetch_room_id
|
95
|
+
connect do |http|
|
96
|
+
response = http.request(http_request(:get, "/rooms.json"))
|
97
|
+
|
98
|
+
case response
|
99
|
+
when Net::HTTPOK
|
100
|
+
find_room_in_json(MultiJson.decode(response.body))
|
101
|
+
else
|
102
|
+
raise ConnectionError
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Internal: Posts a message to the campfire room.
|
108
|
+
#
|
109
|
+
# msg - The String message to send.
|
110
|
+
# type - The String type of campfire message (default: TextMessage).
|
111
|
+
#
|
112
|
+
# Returns true if message is delivered.
|
113
|
+
# Raises ConnectionError if an HTTP error occurs.
|
114
|
+
def send_message(msg, type = 'TextMessage')
|
115
|
+
connect do |http|
|
116
|
+
request = http_request(:post, "/room/#{room_id}/speak.json")
|
117
|
+
request.body = MultiJson.encode(
|
118
|
+
{ :message => { :body => msg, :type => type } })
|
119
|
+
response = http.request(request)
|
120
|
+
|
121
|
+
case response
|
122
|
+
when Net::HTTPCreated
|
123
|
+
true
|
124
|
+
else
|
125
|
+
raise ConnectionError,
|
126
|
+
"Error sending message '#{msg}' (#{response.class})"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Internal: Parses through the rooms JSON response and returns the
|
132
|
+
# Integer room ID.
|
133
|
+
#
|
134
|
+
# json - the rooms Hash of JSON data.
|
135
|
+
#
|
136
|
+
# Returns the Integer room number.
|
137
|
+
# Raises NotFound if a room cannot be found for the given name.
|
138
|
+
def find_room_in_json(json)
|
139
|
+
room_hash = json["rooms"].find { |r| r["name"] == room }
|
140
|
+
|
141
|
+
if room_hash
|
142
|
+
room_hash["id"]
|
143
|
+
else
|
144
|
+
raise NotFound, "Room name '#{room}' could not be found."
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Internal: Creates a Net::HTTP connection and yields to a block with
|
149
|
+
# the connection.
|
150
|
+
#
|
151
|
+
# Yields the Net::HTTP connection.
|
152
|
+
#
|
153
|
+
# Returns the return value (if any) of the block.
|
154
|
+
# Raises ConnectionError if any common HTTP errors are raised.
|
155
|
+
def connect
|
156
|
+
http = Net::HTTP.new(host, port)
|
157
|
+
http.use_ssl = ssl
|
158
|
+
|
159
|
+
begin
|
160
|
+
yield http
|
161
|
+
rescue *HTTP_ERRORS => exception
|
162
|
+
raise ConnectionError, "#{exception.class.name}: #{exception.message}"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Internal: Returns a Net::HTTPRequest object initialized with
|
167
|
+
# authentication and content headers set.
|
168
|
+
#
|
169
|
+
# verb - A Symbol representing an HTTP verb.
|
170
|
+
# path - The String path of the request.
|
171
|
+
#
|
172
|
+
# Examples
|
173
|
+
#
|
174
|
+
# http_request(:get, "/rooms.json")
|
175
|
+
# http_request(:post, "/room/1/speak.json")
|
176
|
+
#
|
177
|
+
# Returns a Net::HTTPRequest object.
|
178
|
+
def http_request(verb, path)
|
179
|
+
klass = klass = Net::HTTP.const_get(verb.to_s.capitalize)
|
180
|
+
request = klass.new(path)
|
181
|
+
request.basic_auth(token, "X")
|
182
|
+
request["Content-Type"] = "application/json"
|
183
|
+
request
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'webmock/minitest'
|
4
|
+
require 'campy/room'
|
5
|
+
|
6
|
+
describe Campy::Room do
|
7
|
+
WRAPPED_ERRORS = [Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
8
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
|
9
|
+
SocketError, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED]
|
10
|
+
|
11
|
+
let(:opts) do
|
12
|
+
{ :account => 'zubzub', :token => 'yepyep',
|
13
|
+
:room => 'myroom', :ssl => true }
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:stub_rooms!) do
|
17
|
+
stub_request(:get, "https://yepyep:X@zubzub.campfirenow.com/rooms.json").
|
18
|
+
with(:headers => {'Content-Type' => 'application/json'}).
|
19
|
+
to_return(:status => 200, :body => fixture("rooms"), :headers => {})
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:stub_rooms_no_room!) do
|
23
|
+
stub_request(:get, "https://yepyep:X@zubzub.campfirenow.com/rooms.json").
|
24
|
+
with(:headers => {'Content-Type' => 'application/json'}).
|
25
|
+
to_return(:status => 200, :body => fixture("no_rooms"), :headers => {})
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:stub_rooms_invalid_token!) do
|
29
|
+
stub_request(:get, "https://yepyep:X@zubzub.campfirenow.com/rooms.json").
|
30
|
+
with(:headers => {'Content-Type' => 'application/json'}).
|
31
|
+
to_return(:status => 401, :body => "HTTP Basic: Access denied.\n",
|
32
|
+
:headers => {})
|
33
|
+
end
|
34
|
+
|
35
|
+
def stub_rooms_error!(error)
|
36
|
+
stub_request(:get, "https://yepyep:X@zubzub.campfirenow.com/rooms.json").
|
37
|
+
with(:headers => {'Content-Type' => 'application/json'}).
|
38
|
+
to_raise(error)
|
39
|
+
end
|
40
|
+
|
41
|
+
def stub_speak!(msg, type = 'TextMessage')
|
42
|
+
stub_request(:post, "https://yepyep:X@zubzub.campfirenow.com/room/123456/speak.json").
|
43
|
+
with(:headers => {'Content-Type' => 'application/json'},
|
44
|
+
:body => {:message => {:body => msg, :type => type}}).
|
45
|
+
to_return(:status => 201, :headers => {},
|
46
|
+
:body => fixture("speak").sub(/@@MESSAGE@@/, msg))
|
47
|
+
end
|
48
|
+
|
49
|
+
def stub_speak_error!(error)
|
50
|
+
stub_request(:post, "https://yepyep:X@zubzub.campfirenow.com/room/123456/speak.json").
|
51
|
+
with(:headers => {'Content-Type' => 'application/json'}).
|
52
|
+
to_raise(error)
|
53
|
+
end
|
54
|
+
|
55
|
+
def fixture(name)
|
56
|
+
File.read(File.dirname(__FILE__) + "/../fixtures/webmock_#{name}.txt")
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#initialize" do
|
60
|
+
it "takes a hash of campfire configuration" do
|
61
|
+
room = Campy::Room.new(opts)
|
62
|
+
room.account.must_equal 'zubzub'
|
63
|
+
room.room.must_equal 'myroom'
|
64
|
+
end
|
65
|
+
|
66
|
+
it "defaults to SSL mode enabled" do
|
67
|
+
opts.delete(:ssl)
|
68
|
+
room = Campy::Room.new(opts)
|
69
|
+
room.ssl.must_equal true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#room_id" do
|
74
|
+
let(:subject) { Campy::Room.new(opts) }
|
75
|
+
|
76
|
+
it "fetches the room id from the API" do
|
77
|
+
stub_rooms!
|
78
|
+
subject.room_id.must_equal 666666
|
79
|
+
end
|
80
|
+
|
81
|
+
it "raises NotFound if no room is found" do
|
82
|
+
stub_rooms_no_room!
|
83
|
+
|
84
|
+
proc { subject.room_id }.must_raise(
|
85
|
+
Campy::Room::NotFound)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "raises ConnectionError if the token is invalid" do
|
89
|
+
stub_rooms_invalid_token!
|
90
|
+
|
91
|
+
proc { subject.room_id }.must_raise(
|
92
|
+
Campy::Room::ConnectionError)
|
93
|
+
end
|
94
|
+
|
95
|
+
WRAPPED_ERRORS.each do |error|
|
96
|
+
it "wraps #{error} and raises a ConnectionError" do
|
97
|
+
stub_rooms_error!(error)
|
98
|
+
|
99
|
+
proc { subject.room_id }.must_raise(
|
100
|
+
Campy::Room::ConnectionError)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "#speak" do
|
106
|
+
let(:subject) { Campy::Room.new(opts) }
|
107
|
+
|
108
|
+
before do
|
109
|
+
# stub out #room_id since we don't care about this API call
|
110
|
+
def subject.room_id ; 123456 ; end
|
111
|
+
end
|
112
|
+
|
113
|
+
it "calls the speak API with a message" do
|
114
|
+
stub = stub_speak!("talking about talking")
|
115
|
+
subject.speak "talking about talking"
|
116
|
+
|
117
|
+
assert_requested(stub)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "returns true when message is delivered" do
|
121
|
+
stub = stub_speak!("talking about talking")
|
122
|
+
|
123
|
+
subject.speak("talking about talking").must_equal true
|
124
|
+
end
|
125
|
+
|
126
|
+
WRAPPED_ERRORS.each do |error|
|
127
|
+
it "wraps #{error} and raises a ConnectionError" do
|
128
|
+
stub_speak_error!(error)
|
129
|
+
|
130
|
+
proc { subject.speak "nope" }.must_raise(
|
131
|
+
Campy::Room::ConnectionError)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "#play" do
|
137
|
+
let(:subject) { Campy::Room.new(opts) }
|
138
|
+
|
139
|
+
before do
|
140
|
+
# stub out #room_id since we don't care about this API call
|
141
|
+
def subject.room_id ; 123456 ; end
|
142
|
+
end
|
143
|
+
|
144
|
+
it "calls the play API with a sound" do
|
145
|
+
stub = stub_speak!("tada", "SoundMessage")
|
146
|
+
subject.play "tada"
|
147
|
+
|
148
|
+
assert_requested(stub)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "returns true when message is delivered" do
|
152
|
+
stub = stub_speak!("tada", "SoundMessage")
|
153
|
+
|
154
|
+
subject.play("tada").must_equal true
|
155
|
+
end
|
156
|
+
|
157
|
+
WRAPPED_ERRORS.each do |error|
|
158
|
+
it "wraps #{error} and raises a ConnectionError" do
|
159
|
+
stub_speak_error!(error)
|
160
|
+
|
161
|
+
proc { subject.play "tada" }.must_raise(
|
162
|
+
Campy::Room::ConnectionError)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"rooms": [
|
3
|
+
{
|
4
|
+
"created_at": "2012/01/01 00:01:02 +0000",
|
5
|
+
"id": 123456,
|
6
|
+
"locked": false,
|
7
|
+
"membership_limit": 4,
|
8
|
+
"name": "nuggettalk",
|
9
|
+
"topic": "Pop go the nuggets",
|
10
|
+
"updated_at": "2012/02/23 02:21:49 +0000"
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"created_at": "2011/01/01 00:02:03 +0000",
|
14
|
+
"id": 666666,
|
15
|
+
"locked": false,
|
16
|
+
"membership_limit": 12,
|
17
|
+
"name": "myroom",
|
18
|
+
"topic": "There is only one test",
|
19
|
+
"updated_at": "2011/12/05 16:23:40 +0000"
|
20
|
+
}
|
21
|
+
]
|
22
|
+
}
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: campy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Fletcher Nichol
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: multi_json
|
16
|
+
requirement: &70347351272720 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70347351272720
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: minitest
|
27
|
+
requirement: &70347351272200 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.12.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70347351272200
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: webmock
|
38
|
+
requirement: &70347351271740 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.8.5
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70347351271740
|
47
|
+
description: Small Campfire client using Net::HTTP.
|
48
|
+
email:
|
49
|
+
- fnichol@nichol.ca
|
50
|
+
executables:
|
51
|
+
- campy
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- .travis.yml
|
57
|
+
- CHANGELOG.md
|
58
|
+
- Gemfile
|
59
|
+
- Guardfile
|
60
|
+
- LICENSE
|
61
|
+
- README.md
|
62
|
+
- Rakefile
|
63
|
+
- bin/campy
|
64
|
+
- campy.gemspec
|
65
|
+
- lib/campy.rb
|
66
|
+
- lib/campy/room.rb
|
67
|
+
- lib/campy/version.rb
|
68
|
+
- spec/campy/room_spec.rb
|
69
|
+
- spec/fixtures/webmock_no_rooms.txt
|
70
|
+
- spec/fixtures/webmock_rooms.txt
|
71
|
+
- spec/fixtures/webmock_speak.txt
|
72
|
+
homepage: http://fnichol.github.com/campy/
|
73
|
+
licenses: []
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
hash: 1286988910110324181
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
hash: 1286988910110324181
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.8.17
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Small Campfire client using Net::HTTP.
|
102
|
+
test_files:
|
103
|
+
- spec/campy/room_spec.rb
|
104
|
+
- spec/fixtures/webmock_no_rooms.txt
|
105
|
+
- spec/fixtures/webmock_rooms.txt
|
106
|
+
- spec/fixtures/webmock_speak.txt
|