timriley-tinder 1.1.9

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/CHANGELOG.txt ADDED
@@ -0,0 +1,30 @@
1
+ 0.1.7 - 2008-07-24
2
+ * Don't join the room when only speaking [Brian Donovan]
3
+ * Added support for HTTP proxies
4
+ * Fix listening for messages that contain URLs [Jared Kuolt]
5
+
6
+ 0.1.6 - 2008-03-07
7
+ * Added Room#topic for getting the current topic [Even Weaver]
8
+ * Trap INT in #listen(&block) [borrowed from Chris Shea's Pyre]
9
+
10
+ 0.1.5 - 2008-01-25
11
+ * Fixed Room#listen, which was broken by latest Campfire deploy
12
+ * Fixed timeout when listening but not speaking that will eventually log you out [Clinton R. Nixon]
13
+
14
+ 0.1.4 - 2007-07-23
15
+ * Support for transcripts
16
+ * Fixed Room#leave, which was broken by a Campfire deployment [Andy Smith]
17
+
18
+ 0.1.3 - 2007-02-12
19
+ * added ssl support [Tero Parviainen]
20
+
21
+ 0.1.2 - 2007-01-27
22
+ * fixed bug preventing #listen from working without a block
23
+
24
+ 0.1.1 - 2007-01-27
25
+ * fix bug preventing speak from working
26
+ * incorporated "watching" from http://soylentfoo.jnewland.com/articles/2006/12/07/updates-to-marshmallow-the-campfire-bot
27
+
28
+ 0.1.0 - 2007-01-23
29
+ * Initial release as gem
30
+ * Get the users in a room [Tero Parviainen]
data/Manifest.txt ADDED
@@ -0,0 +1,9 @@
1
+ CHANGELOG.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ init.rb
6
+ lib/tinder.rb
7
+ lib/tinder/campfire.rb
8
+ lib/tinder/room.rb
9
+ lib/tinder/version.rb
data/README.txt ADDED
@@ -0,0 +1,45 @@
1
+ = Tinder - get the Campfire started
2
+
3
+ This is a fork of tinder that provides file upload support, currently using the mechanize gem.
4
+
5
+ Tinder is a library for interfacing with Campfire, the chat application from 37Signals. Unlike Marshmallow, it is designed to be a full-featured API (since 37Signals doesn't provide a real one), allowing you to programatically manage and speak/listen in chat rooms.
6
+
7
+ == Usage
8
+
9
+ campfire = Campfire.new 'mysubdomain'
10
+ campfire.login 'myemail@example.com', 'mypassword'
11
+
12
+ room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
13
+ room.rename 'New Room Name'
14
+ room.speak 'Hello world!'
15
+ room.paste "my pasted\ncode"
16
+ room.destroy
17
+
18
+ room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
19
+ room.speak 'Hello world!'
20
+
21
+ See the RDoc for more details.
22
+
23
+ == Requirements
24
+
25
+ * Active Support
26
+ gem install activesupport
27
+ * Hpricot
28
+ gem install hpricot
29
+
30
+ == Installation
31
+
32
+ Tinder can be installed as a gem or a Rails plugin:
33
+
34
+ gem install tinder
35
+
36
+ script/plugin install http://source.collectiveidea.com/public/tinder/trunk
37
+
38
+ == Development
39
+
40
+ The source for Tinder is available at http://source.collectiveidea.com/public/tinder/trunk. Development can be followed at http://opensoul.org/tags/tinder. Contributions are welcome!
41
+
42
+ == ToDo
43
+
44
+ * Tests! (unit and remote)
45
+ * Marshmallow-style integration scripts for exception notification and continuous integration
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ require File.join(File.dirname(__FILE__), 'lib', 'tinder', 'version')
4
+
5
+ # RDOC_OPTS = ['--quiet', '--title', "Tinder",
6
+ # "--opname", "index.html",
7
+ # "--line-numbers",
8
+ # "--main", "README",
9
+ # "--inline-source"]
10
+ #
11
+ # Generate all the Rake tasks
12
+
13
+ hoe = Hoe.new('tinder', ENV['VERSION'] || Tinder::VERSION::STRING) do |p|
14
+ p.rubyforge_name = 'tinder'
15
+ p.summary = "An (unofficial) Campfire API"
16
+ p.description = "An API for interfacing with Campfire, the 37Signals chat application."
17
+ p.author = 'Brandon Keepers'
18
+ p.email = 'brandon@opensoul.org'
19
+ p.url = 'http://tinder.rubyforge.org'
20
+ p.test_globs = ["test/**/*_test.rb"]
21
+ p.changes = p.paragraphs_of('CHANGELOG.txt', 0..1).join("\n\n")
22
+ p.extra_deps << ['activesupport']
23
+ p.extra_deps << ['hpricot']
24
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'tinder'
data/lib/tinder.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'uri'
4
+ require 'net/http'
5
+ require 'net/https'
6
+ require 'open-uri'
7
+ require 'hpricot'
8
+ require 'mechanize'
9
+
10
+ Dir[File.join(File.dirname(__FILE__), 'tinder/**/*.rb')].sort.each { |lib| require lib }
11
+
12
+ module Tinder
13
+ class Error < StandardError; end
14
+ class SSLRequiredError < Error; end
15
+ end
@@ -0,0 +1,211 @@
1
+ module Tinder
2
+
3
+ # == Usage
4
+ #
5
+ # campfire = Tinder::Campfire.new 'mysubdomain'
6
+ # campfire.login 'myemail@example.com', 'mypassword'
7
+ #
8
+ # room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
9
+ # room.speak 'Hello world!'
10
+ # room.destroy
11
+ #
12
+ # room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
13
+ # room.speak 'Hello world!'
14
+ class Campfire
15
+ attr_reader :subdomain, :uri
16
+
17
+ # Create a new connection to the campfire account with the given +subdomain+.
18
+ #
19
+ # == Options:
20
+ # * +:ssl+: use SSL for the connection, which is required if you have a Campfire SSL account.
21
+ # Defaults to false
22
+ # * +:proxy+: a proxy URI. (e.g. :proxy => 'http://user:pass@example.com:8000')
23
+ #
24
+ # c = Tinder::Campfire.new("mysubdomain", :ssl => true)
25
+ def initialize(subdomain, options = {})
26
+ options = { :ssl => false }.merge(options)
27
+ @cookie = nil
28
+ @subdomain = subdomain
29
+ @uri = URI.parse("#{options[:ssl] ? 'https' : 'http' }://#{subdomain}.campfirenow.com")
30
+ if options[:proxy]
31
+ uri = URI.parse(options[:proxy])
32
+ @http = Net::HTTP::Proxy(uri.host, uri.port, uri.user, uri.password)
33
+ else
34
+ @http = Net::HTTP
35
+ end
36
+ @logged_in = false
37
+ end
38
+
39
+ # Log in to campfire using your +email+ and +password+
40
+ def login(email, password)
41
+ unless verify_response(post("login", :email_address => email, :password => password), :redirect_to => url_for(:only_path => false))
42
+ raise Error, "Campfire login failed"
43
+ end
44
+ # ensure that SSL is set if required on this account
45
+ raise SSLRequiredError, "Your account requires SSL" unless verify_response(get, :success)
46
+ @logged_in = true
47
+ end
48
+
49
+ # Returns true when successfully logged in
50
+ def logged_in?
51
+ @logged_in == true
52
+ end
53
+
54
+ def logout
55
+ returning verify_response(get("logout"), :redirect) do |result|
56
+ @logged_in = !result
57
+ end
58
+ end
59
+
60
+ # Get an array of all the available rooms
61
+ # TODO: detect rooms that are full (no link)
62
+ def rooms
63
+ Hpricot(get.body).search("//h2/a").collect do |a|
64
+ Room.new(self, room_id_from_url(a.attributes['href']), a.inner_html)
65
+ end
66
+ end
67
+
68
+ # Find a campfire room by name
69
+ def find_room_by_name(name)
70
+ rooms.detect {|room| room.name == name }
71
+ end
72
+
73
+ # Find a campfire room by its guest hash
74
+ def find_room_by_guest_hash(hash, name)
75
+ res = post(hash, :name => name)
76
+
77
+ Room.new(self, room_id_from_url(res['location'])) if verify_response(res, :redirect)
78
+ end
79
+
80
+ # Creates and returns a new Room with the given +name+ and optionally a +topic+
81
+ def create_room(name, topic = nil)
82
+ find_room_by_name(name) if verify_response(post("account/create/room?from=lobby", {:room => {:name => name, :topic => topic}}, :ajax => true), :success)
83
+ end
84
+
85
+ def find_or_create_room_by_name(name)
86
+ find_room_by_name(name) || create_room(name)
87
+ end
88
+
89
+ # List the users that are currently chatting in any room
90
+ def users(*room_names)
91
+ users = Hpricot(get.body).search("div.room").collect do |room|
92
+ if room_names.empty? || room_names.include?((room/"h2/a").inner_html)
93
+ room.search("//li.user").collect { |user| user.inner_html }
94
+ end
95
+ end
96
+ users.flatten.compact.uniq.sort
97
+ end
98
+
99
+ # Get the dates of the available transcripts by room
100
+ #
101
+ # campfire.available_transcripts
102
+ # #=> {"15840" => [#<Date: 4908311/2,0,2299161>, #<Date: 4908285/2,0,2299161>]}
103
+ #
104
+ def available_transcripts(room = nil)
105
+ url = "files%2Btranscripts"
106
+ url += "?room_id#{room}" if room
107
+ transcripts = (Hpricot(get(url).body) / ".transcript").inject({}) do |result,transcript|
108
+ link = (transcript / "a").first.attributes['href']
109
+ (result[room_id_from_url(link)] ||= []) << Date.parse(link.scan(/\/transcript\/(\d{4}\/\d{2}\/\d{2})/).to_s)
110
+ result
111
+ end
112
+ room ? transcripts[room.to_s] : transcripts
113
+ end
114
+
115
+ # Is the connection to campfire using ssl?
116
+ def ssl?
117
+ uri.scheme == 'https'
118
+ end
119
+
120
+ private
121
+
122
+ def room_id_from_url(url)
123
+ url.scan(/room\/(\d*)/).to_s
124
+ end
125
+
126
+ def url_for(*args)
127
+ options = {:only_path => true}.merge(args.last.is_a?(Hash) ? args.pop : {})
128
+ path = args.shift
129
+ "#{options[:only_path] ? '' : uri}/#{path}"
130
+ end
131
+
132
+ def post(path, data = {}, options = {})
133
+ perform_request(options) do
134
+ returning Net::HTTP::Post.new(url_for(path)) do |request|
135
+ request.add_field 'Content-Type', 'application/x-www-form-urlencoded'
136
+ request.set_form_data flatten(data)
137
+ end
138
+ end
139
+ end
140
+
141
+ def post_file(path, file_path, options = {})
142
+ agent = WWW::Mechanize.new
143
+
144
+ agent.additional_headers = { 'User-Agent' => "Tinder/#{Tinder::VERSION::STRING} (http://tinder.rubyforge.org)" }
145
+ agent.additional_headers.merge!({ 'Cookie' => @cookie }) if @cookie
146
+
147
+ node = Hpricot::Elem.new(Hpricot::STag.new('form'))
148
+ node['action'] = url_for(path, :only_path => false)
149
+ node['method'] = 'POST'
150
+ node['enctype'] = 'multipart/form-data'
151
+
152
+ form = WWW::Mechanize::Form.new(node)
153
+ form.file_uploads << WWW::Mechanize::Form::FileUpload.new('upload', file_path)
154
+
155
+ page = agent.submit(form)
156
+ return page.response
157
+ end
158
+
159
+ def get(path = nil, options = {})
160
+ perform_request(options) { Net::HTTP::Get.new(url_for(path)) }
161
+ end
162
+
163
+ def prepare_request(request, options = {})
164
+ returning request do
165
+ request.add_field 'User-Agent', "Tinder/#{Tinder::VERSION::STRING} (http://tinder.rubyforge.org)"
166
+ request.add_field 'Cookie', @cookie if @cookie
167
+ if options[:ajax]
168
+ request.add_field 'X-Requested-With', 'XMLHttpRequest'
169
+ request.add_field 'X-Prototype-Version', '1.5.1.1'
170
+ end
171
+ end
172
+ end
173
+
174
+ def perform_request(options = {}, &block)
175
+ @request = prepare_request(yield, options)
176
+ http = @http.new(uri.host, uri.port)
177
+ http.use_ssl = ssl?
178
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if ssl?
179
+ @response = returning http.request(@request) do |response|
180
+ @cookie = response['set-cookie'] if response['set-cookie']
181
+ end
182
+ end
183
+
184
+ # flatten a nested hash (:room => {:name => 'foobar'} to 'user[name]' => 'foobar')
185
+ def flatten(params)
186
+ params = params.dup
187
+ params.stringify_keys!.each do |k,v|
188
+ if v.is_a? Hash
189
+ params.delete(k)
190
+ v.each {|subk,v| params["#{k}[#{subk}]"] = v }
191
+ end
192
+ end
193
+ end
194
+
195
+ def verify_response(response, options = {})
196
+ if options.is_a?(Symbol)
197
+ codes = case options
198
+ when :success; [200]
199
+ when :redirect; 300..399
200
+ else raise(ArgumentError, "Unknown response #{options}")
201
+ end
202
+ codes.include?(response.code.to_i)
203
+ elsif options[:redirect_to]
204
+ verify_response(response, :redirect) && response['location'] == options[:redirect_to]
205
+ else
206
+ false
207
+ end
208
+ end
209
+
210
+ end
211
+ end
@@ -0,0 +1,17 @@
1
+ # from http://d.hatena.ne.jp/kitamomonga/20080720/ruby_mechanize_tadd_addtitional_header
2
+
3
+ module WWW
4
+ class Mechanize
5
+ attr_accessor :additional_headers
6
+ alias :_set_headers :set_headers
7
+ def set_headers(uri, request, cur_page)
8
+ request = _set_headers(uri, request, cur_page)
9
+ if @additional_headers then
10
+ @additional_headers.each do |k, v|
11
+ (v ? request[k] = v : request.delete(k))
12
+ end
13
+ end
14
+ request
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,206 @@
1
+ module Tinder
2
+ # A campfire room
3
+ class Room
4
+ attr_reader :id, :name
5
+
6
+ def initialize(campfire, id, name = nil)
7
+ @campfire = campfire
8
+ @id = id
9
+ @name = name
10
+ end
11
+
12
+ # Join the room. Pass +true+ to join even if you've already joined.
13
+ def join(force = false)
14
+ @room = returning(get("room/#{id}")) do |room|
15
+ raise Error, "Could not join room" unless verify_response(room, :success)
16
+ @membership_key = room.body.scan(/\"membershipKey\": \"([a-z0-9]+)\"/).to_s
17
+ @user_id = room.body.scan(/\"userID\": (\d+)/).to_s
18
+ @last_cache_id = room.body.scan(/\"lastCacheID\": (\d+)/).to_s
19
+ @timestamp = room.body.scan(/\"timestamp\": (\d+)/).to_s
20
+ @idle_since = Time.now
21
+ end if @room.nil? || force
22
+ ping
23
+ true
24
+ end
25
+
26
+ # Leave a room
27
+ def leave
28
+ returning verify_response(post("room/#{id}/leave"), :redirect) do
29
+ @room, @membership_key, @user_id, @last_cache_id, @timestamp, @idle_since = nil
30
+ end
31
+ end
32
+
33
+ # Toggle guest access on or off
34
+ def toggle_guest_access
35
+ # re-join the room to get the guest url
36
+ verify_response(post("room/#{id}/toggle_guest_access"), :success) && join(true)
37
+ end
38
+
39
+ # Get the url for guest access
40
+ def guest_url
41
+ join
42
+ link = (Hpricot(@room.body)/"#guest_access h4").first
43
+ link.inner_html if link
44
+ end
45
+
46
+ def guest_access_enabled?
47
+ !guest_url.nil?
48
+ end
49
+
50
+ # The invite code use for guest
51
+ def guest_invite_code
52
+ guest_url.scan(/\/(\w*)$/).to_s
53
+ end
54
+
55
+ # Change the name of the room
56
+ def name=(name)
57
+ @name = name if verify_response(post("account/edit/room/#{id}", { :room => { :name => name }}, :ajax => true), :success)
58
+ end
59
+ alias_method :rename, :name=
60
+
61
+ # Change the topic
62
+ def topic=(topic)
63
+ topic if verify_response(post("room/#{id}/change_topic", { 'room' => { 'topic' => topic }}, :ajax => true), :success)
64
+ end
65
+
66
+ # Get the current topic
67
+ def topic
68
+ join
69
+ h = (Hpricot(@room.body)/"#topic")
70
+ if h
71
+ (h/:span).remove
72
+ h.inner_text.strip
73
+ end
74
+ end
75
+
76
+ # Lock the room to prevent new users from entering and to disable logging
77
+ def lock
78
+ verify_response(post("room/#{id}/lock", {}, :ajax => true), :success)
79
+ end
80
+
81
+ # Unlock the room
82
+ def unlock
83
+ verify_response(post("room/#{id}/unlock", {}, :ajax => true), :success)
84
+ end
85
+
86
+ def ping(force = false)
87
+ returning verify_response(post("room/#{id}/tabs", { }, :ajax => true), :success) do
88
+ @idle_since = Time.now
89
+ end if @idle_since < 1.minute.ago || force
90
+ end
91
+
92
+ def destroy
93
+ verify_response(post("account/delete/room/#{id}"), :success)
94
+ end
95
+
96
+ # Post a new message to the chat room
97
+ def speak(message, options = {})
98
+ message if verify_response(post("room/#{id}/speak", {:message => message,
99
+ :t => Time.now.to_i}.merge(options), :ajax => true), :success)
100
+ end
101
+
102
+ def paste(message)
103
+ speak message, :paste => true
104
+ end
105
+
106
+ def upload(file_path)
107
+ post_file("upload.cgi/room/#{id}/uploads/new", file_path)
108
+ end
109
+
110
+ # Get the list of users currently chatting for this room
111
+ def users
112
+ @campfire.users name
113
+ end
114
+
115
+ # Get and array of the messages that have been posted to the room. Each
116
+ # messages is a hash with:
117
+ # * +:person+: the display name of the person that posted the message
118
+ # * +:message+: the body of the message
119
+ # * +:user_id+: Campfire user id
120
+ # * +:id+: Campfire message id
121
+ #
122
+ # room.listen
123
+ # #=> [{:person=>"Brandon", :message=>"I'm getting very sleepy", :user_id=>"148583", :id=>"16434003"}]
124
+ #
125
+ # Called without a block, listen will return an array of messages that have been
126
+ # posted since you joined. listen also takes an optional block, which then polls
127
+ # for new messages every 5 seconds and calls the block for each message.
128
+ #
129
+ # room.listen do |m|
130
+ # room.speak "#{m[:person]}, Go away!" if m[:message] =~ /Java/i
131
+ # end
132
+ #
133
+ def listen(interval = 5)
134
+ join
135
+ if block_given?
136
+ catch(:stop_listening) do
137
+ trap('INT') { throw :stop_listening }
138
+ loop do
139
+ ping
140
+ self.messages.each {|msg| yield msg }
141
+ sleep interval
142
+ end
143
+ end
144
+ else
145
+ self.messages
146
+ end
147
+ end
148
+
149
+ # Get the dates for the available transcripts for this room
150
+ def available_transcripts
151
+ @campfire.available_transcripts(id)
152
+ end
153
+
154
+ # Get the transcript for the given date (Returns a hash in the same format as #listen)
155
+ #
156
+ # room.transcript(room.available_transcripts.first)
157
+ # #=> [{:message=>"foobar!", :user_id=>"99999", :person=>"Brandon", :id=>"18659245"}]
158
+ #
159
+ def transcript(date)
160
+ (Hpricot(get("room/#{id}/transcript/#{date.to_date.strftime('%Y/%m/%d')}").body) / ".message").collect do |message|
161
+ person = (message / '.person span').first
162
+ body = (message / '.body div').first
163
+ {:id => message.attributes['id'].scan(/message_(\d+)/).to_s,
164
+ :person => person ? person.inner_html : nil,
165
+ :user_id => message.attributes['class'].scan(/user_(\d+)/).to_s,
166
+ :message => body ? body.inner_html : nil
167
+ }
168
+ end
169
+ end
170
+
171
+ protected
172
+
173
+ def messages
174
+ returning [] do |messages|
175
+ response = post("poll.fcgi", {:l => @last_cache_id, :m => @membership_key,
176
+ :s => @timestamp, :t => "#{Time.now.to_i}000"}, :ajax => true)
177
+ if response.body.length > 1
178
+ lines = response.body.split("\r\n")
179
+
180
+ if lines.length > 0
181
+ @last_cache_id = lines.pop.scan(/chat.poller.lastCacheID = (\d+)/).to_s
182
+ lines.each do |msg|
183
+ unless msg.match(/timestamp_message/)
184
+ if msg.length > 0
185
+ messages << {
186
+ :id => msg.scan(/message_(\d+)/).to_s,
187
+ :user_id => msg.scan(/user_(\d+)/).to_s,
188
+ :person => msg.scan(/\\u003Ctd class=\\"person\\"\\u003E(?:\\u003Cspan\\u003E)?(.+?)(?:\\u003C\/span\\u003E)?\\u003C\/td\\u003E/).to_s,
189
+ :message => msg.scan(/\\u003Ctd class=\\"body\\"\\u003E\\u003Cdiv\\u003E(.+?)\\u003C\/div\\u003E\\u003C\/td\\u003E/).to_s
190
+ }
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ [:post, :post_file, :get, :verify_response].each do |method|
200
+ define_method method do |*args|
201
+ @campfire.send method, *args
202
+ end
203
+ end
204
+
205
+ end
206
+ end
@@ -0,0 +1,9 @@
1
+ module Tinder #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ TINY = 8
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,140 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ context "Preparing a campfire request" do
4
+ setup do
5
+ @campfire = Tinder::Campfire.new("foobar")
6
+ @request = Net::HTTP::Get.new("does_not_matter")
7
+ end
8
+
9
+ def prepare_request
10
+ @campfire.send(:prepare_request, @request)
11
+ end
12
+
13
+ specify "should return the request" do
14
+ prepare_request.should equal(@request)
15
+ end
16
+
17
+ specify "should set the cookie" do
18
+ @campfire.instance_variable_set("@cookie", "foobar")
19
+ prepare_request['Cookie'].should == 'foobar'
20
+ end
21
+
22
+ specify "should set the user agent" do
23
+ prepare_request['User-Agent'].should =~ /^Tinder/
24
+ end
25
+ end
26
+
27
+ # context "Performing a campfire request" do
28
+ #
29
+ # setup do
30
+ # @response = mock("response")
31
+ # Net::HTTP.any_instance.stubs(:request).returns(response)
32
+ # request = Net::HTTP::Get.new("does_not_matter")
33
+ # response.expects(:[]).with('set-cookie').and_return('foobar')
34
+ # @campfire.send(:perform_request) { request }
35
+ # end
36
+ #
37
+ # specify "should set cookie" do
38
+ # @campfire.instance_variable_get("@cookie").should == 'foobar'
39
+ # end
40
+ #
41
+ # end
42
+
43
+ context "Verifying a 200 response" do
44
+
45
+ setup do
46
+ @campfire = Tinder::Campfire.new("foobar")
47
+ @response.should_receive(:code).and_return(200)
48
+ end
49
+
50
+ specify "should return true when expecting success" do
51
+ @campfire.send(:verify_response, @response, :success).should equal(true)
52
+ end
53
+
54
+ specify "should return false when expecting a redirect" do
55
+ @campfire.send(:verify_response, @response, :redirect).should equal(false)
56
+ end
57
+
58
+ specify "should return false when expecting a redirect to a specific path" do
59
+ @campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(false)
60
+ end
61
+
62
+ end
63
+
64
+ context "Verifying a 302 response" do
65
+
66
+ setup do
67
+ @campfire = Tinder::Campfire.new("foobar")
68
+ @response.should_receive(:code).and_return(302)
69
+ end
70
+
71
+ specify "should return true when expecting redirect" do
72
+ @campfire.send(:verify_response, @response, :redirect).should equal(true)
73
+ end
74
+
75
+ specify "should return false when expecting success" do
76
+ @campfire.send(:verify_response, @response, :success).should equal(false)
77
+ end
78
+
79
+ specify "should return true when expecting a redirect to a specific path" do
80
+ @response.should_receive(:[]).with('location').and_return("/foobar")
81
+ @campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(true)
82
+ end
83
+
84
+ specify "should return false when redirecting to a different path than expected" do
85
+ @response.should_receive(:[]).with('location').and_return("/baz")
86
+ @campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(false)
87
+ end
88
+
89
+ end
90
+
91
+ context "A failed login" do
92
+
93
+ setup do
94
+ @campfire = Tinder::Campfire.new 'foobar'
95
+ @response = mock("response")
96
+ @campfire.should_receive(:post).and_return(@response)
97
+ @response.should_receive(:code).and_return("302")
98
+ @response.should_receive(:[]).with("location").and_return("/login")
99
+ end
100
+
101
+ specify "should raise an error" do
102
+ lambda do
103
+ @campfire.login "doesn't", "matter"
104
+ end.should raise_error(Tinder::Error)
105
+ end
106
+
107
+ specify "should not set logged in status" do
108
+ @campfire.login 'foo', 'bar' rescue
109
+ @campfire.logged_in?.should equal(false)
110
+ end
111
+
112
+ end
113
+
114
+ context "Accessing a room with guest access" do
115
+
116
+ setup do
117
+ @room_id = 123
118
+ @campfire = Tinder::Campfire.new 'foobar'
119
+ @response = mock("response")
120
+ @campfire.stub!(:post).and_return(@response)
121
+ end
122
+
123
+ specify "should return a room for the public room" do
124
+ @response.should_receive(:code).and_return(302)
125
+ @response.should_receive(:[]).with("location").and_return("/rooms/#{@room_id}")
126
+
127
+ room = @campfire.find_room_by_guest_hash "valid_hash", "John Doe"
128
+ room.should be_kind_of(Tinder::Room)
129
+ room.campfire.should == @campfire
130
+ room.id.to_i.should == @room_id
131
+ end
132
+
133
+ specify "should raise an error if given an invalid room hash" do
134
+ @response.should_receive(:code).and_return(500)
135
+
136
+ room = @campfire.find_room_by_guest_hash "invalid_hash", "John Doe"
137
+ room.should be_nil
138
+ end
139
+
140
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require File.dirname(__FILE__) + '/../lib/tinder.rb'
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class RemoteCampfireTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ # @subdomain = 'domain'
7
+ # @user, @pass = 'email@example.com', 'password'
8
+ @ssl = false
9
+ raise "Set your campfire credentials before running the remote tests" unless @user && @pass && @subdomain
10
+ @campfire = Tinder::Campfire.new @subdomain, :ssl => @ssl
11
+ end
12
+
13
+ def test_ssl_required
14
+ if @ssl
15
+ campfire = Tinder::Campfire.new @subdomain
16
+ assert_raises(Tinder::SSLRequiredError) do
17
+ campfire.login(@user, @pass)
18
+ end
19
+ end
20
+ end
21
+
22
+ def test_create_and_delete_room
23
+ assert login
24
+ assert @campfire.logged_in?
25
+
26
+ room = @campfire.create_room("Testing#{Time.now.to_i}")
27
+
28
+ assert_instance_of Tinder::Room, room
29
+ assert_not_nil room.id
30
+
31
+ room.name = "new name"
32
+ assert_equal "new name", room.name
33
+
34
+ room.destroy
35
+ assert_nil @campfire.find_room_by_name(room.name)
36
+
37
+ assert @campfire.logout
38
+ ensure
39
+ room.destroy rescue nil
40
+ end
41
+
42
+ def test_failed_login
43
+ assert_raises(Tinder::Error) { @campfire.login(@user, 'notmypassword') }
44
+ assert !@campfire.logged_in?
45
+ end
46
+
47
+ def test_find_nonexistent_room
48
+ login
49
+ assert_nil @campfire.find_room_by_name('No Room Should Have This Name')
50
+ end
51
+
52
+ private
53
+
54
+ def login(user = @user, pass = @pass)
55
+ @campfire.login(user, pass)
56
+ end
57
+
58
+ end
@@ -0,0 +1,7 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/mocks')
2
+ require 'test/unit'
3
+ require 'rubygems'
4
+ require 'active_support'
5
+ require File.dirname(__FILE__) + '/../lib/tinder.rb'
6
+ require 'mocha'
7
+ require 'stubba'
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timriley-tinder
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.9
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Keepers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-10-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mechanize
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">"
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.0
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: activesupport
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">"
30
+ - !ruby/object:Gem::Version
31
+ version: 0.0.0
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: hpricot
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.0
41
+ version:
42
+ - !ruby/object:Gem::Dependency
43
+ name: mechanize
44
+ version_requirement:
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">"
48
+ - !ruby/object:Gem::Version
49
+ version: 0.0.0
50
+ version:
51
+ - !ruby/object:Gem::Dependency
52
+ name: hoe
53
+ version_requirement:
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">"
57
+ - !ruby/object:Gem::Version
58
+ version: 1.7.0
59
+ version:
60
+ description: This is a fork of Tinder with file upload support.
61
+ email: brandon@opensoul.org
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files:
67
+ - CHANGELOG.txt
68
+ - Manifest.txt
69
+ - README.txt
70
+ files:
71
+ - CHANGELOG.txt
72
+ - Manifest.txt
73
+ - README.txt
74
+ - Rakefile
75
+ - init.rb
76
+ - lib/tinder.rb
77
+ - lib/tinder/campfire.rb
78
+ - lib/tinder/room.rb
79
+ - lib/tinder/version.rb
80
+ - lib/tinder/mechanize_ext.rb
81
+ has_rdoc: true
82
+ homepage: http://github.com/timriley/tinder
83
+ post_install_message:
84
+ rdoc_options:
85
+ - --main
86
+ - README.txt
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: "0"
94
+ version:
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: "0"
100
+ version:
101
+ requirements: []
102
+
103
+ rubyforge_project:
104
+ rubygems_version: 1.2.0
105
+ signing_key:
106
+ specification_version: 2
107
+ summary: An API for interfacing with Campfire, the 37Signals chat application.
108
+ test_files:
109
+ - test/test_helper.rb
110
+ - test/remote/remote_campfire_test.rb
111
+ - spec/campfire_spec.rb
112
+ - spec/spec_helper.rb