theIV-tinder 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt ADDED
@@ -0,0 +1,36 @@
1
+ 1.2.0 - 2009-01-28
2
+ * Get the list of available files [Christopher MacGown]
3
+ * Upload files [Joshua Wand]
4
+ * Find rooms even when full [Josh Owens]
5
+ * Join rooms as a guest [Ian Lesperance]
6
+
7
+ 1.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
+
12
+ 0.1.6 - 2008-03-07
13
+ * Added Room#topic for getting the current topic [Even Weaver]
14
+ * Trap INT in #listen(&block) [borrowed from Chris Shea's Pyre]
15
+
16
+ 0.1.5 - 2008-01-25
17
+ * Fixed Room#listen, which was broken by latest Campfire deploy
18
+ * Fixed timeout when listening but not speaking that will eventually log you out [Clinton R. Nixon]
19
+
20
+ 0.1.4 - 2007-07-23
21
+ * Support for transcripts
22
+ * Fixed Room#leave, which was broken by a Campfire deployment [Andy Smith]
23
+
24
+ 0.1.3 - 2007-02-12
25
+ * added ssl support [Tero Parviainen]
26
+
27
+ 0.1.2 - 2007-01-27
28
+ * fixed bug preventing #listen from working without a block
29
+
30
+ 0.1.1 - 2007-01-27
31
+ * fix bug preventing speak from working
32
+ * incorporated "watching" from http://soylentfoo.jnewland.com/articles/2006/12/07/updates-to-marshmallow-the-campfire-bot
33
+
34
+ 0.1.0 - 2007-01-23
35
+ * Initial release as gem
36
+ * Get the users in a room [Tero Parviainen]
data/Manifest.txt ADDED
@@ -0,0 +1,10 @@
1
+ CHANGELOG.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ init.rb
6
+ lib/tinder.rb
7
+ lib/tinder/campfire.rb
8
+ lib/tinder/multipart.rb
9
+ lib/tinder/room.rb
10
+ lib/tinder/version.rb
data/README.txt ADDED
@@ -0,0 +1,43 @@
1
+ = Tinder - get the Campfire started
2
+
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
6
+
7
+ campfire = Campfire.new 'mysubdomain'
8
+ campfire.login 'myemail@example.com', 'mypassword'
9
+
10
+ room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
11
+ room.rename 'New Room Name'
12
+ room.speak 'Hello world!'
13
+ room.paste "my pasted\ncode"
14
+ room.destroy
15
+
16
+ room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
17
+ room.speak 'Hello world!'
18
+
19
+ See the RDoc for more details.
20
+
21
+ == Requirements
22
+
23
+ * Active Support
24
+ gem install activesupport
25
+ * Hpricot
26
+ gem install hpricot
27
+
28
+ == Installation
29
+
30
+ Tinder can be installed as a gem or a Rails plugin:
31
+
32
+ gem install tinder
33
+
34
+ script/plugin install http://source.collectiveidea.com/public/tinder/trunk
35
+
36
+ == Development
37
+
38
+ 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!
39
+
40
+ == ToDo
41
+
42
+ * Tests! (unit and remote)
43
+ * Marshmallow-style integration scripts for exception notification and continuous integration
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
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
10
+ require File.join(File.dirname(__FILE__), 'lib', 'tinder', 'version')
11
+
12
+ # RDOC_OPTS = ['--quiet', '--title', "Tinder",
13
+ # "--opname", "index.html",
14
+ # "--line-numbers",
15
+ # "--main", "README",
16
+ # "--inline-source"]
17
+ #
18
+ # Generate all the Rake tasks
19
+
20
+ hoe = Hoe.new('tinder', ENV['VERSION'] || Tinder::VERSION::STRING) do |p|
21
+ p.rubyforge_name = 'tinder'
22
+ p.summary = "An (unofficial) Campfire API"
23
+ p.description = "An API for interfacing with Campfire, the 37Signals chat application."
24
+ p.author = 'Brandon Keepers'
25
+ p.email = 'brandon@opensoul.org'
26
+ p.url = 'http://tinder.rubyforge.org'
27
+ p.test_globs = ["test/**/*_test.rb"]
28
+ p.changes = p.paragraphs_of('CHANGELOG.txt', 0..1).join("\n\n")
29
+ p.extra_deps << ['hpricot']
30
+ p.extra_deps << ['mime-types']
31
+ end
32
+
33
+ desc "Run the specs under spec"
34
+ Spec::Rake::SpecTask.new do |t|
35
+ t.spec_opts = ['--options', "spec/spec.opts"]
36
+ t.spec_files = FileList['spec/**/*_spec.rb']
37
+ end
38
+
39
+ desc "Default task is to run specs"
40
+ task :default => :spec
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'tinder'
data/lib/tinder.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'uri'
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'open-uri'
6
+ require 'hpricot'
7
+
8
+ Dir[File.join(File.dirname(__FILE__), 'tinder/**/*.rb')].sort.each { |lib| require lib }
9
+
10
+ module Tinder
11
+ class Error < StandardError; end
12
+ class SSLRequiredError < Error; end
13
+ end
@@ -0,0 +1,207 @@
1
+ module Tinder
2
+
3
+ # == Usage
4
+ #
5
+ # campfire = Tinder::Campfire.new 'mysubdomain'
6
+ # campfire.login 'myemail@example.com', 'mypassword'
7
+ #
8
+ # room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
9
+ # room.speak 'Hello world!'
10
+ # room.destroy
11
+ #
12
+ # room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
13
+ # room.speak 'Hello world!'
14
+ class Campfire
15
+ attr_reader :subdomain, :uri
16
+
17
+ # Create a new connection to the campfire account with the given +subdomain+.
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')
23
+ #
24
+ # c = Tinder::Campfire.new("mysubdomain", :ssl => true)
25
+ def initialize(subdomain, options = {})
26
+ options = { :ssl => false }.merge(options)
27
+ @cookie = nil
28
+ @subdomain = subdomain
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
36
+ @logged_in = false
37
+ end
38
+
39
+ # Log in to campfire using your +email+ and +password+
40
+ def login(email, password)
41
+ unless verify_response(post("login", :email_address => email, :password => password), :redirect_to => url_for(:only_path => false))
42
+ raise Error, "Campfire login failed"
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)
46
+ @logged_in = true
47
+ end
48
+
49
+ # Returns true when successfully logged in
50
+ def logged_in?
51
+ @logged_in == true
52
+ end
53
+
54
+ def logout
55
+ returning verify_response(get("logout"), :redirect) do |result|
56
+ @logged_in = !result
57
+ end
58
+ end
59
+
60
+ # Get an array of all the available rooms
61
+ # TODO: detect rooms that are full (no link)
62
+ def rooms
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)
67
+ end
68
+ end
69
+
70
+ # Find a campfire room by name
71
+ def find_room_by_name(name)
72
+ rooms.detect {|room| room.name == name }
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
81
+
82
+ # Creates and returns a new Room with the given +name+ and optionally a +topic+
83
+ def create_room(name, topic = nil)
84
+ find_room_by_name(name) if verify_response(post("account/create/room?from=lobby", {:room => {:name => name, :topic => topic}}, :ajax => true), :success)
85
+ end
86
+
87
+ def find_or_create_room_by_name(name)
88
+ find_room_by_name(name) || create_room(name)
89
+ end
90
+
91
+ # List the users that are currently chatting in any room
92
+ def users(*room_names)
93
+ users = Hpricot(get.body).search("div.room").collect do |room|
94
+ if room_names.empty? || room_names.include?((room/"h2/a").inner_html)
95
+ room.search("//li.user").collect { |user| user.inner_html }
96
+ end
97
+ end
98
+ users.flatten.compact.uniq.sort
99
+ end
100
+
101
+ # Get the dates of the available transcripts by room
102
+ #
103
+ # campfire.available_transcripts
104
+ # #=> {"15840" => [#<Date: 4908311/2,0,2299161>, #<Date: 4908285/2,0,2299161>]}
105
+ #
106
+ def available_transcripts(room = nil)
107
+ url = "files%2Btranscripts"
108
+ url += "?room_id#{room}" if room
109
+ transcripts = (Hpricot(get(url).body) / ".transcript").inject({}) do |result,transcript|
110
+ link = (transcript / "a").first.attributes['href']
111
+ (result[room_id_from_url(link)] ||= []) << Date.parse(link.scan(/\/transcript\/(\d{4}\/\d{2}\/\d{2})/).to_s)
112
+ result
113
+ end
114
+ room ? transcripts[room.to_s] : transcripts
115
+ end
116
+
117
+ # Is the connection to campfire using ssl?
118
+ def ssl?
119
+ uri.scheme == 'https'
120
+ end
121
+
122
+ private
123
+
124
+ def room_id_from_url(url)
125
+ url.scan(/room\/(\d*)/).to_s
126
+ end
127
+
128
+ def room_id_from_element(element)
129
+ element.split("_").last
130
+ end
131
+
132
+ def url_for(*args)
133
+ options = {:only_path => true}.merge(args.last.is_a?(Hash) ? args.pop : {})
134
+ path = args.shift
135
+ "#{options[:only_path] ? '' : uri}/#{path}"
136
+ end
137
+
138
+ def post(path, data = {}, options = {})
139
+ perform_request(options) do
140
+ returning Net::HTTP::Post.new(url_for(path)) do |request|
141
+ if options[:multipart]
142
+ request.body = data
143
+ else
144
+ request.set_form_data(flatten(data))
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ def get(path = nil, options = {})
151
+ perform_request(options) { Net::HTTP::Get.new(url_for(path)) }
152
+ end
153
+
154
+ def prepare_request(request, options = {})
155
+ returning request do
156
+ request.add_field 'User-Agent', "Tinder/#{Tinder::VERSION::STRING} (http://tinder.rubyforge.org)"
157
+ request.add_field 'Cookie', @cookie if @cookie
158
+ if options[:ajax]
159
+ request.add_field 'X-Requested-With', 'XMLHttpRequest'
160
+ request.add_field 'X-Prototype-Version', '1.5.1.1'
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
167
+ end
168
+ end
169
+
170
+ def perform_request(options = {}, &block)
171
+ @request = prepare_request(yield, options)
172
+ http = @http.new(uri.host, uri.port)
173
+ http.use_ssl = ssl?
174
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if ssl?
175
+ @response = returning http.request(@request) do |response|
176
+ @cookie = response['set-cookie'] if response['set-cookie']
177
+ end
178
+ end
179
+
180
+ # flatten a nested hash (:room => {:name => 'foobar'} to 'user[name]' => 'foobar')
181
+ def flatten(params)
182
+ params = params.dup
183
+ params.stringify_keys!.each do |k,v|
184
+ if v.is_a? Hash
185
+ params.delete(k)
186
+ v.each {|subk,v| params["#{k}[#{subk}]"] = v }
187
+ end
188
+ end
189
+ end
190
+
191
+ def verify_response(response, options = {})
192
+ if options.is_a?(Symbol)
193
+ codes = case options
194
+ when :success; [200]
195
+ when :redirect; 300..399
196
+ else raise(ArgumentError, "Unknown response #{options}")
197
+ end
198
+ codes.include?(response.code.to_i)
199
+ elsif options[:redirect_to]
200
+ verify_response(response, :redirect) && response['location'] == options[:redirect_to]
201
+ else
202
+ false
203
+ end
204
+ end
205
+
206
+ end
207
+ end
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'mime/types'
3
+ require 'net/http'
4
+ require 'cgi'
5
+
6
+ module Multipart #:nodoc:
7
+ # From: http://deftcode.com/code/flickr_upload/multipartpost.rb
8
+ ## Helper class to prepare an HTTP POST request with a file upload
9
+ ## Mostly taken from
10
+ #http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/113774
11
+ ### WAS:
12
+ ## Anything that's broken and wrong probably the fault of Bill Stilwell
13
+ ##(bill@marginalia.org)
14
+ ### NOW:
15
+ ## Everything wrong is due to keith@oreilly.com
16
+
17
+ class Param #:nodoc:
18
+ attr_accessor :k, :v
19
+ def initialize(k, v)
20
+ @k = k
21
+ @v = v
22
+ end
23
+
24
+ def to_multipart
25
+ "Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n#{v}\r\n"
26
+ end
27
+ end
28
+
29
+ class FileParam #:nodoc:
30
+ attr_accessor :k, :filename, :content
31
+ def initialize(k, filename, content)
32
+ @k = k
33
+ @filename = filename
34
+ @content = content
35
+ end
36
+
37
+ def to_multipart
38
+ "Content-Disposition: form-data; name=\"#{k}\"; filename=\"#{filename}\"\r\n" +
39
+ "Content-Transfer-Encoding: binary\r\n" +
40
+ "Content-Type: #{MIME::Types.type_for(@filename)}\r\n\r\n" +
41
+ @content + "\r\n"
42
+ end
43
+ end
44
+
45
+ class MultipartPost #:nodoc:
46
+ BOUNDARY = 'campfire-is-awesome'
47
+ HEADER = {"Content-type" => "multipart/form-data, boundary=" + BOUNDARY + " "}
48
+ TIMEOUT_SECONDS = 30
49
+
50
+ attr_accessor :params, :query, :headers
51
+ def initialize(params)
52
+ @params = params
53
+ @query = {}
54
+ self.prepare_query
55
+ end
56
+
57
+ def prepare_query()
58
+ @query = @params.map do |k,v|
59
+ param = v.respond_to?(:read) ? FileParam.new(k, v.path, v.read) : Param.new(k, v)
60
+ "--#{BOUNDARY}\r\n#{param.to_multipart}"
61
+ end.join("") + "--#{BOUNDARY}--"
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,226 @@
1
+ module Tinder
2
+ # A campfire room
3
+ class Room
4
+ attr_reader :id, :name
5
+
6
+ def initialize(campfire, id, name = nil)
7
+ @campfire = campfire
8
+ @id = id
9
+ @name = name
10
+ end
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
+ raise Error, "Could not join room" 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
+ @idle_since = Time.now
21
+ end if @room.nil? || force
22
+ ping
23
+ true
24
+ end
25
+
26
+ # Leave a room
27
+ def leave
28
+ returning verify_response(post("room/#{id}/leave"), :redirect) do
29
+ @room, @membership_key, @user_id, @last_cache_id, @timestamp, @idle_since = nil
30
+ end
31
+ end
32
+
33
+ # Toggle guest access on or off
34
+ def toggle_guest_access
35
+ # re-join the room to get the guest url
36
+ verify_response(post("room/#{id}/toggle_guest_access"), :success) && join(true)
37
+ end
38
+
39
+ # Get the url for guest access
40
+ def guest_url
41
+ join
42
+ link = (Hpricot(@room.body)/"#guest_access h4").first
43
+ link.inner_html if link
44
+ end
45
+
46
+ def guest_access_enabled?
47
+ !guest_url.nil?
48
+ end
49
+
50
+ # The invite code use for guest
51
+ def guest_invite_code
52
+ guest_url.scan(/\/(\w*)$/).to_s
53
+ end
54
+
55
+ # Change the name of the room
56
+ def name=(name)
57
+ @name = name if verify_response(post("account/edit/room/#{id}", { :room => { :name => name }}, :ajax => true), :success)
58
+ end
59
+ alias_method :rename, :name=
60
+
61
+ # Change the topic
62
+ def topic=(topic)
63
+ topic if verify_response(post("room/#{id}/change_topic", { 'room' => { 'topic' => topic }}, :ajax => true), :success)
64
+ end
65
+
66
+ # Get the current topic
67
+ def topic
68
+ join
69
+ h = (Hpricot(@room.body)/"#topic")
70
+ if h
71
+ (h/:span).remove
72
+ h.inner_text.strip
73
+ end
74
+ end
75
+
76
+ # Lock the room to prevent new users from entering and to disable logging
77
+ def lock
78
+ verify_response(post("room/#{id}/lock", {}, :ajax => true), :success)
79
+ end
80
+
81
+ # Unlock the room
82
+ def unlock
83
+ verify_response(post("room/#{id}/unlock", {}, :ajax => true), :success)
84
+ end
85
+
86
+ def ping(force = false)
87
+ returning verify_response(post("room/#{id}/tabs", { }, :ajax => true), :success) do
88
+ @idle_since = Time.now
89
+ end if @idle_since < 1.minute.ago || force
90
+ end
91
+
92
+ def destroy
93
+ verify_response(post("account/delete/room/#{id}"), :success)
94
+ end
95
+
96
+ # Post a new message to the chat room
97
+ def speak(message, options = {})
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
109
+ end
110
+
111
+ def paste(message)
112
+ speak message, :paste => true
113
+ end
114
+
115
+ # Get the list of users currently chatting for this room
116
+ def users
117
+ @campfire.users name
118
+ end
119
+
120
+ # Get and array of the messages that have been posted to the room. Each
121
+ # messages is a hash with:
122
+ # * +:person+: the display name of the person that posted the message
123
+ # * +:message+: the body of the message
124
+ # * +:user_id+: Campfire user id
125
+ # * +:id+: Campfire message id
126
+ #
127
+ # room.listen
128
+ # #=> [{:person=>"Brandon", :message=>"I'm getting very sleepy", :user_id=>"148583", :id=>"16434003"}]
129
+ #
130
+ # Called without a block, listen will return an array of messages that have been
131
+ # posted since you joined. listen also takes an optional block, which then polls
132
+ # for new messages every 5 seconds and calls the block for each message.
133
+ #
134
+ # room.listen do |m|
135
+ # room.speak "#{m[:person]}, Go away!" if m[:message] =~ /Java/i
136
+ # end
137
+ #
138
+ def listen(interval = 5)
139
+ join
140
+ if block_given?
141
+ catch(:stop_listening) do
142
+ trap('INT') { throw :stop_listening }
143
+ loop do
144
+ ping
145
+ self.messages.each {|msg| yield msg }
146
+ sleep interval
147
+ end
148
+ end
149
+ else
150
+ self.messages
151
+ end
152
+ end
153
+
154
+ # Get the dates for the available transcripts for this room
155
+ def available_transcripts
156
+ @campfire.available_transcripts(id)
157
+ end
158
+
159
+ # Get the transcript for the given date (Returns a hash in the same format as #listen)
160
+ #
161
+ # room.transcript(room.available_transcripts.first)
162
+ # #=> [{:message=>"foobar!", :user_id=>"99999", :person=>"Brandon", :id=>"18659245"}]
163
+ #
164
+ def transcript(date)
165
+ (Hpricot(get("room/#{id}/transcript/#{date.to_date.strftime('%Y/%m/%d')}").body) / ".message").collect do |message|
166
+ person = (message / '.person span').first
167
+ body = (message / '.body div').first
168
+ {:id => message.attributes['id'].scan(/message_(\d+)/).to_s,
169
+ :person => person ? person.inner_html : nil,
170
+ :user_id => message.attributes['class'].scan(/user_(\d+)/).to_s,
171
+ :message => body ? body.inner_html : nil
172
+ }
173
+ end
174
+ end
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
+
191
+ protected
192
+
193
+ def messages
194
+ returning [] do |messages|
195
+ response = post("poll.fcgi", {:l => @last_cache_id, :m => @membership_key,
196
+ :s => @timestamp, :t => "#{Time.now.to_i}000"}, :ajax => true)
197
+ if response.body.length > 1
198
+ lines = response.body.split("\r\n")
199
+
200
+ if lines.length > 0
201
+ @last_cache_id = lines.pop.scan(/chat.poller.lastCacheID = (\d+)/).to_s
202
+ lines.each do |msg|
203
+ unless msg.match(/timestamp_message/)
204
+ if msg.length > 0
205
+ messages << {
206
+ :id => msg.scan(/message_(\d+)/).to_s,
207
+ :user_id => msg.scan(/user_(\d+)/).to_s,
208
+ :person => msg.scan(/\\u003Ctd class=\\"person\\"\\u003E(?:\\u003Cspan\\u003E)?(.+?)(?:\\u003C\/span\\u003E)?\\u003C\/td\\u003E/).to_s,
209
+ :message => msg.scan(/\\u003Ctd class=\\"body\\"\\u003E\\u003Cdiv\\u003E(.+?)\\u003C\/div\\u003E\\u003C\/td\\u003E/).to_s
210
+ }
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ [:post, :get, :verify_response].each do |method|
220
+ define_method method do |*args|
221
+ @campfire.send method, *args
222
+ end
223
+ end
224
+
225
+ end
226
+ end
@@ -0,0 +1,9 @@
1
+ module Tinder #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 1
4
+ MINOR = 2
5
+ TINY = 2
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class RemoteCampfireTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ # @subdomain = 'domain'
7
+ # @user, @pass = 'email@example.com', 'password'
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
20
+ end
21
+
22
+ def test_create_and_delete_room
23
+ assert login
24
+ assert @campfire.logged_in?
25
+
26
+ room = @campfire.create_room("Testing#{Time.now.to_i}")
27
+
28
+ assert_instance_of Tinder::Room, room
29
+ assert_not_nil room.id
30
+
31
+ room.name = "new name"
32
+ assert_equal "new name", room.name
33
+
34
+ room.destroy
35
+ assert_nil @campfire.find_room_by_name(room.name)
36
+
37
+ assert @campfire.logout
38
+ ensure
39
+ room.destroy rescue nil
40
+ end
41
+
42
+ def test_failed_login
43
+ assert_raises(Tinder::Error) { @campfire.login(@user, 'notmypassword') }
44
+ assert !@campfire.logged_in?
45
+ end
46
+
47
+ def test_find_nonexistent_room
48
+ login
49
+ assert_nil @campfire.find_room_by_name('No Room Should Have This Name')
50
+ end
51
+
52
+ private
53
+
54
+ def login(user = @user, pass = @pass)
55
+ @campfire.login(user, pass)
56
+ end
57
+
58
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: theIV-tinder
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Keepers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-10 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hpricot
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: mime-types
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: hoe
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.9.0
44
+ version:
45
+ description: An API for interfacing with Campfire, the 37Signals chat application.
46
+ email: brandon@opensoul.org
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - CHANGELOG.txt
53
+ - Manifest.txt
54
+ - README.txt
55
+ files:
56
+ - CHANGELOG.txt
57
+ - Manifest.txt
58
+ - README.txt
59
+ - Rakefile
60
+ - init.rb
61
+ - lib/tinder.rb
62
+ - lib/tinder/campfire.rb
63
+ - lib/tinder/multipart.rb
64
+ - lib/tinder/room.rb
65
+ - lib/tinder/version.rb
66
+ - test/remote/remote_campfire_test.rb
67
+ has_rdoc: true
68
+ homepage: http://tinder.rubyforge.org
69
+ post_install_message:
70
+ rdoc_options:
71
+ - --main
72
+ - README.txt
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ version:
87
+ requirements: []
88
+
89
+ rubyforge_project: tinder
90
+ rubygems_version: 1.2.0
91
+ signing_key:
92
+ specification_version: 2
93
+ summary: An (unofficial) Campfire API
94
+ test_files:
95
+ - test/remote/remote_campfire_test.rb