timriley-tinder 1.1.9

Sign up to get free protection for your applications and to get access to all the features.
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