tinder 0.1.2 → 0.1.3

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 CHANGED
@@ -1,3 +1,6 @@
1
+ 0.1.3
2
+ * added ssl support [Tero Parviainen]
3
+
1
4
  0.1.2 - 2007-01-27
2
5
  * fixed bug preventing #listen from working without a block
3
6
 
data/README.txt CHANGED
@@ -1,14 +1,18 @@
1
- = Tinder
1
+ = Tinder - get the Campfire started
2
2
 
3
- Tinder is a library for interfacing with Campfire, the chat application from 37Signals.
3
+ 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
+
5
+ == Usage
4
6
 
5
7
  campfire = Campfire.new 'mysubdomain'
6
8
  campfire.login 'myemail@example.com', 'mypassword'
7
9
  room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
8
10
  room.rename 'New Room Name'
9
11
  room.speak 'Hello world!'
10
- room.speak "my pasted\ncode", :paste => true
12
+ room.paste "my pasted\ncode"
11
13
  room.destroy
14
+
15
+ See the RDoc for more details.
12
16
 
13
17
  == Requirements
14
18
 
@@ -16,9 +20,21 @@ Tinder is a library for interfacing with Campfire, the chat application from 37S
16
20
  gem install activesupport
17
21
  * Hpricot
18
22
  gem install hpricot
23
+
24
+ == Installation
25
+
26
+ Tinder can be installed as a gem or a Rails plugin:
27
+
28
+ gem install tinder
29
+
30
+ script/plugin install http://source.collectiveidea.com/public/tinder/trunk
31
+
32
+ == Development
33
+
34
+ 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!
19
35
 
20
36
  == ToDo
21
37
 
22
38
  * Tests! (unit and remote)
23
39
  * Log in via guest url
24
- * SSL
40
+ * Marshmallow-style integration scripts for exception notification and continuous integration
data/lib/tinder.rb CHANGED
@@ -1,7 +1,9 @@
1
1
 
2
2
  require 'rubygems'
3
3
  require 'active_support'
4
+ require 'uri'
4
5
  require 'net/http'
6
+ require 'net/https'
5
7
  require 'open-uri'
6
8
  require 'hpricot'
7
9
 
@@ -2,41 +2,52 @@ module Tinder
2
2
 
3
3
  # == Usage
4
4
  #
5
- # campfire = Campfire.new 'mysubdomain'
5
+ # campfire = Tinder::Campfire.new 'mysubdomain'
6
6
  # campfire.login 'myemail@example.com', 'mypassword'
7
7
  # room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
8
8
  # room.speak 'Hello world!'
9
9
  # room.destroy
10
10
  class Campfire
11
- attr_accessor :subdomain, :host
11
+ attr_reader :subdomain, :uri
12
12
 
13
- def initialize(subdomain)
13
+ # Create a new connection to the campfire account with the given +subdomain+.
14
+ # There's an optional +:ssl+ option to use SSL for the connection.
15
+ #
16
+ # c = Tinder::Campfire.new("mysubdomain", :ssl => true)
17
+ def initialize(subdomain, options = {})
18
+ options = { :ssl => false }.merge(options)
14
19
  @cookie = nil
15
- self.subdomain = subdomain
16
- self.host = "#{subdomain}.campfirenow.com"
20
+ @subdomain = subdomain
21
+ @uri = URI.parse("#{options[:ssl] ? 'https' : 'http' }://#{subdomain}.campfirenow.com")
17
22
  end
18
-
23
+
24
+ # Log in to campfire using your +email+ and +password+
19
25
  def login(email, password)
20
26
  @logged_in = verify_response(post("login", :email_address => email, :password => password), :redirect_to => url_for)
21
27
  end
22
-
28
+
23
29
  def logged_in?
24
30
  @logged_in
25
31
  end
26
32
 
27
33
  def logout
28
- @logged_in = !verify_response(get("logout"), :redirect)
34
+ returning verify_response(get("logout"), :redirect) do |result|
35
+ @logged_in = !result
36
+ end
29
37
  end
30
38
 
39
+ # Creates and returns a new Room with the given +name+ and optionally a +topic+
31
40
  def create_room(name, topic = nil)
32
41
  find_room_by_name(name) if verify_response(post("account/create/room?from=lobby", {:room => {:name => name, :topic => topic}}, :ajax => true), :success)
33
42
  end
34
-
43
+
44
+ # Find a campfire room by name
35
45
  def find_room_by_name(name)
36
46
  link = Hpricot(get.body).search("//h2/a").detect { |a| a.inner_html == name }
37
47
  link.blank? ? nil : Room.new(self, link.attributes['href'].scan(/room\/(\d*)$/).to_s, name)
38
48
  end
39
-
49
+
50
+ # List the users that are currently chatting in any room
40
51
  def users(*room_names)
41
52
  users = Hpricot(get.body).search("div.room").collect do |room|
42
53
  if room_names.empty? || room_names.include?((room/"h2/a").inner_html)
@@ -46,37 +57,52 @@ module Tinder
46
57
  users.flatten.compact.uniq.sort
47
58
  end
48
59
 
60
+ # Deprecated: only included for backwards compatability
61
+ def host #:nodoc:
62
+ uri.host
63
+ end
64
+
65
+ # Is the connection to campfire using ssl?
66
+ def ssl?
67
+ uri.scheme == 'https'
68
+ end
69
+
49
70
  private
50
71
 
51
72
  def url_for(path = "")
52
- "http://#{host}/#{path}"
73
+ "#{uri}/#{path}"
53
74
  end
54
75
 
55
76
  def post(path, data = {}, options = {})
56
- @request = returning Net::HTTP::Post.new(url_for(path)) do |request|
57
- prepare_request(request, options)
58
- request.add_field 'Content-Type', 'application/x-www-form-urlencoded'
59
- request.set_form_data flatten(data)
60
- end
61
- returning @response = Net::HTTP.new(host, 80).start { |http| http.request(@request) } do |response|
62
- @cookie = response['set-cookie'] if response['set-cookie']
77
+ perform_request(options) do
78
+ returning Net::HTTP::Post.new(url_for(path)) do |request|
79
+ request.add_field 'Content-Type', 'application/x-www-form-urlencoded'
80
+ request.set_form_data flatten(data)
81
+ end
63
82
  end
64
83
  end
65
84
 
66
85
  def get(path = nil, options = {})
67
- @request = returning Net::HTTP::Get.new(url_for(path)) do |request|
68
- prepare_request(request, options)
69
- end
70
- returning @response = Net::HTTP.new(host, 80).start { |http| http.request(@request) } do |response|
71
- @cookie = response['set-cookie'] if response['set-cookie']
72
- end
86
+ perform_request(options) { Net::HTTP::Get.new(url_for(path)) }
73
87
  end
74
88
 
75
89
  def prepare_request(request, options = {})
76
- request.add_field 'Cookie', @cookie if @cookie
77
- if options[:ajax]
78
- request.add_field 'X-Requested-With', 'XMLHttpRequest'
79
- request.add_field 'X-Prototype-Version', '1.5.0_rc1'
90
+ returning request do
91
+ request.add_field 'Cookie', @cookie if @cookie
92
+ if options[:ajax]
93
+ request.add_field 'X-Requested-With', 'XMLHttpRequest'
94
+ request.add_field 'X-Prototype-Version', '1.5.0_rc1'
95
+ end
96
+ end
97
+ end
98
+
99
+ def perform_request(options = {}, &block)
100
+ @request = prepare_request(yield, options)
101
+ http = Net::HTTP.new(uri.host, uri.port)
102
+ http.use_ssl = ssl?
103
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if ssl?
104
+ @response = returning http.request(@request) do |response|
105
+ @cookie = response['set-cookie'] if response['set-cookie']
80
106
  end
81
107
  end
82
108
 
@@ -93,11 +119,12 @@ module Tinder
93
119
 
94
120
  def verify_response(response, options = {})
95
121
  if options.is_a?(Symbol)
96
- case options
122
+ codes = case options
97
123
  when :success then [200]
98
124
  when :redirect then 300..399
99
125
  else raise ArgumentError.new("Unknown response #{options}")
100
- end.include?(response.code.to_i)
126
+ end
127
+ codes.include?(response.code.to_i)
101
128
  elsif options[:redirect_to]
102
129
  verify_response(response, :redirect) && response['location'] == options[:redirect_to]
103
130
  else
data/lib/tinder/room.rb CHANGED
@@ -1,67 +1,110 @@
1
1
  module Tinder
2
+ # A campfire room
2
3
  class Room
3
- attr_accessor :id, :name
4
+ attr_reader :id, :name
4
5
 
5
6
  def initialize(campfire, id, name = nil)
6
7
  @campfire = campfire
7
- self.id = id
8
- self.name = name
9
- @room = get("room/#{self.id}")
10
- @membership_key = @room.body.scan(/\"membershipKey\": \"([a-z0-9]+)\"/).to_s
11
- @user_id = @room.body.scan(/\"userID\": (\d+)/).to_s
12
- @last_cache_id = @room.body.scan(/\"lastCacheID\": (\d+)/).to_s
13
- @timestamp = @room.body.scan(/\"timestamp\": (\d+)/).to_s
8
+ @id = id
9
+ @name = name
14
10
  end
15
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
+ return false 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
+ end unless @room || force
21
+ true
22
+ end
23
+
24
+ # Leave a room
16
25
  def leave
17
- verify_response get("/room/#{@room_id}/leave"), :redirect
26
+ returning verify_response(get("room/#{id}/leave"), :redirect) do
27
+ @room, @membership_key, @user_id, @last_cache_id, @timestamp = nil
28
+ end
18
29
  end
19
30
 
31
+ # Toggle guest access on or off
20
32
  def toggle_guest_access
21
- verify_response(post("room/#{self.id}/toggle_guest_access"), :success)
33
+ verify_response(post("room/#{id}/toggle_guest_access"), :success)
22
34
  end
23
35
 
36
+ # Get the url for guest access
24
37
  def guest_url
25
- (Hpricot(get("room/#{self.id}").body)/"#guest_access h4").first.inner_html
38
+ join
39
+ (Hpricot(@room.body)/"#guest_access h4").first.inner_html
26
40
  end
27
41
 
42
+ # The invite code use for guest
28
43
  def guest_invite_code
29
- guest_url.scan(/^http:\/\/#{@campfire.host}\/(\w*)$/).to_s
44
+ guest_url.scan(/\/(\w*)$/).to_s
30
45
  end
31
46
 
32
- def rename(name)
33
- name if verify_response(post("account/edit/room/#{self.id}", { :room => { :name => name }}, :ajax => true), :success)
47
+ # Change the name of the room
48
+ def name=(name)
49
+ @name = name if verify_response(post("account/edit/room/#{id}", { :room => { :name => name }}, :ajax => true), :success)
34
50
  end
51
+ alias_method :rename, :name=
35
52
 
53
+ # Change the topic
36
54
  def topic=(topic)
37
- topic if verify_response(post("room/#{self.id}/change_topic", { 'room' => { 'topic' => topic }}, :ajax => true), :success)
55
+ topic if verify_response(post("room/#{id}/change_topic", { 'room' => { 'topic' => topic }}, :ajax => true), :success)
38
56
  end
39
-
57
+
58
+ # Lock the room to prevent new users from entering and to disable logging
40
59
  def lock
41
- verify_response(post("room/#{self.id}/lock", {}, :ajax => true), :success)
60
+ verify_response(post("room/#{id}/lock", {}, :ajax => true), :success)
42
61
  end
43
62
 
63
+ # Unlock the room
44
64
  def unlock
45
- verify_response(post("room/#{self.id}/unlock", {}, :ajax => true), :success)
65
+ verify_response(post("room/#{id}/unlock", {}, :ajax => true), :success)
46
66
  end
47
67
 
48
68
  def destroy
49
- verify_response(post("account/delete/room/#{self.id}"), :success)
69
+ verify_response(post("account/delete/room/#{id}"), :success)
50
70
  end
51
71
 
72
+ # Post a new message to the chat room
52
73
  def speak(message)
74
+ join
53
75
  send message
54
76
  end
55
-
77
+
56
78
  def paste(message)
79
+ join
57
80
  send message, { :paste => true }
58
81
  end
59
-
82
+
83
+ # Get the list of users currently chatting for this room
60
84
  def users
61
- @campfire.users self.name
85
+ @campfire.users name
62
86
  end
63
87
 
88
+ # Get and array of the messages that have been posted to the room since you joined. Each
89
+ # messages is a hash with:
90
+ # * +:person+: the display name of the person that posted the message
91
+ # * +:message+: the body of the message
92
+ # * +:user_id+: Campfire user id
93
+ # * +:id+: Campfire message id
94
+ #
95
+ # room.listen
96
+ # #=> [{:person=>"Brandon", :message=>"I'm getting very sleepy", :user_id=>"148583", :id=>"16434003"}]
97
+ #
98
+ # listen also takes an optional block, which then polls for new messages every 5 seconds
99
+ # and calls the block for each message.
100
+ #
101
+ # room.listen do |m|
102
+ # room.speak "#{m[:person]}, Go away!" if m[:message] =~ /Java/i
103
+ # end
104
+ #
64
105
  def listen
106
+ # FIXME: this method needs refactored!
107
+ join
65
108
  continue = true
66
109
  while(continue)
67
110
  messages = []
@@ -93,7 +136,6 @@ module Tinder
93
136
  end
94
137
  messages
95
138
  end
96
-
97
139
 
98
140
  private
99
141
 
@@ -110,7 +152,7 @@ module Tinder
110
152
  end
111
153
 
112
154
  def send(message, options = {})
113
- message if verify_response(post("room/#{self.id}/speak", { :message => message, :t => Time.now.to_i }.merge(options), :ajax => true), :success)
155
+ message if verify_response(post("room/#{id}/speak", { :message => message, :t => Time.now.to_i }.merge(options), :ajax => true), :success)
114
156
  end
115
157
 
116
158
  end
@@ -2,8 +2,8 @@ module Tinder #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 2
6
-
5
+ TINY = 3
6
+
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
9
9
  end
data/test/test_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'test/unit'
2
2
  require 'rubygems'
3
3
  require 'active_support'
4
+ require 'breakpoint'
4
5
  require File.dirname(__FILE__) + '/../lib/tinder.rb'
5
6
  require 'mocha'
6
7
  require 'stubba'
@@ -39,5 +39,23 @@ class CampfireTest < Test::Unit::TestCase
39
39
  assert false === @campfire.send(:verify_response, @response, :redirect_to => '/foobar')
40
40
  end
41
41
 
42
+ def test_prepare_request_returns_request
43
+ request = Net::HTTP::Get.new("does_not_matter")
44
+ assert_equal request, @campfire.send(:prepare_request, request)
45
+ end
46
+
47
+ def test_prepare_request_sets_cookie
48
+ request = Net::HTTP::Get.new("does_not_matter")
49
+ @campfire.instance_variable_set("@cookie", "foobar")
50
+ assert_equal "foobar", @campfire.send(:prepare_request, request)['Cookie']
51
+ end
42
52
 
53
+ def test_perform_request
54
+ response = mock("response")
55
+ Net::HTTP.any_instance.stubs(:request).returns(response)
56
+ request = Net::HTTP::Get.new("does_not_matter")
57
+ response.expects(:[]).with('set-cookie')
58
+
59
+ assert_equal response, @campfire.send(:perform_request) { request }
60
+ end
43
61
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: tinder
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.2
7
- date: 2007-01-27 00:00:00 -05:00
6
+ version: 0.1.3
7
+ date: 2007-02-12 00:00:00 -05:00
8
8
  summary: An (unofficial) Campfire API
9
9
  require_paths:
10
10
  - lib