tinder 0.1.2 → 0.1.3

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