theIV-tinder 1.2.2

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 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