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 +3 -0
- data/README.txt +20 -4
- data/lib/tinder.rb +2 -0
- data/lib/tinder/campfire.rb +57 -30
- data/lib/tinder/room.rb +66 -24
- data/lib/tinder/version.rb +2 -2
- data/test/test_helper.rb +1 -0
- data/test/unit/campfire_test.rb +18 -0
- metadata +2 -2
data/CHANGELOG.txt
CHANGED
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.
|
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
|
-
*
|
40
|
+
* Marshmallow-style integration scripts for exception notification and continuous integration
|
data/lib/tinder.rb
CHANGED
data/lib/tinder/campfire.rb
CHANGED
@@ -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
|
-
|
11
|
+
attr_reader :subdomain, :uri
|
12
12
|
|
13
|
-
|
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
|
-
|
16
|
-
|
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
|
-
|
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
|
-
"
|
73
|
+
"#{uri}/#{path}"
|
53
74
|
end
|
54
75
|
|
55
76
|
def post(path, data = {}, options = {})
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
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
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
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
|
-
|
4
|
+
attr_reader :id, :name
|
4
5
|
|
5
6
|
def initialize(campfire, id, name = nil)
|
6
7
|
@campfire = campfire
|
7
|
-
|
8
|
-
|
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
|
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/#{
|
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
|
-
|
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(
|
44
|
+
guest_url.scan(/\/(\w*)$/).to_s
|
30
45
|
end
|
31
46
|
|
32
|
-
|
33
|
-
|
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/#{
|
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/#{
|
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/#{
|
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/#{
|
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
|
-
|
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/#{
|
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
|
data/lib/tinder/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
data/test/unit/campfire_test.rb
CHANGED
@@ -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.
|
7
|
-
date: 2007-
|
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
|