dropio 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +3 -0
- data/LICENSE.txt +19 -0
- data/Manifest +22 -0
- data/Rakefile +62 -0
- data/Readme.rdoc +17 -0
- data/Todo.rdoc +5 -0
- data/dropio.gemspec +34 -0
- data/lib/dropio/asset.rb +60 -0
- data/lib/dropio/client/mapper.rb +47 -0
- data/lib/dropio/client/multipart_post.rb +35 -0
- data/lib/dropio/client.rb +321 -0
- data/lib/dropio/comment.rb +15 -0
- data/lib/dropio/drop.rb +54 -0
- data/lib/dropio/resource.rb +9 -0
- data/lib/dropio.rb +35 -0
- data/spec/dropio/asset_spec.rb +59 -0
- data/spec/dropio/client/mapper_spec.rb +169 -0
- data/spec/dropio/client_spec.rb +322 -0
- data/spec/dropio/comment_spec.rb +23 -0
- data/spec/dropio/drop_spec.rb +24 -0
- data/spec/dropio_spec.rb +8 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +42 -0
- metadata +93 -0
data/History.rdoc
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 Drop.io, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
History.rdoc
|
2
|
+
lib/dropio/asset.rb
|
3
|
+
lib/dropio/client/mapper.rb
|
4
|
+
lib/dropio/client/multipart_post.rb
|
5
|
+
lib/dropio/client.rb
|
6
|
+
lib/dropio/comment.rb
|
7
|
+
lib/dropio/drop.rb
|
8
|
+
lib/dropio/resource.rb
|
9
|
+
lib/dropio.rb
|
10
|
+
LICENSE.txt
|
11
|
+
Manifest
|
12
|
+
Rakefile
|
13
|
+
Readme.rdoc
|
14
|
+
spec/dropio/asset_spec.rb
|
15
|
+
spec/dropio/client/mapper_spec.rb
|
16
|
+
spec/dropio/client_spec.rb
|
17
|
+
spec/dropio/comment_spec.rb
|
18
|
+
spec/dropio/drop_spec.rb
|
19
|
+
spec/dropio_spec.rb
|
20
|
+
spec/spec.opts
|
21
|
+
spec/spec_helper.rb
|
22
|
+
Todo.rdoc
|
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
$: << 'lib'
|
2
|
+
require 'dropio'
|
3
|
+
|
4
|
+
### Echoe
|
5
|
+
begin
|
6
|
+
require 'echoe'
|
7
|
+
|
8
|
+
Echoe.new('dropio', Dropio::VERSION) do |echoe|
|
9
|
+
echoe.summary = "A Ruby client library for the Drop.io API (http://api.drop.io)"
|
10
|
+
echoe.author = ["Jake Good", "Peter Jaros"]
|
11
|
+
echoe.email = ["jake@dropio.com", "peeja@dropio.com"]
|
12
|
+
echoe.url = "http://github.com/whoisjake/dropio_api_ruby"
|
13
|
+
echoe.changelog = "History.txt"
|
14
|
+
echoe.ignore_pattern = "tmtags"
|
15
|
+
|
16
|
+
# Comment out this line when building docs locally or publishing docs.
|
17
|
+
echoe.rdoc_pattern = "*.rdoc"
|
18
|
+
end
|
19
|
+
|
20
|
+
# Until we find a way to undefine rake tasks...
|
21
|
+
%w{coverage clobber_coverage}.each { |name| Rake::Task[name].comment = "(don't use)" }
|
22
|
+
|
23
|
+
# default depends on test, but we don't have a test task. Define a trivial one.
|
24
|
+
task :test
|
25
|
+
rescue LoadError
|
26
|
+
puts "(Note: Echoe not found. Install echoe gem for package management tasks.)"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
### RSpec
|
31
|
+
require 'spec/rake/spectask'
|
32
|
+
|
33
|
+
task :default => :spec
|
34
|
+
Spec::Rake::SpecTask.new(:spec)
|
35
|
+
|
36
|
+
namespace :spec do
|
37
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
38
|
+
t.rcov = true
|
39
|
+
t.rcov_opts = %w{ --exclude ^/ --exclude ^spec/ --sort coverage }
|
40
|
+
end
|
41
|
+
|
42
|
+
namespace :rcov do
|
43
|
+
desc "Generate and view RCov report"
|
44
|
+
task :view => :rcov do
|
45
|
+
coverage_index = File.expand_path(File.join(File.dirname(__FILE__), 'coverage', 'index.html'))
|
46
|
+
sh "open file://#{coverage_index}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
### RDoc
|
53
|
+
require 'rake/rdoctask'
|
54
|
+
|
55
|
+
namespace :docs do
|
56
|
+
desc "Generate and view RDoc documentation"
|
57
|
+
task :view => :docs do
|
58
|
+
doc_index = File.expand_path(File.join(File.dirname(__FILE__), 'doc', 'index.html'))
|
59
|
+
sh "open file://#{doc_index}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
data/Readme.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
(Note: This is very beta. The code is mostly functional. The docs are mostly not. The tests are somewhere in between. Have fun, be safe, and stay tuned.)
|
2
|
+
|
3
|
+
= drop.io API library for Ruby
|
4
|
+
|
5
|
+
Before using the Dropio library, the application must set an API key. This key will be used for all requests to the server. To get an API key, go to http://api.drop.io. Then make sure you set the API key before you use the API:
|
6
|
+
|
7
|
+
Dropio.api_key = "83a05513ddddb73e75c9d8146c115f7fd8e90de6"
|
8
|
+
|
9
|
+
|
10
|
+
== The Drop object
|
11
|
+
|
12
|
+
There are two ways to get a +Drop+ object. The first is to access an existing drop:
|
13
|
+
|
14
|
+
drop = Dropio::Drop.find("mystuff")
|
15
|
+
auth_drop = Dropio::Drop.find("mystuff", "b9b2c8f2b8e655679d2fb62b83f8efec4fb4c8af")
|
16
|
+
|
17
|
+
<tt>Drop#find</tt> takes two arguments: the name of the drop to get, and a credential token. This can be an admin token, a user token, an admin password, or a guest password. The drop's capabilities will be limited by the token, and the token is optional. If the drop is authenticated with the admin token, it will be able to do anything. If the drop is not authenticated with a token, it will have the same capabilities as any user visiting the drop. If the drop is not found or the token is not accepted, <tt>#find</tt> will return +nil+.
|
data/Todo.rdoc
ADDED
data/dropio.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{dropio}
|
5
|
+
s.version = "0.9.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Jake Good, Peter Jaros"]
|
9
|
+
s.date = %q{2008-11-10}
|
10
|
+
s.description = %q{A Ruby client library for the Drop.io API (http://api.drop.io)}
|
11
|
+
s.email = ["jake@dropio.com", "peeja@dropio.com"]
|
12
|
+
s.extra_rdoc_files = ["History.rdoc", "Readme.rdoc", "Todo.rdoc"]
|
13
|
+
s.files = ["History.rdoc", "lib/dropio/asset.rb", "lib/dropio/client/mapper.rb", "lib/dropio/client/multipart_post.rb", "lib/dropio/client.rb", "lib/dropio/comment.rb", "lib/dropio/drop.rb", "lib/dropio/resource.rb", "lib/dropio.rb", "LICENSE.txt", "Manifest", "Rakefile", "Readme.rdoc", "spec/dropio/asset_spec.rb", "spec/dropio/client/mapper_spec.rb", "spec/dropio/client_spec.rb", "spec/dropio/comment_spec.rb", "spec/dropio/drop_spec.rb", "spec/dropio_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "Todo.rdoc", "dropio.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/whoisjake/dropio_api_ruby}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Dropio", "--main", "Readme.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{dropio}
|
19
|
+
s.rubygems_version = %q{1.3.0}
|
20
|
+
s.summary = %q{A Ruby client library for the Drop.io API (http://api.drop.io)}
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 2
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_development_dependency(%q<echoe>, [">= 0"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
30
|
+
end
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
33
|
+
end
|
34
|
+
end
|
data/lib/dropio/asset.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
class Dropio::Asset < Dropio::Resource
|
2
|
+
|
3
|
+
attr_accessor :drop, :name, :type, :title, :description, :filesize, :created_at,
|
4
|
+
:thumbnail, :status, :file, :converted, :hidden_url, :pages,
|
5
|
+
:duration, :artist, :track_title, :height, :width, :contents, :url
|
6
|
+
|
7
|
+
# Returns the comments on this asset. Comments are loaded lazily. The first
|
8
|
+
# call to +comments+ will fetch the comments from the server. They are then
|
9
|
+
# cached until the asset is reloaded.
|
10
|
+
def comments
|
11
|
+
@comments = Dropio::Client.instance.find_comments(self) if @comments.nil?
|
12
|
+
@comments ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
# Adds a comment to the asset with the given +contents+. Returns the
|
16
|
+
# new +Comment+.
|
17
|
+
def create_comment(contents)
|
18
|
+
Dropio::Client.instance.create_comment(self, contents)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Saves the asset back to drop.io.
|
22
|
+
def save
|
23
|
+
Dropio::Client.instance.save_asset(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Destroys the asset on drop.io. Don't try to use an Asset after destroying it.
|
27
|
+
def destroy!
|
28
|
+
Dropio::Client.instance.destroy_asset(self)
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns true if the Asset can be faxed.
|
33
|
+
def faxable?
|
34
|
+
return type == "Document"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Fax the asset to the given +fax_number+. Make sure the Asset is +faxable?+
|
38
|
+
# first, or +send_to_fax+ will raise an error.
|
39
|
+
def send_to_fax(fax_number)
|
40
|
+
raise "Can't fax Asset: #{self.inspect} is not faxable" unless faxable?
|
41
|
+
Dropio::Client.instance.send_to_fax(self, fax_number)
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
# Sends the asset to the given +emails+ with an optional +message+.
|
46
|
+
def send_to_emails(emails = [], message = nil)
|
47
|
+
Dropio::Client.instance.send_to_emails(self, emails, message)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Sends the asset to a Drop by +drop_name+
|
51
|
+
def send_to_drop(drop_name)
|
52
|
+
Dropio::Client.instance.send_to_drop(self, drop_name)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Generates an authenticated URL that will bypass any login action.
|
56
|
+
def generate_url
|
57
|
+
Dropio::Client.instance.generate_asset_url(self)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Dropio::Client::Mapper
|
2
|
+
|
3
|
+
def self.map_drops(response_body)
|
4
|
+
return parse_and_map(Dropio::Drop, response_body)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.map_assets(drop, response_body)
|
8
|
+
assets = parse_and_map(Dropio::Asset, response_body)
|
9
|
+
|
10
|
+
assets.drop = drop if assets.is_a?(Dropio::Asset)
|
11
|
+
assets.each{ |a| a.drop = drop } if assets.is_a?(Array)
|
12
|
+
|
13
|
+
return assets
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.map_comments(asset, response_body)
|
17
|
+
comments = parse_and_map(Dropio::Comment, response_body)
|
18
|
+
|
19
|
+
comments.asset = asset if comments.is_a?(Dropio::Comment)
|
20
|
+
comments.each{ |c| c.asset = asset } if comments.is_a?(Array)
|
21
|
+
|
22
|
+
return comments
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def self.parse_and_map(model_class, response_body)
|
28
|
+
h = JSON.parse(response_body)
|
29
|
+
|
30
|
+
# single model
|
31
|
+
return model_class.new(h) if h.is_a?(Hash)
|
32
|
+
|
33
|
+
# multiple models
|
34
|
+
models = []
|
35
|
+
|
36
|
+
h.each do |model_hash|
|
37
|
+
if model_hash.is_a?(Hash)
|
38
|
+
model = model_class.new(model_hash)
|
39
|
+
models << model
|
40
|
+
end
|
41
|
+
end if h.is_a?(Array)
|
42
|
+
|
43
|
+
return models
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Dropio::Client::MultipartPost
|
2
|
+
def multipart_params=(param_hash={})
|
3
|
+
boundary_token = [Array.new(8) {rand(256)}].join
|
4
|
+
self.content_type = "multipart/form-data; boundary=#{boundary_token}"
|
5
|
+
boundary_marker = "--#{boundary_token}\r\n"
|
6
|
+
self.body = param_hash.map { |param_name, param_value|
|
7
|
+
unless param_value.nil?
|
8
|
+
boundary_marker + case param_value
|
9
|
+
when String
|
10
|
+
text_to_multipart(param_name, param_value.to_s)
|
11
|
+
when File
|
12
|
+
file_to_multipart(param_name, param_value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
}.join('') + "--#{boundary_token}--\r\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
def file_to_multipart(key,file)
|
20
|
+
filename = File.basename(file.path)
|
21
|
+
mime_types = MIME::Types.of(filename)
|
22
|
+
mime_type = mime_types.empty? ? "application/octet-stream" : mime_types.first.content_type
|
23
|
+
part = "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{filename}\"\r\n"
|
24
|
+
part += "Content-Transfer-Encoding: binary\r\n"
|
25
|
+
part += "Content-Type: #{mime_type}\r\n\r\n#{file.read}\r\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def text_to_multipart(key,value)
|
29
|
+
"Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n#{value}\r\n"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Net::HTTP::Post
|
34
|
+
include Dropio::Client::MultipartPost
|
35
|
+
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
class Dropio::Client
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
# Generates a user agent string.
|
7
|
+
def self.user_agent_string
|
8
|
+
ruby_version = %w{MAJOR MINOR TEENY}.map { |k| Config::CONFIG[k] }.join(".")
|
9
|
+
"DropioAPI-Ruby/#{Dropio::VERSION} (Ruby #{ruby_version} #{Config::CONFIG["host"]}; +http://dropio.rubyforge.org/)"
|
10
|
+
end
|
11
|
+
|
12
|
+
# The default set of headers for each request.
|
13
|
+
DEFAULT_HEADER = {
|
14
|
+
'User-Agent' => user_agent_string,
|
15
|
+
'Accept' => 'application/json'
|
16
|
+
}
|
17
|
+
|
18
|
+
# Takes a drop name and optional token and returns a +Drop+ or errors.
|
19
|
+
def find_drop(drop_name, token = nil)
|
20
|
+
uri = URI::HTTP.build({:path => drop_path(drop_name), :query => get_request_tokens(token)})
|
21
|
+
req = Net::HTTP::Get.new(uri.request_uri, DEFAULT_HEADER)
|
22
|
+
drop = nil
|
23
|
+
complete_request(req) { |body| drop = Mapper.map_drops(body) }
|
24
|
+
drop
|
25
|
+
end
|
26
|
+
|
27
|
+
# Finds a collection of +Asset+ objects for a given +Drop+.
|
28
|
+
def find_assets(drop, page = 1)
|
29
|
+
token = get_default_token(drop)
|
30
|
+
uri = URI::HTTP.build({:path => asset_path(drop), :query => get_request_tokens(token) + "&page=#{page}"})
|
31
|
+
req = Net::HTTP::Get.new(uri.request_uri, DEFAULT_HEADER)
|
32
|
+
assets = nil
|
33
|
+
complete_request(req) { |body| assets = Mapper.map_assets(drop, body) }
|
34
|
+
assets
|
35
|
+
end
|
36
|
+
|
37
|
+
# Finds a collection of +Comment+ objects for a given +Asset+.
|
38
|
+
def find_comments(asset)
|
39
|
+
token = get_default_token(asset.drop)
|
40
|
+
uri = URI::HTTP.build({:path => comment_path(asset.drop, asset), :query => get_request_tokens(token)})
|
41
|
+
req = Net::HTTP::Get.new(uri.request_uri, DEFAULT_HEADER)
|
42
|
+
comments = nil
|
43
|
+
complete_request(req) { |body| comments = Mapper.map_comments(asset, body) }
|
44
|
+
comments
|
45
|
+
end
|
46
|
+
|
47
|
+
# Creates a drop with an +attributes+ hash.
|
48
|
+
# Valid attributes: name (string), guests_can_comment (boolean), guests_can_add (boolean), guests_can_delete (boolean), expiration_length (string), password (string), admin_password (string), and premium_code (string)
|
49
|
+
# Descriptions can be found here: http://groups.google.com/group/dropio-api/web/full-api-documentation
|
50
|
+
def create_drop(attributes = {})
|
51
|
+
uri = URI::HTTP.build({:path => drop_path})
|
52
|
+
form = create_form(attributes)
|
53
|
+
req = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
|
54
|
+
req.set_form_data(form)
|
55
|
+
drop = nil
|
56
|
+
complete_request(req) { |body| drop = Mapper.map_drops(body) }
|
57
|
+
drop
|
58
|
+
end
|
59
|
+
|
60
|
+
# Saves a +Drop+ back to drop.io
|
61
|
+
def save_drop(drop)
|
62
|
+
uri = URI::HTTP.build({:path => drop_path(drop) })
|
63
|
+
token = get_admin_token(drop)
|
64
|
+
form = create_form :token => token,
|
65
|
+
:expiration_length => drop.expiration_length,
|
66
|
+
:guests_can_comment => drop.guests_can_comment,
|
67
|
+
:premium_code => drop.premium_code,
|
68
|
+
:guests_can_add => drop.guests_can_add,
|
69
|
+
:guests_can_delete => drop.guests_can_delete,
|
70
|
+
:password => drop.password,
|
71
|
+
:admin_password => drop.admin_password
|
72
|
+
req = Net::HTTP::Put.new(uri.request_uri, DEFAULT_HEADER)
|
73
|
+
req.set_form_data(form)
|
74
|
+
drop = nil
|
75
|
+
complete_request(req) { |body| drop = Mapper.map_drops(body) }
|
76
|
+
drop
|
77
|
+
end
|
78
|
+
|
79
|
+
# Destroys a +Drop+
|
80
|
+
def destroy_drop(drop)
|
81
|
+
token = get_admin_token(drop)
|
82
|
+
uri = URI::HTTP.build({:path => drop_path(drop)})
|
83
|
+
form = create_form( { :token => token })
|
84
|
+
req = Net::HTTP::Delete.new(uri.request_uri, DEFAULT_HEADER)
|
85
|
+
req.set_form_data(form)
|
86
|
+
complete_request(req)
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
# Adds a file to a +Drop+
|
91
|
+
def add_file(drop, file_path)
|
92
|
+
token = get_default_token(drop)
|
93
|
+
asset = nil
|
94
|
+
|
95
|
+
File.open(file_path, 'r') do |file|
|
96
|
+
uri = URI.parse(Dropio.upload_url)
|
97
|
+
req = Net::HTTP::Post.new(uri.path, DEFAULT_HEADER)
|
98
|
+
form = create_form( { :drop_name => drop.name, :token => token , :file => file } )
|
99
|
+
req.multipart_params = form
|
100
|
+
complete_request(req, uri.host) { |body| asset = Mapper.map_assets(drop, body) }
|
101
|
+
end
|
102
|
+
|
103
|
+
asset
|
104
|
+
end
|
105
|
+
|
106
|
+
# Creates a note +Asset+
|
107
|
+
def create_note(drop, title, contents)
|
108
|
+
token = get_default_token(drop)
|
109
|
+
uri = URI::HTTP.build({:path => asset_path(drop)})
|
110
|
+
form = create_form( { :token => token, :title => title, :contents => contents })
|
111
|
+
req = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
|
112
|
+
req.set_form_data(form)
|
113
|
+
asset = nil
|
114
|
+
complete_request(req) { |body| asset = Mapper.map_assets(drop, body) }
|
115
|
+
asset
|
116
|
+
end
|
117
|
+
|
118
|
+
# Creates a link +Asset+
|
119
|
+
def create_link(drop, url, title = nil, description = nil)
|
120
|
+
token = get_default_token(drop)
|
121
|
+
uri = URI::HTTP.build({:path => asset_path(drop)})
|
122
|
+
form = create_form( { :token => token, :url => url, :title => title, :description => description })
|
123
|
+
req = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
|
124
|
+
req.set_form_data(form)
|
125
|
+
asset = nil
|
126
|
+
complete_request(req) { |body| asset = Mapper.map_assets(drop, body) }
|
127
|
+
asset
|
128
|
+
end
|
129
|
+
|
130
|
+
# Saves a +Comment+, requires admin token.
|
131
|
+
def save_comment(comment)
|
132
|
+
token = get_default_token(comment.asset.drop)
|
133
|
+
uri = URI::HTTP.build({:path => comment_path(comment.asset.drop, comment.asset, comment)})
|
134
|
+
form = create_form( { :token => token, :contents => comment.contents })
|
135
|
+
req = Net::HTTP::Put.new(uri.request_uri, DEFAULT_HEADER)
|
136
|
+
req.set_form_data(form)
|
137
|
+
complete_request(req) { |body| comment = Mapper.map_comments(comment.asset, body) }
|
138
|
+
comment
|
139
|
+
end
|
140
|
+
|
141
|
+
# Destroys a +Comment+, requires admin token.
|
142
|
+
def destroy_comment(comment)
|
143
|
+
token = get_admin_token(comment.asset.drop)
|
144
|
+
uri = URI::HTTP.build({:path => comment_path(comment.asset.drop, comment.asset, comment)})
|
145
|
+
form = create_form( { :token => token })
|
146
|
+
req = Net::HTTP::Delete.new(uri.request_uri, DEFAULT_HEADER)
|
147
|
+
req.set_form_data(form)
|
148
|
+
complete_request(req)
|
149
|
+
true
|
150
|
+
end
|
151
|
+
|
152
|
+
# Creates a +Comment+
|
153
|
+
def create_comment(asset, contents)
|
154
|
+
token = get_default_token(asset.drop)
|
155
|
+
uri = URI::HTTP.build({:path => comment_path(asset.drop, asset)})
|
156
|
+
form = create_form( { :token => token, :contents => contents })
|
157
|
+
req = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
|
158
|
+
req.set_form_data(form)
|
159
|
+
comment = nil
|
160
|
+
complete_request(req) { |body| comment = Mapper.map_comments(asset, body) }
|
161
|
+
comment
|
162
|
+
end
|
163
|
+
|
164
|
+
# Sends an +Asset+ (of type Document) to a +fax_number+
|
165
|
+
def send_to_fax(asset, fax_number)
|
166
|
+
params = { :medium => "fax", :fax_number => fax_number }
|
167
|
+
send_asset(asset,params)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Sends an email +message+, containing the +asset+ to a list of +emails+
|
171
|
+
def send_to_emails(asset, emails = [], message = nil)
|
172
|
+
params = { :medium => "email", :emails => emails.join(","), :message => message }
|
173
|
+
send_asset(asset,params)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Sends an +Asset+ to a given +Drop+ with +drop_name+
|
177
|
+
def send_to_drop(asset, drop_name)
|
178
|
+
params = { :medium => "drop", :drop_name => drop_name }
|
179
|
+
send_asset(asset,params)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Saves an +Asset+ back to drop.io
|
183
|
+
def save_asset(asset)
|
184
|
+
token = get_default_token(asset.drop)
|
185
|
+
uri = URI::HTTP.build({:path => asset_path(asset.drop, asset)})
|
186
|
+
form = create_form({ :token => token,
|
187
|
+
:title => asset.title,
|
188
|
+
:url => asset.url,
|
189
|
+
:description => asset.description,
|
190
|
+
:contents => asset.contents })
|
191
|
+
req = Net::HTTP::Put.new(uri.request_uri, DEFAULT_HEADER)
|
192
|
+
req.set_form_data(form)
|
193
|
+
complete_request(req) { |body| asset = Mapper.map_assets(asset.drop, body)}
|
194
|
+
asset
|
195
|
+
end
|
196
|
+
|
197
|
+
# Destroys an +Asset+
|
198
|
+
def destroy_asset(asset)
|
199
|
+
token = get_default_token(asset.drop)
|
200
|
+
uri = URI::HTTP.build({:path => asset_path(asset.drop, asset)})
|
201
|
+
form = create_form( { :token => token })
|
202
|
+
req = Net::HTTP::Delete.new(uri.request_uri, DEFAULT_HEADER)
|
203
|
+
req.set_form_data(form)
|
204
|
+
complete_request(req)
|
205
|
+
true
|
206
|
+
end
|
207
|
+
|
208
|
+
# Generates the authenticated +Drop+ url.
|
209
|
+
def generate_drop_url(drop)
|
210
|
+
signed_url(drop)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Generates the authenticated +Asset+ url.
|
214
|
+
def generate_asset_url(asset)
|
215
|
+
signed_url(asset.drop, asset)
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
protected
|
220
|
+
|
221
|
+
def signed_url(drop, asset = nil)
|
222
|
+
# 10 minute window.
|
223
|
+
expires = (Time.now.utc + 10*60).to_i
|
224
|
+
token = get_default_token(drop)
|
225
|
+
path = Dropio.base_url + "/#{drop.name}"
|
226
|
+
path += "/asset/#{asset.name}" if asset
|
227
|
+
path += "/from_api"
|
228
|
+
sig = Digest::SHA1.hexdigest("#{expires}+#{token}+#{drop.name}")
|
229
|
+
path + "?expires=#{expires}&signature=#{sig}"
|
230
|
+
end
|
231
|
+
|
232
|
+
def create_form(options = {})
|
233
|
+
{ :api_key => Dropio.api_key, :format => 'json', :version => '1.0' }.merge(options)
|
234
|
+
end
|
235
|
+
|
236
|
+
def send_asset(asset, params = {})
|
237
|
+
token = get_default_token(asset.drop)
|
238
|
+
uri = URI::HTTP.build({:path => send_to_path(asset.drop, asset)})
|
239
|
+
form = create_form( { :token => token }.merge(params) )
|
240
|
+
req = Net::HTTP::Post.new(uri.request_uri, DEFAULT_HEADER)
|
241
|
+
req.set_form_data(form)
|
242
|
+
complete_request(req)
|
243
|
+
true
|
244
|
+
end
|
245
|
+
|
246
|
+
def get_default_token(drop)
|
247
|
+
drop.admin_token || drop.guest_token
|
248
|
+
end
|
249
|
+
|
250
|
+
def get_admin_token(drop)
|
251
|
+
drop ? drop.admin_token : nil
|
252
|
+
end
|
253
|
+
|
254
|
+
def get_request_tokens(token = '')
|
255
|
+
"api_key=#{Dropio.api_key}&token=#{token}&version=1.0&format=json"
|
256
|
+
end
|
257
|
+
|
258
|
+
# Creates a path directly to a comment resource or a collection of comments.
|
259
|
+
def comment_path(drop, asset, comment = nil)
|
260
|
+
comment_id = (comment) ? comment.id.to_s : ''
|
261
|
+
return asset_path(drop,asset) + "/comments/" + comment_id
|
262
|
+
end
|
263
|
+
|
264
|
+
# Creates a path directly to an asset resource or collection of assets.
|
265
|
+
def asset_path(drop, asset = nil)
|
266
|
+
asset_name = (asset) ? asset.name : ''
|
267
|
+
return drop_path(drop) + "/assets/" + asset_name
|
268
|
+
end
|
269
|
+
|
270
|
+
# Creates a path directly to a drop resource or collection of drops.
|
271
|
+
def drop_path(drop = nil)
|
272
|
+
drop_name = case drop
|
273
|
+
when Dropio::Drop
|
274
|
+
drop.name
|
275
|
+
when String
|
276
|
+
drop
|
277
|
+
when nil
|
278
|
+
''
|
279
|
+
else
|
280
|
+
raise ArgumentError, "Client#drop_path takes a Drop or a String, got #{drop.inspect}"
|
281
|
+
end
|
282
|
+
|
283
|
+
return "/drops/" + drop_name
|
284
|
+
end
|
285
|
+
|
286
|
+
# Creates a path for sending an +Asset+
|
287
|
+
def send_to_path(drop, asset)
|
288
|
+
return asset_path(drop, asset) + "/send_to"
|
289
|
+
end
|
290
|
+
|
291
|
+
# Starts and completes the given request. Returns or yields the response body.
|
292
|
+
def complete_request(request, host = URI.parse(Dropio.api_url).host)
|
293
|
+
http = Net::HTTP.new(host)
|
294
|
+
# Set to debug http output.
|
295
|
+
# http.set_debug_output $stderr
|
296
|
+
response = http.start { |http| http.request(request) }
|
297
|
+
|
298
|
+
case response
|
299
|
+
when Net::HTTPSuccess then yield response.body if block_given?
|
300
|
+
when Net::HTTPBadRequest then raise Dropio::RequestError, parse_error_message(response)
|
301
|
+
when Net::HTTPForbidden then raise Dropio::AuthorizationError, parse_error_message(response)
|
302
|
+
when Net::HTTPNotFound then raise Dropio::MissingResourceError, parse_error_message(response)
|
303
|
+
when Net::HTTPServerError then raise Dropio::ServerError, "There was a problem connecting to Drop.io."
|
304
|
+
else raise "Received an unexpected HTTP response: #{response}"
|
305
|
+
end
|
306
|
+
|
307
|
+
response.body
|
308
|
+
end
|
309
|
+
|
310
|
+
# Extracts the error message from the response for the exception.
|
311
|
+
def parse_error_message(response)
|
312
|
+
error_hash = JSON.parse(response.body) rescue nil
|
313
|
+
|
314
|
+
if (error_hash && error_hash.is_a?(Hash) && error_hash["response"] && error_hash["response"]["message"])
|
315
|
+
return error_hash["response"]["message"]
|
316
|
+
else
|
317
|
+
return "There was a problem connecting to Drop.io."
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Dropio::Comment < Dropio::Resource
|
2
|
+
|
3
|
+
attr_accessor :id, :contents, :created_at, :asset
|
4
|
+
|
5
|
+
# Saves the comment back to drop.io
|
6
|
+
def save
|
7
|
+
Dropio::Client.instance.save_comment(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Destroys the comment on drop.io. Don't try to use an Comment after destroying it.
|
11
|
+
def destroy
|
12
|
+
Dropio::Client.instance.destroy_comment(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|