tinder 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt CHANGED
@@ -1,10 +1,16 @@
1
1
  = Tinder - get the Campfire started
2
2
 
3
+
4
+ This branch is a rewrite of Tinder to use the official Campfire API. The API is intended to be backwards compatible so consumers can easily migrate off the HTML API.
5
+
6
+ -- Joshua Peek (Programmer, 37signals)
7
+
8
+
3
9
  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.
4
10
 
5
11
  == Usage
6
12
 
7
- campfire = Campfire.new 'mysubdomain'
13
+ campfire = Tinder::Campfire.new 'mysubdomain'
8
14
  campfire.login 'myemail@example.com', 'mypassword'
9
15
 
10
16
  room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
data/Rakefile CHANGED
@@ -9,14 +9,10 @@ begin
9
9
  gem.homepage = 'http://github.com/collectiveidea/tinder'
10
10
  gem.rubyforge_project = "tinder"
11
11
  gem.add_dependency "activesupport"
12
- gem.add_dependency "hpricot"
13
12
  gem.add_dependency "mime-types"
14
13
  gem.add_development_dependency "rspec"
15
14
  end
16
15
  Jeweler::GemcutterTasks.new
17
- Jeweler::RubyforgeTasks.new do |rubyforge|
18
- rubyforge.doc_task = "rdoc"
19
- end
20
16
  rescue LoadError
21
17
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
22
18
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.2
1
+ 1.3.0
@@ -4,8 +4,8 @@ require 'uri'
4
4
  require 'net/http'
5
5
  require 'net/https'
6
6
  require 'open-uri'
7
- require 'hpricot'
8
7
 
8
+ require 'tinder/connection'
9
9
  require 'tinder/multipart'
10
10
  require 'tinder/campfire'
11
11
  require 'tinder/room'
@@ -13,4 +13,4 @@ require 'tinder/room'
13
13
  module Tinder
14
14
  class Error < StandardError; end
15
15
  class SSLRequiredError < Error; end
16
- end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module Tinder
2
-
2
+
3
3
  # == Usage
4
4
  #
5
5
  # campfire = Tinder::Campfire.new 'mysubdomain'
@@ -12,7 +12,9 @@ module Tinder
12
12
  # room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
13
13
  # room.speak 'Hello world!'
14
14
  class Campfire
15
- attr_reader :subdomain, :uri
15
+ HOST = "campfirenow.com"
16
+
17
+ attr_reader :connection, :subdomain, :uri
16
18
 
17
19
  # Create a new connection to the campfire account with the given +subdomain+.
18
20
  #
@@ -24,9 +26,11 @@ module Tinder
24
26
  # c = Tinder::Campfire.new("mysubdomain", :ssl => true)
25
27
  def initialize(subdomain, options = {})
26
28
  options = { :ssl => false }.merge(options)
29
+ @connection = Connection.new
27
30
  @cookie = nil
28
31
  @subdomain = subdomain
29
- @uri = URI.parse("#{options[:ssl] ? 'https' : 'http' }://#{subdomain}.campfirenow.com")
32
+ @uri = URI.parse("#{options[:ssl] ? 'https' : 'http' }://#{subdomain}.#{HOST}")
33
+ connection.base_uri @uri.to_s
30
34
  if options[:proxy]
31
35
  uri = URI.parse(options[:proxy])
32
36
  @http = Net::HTTP::Proxy(uri.host, uri.port, uri.user, uri.password)
@@ -35,173 +39,68 @@ module Tinder
35
39
  end
36
40
  @logged_in = false
37
41
  end
38
-
42
+
39
43
  # 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)
44
+ def login(username, password)
45
+ connection.basic_auth(username, password)
46
46
  @logged_in = true
47
47
  end
48
-
48
+
49
49
  # Returns true when successfully logged in
50
50
  def logged_in?
51
51
  @logged_in == true
52
52
  end
53
-
53
+
54
54
  def logout
55
- returning verify_response(get("logout"), :redirect) do |result|
56
- @logged_in = !result
57
- end
55
+ connection.default_options.delete(:basic_auth)
56
+ @logged_in = false
58
57
  end
59
-
58
+
60
59
  # Get an array of all the available rooms
61
60
  # TODO: detect rooms that are full (no link)
62
61
  def rooms
63
- Hpricot(get.body).search("//div.room").collect do |a|
64
- name = a.search("//h2/a").inner_html.strip
65
- name = a.search("//h2").inner_html.strip if name.empty?
66
- Room.new(self, room_id_from_element(a.attributes['id']), name)
62
+ connection.get('/rooms.json')['rooms'].map do |room|
63
+ Room.new(self, room)
67
64
  end
68
65
  end
69
-
66
+
70
67
  # Find a campfire room by name
71
68
  def find_room_by_name(name)
72
- rooms.detect {|room| room.name == name }
69
+ rooms.detect { |room| room.name == name }
73
70
  end
74
71
 
75
72
  # Find a campfire room by its guest hash
76
73
  def find_room_by_guest_hash(hash, name)
77
- res = post(hash, :name => name)
78
-
79
- Room.new(self, room_id_from_url(res['location'])) if verify_response(res, :redirect)
74
+ rooms.detect { |room| room.guest_invite_code == hash }
80
75
  end
81
-
76
+
82
77
  # Creates and returns a new Room with the given +name+ and optionally a +topic+
83
78
  def create_room(name, topic = nil)
84
- find_room_by_name(name) if verify_response(post("account/create/room?from=lobby", {:room => {:name => name, :topic => topic}}, :ajax => true), :success)
79
+ connection.post('/rooms.json', :body => { :room => { :name => name, :topic => topic } }.to_json)
80
+ find_room_by_name(name)
85
81
  end
86
-
82
+
87
83
  def find_or_create_room_by_name(name)
88
84
  find_room_by_name(name) || create_room(name)
89
85
  end
90
-
86
+
91
87
  # List the users that are currently chatting in any room
92
88
  def users(*room_names)
93
- users = Hpricot(get.body).search("div.room").collect do |room|
94
- if room_names.empty? || room_names.include?((room/"h2/a").inner_html)
95
- room.search("//li.user").collect { |user| user.inner_html }
96
- end
97
- end
98
- users.flatten.compact.uniq.sort
89
+ rooms.map(&:users).flatten.compact.uniq.sort
99
90
  end
100
-
91
+
101
92
  # Get the dates of the available transcripts by room
102
93
  #
103
94
  # campfire.available_transcripts
104
95
  # #=> {"15840" => [#<Date: 4908311/2,0,2299161>, #<Date: 4908285/2,0,2299161>]}
105
96
  #
106
97
  def available_transcripts(room = nil)
107
- url = "files%2Btranscripts"
108
- url += "?room_id#{room}" if room
109
- transcripts = (Hpricot(get(url).body) / ".transcript").inject({}) do |result,transcript|
110
- link = (transcript / "a").first.attributes['href']
111
- (result[room_id_from_url(link)] ||= []) << Date.parse(link.scan(/\/transcript\/(\d{4}\/\d{2}\/\d{2})/).to_s)
112
- result
113
- end
114
- room ? transcripts[room.to_s] : transcripts
98
+ raise NotImplementedError
115
99
  end
116
-
100
+
117
101
  # Is the connection to campfire using ssl?
118
102
  def ssl?
119
103
  uri.scheme == 'https'
120
104
  end
121
-
122
- private
123
-
124
- def room_id_from_url(url)
125
- url.scan(/room\/(\d*)/).to_s
126
- end
127
-
128
- def room_id_from_element(element)
129
- element.split("_").last
130
- end
131
-
132
- def url_for(*args)
133
- options = {:only_path => true}.merge(args.last.is_a?(Hash) ? args.pop : {})
134
- path = args.shift
135
- "#{options[:only_path] ? '' : uri}/#{path}"
136
- end
137
-
138
- def post(path, data = {}, options = {})
139
- perform_request(options) do
140
- returning Net::HTTP::Post.new(url_for(path)) do |request|
141
- if options[:multipart]
142
- request.body = data
143
- else
144
- request.set_form_data(flatten(data))
145
- end
146
- end
147
- end
148
- end
149
-
150
- def get(path = nil, options = {})
151
- perform_request(options) { Net::HTTP::Get.new(url_for(path)) }
152
- end
153
-
154
- def prepare_request(request, options = {})
155
- returning request do
156
- request.add_field 'User-Agent', "Tinder (http://tinder.rubyforge.org)"
157
- request.add_field 'Cookie', @cookie if @cookie
158
- request.add_field 'X-Requested-With', 'XMLHttpRequest'
159
- if options[:ajax]
160
- request.add_field 'X-Prototype-Version', '1.5.1.1'
161
- end
162
- if options[:multipart]
163
- request.add_field 'Content-Type', 'multipart/form-data, boundary=' + Multipart::MultipartPost::BOUNDARY + " "
164
- else
165
- request.add_field 'Content-Type', 'application/x-www-form-urlencoded'
166
- end
167
- end
168
- end
169
-
170
- def perform_request(options = {}, &block)
171
- @request = prepare_request(yield, options)
172
- http = @http.new(uri.host, uri.port)
173
- http.use_ssl = ssl?
174
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE if ssl?
175
- @response = returning http.request(@request) do |response|
176
- @cookie = response['set-cookie'] if response['set-cookie']
177
- end
178
- end
179
-
180
- # flatten a nested hash (:room => {:name => 'foobar'} to 'user[name]' => 'foobar')
181
- def flatten(params)
182
- params = params.dup
183
- params.stringify_keys!.each do |k,v|
184
- if v.is_a? Hash
185
- params.delete(k)
186
- v.each {|subk,v| params["#{k}[#{subk}]"] = v }
187
- end
188
- end
189
- end
190
-
191
- def verify_response(response, options = {})
192
- if options.is_a?(Symbol)
193
- codes = case options
194
- when :success; [200]
195
- when :redirect; 300..399
196
- else raise(ArgumentError, "Unknown response #{options}")
197
- end
198
- codes.include?(response.code.to_i)
199
- elsif options[:redirect_to]
200
- verify_response(response, :redirect) && response['location'] == options[:redirect_to]
201
- else
202
- false
203
- end
204
- end
205
-
206
105
  end
207
106
  end
@@ -0,0 +1,21 @@
1
+ require 'httparty'
2
+
3
+ module Tinder
4
+ class Connection
5
+ def initialize
6
+ class << self
7
+ include HTTParty
8
+
9
+ headers 'Content-Type' => 'application/json'
10
+ end
11
+ end
12
+
13
+ def metaclass
14
+ class << self; self; end
15
+ end
16
+
17
+ def method_missing(*args, &block)
18
+ metaclass.send(*args, &block)
19
+ end
20
+ end
21
+ end
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'mime/types'
3
2
  require 'net/http'
4
3
  require 'cgi'
@@ -41,7 +40,7 @@ module Multipart #:nodoc:
41
40
  @content + "\r\n"
42
41
  end
43
42
  end
44
-
43
+
45
44
  class MultipartPost #:nodoc:
46
45
  BOUNDARY = 'campfire-is-awesome'
47
46
  HEADER = {"Content-type" => "multipart/form-data, boundary=" + BOUNDARY + " "}
@@ -3,118 +3,96 @@ module Tinder
3
3
  class Room
4
4
  attr_reader :id, :name
5
5
 
6
- def initialize(campfire, id, name = nil)
6
+ def initialize(campfire, attributes = {})
7
7
  @campfire = campfire
8
- @id = id
9
- @name = name
8
+ @id = attributes['id']
9
+ @name = attributes['name']
10
+ @loaded = false
10
11
  end
11
-
12
+
12
13
  # Join the room. Pass +true+ to join even if you've already joined.
13
14
  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\":\s?\"([a-z0-9]+)\"/).to_s
17
- @user_id = room.body.scan(/\"userID\":\s?(\d+)/).to_s
18
- @last_cache_id = room.body.scan(/\"lastCacheID\":\s?(\d+)/).to_s
19
- @timestamp = room.body.scan(/\"timestamp\":\s?(\d+)/).to_s
20
- @idle_since = Time.now
21
- end if @room.nil? || force
22
- ping
23
- true
24
- end
25
-
15
+ post 'join'
16
+ end
17
+
26
18
  # Leave a room
27
19
  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
20
+ post 'leave'
31
21
  end
32
22
 
33
23
  # Toggle guest access on or off
34
24
  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)
25
+ raise NotImplementedError
37
26
  end
38
27
 
39
28
  # Get the url for guest access
40
29
  def guest_url
41
- join
42
- link = (Hpricot(@room.body)/"#guest_access h4").first
43
- link.inner_html if link
30
+ if guest_access_enabled?
31
+ "http://#{@campfire.subdomain}.campfirenow.com/#{guest_invite_code}"
32
+ else
33
+ nil
34
+ end
44
35
  end
45
-
36
+
46
37
  def guest_access_enabled?
47
- !guest_url.nil?
38
+ load
39
+ @open_to_guests ? true : false
48
40
  end
49
41
 
50
42
  # The invite code use for guest
51
43
  def guest_invite_code
52
- guest_url.scan(/\/(\w*)$/).to_s
44
+ load
45
+ @active_token_value
53
46
  end
54
47
 
55
48
  # Change the name of the room
56
49
  def name=(name)
57
- @name = name if verify_response(post("account/edit/room/#{id}", { :room => { :name => name }}, :ajax => true), :success)
50
+ connection.post("/room/#{@id}.json", :body => { :room => { :name => name } })
58
51
  end
59
52
  alias_method :rename, :name=
60
53
 
61
54
  # Change the topic
62
55
  def topic=(topic)
63
- topic if verify_response(post("room/#{id}/change_topic", { 'room' => { 'topic' => topic }}, :ajax => true), :success)
56
+ connection.post("/room/#{@id}.json", :body => { :room => { :topic => name } })
64
57
  end
65
-
58
+
66
59
  # Get the current topic
67
60
  def topic
68
- join
69
- h = (Hpricot(@room.body)/"#topic")
70
- if h
71
- (h/:span).remove
72
- h.inner_text.strip
73
- end
61
+ load
62
+ @topic
74
63
  end
75
-
64
+
76
65
  # Lock the room to prevent new users from entering and to disable logging
77
66
  def lock
78
- verify_response(post("room/#{id}/lock", {}, :ajax => true), :success)
67
+ post :lock
79
68
  end
80
69
 
81
70
  # Unlock the room
82
71
  def unlock
83
- verify_response(post("room/#{id}/unlock", {}, :ajax => true), :success)
72
+ post :unlock
84
73
  end
85
74
 
86
75
  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
76
+ raise NotImplementedError
90
77
  end
91
78
 
92
79
  def destroy
93
- verify_response(post("account/delete/room/#{id}"), :success)
80
+ raise NotImplementedError
94
81
  end
95
82
 
96
83
  # Post a new message to the chat room
97
84
  def speak(message, options = {})
98
- post_options = {
99
- :message => message,
100
- :t => Time.now.to_i
101
- }.merge(options)
102
-
103
- post_options.delete(:paste) unless post_options[:paste]
104
- response = post("room/#{id}/speak", post_options, :ajax => true)
105
-
106
- if verify_response(response, :success)
107
- message
108
- end
85
+ send_message(message)
109
86
  end
110
87
 
111
88
  def paste(message)
112
- speak message, :paste => true
89
+ send_message(message, 'PasteMassage')
113
90
  end
114
-
91
+
115
92
  # Get the list of users currently chatting for this room
116
93
  def users
117
- @campfire.users name
94
+ reload!
95
+ @users
118
96
  end
119
97
 
120
98
  # Get and array of the messages that have been posted to the room. Each
@@ -136,26 +114,22 @@ module Tinder
136
114
  # end
137
115
  #
138
116
  def listen(interval = 5)
139
- join
140
- if block_given?
141
- catch(:stop_listening) do
142
- trap('INT') { throw :stop_listening }
143
- loop do
144
- ping
145
- self.messages.each {|msg| yield msg }
146
- sleep interval
147
- end
148
- end
149
- else
150
- self.messages
117
+ require 'yajl/http_stream'
118
+
119
+ auth = connection.default_options[:basic_auth]
120
+ url = URI.parse("http://#{auth[:username]}:#{auth[:password]}@streaming.#{Campfire::HOST}/room/#{@id}/live.json")
121
+ Yajl::HttpStream.get(url) do |message|
122
+ { :id => message['id'],
123
+ :user_id => message['user_id'],
124
+ :message => message['body'] }
151
125
  end
152
126
  end
153
-
127
+
154
128
  # Get the dates for the available transcripts for this room
155
129
  def available_transcripts
156
- @campfire.available_transcripts(id)
130
+ raise NotImplementedError
157
131
  end
158
-
132
+
159
133
  # Get the transcript for the given date (Returns a hash in the same format as #listen)
160
134
  #
161
135
  # room.transcript(room.available_transcripts.first)
@@ -168,79 +142,64 @@ module Tinder
168
142
  # The timestamp slot will typically have a granularity of five minutes.
169
143
  #
170
144
  def transcript(transcript_date)
171
- url = "room/#{id}/transcript/#{transcript_date.to_date.strftime('%Y/%m/%d')}"
172
- date, time = nil, nil
173
- (Hpricot(get(url).body) / ".message").collect do |message|
174
- person = (message / '.person span').first
175
- if !person
176
- # No span for enter/leave the room messages
177
- person = (message / '.person').first
178
- end
179
- body = (message / '.body div').first
180
- if d = (message / '.date span').first
181
- date = d.inner_html
182
- end
183
- if t = (message / '.time div').first
184
- time = t.inner_html
185
- end
186
- {:id => message.attributes['id'].scan(/message_(\d+)/).to_s,
187
- :person => person ? person.inner_html : nil,
188
- :user_id => message.attributes['class'].scan(/user_(\d+)/).to_s,
189
- :message => body ? body.inner_html : nil,
190
- # Use the transcript_date to fill in the correct year
191
- :timestamp => Time.parse("#{date} #{time}", transcript_date)
192
- }
145
+ url = "/room/#{@id}/transcript/#{transcript_date.to_date.strftime('%Y/%m/%d')}.json"
146
+ connection.get(url)['messages'].map do |room|
147
+ { :id => room['id'],
148
+ :user_id => room['user_id'],
149
+ :message => room['body'],
150
+ :timestamp => Time.parse(room['created_at']) }
193
151
  end
194
152
  end
195
-
153
+
196
154
  def upload(filename)
197
155
  File.open(filename, "rb") do |file|
198
- params = Multipart::MultipartPost.new({'upload' => file, 'submit' => "Upload"})
199
- verify_response post("upload.cgi/room/#{@id}/uploads/new", params.query, :multipart => true), :success
156
+ params = Multipart::MultipartPost.new('upload' => file)
157
+ connection.post("/room/#{@id}/uploads.json", :body => params.query)
200
158
  end
201
159
  end
202
-
160
+
203
161
  # Get the list of latest files for this room
204
162
  def files(count = 5)
205
- join
206
- (Hpricot(@room.body)/"#file_list li a").to_a[0,count].map do |link|
207
- @campfire.send :url_for, link.attributes['href'][1..-1], :only_path => false
208
- end
163
+ connection.get(room_url_for(:uploads))['uploads'].map { |u| u['full_url'] }
209
164
  end
210
-
211
- protected
212
-
213
- def messages
214
- returning [] do |messages|
215
- response = post("poll.fcgi", {:l => @last_cache_id, :m => @membership_key,
216
- :s => @timestamp, :t => "#{Time.now.to_i}000"}, :ajax => true)
217
- if response.body.length > 1
218
- lines = response.body.split("\r\n")
219
-
220
- if lines.length > 0
221
- @last_cache_id = lines.pop.scan(/chat.poller.lastCacheID = (\d+)/).to_s
222
- lines.each do |msg|
223
- unless msg.match(/timestamp_message/)
224
- if msg.length > 0
225
- messages << {
226
- :id => msg.scan(/message_(\d+)/).to_s,
227
- :user_id => msg.scan(/user_(\d+)/).to_s,
228
- :person => msg.scan(/\\u003Ctd class=\\"person\\"\\u003E(?:\\u003Cspan\\u003E)?(.+?)(?:\\u003C\/span\\u003E)?\\u003C\/td\\u003E/).to_s,
229
- :message => msg.scan(/\\u003Ctd class=\\"body\\"\\u003E\\u003Cdiv\\u003E(.+?)\\u003C\/div\\u003E\\u003C\/td\\u003E/).to_s
230
- }
231
- end
232
- end
233
- end
234
- end
235
- end
165
+
166
+ protected
167
+ def load
168
+ reload! unless @loaded
236
169
  end
237
- end
238
-
239
- [:post, :get, :verify_response].each do |method|
240
- define_method method do |*args|
241
- @campfire.send method, *args
170
+
171
+ def reload!
172
+ attributes = connection.get("/room/#{@id}.json")['room']
173
+
174
+ @id = attributes['id']
175
+ @name = attributes['name']
176
+ @topic = attributes['topic']
177
+ @full = attributes['full']
178
+ @open_to_guests = attributes['open-to-guests']
179
+ @active_token_value = attributes['active-token-value']
180
+ @users = attributes['users'].map { |u| u['name'] }
181
+
182
+ @loaded = true
242
183
  end
243
- end
244
184
 
185
+ def send_message(message, type = 'Textmessage')
186
+ post 'speak', :body => {:message => {:body => message, :type => type}}.to_json
187
+ end
188
+
189
+ def get(action, options = {})
190
+ connection.get(room_url_for(action), options)
191
+ end
192
+
193
+ def post(action, options = {})
194
+ connection.post(room_url_for(action), options)
195
+ end
196
+
197
+ def room_url_for(action)
198
+ "/room/#{@id}/#{action}.json"
199
+ end
200
+
201
+ def connection
202
+ @campfire.connection
203
+ end
245
204
  end
246
205
  end
@@ -1,15 +1,15 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
1
+ require 'spec_helper'
2
2
 
3
3
  describe "Preparing a campfire request" do
4
4
  before do
5
5
  @campfire = Tinder::Campfire.new("foobar")
6
6
  @request = Net::HTTP::Get.new("does_not_matter")
7
7
  end
8
-
8
+
9
9
  def prepare_request
10
10
  @campfire.send(:prepare_request, @request)
11
11
  end
12
-
12
+
13
13
  it "should return the request" do
14
14
  prepare_request.should equal(@request)
15
15
  end
@@ -18,14 +18,14 @@ describe "Preparing a campfire request" do
18
18
  @campfire.instance_variable_set("@cookie", "foobar")
19
19
  prepare_request['Cookie'].should == 'foobar'
20
20
  end
21
-
21
+
22
22
  it "should set the user agent" do
23
23
  prepare_request['User-Agent'].should =~ /^Tinder/
24
24
  end
25
25
  end
26
26
 
27
27
  # describe "Performing a campfire request" do
28
- #
28
+ #
29
29
  # before do
30
30
  # @response = mock("response")
31
31
  # Net::HTTP.any_instance.stubs(:request).returns(response)
@@ -33,56 +33,56 @@ end
33
33
  # response.expects(:[]).with('set-cookie').and_return('foobar')
34
34
  # @campfire.send(:perform_request) { request }
35
35
  # end
36
- #
36
+ #
37
37
  # it "should set cookie" do
38
38
  # @campfire.instance_variable_get("@cookie").should == 'foobar'
39
39
  # end
40
- #
40
+ #
41
41
  # end
42
42
 
43
43
  describe "Verifying a 200 response" do
44
-
44
+
45
45
  before do
46
46
  @campfire = Tinder::Campfire.new("foobar")
47
47
  @response = mock("response")
48
48
  @response.should_receive(:code).and_return(200)
49
49
  end
50
-
50
+
51
51
  it "should return true when expecting success" do
52
52
  @campfire.send(:verify_response, @response, :success).should equal(true)
53
53
  end
54
-
54
+
55
55
  it "should return false when expecting a redirect" do
56
56
  @campfire.send(:verify_response, @response, :redirect).should equal(false)
57
57
  end
58
-
58
+
59
59
  it "should return false when expecting a redirect to a specific path" do
60
60
  @campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(false)
61
61
  end
62
-
62
+
63
63
  end
64
64
 
65
65
  describe "Verifying a 302 response" do
66
-
66
+
67
67
  before do
68
68
  @campfire = Tinder::Campfire.new("foobar")
69
69
  @response = mock("response")
70
70
  @response.should_receive(:code).and_return(302)
71
71
  end
72
-
72
+
73
73
  it "should return true when expecting redirect" do
74
74
  @campfire.send(:verify_response, @response, :redirect).should equal(true)
75
75
  end
76
-
76
+
77
77
  it "should return false when expecting success" do
78
78
  @campfire.send(:verify_response, @response, :success).should equal(false)
79
79
  end
80
-
80
+
81
81
  it "should return true when expecting a redirect to a specific path" do
82
82
  @response.should_receive(:[]).with('location').and_return("/foobar")
83
83
  @campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(true)
84
84
  end
85
-
85
+
86
86
  it "should return false when redirecting to a different path than expected" do
87
87
  @response.should_receive(:[]).with('location').and_return("/baz")
88
88
  @campfire.send(:verify_response, @response, :redirect_to => '/foobar').should equal(false)
@@ -91,7 +91,7 @@ describe "Verifying a 302 response" do
91
91
  end
92
92
 
93
93
  describe "A failed login" do
94
-
94
+
95
95
  before do
96
96
  @campfire = Tinder::Campfire.new 'foobar'
97
97
  @response = mock("response")
@@ -99,18 +99,18 @@ describe "A failed login" do
99
99
  @response.should_receive(:code).and_return("302")
100
100
  @response.should_receive(:[]).with("location").and_return("/login")
101
101
  end
102
-
102
+
103
103
  it "should raise an error" do
104
104
  lambda do
105
105
  @campfire.login "doesn't", "matter"
106
106
  end.should raise_error(Tinder::Error)
107
107
  end
108
-
108
+
109
109
  it "should not set logged in status" do
110
110
  @campfire.login 'foo', 'bar' rescue
111
111
  @campfire.logged_in?.should equal(false)
112
112
  end
113
-
113
+
114
114
  end
115
115
 
116
116
  describe "Accessing a room with guest access" do
@@ -151,40 +151,40 @@ describe "Accessing a room" do
151
151
  end
152
152
 
153
153
  describe "when the room is full" do
154
-
154
+
155
155
  before do
156
156
  @html = File.read(File.dirname(__FILE__) + '/html/full_lobby.html')
157
157
  @response.stub!(:body).and_return(@html)
158
158
  @campfire = Tinder::Campfire.new 'foobar'
159
159
  end
160
-
160
+
161
161
  it "should return a room" do
162
162
  @campfire.rooms.should_not be_empty
163
163
  end
164
-
164
+
165
165
  it "should find a room by name" do
166
166
  @campfire.find_room_by_name("Just Fishin").class.should == Tinder::Room
167
167
  end
168
-
168
+
169
169
  end
170
170
 
171
171
  describe "when the room is not full" do
172
-
172
+
173
173
  before do
174
174
  @html = File.read(File.dirname(__FILE__) + '/html/normal_lobby.html')
175
175
  @response.stub!(:body).and_return(@html)
176
176
  @campfire = Tinder::Campfire.new 'foobar'
177
177
  end
178
-
178
+
179
179
  it "should return a room" do
180
180
  @campfire.rooms.should_not be_empty
181
181
  end
182
-
182
+
183
183
  it "should find a room by name" do
184
184
  @campfire.find_room_by_name("Just Fishin").class.should == Tinder::Room
185
185
  end
186
186
  end
187
-
187
+
188
188
  end
189
189
 
190
190
  describe "Accessing a room's transcript" do
@@ -216,7 +216,7 @@ describe "Accessing a room's transcript" do
216
216
  @transcript.second[:timestamp].should == Time.parse("2009-05-05 09:35")
217
217
  end
218
218
  end
219
-
219
+
220
220
  describe "when entering the room" do
221
221
  it "a transcript message should include the person who entered" do
222
222
  @transcript.second[:person].should == "Marcel"
@@ -1,4 +1,3 @@
1
- $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
2
1
  require 'rubygems'
3
2
  require 'spec'
4
3
  require 'tinder'
@@ -1,8 +1,8 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
- require File.dirname(__FILE__) + '/credentials'
1
+ require 'test_helper'
2
+ require 'remote/credentials'
3
3
 
4
4
  class RemoteCampfireTest < Test::Unit::TestCase
5
-
5
+
6
6
  def setup
7
7
  @subdomain = SUBDOMAIN
8
8
  @user, @pass = USER, PASS
@@ -10,7 +10,7 @@ class RemoteCampfireTest < Test::Unit::TestCase
10
10
  raise "Set your campfire credentials in /test/remote/credentials.rb before running the remote tests" unless @user && @pass && @subdomain
11
11
  @campfire = Tinder::Campfire.new @subdomain, :ssl => @ssl
12
12
  end
13
-
13
+
14
14
  def test_ssl_required
15
15
  if @ssl
16
16
  campfire = Tinder::Campfire.new @subdomain
@@ -19,32 +19,32 @@ class RemoteCampfireTest < Test::Unit::TestCase
19
19
  end
20
20
  end
21
21
  end
22
-
22
+
23
23
  def test_create_and_delete_room
24
24
  assert login
25
25
  assert @campfire.logged_in?
26
-
26
+
27
27
  room = @campfire.create_room("Testing#{Time.now.to_i}")
28
-
28
+
29
29
  assert_instance_of Tinder::Room, room
30
30
  assert_not_nil room.id
31
-
31
+
32
32
  room.name = "new name"
33
33
  assert_equal "new name", room.name
34
-
34
+
35
35
  room.destroy
36
36
  assert_nil @campfire.find_room_by_name(room.name)
37
-
37
+
38
38
  assert @campfire.logout
39
39
  ensure
40
40
  room.destroy rescue nil
41
41
  end
42
-
42
+
43
43
  def test_failed_login
44
44
  assert_raises(Tinder::Error) { @campfire.login(@user, 'notmypassword') }
45
45
  assert !@campfire.logged_in?
46
46
  end
47
-
47
+
48
48
  def test_find_nonexistent_room
49
49
  login
50
50
  assert_nil @campfire.find_room_by_name('No Room Should Have This Name')
@@ -55,5 +55,5 @@ private
55
55
  def login(user = @user, pass = @pass)
56
56
  @campfire.login(user, pass)
57
57
  end
58
-
59
- end
58
+
59
+ end
@@ -1,3 +1,2 @@
1
1
  require 'test/unit'
2
- require 'rubygems'
3
- require File.dirname(__FILE__) + '/../lib/tinder.rb'
2
+ require 'tinder'
@@ -1,15 +1,15 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tinder}
8
- s.version = "1.2.2"
8
+ s.version = "1.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Brandon Keepers"]
12
- s.date = %q{2009-09-12}
12
+ s.date = %q{2009-12-17}
13
13
  s.description = %q{An API for interfacing with Campfire, the 37Signals chat application.}
14
14
  s.email = %q{brandon@opensoul.org}
15
15
  s.extra_rdoc_files = [
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
25
25
  "init.rb",
26
26
  "lib/tinder.rb",
27
27
  "lib/tinder/campfire.rb",
28
+ "lib/tinder/connection.rb",
28
29
  "lib/tinder/multipart.rb",
29
30
  "lib/tinder/room.rb",
30
31
  "site/index.html",
@@ -44,7 +45,7 @@ Gem::Specification.new do |s|
44
45
  s.rdoc_options = ["--charset=UTF-8"]
45
46
  s.require_paths = ["lib"]
46
47
  s.rubyforge_project = %q{tinder}
47
- s.rubygems_version = %q{1.3.3}
48
+ s.rubygems_version = %q{1.3.5}
48
49
  s.summary = %q{An (unofficial) Campfire API}
49
50
  s.test_files = [
50
51
  "spec/campfire_spec.rb",
@@ -59,19 +60,17 @@ Gem::Specification.new do |s|
59
60
 
60
61
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
61
62
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
62
- s.add_runtime_dependency(%q<hpricot>, [">= 0"])
63
63
  s.add_runtime_dependency(%q<mime-types>, [">= 0"])
64
64
  s.add_development_dependency(%q<rspec>, [">= 0"])
65
65
  else
66
66
  s.add_dependency(%q<activesupport>, [">= 0"])
67
- s.add_dependency(%q<hpricot>, [">= 0"])
68
67
  s.add_dependency(%q<mime-types>, [">= 0"])
69
68
  s.add_dependency(%q<rspec>, [">= 0"])
70
69
  end
71
70
  else
72
71
  s.add_dependency(%q<activesupport>, [">= 0"])
73
- s.add_dependency(%q<hpricot>, [">= 0"])
74
72
  s.add_dependency(%q<mime-types>, [">= 0"])
75
73
  s.add_dependency(%q<rspec>, [">= 0"])
76
74
  end
77
75
  end
76
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tinder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Keepers
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-12 00:00:00 -04:00
12
+ date: 2009-12-17 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,16 +22,6 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- - !ruby/object:Gem::Dependency
26
- name: hpricot
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
35
25
  - !ruby/object:Gem::Dependency
36
26
  name: mime-types
37
27
  type: :runtime
@@ -70,6 +60,7 @@ files:
70
60
  - init.rb
71
61
  - lib/tinder.rb
72
62
  - lib/tinder/campfire.rb
63
+ - lib/tinder/connection.rb
73
64
  - lib/tinder/multipart.rb
74
65
  - lib/tinder/room.rb
75
66
  - site/index.html
@@ -108,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
99
  requirements: []
109
100
 
110
101
  rubyforge_project: tinder
111
- rubygems_version: 1.3.3
102
+ rubygems_version: 1.3.5
112
103
  signing_key:
113
104
  specification_version: 3
114
105
  summary: An (unofficial) Campfire API