tinder 0.1.6 → 0.1.8

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.
@@ -1,3 +1,14 @@
1
+ 0.1.8
2
+ * Get the list of available files [Christopher MacGown]
3
+ * Upload files [Joshua Want]
4
+ * Find rooms even when full [Josh Owens]
5
+ * Join rooms as a guest [Ian Lesperance]
6
+
7
+ 0.1.7 - 2008-07-24
8
+ * Don't join the room when only speaking [Brian Donovan]
9
+ * Added support for HTTP proxies
10
+ * Fix listening for messages that contain URLs [Jared Kuolt]
11
+
1
12
  0.1.6 - 2008-03-07
2
13
  * Added Room#topic for getting the current topic [Even Weaver]
3
14
  * Trap INT in #listen(&block) [borrowed from Chris Shea's Pyre]
data/README.txt CHANGED
@@ -6,11 +6,15 @@ Tinder is a library for interfacing with Campfire, the chat application from 37S
6
6
 
7
7
  campfire = Campfire.new 'mysubdomain'
8
8
  campfire.login 'myemail@example.com', 'mypassword'
9
+
9
10
  room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
10
11
  room.rename 'New Room Name'
11
12
  room.speak 'Hello world!'
12
13
  room.paste "my pasted\ncode"
13
14
  room.destroy
15
+
16
+ room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
17
+ room.speak 'Hello world!'
14
18
 
15
19
  See the RDoc for more details.
16
20
 
@@ -36,5 +40,4 @@ The source for Tinder is available at http://source.collectiveidea.com/public/ti
36
40
  == ToDo
37
41
 
38
42
  * Tests! (unit and remote)
39
- * Log in via guest url
40
43
  * Marshmallow-style integration scripts for exception notification and continuous integration
data/Rakefile CHANGED
@@ -1,5 +1,12 @@
1
1
  require 'rubygems'
2
2
  require 'hoe'
3
+ begin
4
+ require 'spec/rake/spectask'
5
+ rescue LoadError
6
+ puts 'To use rspec for testing you must install rspec gem:'
7
+ puts '$ sudo gem install rspec'
8
+ exit
9
+ end
3
10
  require File.join(File.dirname(__FILE__), 'lib', 'tinder', 'version')
4
11
 
5
12
  # RDOC_OPTS = ['--quiet', '--title', "Tinder",
@@ -21,4 +28,14 @@ hoe = Hoe.new('tinder', ENV['VERSION'] || Tinder::VERSION::STRING) do |p|
21
28
  p.changes = p.paragraphs_of('CHANGELOG.txt', 0..1).join("\n\n")
22
29
  p.extra_deps << ['activesupport']
23
30
  p.extra_deps << ['hpricot']
31
+ p.extra_deps << ['mime-types']
32
+ end
33
+
34
+ desc "Run the specs under spec"
35
+ Spec::Rake::SpecTask.new do |t|
36
+ t.spec_opts = ['--options', "spec/spec.opts"]
37
+ t.spec_files = FileList['spec/**/*_spec.rb']
24
38
  end
39
+
40
+ desc "Default task is to run specs"
41
+ task :default => :spec
@@ -10,4 +10,5 @@ Dir[File.join(File.dirname(__FILE__), 'tinder/**/*.rb')].sort.each { |lib| requi
10
10
 
11
11
  module Tinder
12
12
  class Error < StandardError; end
13
+ class SSLRequiredError < Error; end
13
14
  end
@@ -4,14 +4,22 @@ module Tinder
4
4
  #
5
5
  # campfire = Tinder::Campfire.new 'mysubdomain'
6
6
  # campfire.login 'myemail@example.com', 'mypassword'
7
+ #
7
8
  # room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
8
9
  # room.speak 'Hello world!'
9
10
  # room.destroy
11
+ #
12
+ # room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
13
+ # room.speak 'Hello world!'
10
14
  class Campfire
11
15
  attr_reader :subdomain, :uri
12
16
 
13
17
  # Create a new connection to the campfire account with the given +subdomain+.
14
- # There's an +:ssl+ option to use SSL for the connection.
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')
15
23
  #
16
24
  # c = Tinder::Campfire.new("mysubdomain", :ssl => true)
17
25
  def initialize(subdomain, options = {})
@@ -19,6 +27,12 @@ module Tinder
19
27
  @cookie = nil
20
28
  @subdomain = subdomain
21
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
22
36
  @logged_in = false
23
37
  end
24
38
 
@@ -27,12 +41,14 @@ module Tinder
27
41
  unless verify_response(post("login", :email_address => email, :password => password), :redirect_to => url_for(:only_path => false))
28
42
  raise Error, "Campfire login failed"
29
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)
30
46
  @logged_in = true
31
47
  end
32
48
 
33
49
  # Returns true when successfully logged in
34
50
  def logged_in?
35
- @logged_in === true
51
+ @logged_in == true
36
52
  end
37
53
 
38
54
  def logout
@@ -44,8 +60,10 @@ module Tinder
44
60
  # Get an array of all the available rooms
45
61
  # TODO: detect rooms that are full (no link)
46
62
  def rooms
47
- Hpricot(get.body).search("//h2/a").collect do |a|
48
- Room.new(self, room_id_from_url(a.attributes['href']), a.inner_html)
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)
49
67
  end
50
68
  end
51
69
 
@@ -53,6 +71,13 @@ module Tinder
53
71
  def find_room_by_name(name)
54
72
  rooms.detect {|room| room.name == name }
55
73
  end
74
+
75
+ # Find a campfire room by its guest hash
76
+ 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)
80
+ end
56
81
 
57
82
  # Creates and returns a new Room with the given +name+ and optionally a +topic+
58
83
  def create_room(name, topic = nil)
@@ -99,6 +124,10 @@ module Tinder
99
124
  def room_id_from_url(url)
100
125
  url.scan(/room\/(\d*)/).to_s
101
126
  end
127
+
128
+ def room_id_from_element(element)
129
+ element.split("_").last
130
+ end
102
131
 
103
132
  def url_for(*args)
104
133
  options = {:only_path => true}.merge(args.last.is_a?(Hash) ? args.pop : {})
@@ -109,8 +138,11 @@ module Tinder
109
138
  def post(path, data = {}, options = {})
110
139
  perform_request(options) do
111
140
  returning Net::HTTP::Post.new(url_for(path)) do |request|
112
- request.add_field 'Content-Type', 'application/x-www-form-urlencoded'
113
- request.set_form_data flatten(data)
141
+ if options[:multipart]
142
+ request.body = data
143
+ else
144
+ request.set_form_data(flatten(data))
145
+ end
114
146
  end
115
147
  end
116
148
  end
@@ -127,12 +159,17 @@ module Tinder
127
159
  request.add_field 'X-Requested-With', 'XMLHttpRequest'
128
160
  request.add_field 'X-Prototype-Version', '1.5.1.1'
129
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
130
167
  end
131
168
  end
132
169
 
133
170
  def perform_request(options = {}, &block)
134
171
  @request = prepare_request(yield, options)
135
- http = Net::HTTP.new(uri.host, uri.port)
172
+ http = @http.new(uri.host, uri.port)
136
173
  http.use_ssl = ssl?
137
174
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE if ssl?
138
175
  @response = returning http.request(@request) do |response|
@@ -154,9 +191,9 @@ module Tinder
154
191
  def verify_response(response, options = {})
155
192
  if options.is_a?(Symbol)
156
193
  codes = case options
157
- when :success then [200]
158
- when :redirect then 300..399
159
- else raise ArgumentError.new("Unknown response #{options}")
194
+ when :success; [200]
195
+ when :redirect; 300..399
196
+ else raise(ArgumentError, "Unknown response #{options}")
160
197
  end
161
198
  codes.include?(response.code.to_i)
162
199
  elsif options[:redirect_to]
@@ -44,13 +44,11 @@ module Tinder
44
44
  end
45
45
 
46
46
  def guest_access_enabled?
47
- join
48
47
  !guest_url.nil?
49
48
  end
50
49
 
51
50
  # The invite code use for guest
52
51
  def guest_invite_code
53
- join
54
52
  guest_url.scan(/\/(\w*)$/).to_s
55
53
  end
56
54
 
@@ -97,13 +95,20 @@ module Tinder
97
95
 
98
96
  # Post a new message to the chat room
99
97
  def speak(message, options = {})
100
- join
101
- message if verify_response(post("room/#{id}/speak", {:message => message,
102
- :t => Time.now.to_i}.merge(options), :ajax => true), :success)
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
103
109
  end
104
110
 
105
111
  def paste(message)
106
- join
107
112
  speak message, :paste => true
108
113
  end
109
114
 
@@ -111,7 +116,7 @@ module Tinder
111
116
  def users
112
117
  @campfire.users name
113
118
  end
114
-
119
+
115
120
  # Get and array of the messages that have been posted to the room. Each
116
121
  # messages is a hash with:
117
122
  # * +:person+: the display name of the person that posted the message
@@ -167,25 +172,35 @@ module Tinder
167
172
  }
168
173
  end
169
174
  end
170
-
175
+
176
+ def upload(filename)
177
+ File.open(filename, "rb") do |file|
178
+ params = Multipart::MultipartPost.new({'upload' => file, 'submit' => "Upload"})
179
+ verify_response post("upload.cgi/room/#{@id}/uploads/new", params.query, :multipart => true), :success
180
+ end
181
+ end
182
+
183
+ # Get the list of latest files for this room
184
+ def files(count = 5)
185
+ join
186
+ (Hpricot(@room.body)/"#file_list li a").to_a[0,count].map do |link|
187
+ @campfire.send :url_for, link.attributes['href'][1..-1], :only_path => false
188
+ end
189
+ end
190
+
171
191
  protected
172
-
192
+
173
193
  def messages
174
194
  returning [] do |messages|
175
195
  response = post("poll.fcgi", {:l => @last_cache_id, :m => @membership_key,
176
196
  :s => @timestamp, :t => "#{Time.now.to_i}000"}, :ajax => true)
177
197
  if response.body.length > 1
178
- # deal with "chat.redirectTo('/');" - relogin
179
- join(true) && self.messages if response.body.match('chat\.redirectTo')
180
-
181
198
  lines = response.body.split("\r\n")
182
199
 
183
200
  if lines.length > 0
184
201
  @last_cache_id = lines.pop.scan(/chat.poller.lastCacheID = (\d+)/).to_s
185
202
  lines.each do |msg|
186
203
  unless msg.match(/timestamp_message/)
187
- # pull out only the chat.transcript.queueMessage part for now
188
- msg = msg.scan(/(chat\.transcript\.queueMessage(?:.+?);)/).to_s
189
204
  if msg.length > 0
190
205
  messages << {
191
206
  :id => msg.scan(/message_(\d+)/).to_s,
@@ -2,7 +2,7 @@ module Tinder #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 6
5
+ TINY = 8
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -3,9 +3,20 @@ require File.dirname(__FILE__) + '/../test_helper'
3
3
  class RemoteCampfireTest < Test::Unit::TestCase
4
4
 
5
5
  def setup
6
- @campfire = Tinder::Campfire.new 'domain'
6
+ # @subdomain = 'domain'
7
7
  # @user, @pass = 'email@example.com', 'password'
8
- raise "Set your campfire credentials before running the remote tests" unless @user && @pass
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
9
20
  end
10
21
 
11
22
  def test_create_and_delete_room
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: 0.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Keepers
@@ -9,11 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-03-07 00:00:00 -05:00
12
+ date: 2009-01-28 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -23,6 +24,17 @@ dependencies:
23
24
  version:
24
25
  - !ruby/object:Gem::Dependency
25
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
+ - !ruby/object:Gem::Dependency
36
+ name: mime-types
37
+ type: :runtime
26
38
  version_requirement:
27
39
  version_requirements: !ruby/object:Gem::Requirement
28
40
  requirements:
@@ -32,12 +44,13 @@ dependencies:
32
44
  version:
33
45
  - !ruby/object:Gem::Dependency
34
46
  name: hoe
47
+ type: :development
35
48
  version_requirement:
36
49
  version_requirements: !ruby/object:Gem::Requirement
37
50
  requirements:
38
51
  - - ">="
39
52
  - !ruby/object:Gem::Version
40
- version: 1.5.1
53
+ version: 1.8.2
41
54
  version:
42
55
  description: An API for interfacing with Campfire, the 37Signals chat application.
43
56
  email: brandon@opensoul.org
@@ -82,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
95
  requirements: []
83
96
 
84
97
  rubyforge_project: tinder
85
- rubygems_version: 1.0.1
98
+ rubygems_version: 1.3.1
86
99
  signing_key:
87
100
  specification_version: 2
88
101
  summary: An (unofficial) Campfire API