tinder 0.1.6 → 0.1.8

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