rapidshare-ext 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/History.md +17 -0
- data/LICENSE +22 -0
- data/README.md +164 -0
- data/Rakefile +24 -0
- data/lib/rapidshare-base/api.rb +61 -0
- data/lib/rapidshare-base/utils.rb +12 -0
- data/lib/rapidshare-ext/api.rb +499 -0
- data/lib/rapidshare-ext/version.rb +5 -0
- data/lib/rapidshare-ext.rb +10 -0
- data/rapidshare-ext.gemspec +27 -0
- data/test/fixtures/files/upload1.txt +1 -0
- data/test/fixtures/getaccountdetails_valid.txt +16 -0
- data/test/integration/rapidshare-ext_test.rb +173 -0
- data/test/test_helper.rb +40 -0
- data/test/unit/rapidshare-ext_test.rb +28 -0
- metadata +135 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/History.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
## ver.0.0.1 2012-11-17
|
2
|
+
|
3
|
+
It has began. We have the features as follows:
|
4
|
+
|
5
|
+
* [added] Creating folders
|
6
|
+
* [added] Removing folders
|
7
|
+
* [added] Moving folders
|
8
|
+
* [added] Uploading files
|
9
|
+
* [added] Removing files
|
10
|
+
* [added] Renaming files
|
11
|
+
* [added] Moving files
|
12
|
+
* [added] Viewing folders hierarchy
|
13
|
+
* [added] Dealing with orphan folders
|
14
|
+
* [added] Erasing all account data
|
15
|
+
* [added] Get file info
|
16
|
+
* [added] Folder/file identification by path
|
17
|
+
* [added] Integration tests (Forkers, be careful, account is fully erased after each test !!!)
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 odiszapc
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# Rapidshare::Ext
|
2
|
+
|
3
|
+
Makes your interactions with Rapidshare API more pleasant by providing new handy features: creating/moving/deleting files/folders in a user friendly way, upload files, etc.
|
4
|
+
|
5
|
+
This gem extends the existing one - https://github.com/defkode/rapidshare, so it has all features implemented in the source library. In addition, it much simplifies operations with data in your Rapidshare account.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your Gemfile:
|
10
|
+
|
11
|
+
gem 'rapidshare-ext'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install rapidshare-ext
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
First, create an instance:
|
24
|
+
```ruby
|
25
|
+
api = Rapidshare::API.new(:login => 'my_login', :password => 'my_password')
|
26
|
+
api = Rapidshare::API.new(:cookie => 'cookie_here') # More preferable way
|
27
|
+
```
|
28
|
+
|
29
|
+
### Folders
|
30
|
+
As you note you can have a hierarchy of folders in your account.
|
31
|
+
|
32
|
+
Creating folders:
|
33
|
+
```ruby
|
34
|
+
folder_id = api.add_folder "a/b/c" # => <FOLDER ID>
|
35
|
+
```
|
36
|
+
|
37
|
+
Deleting folders:
|
38
|
+
```ruby
|
39
|
+
api.remove_folder("/a/b/c")
|
40
|
+
```
|
41
|
+
|
42
|
+
Moving folders:
|
43
|
+
```ruby
|
44
|
+
api.move_folder("/a/b/c", :to => "/a")
|
45
|
+
```
|
46
|
+
This moves folder "c" from directory "/a/b/" and places it under the directory "/a"
|
47
|
+
|
48
|
+
Get hierarchy of all folders in account:
|
49
|
+
```ruby
|
50
|
+
api.folders_hierarchy
|
51
|
+
# => {
|
52
|
+
# <folder ID> => {
|
53
|
+
# :parent => <parent folder ID>,
|
54
|
+
# :name => <folder name>,
|
55
|
+
# :path => <folder absolute path>
|
56
|
+
# },
|
57
|
+
# ...
|
58
|
+
# }
|
59
|
+
```
|
60
|
+
|
61
|
+
Note, that after the folder hierarhy is generated first time the data is cached permanently to improve performance.
|
62
|
+
|
63
|
+
So, if you want to invalidate the cache just call the above method with trailing "!":
|
64
|
+
```ruby
|
65
|
+
api.folders_hierarchy!
|
66
|
+
```
|
67
|
+
|
68
|
+
If folder tree is inconsistent (orphans are found) the Exception will be thrown. To automatically normalize the tree, call the method with :consistent flag:
|
69
|
+
```ruby
|
70
|
+
api.folders_hierarchy :consistent => true
|
71
|
+
```
|
72
|
+
Be careful with a tree consistency, orphan folders may contain a critical data.
|
73
|
+
|
74
|
+
A more secure way to deal with consistency is to fix orphans first and then generate folders tree:
|
75
|
+
```ruby
|
76
|
+
api.add_folder "/garbage"
|
77
|
+
api.move_orphans :to => "/garbage" # Collect all orphans and place them under the /garbage folder
|
78
|
+
tree = api.folders_hierarchy
|
79
|
+
```
|
80
|
+
|
81
|
+
### Orphans
|
82
|
+
Ok, the Rapidshare has its common problem: orphan folders. What is this? For example we have the following directory tree:
|
83
|
+
```
|
84
|
+
ROOT
|
85
|
+
`-a <- RS API allows us to delete JUST THIS folder, so hierarchy relation between folders will be lost and the folders "c" and "b" will become orphans
|
86
|
+
`-b
|
87
|
+
`-c
|
88
|
+
```
|
89
|
+
Orphans is invisible in your File Manager on the Rapidshare web site, so you may want to hide data in that way (stupid idea)
|
90
|
+
We can fix it by detecting all orphan fodlers and moving them to a specific fodler:
|
91
|
+
```ruby
|
92
|
+
move_orphans :to => "/"
|
93
|
+
```
|
94
|
+
|
95
|
+
Or we can just kill'em all:
|
96
|
+
```ruby
|
97
|
+
remove_orphans!
|
98
|
+
```
|
99
|
+
|
100
|
+
Get folder ID or path:
|
101
|
+
```ruby
|
102
|
+
id = api.folder_id("/foo/bar") # <ID>
|
103
|
+
api.folder_path(id) # "/foo/bar"
|
104
|
+
```
|
105
|
+
|
106
|
+
### Files
|
107
|
+
|
108
|
+
File uploading is simple now:
|
109
|
+
```ruby
|
110
|
+
api.upload("/home/odiszapc/my_damn_cat.mov", :to => "/gallery/video", :as => "cat1.mov")
|
111
|
+
# => {
|
112
|
+
# :id => 1,
|
113
|
+
# :size => 12345, # File size in bytes
|
114
|
+
# :checksum => <MD5>,
|
115
|
+
# :url => <DOWNLOAD_URL>, # https://rapidshare/.......
|
116
|
+
# :already_exists? => true/false # Does the file already exists within a specific folder, real uploading will not being performed in this case
|
117
|
+
#}
|
118
|
+
```
|
119
|
+
After uploading has been completed the file will be stored in a Rapidshare as "/gallery/video/cat1.mov"
|
120
|
+
To get download url after uploading:
|
121
|
+
```ruby
|
122
|
+
result = api.upload("/home/odiszapc/my_damn_cat.mov", :to => "/gallery/video", :as => "cat1.mov")
|
123
|
+
result[:url]
|
124
|
+
```
|
125
|
+
|
126
|
+
By default, file is uploaded to root folder:
|
127
|
+
```ruby
|
128
|
+
api.upload("/home/odiszapc/my_damn_humster.mov")
|
129
|
+
```
|
130
|
+
|
131
|
+
Deleting files:
|
132
|
+
```ruby
|
133
|
+
api.remove_file("/putin/is/a/good/reason/to/live/abroad/ticket_to_Nikaragua.jpg")
|
134
|
+
```
|
135
|
+
|
136
|
+
Renaming files:
|
137
|
+
```ruby
|
138
|
+
api.rename_file("/foo/bar.rar", "baz.rar")
|
139
|
+
```
|
140
|
+
|
141
|
+
Moving files:
|
142
|
+
```ruby
|
143
|
+
api.move_file("/foo/bar/baz.rar", :to => "/foo") # new file path: "/foo/baz.rar"
|
144
|
+
api.move_file("/foo/bar/baz.rar") # move to a root folder
|
145
|
+
```
|
146
|
+
|
147
|
+
Get file ID:
|
148
|
+
```ruby
|
149
|
+
api.file_id("/foo/bar/baz.rar") # => <ID>
|
150
|
+
```
|
151
|
+
|
152
|
+
### Account
|
153
|
+
You can null your account by deleting all data involved. Be carefull with it, all data will be lost:
|
154
|
+
```ruby
|
155
|
+
api.erase_all_data!
|
156
|
+
```
|
157
|
+
|
158
|
+
## Contributing
|
159
|
+
|
160
|
+
1. Fork it
|
161
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
162
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
163
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
164
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require 'rake/testtask'
|
4
|
+
include Rake::DSL
|
5
|
+
|
6
|
+
desc "Run tests"
|
7
|
+
task :test => ['test:unit', 'test:integration']
|
8
|
+
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
namespace :test do
|
12
|
+
Rake::TestTask.new :unit do |t|
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/unit/*_test.rb'
|
15
|
+
end
|
16
|
+
|
17
|
+
Rake::TestTask.new :integration do |t|
|
18
|
+
t.libs << 'test'
|
19
|
+
t.pattern = 'test/integration/*_test.rb'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Rapidshare
|
2
|
+
class API
|
3
|
+
# TODO this class is getting long. keep general request-related and helper
|
4
|
+
# method here and move specific method calls like :getaccountdetails to other
|
5
|
+
# class (service)?
|
6
|
+
#
|
7
|
+
# TODO enable users to define their own parsers and pass them as code blocks?
|
8
|
+
# not really that practical, but it would be a cool piece of code :)
|
9
|
+
|
10
|
+
# Calls specific RapidShare API service and returns result.
|
11
|
+
#
|
12
|
+
# Throws exception if error is received from RapidShare API.
|
13
|
+
#
|
14
|
+
# Params:
|
15
|
+
# * *service_name* - name of the RapidShare service, for example +checkfiles+
|
16
|
+
# * *params* - hash of service parameters and options (listed below)
|
17
|
+
# * *parser* - option, determines how the response body will be parsed:
|
18
|
+
# * *none* - default value, returns response body as it is
|
19
|
+
# * *csv* - comma-separated values, for example: _getrapidtranslogs_.
|
20
|
+
# Returns array or arrays, one array per each line.
|
21
|
+
# * *hash* - lines with key and value separated by "=", for example:
|
22
|
+
# _getaccountdetails_. Returns hash.
|
23
|
+
# * *server* - option, determines which server will be used to send request
|
24
|
+
#
|
25
|
+
def self.request(service_name, params = {})
|
26
|
+
params.symbolize_keys!
|
27
|
+
|
28
|
+
parser = (params.delete(:parser) || :none).to_sym
|
29
|
+
unless [:none, :csv, :hash].include?(parser)
|
30
|
+
raise Rapidshare::API::Error.new("Invalid parser for request method: #{parser}")
|
31
|
+
end
|
32
|
+
|
33
|
+
server = params.delete(:server)
|
34
|
+
server_url = server ? "https://#{server}/cgi-bin/rsapi.cgi?sub=%s&%s" : URL
|
35
|
+
|
36
|
+
http_method = (params.delete(:method) || :get).to_sym
|
37
|
+
raise Exception, "invalid HTTP method #{http_method}" unless self.respond_to? http_method
|
38
|
+
|
39
|
+
case http_method
|
40
|
+
when :get
|
41
|
+
response = self.send(http_method, server_url % [service_name, params.to_query])
|
42
|
+
else
|
43
|
+
params[:sub] = service_name
|
44
|
+
response = self.send(http_method, server_url.gsub(/\?sub=%s&%s$/,''), params)
|
45
|
+
end
|
46
|
+
|
47
|
+
if response.start_with?(ERROR_PREFIX)
|
48
|
+
case error = response.sub(ERROR_PREFIX, "").split('.').first
|
49
|
+
when "Login failed"
|
50
|
+
raise Rapidshare::API::Error::LoginFailed
|
51
|
+
when "Invalid routine called"
|
52
|
+
raise Rapidshare::API::Error::InvalidRoutineCalled.new(service_name)
|
53
|
+
else
|
54
|
+
raise Rapidshare::API::Error.new(error)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
self.parse_response(parser, response)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,499 @@
|
|
1
|
+
module Rapidshare
|
2
|
+
module Ext
|
3
|
+
module API
|
4
|
+
|
5
|
+
FILE_COLUMNS = "downloads,lastdownload,filename,size,serverid,type,x,y,realfolder,killdeadline,uploadtime,comment,md5hex,licids,sentby"
|
6
|
+
|
7
|
+
# @param [String] path Folder name with absolute path to be created
|
8
|
+
# @param [Hash] params
|
9
|
+
# @return [Integer]
|
10
|
+
#
|
11
|
+
# Creates a folder in a Rapidshare virtual filesystem
|
12
|
+
#
|
13
|
+
# api.add_folder("/a/b/c") #=> <Random folder ID from Rapidshare>, 1234 for example
|
14
|
+
def add_folder(path, params = {})
|
15
|
+
@tree = folders_hierarchy
|
16
|
+
i = 1
|
17
|
+
parent = 0
|
18
|
+
folder_id = nil
|
19
|
+
while i <= path.split('/').count do
|
20
|
+
base_path = path.split('/')[0,i].join('/')
|
21
|
+
folder_id = self.folder_id base_path
|
22
|
+
if folder_id
|
23
|
+
parent = folder_id
|
24
|
+
i += 1
|
25
|
+
else
|
26
|
+
# Create folder
|
27
|
+
folder_name = path.split('/')[i-1]
|
28
|
+
add_folder_params = {
|
29
|
+
:name => folder_name,
|
30
|
+
:parent => parent
|
31
|
+
}.merge params
|
32
|
+
|
33
|
+
# The following code deals with #{} because of rest client #to_i returns HTTP code
|
34
|
+
folder_id = "#{addrealfolder(add_folder_params)}".to_i
|
35
|
+
raise "error while creating folder" if parent < 0
|
36
|
+
@tree[folder_id] = {
|
37
|
+
:parent => parent,
|
38
|
+
:name => folder_name,
|
39
|
+
:path => (@tree[parent] || {})[:path].to_s + ('/' if @tree[parent]).to_s + folder_name
|
40
|
+
}
|
41
|
+
parent = folder_id
|
42
|
+
path == base_path + '/' + folder_name
|
43
|
+
i += 1
|
44
|
+
next
|
45
|
+
end
|
46
|
+
end
|
47
|
+
folder_id
|
48
|
+
end
|
49
|
+
|
50
|
+
# Removes a specified folder
|
51
|
+
#
|
52
|
+
# @param [String] path
|
53
|
+
# @param [Hash] params
|
54
|
+
# @return [Array]
|
55
|
+
#
|
56
|
+
# api.remove_folder("/a/b/c")
|
57
|
+
def remove_folder(path, params = {})
|
58
|
+
folder_id = self.folder_id path_trim(path)
|
59
|
+
raise Exception, "Folder #{path} could not be found" if folder_id.nil?
|
60
|
+
|
61
|
+
# TODO
|
62
|
+
tree = folders_hierarchy :from => path
|
63
|
+
tree.each_pair do |child_folder_id, data|
|
64
|
+
delrealfolder_params = {
|
65
|
+
:realfolder => child_folder_id
|
66
|
+
}.merge params
|
67
|
+
|
68
|
+
delrealfolder delrealfolder_params
|
69
|
+
@tree.delete folder_id
|
70
|
+
end
|
71
|
+
|
72
|
+
params = {
|
73
|
+
:realfolder => folder_id
|
74
|
+
}.merge params
|
75
|
+
|
76
|
+
delrealfolder params
|
77
|
+
|
78
|
+
@tree.delete folder_id
|
79
|
+
end
|
80
|
+
|
81
|
+
# Moves folder into a specified one
|
82
|
+
#
|
83
|
+
# @param [String] source_path
|
84
|
+
# @param [Hash] params
|
85
|
+
# :to => <destination folder path>, default: "/"
|
86
|
+
#
|
87
|
+
# api.move_folder("/a/b/c", :to => "/a")
|
88
|
+
def move_folder(source_path, params = {})
|
89
|
+
dest_path = path_trim(params.delete(:to) || '/')
|
90
|
+
source_folder_id = folder_id(source_path)
|
91
|
+
dest_folder_id = folder_id(dest_path)
|
92
|
+
|
93
|
+
params = {
|
94
|
+
:realfolder => source_folder_id,
|
95
|
+
:newparent => dest_folder_id
|
96
|
+
}.merge params
|
97
|
+
|
98
|
+
moverealfolder params
|
99
|
+
|
100
|
+
@tree = folders_hierarchy
|
101
|
+
@tree[source_folder_id][:parent] = dest_folder_id
|
102
|
+
@tree[source_folder_id][:path] = "#{folder_path(dest_folder_id)}/#{@tree[source_folder_id][:name]}"
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
# Upload file to a specified folder
|
107
|
+
#
|
108
|
+
# @param [String] file_path
|
109
|
+
# @param [Hash] params
|
110
|
+
# <tt>:to</tt>::
|
111
|
+
# Folder to place uploaded file to, default: "/"
|
112
|
+
# <tt>:as</tt>::
|
113
|
+
# The name file will have in storage after it has been uploaded
|
114
|
+
#
|
115
|
+
# api.upload("/home/odiszapc/my_damn_cat.mov", :to => "/gallery/video", :as => "cat1.mov")
|
116
|
+
def upload(file_path, params = {})
|
117
|
+
raise Exception unless File.exist? file_path
|
118
|
+
dest_path = path_trim(params.delete(:to) || '/')
|
119
|
+
folder_id = self.add_folder dest_path
|
120
|
+
file_name = params.delete(:as) || File.basename(file_path)
|
121
|
+
|
122
|
+
# Check file already exists within a folder
|
123
|
+
listfiles_params = {
|
124
|
+
:realfolder => folder_id,
|
125
|
+
:filename => "#{file_name}",
|
126
|
+
:fields => "md5hex,size",
|
127
|
+
:parser => :csv
|
128
|
+
}
|
129
|
+
listfiles_response = self.listfiles listfiles_params
|
130
|
+
|
131
|
+
# In case of file is not existing upload it
|
132
|
+
if "NONE" == listfiles_response[0][0]
|
133
|
+
upload_server = "rs#{self.nextuploadserver}.rapidshare.com"
|
134
|
+
|
135
|
+
upload_params = {
|
136
|
+
:server => upload_server,
|
137
|
+
:folder => folder_id,
|
138
|
+
:filename => file_name,
|
139
|
+
:filecontent => file_path,
|
140
|
+
:method => :post,
|
141
|
+
:parser => :csv
|
142
|
+
}.merge params
|
143
|
+
|
144
|
+
resp = request(:upload, upload_params)
|
145
|
+
raise Exception, "File uploading failed: #{resp.inspect}" unless "COMPLETE" == resp[0][0]
|
146
|
+
|
147
|
+
id = resp[1][0].to_i
|
148
|
+
md5_hash = resp[1][3]
|
149
|
+
size = resp[1][2].to_i
|
150
|
+
already_exists = false
|
151
|
+
else
|
152
|
+
id = listfiles_response[0][0].to_i
|
153
|
+
md5_hash = listfiles_response[0][1]
|
154
|
+
size = listfiles_response[0][2].to_i
|
155
|
+
already_exists = true
|
156
|
+
end
|
157
|
+
|
158
|
+
raise Exception, "Invalid File ID: #{resp.inspect}" unless id
|
159
|
+
raise Exception, "Invalid MD5 hash: #{resp.inspect}" unless md5_hash
|
160
|
+
raise Exception, "Invalid File Size: #{resp.inspect}" unless size
|
161
|
+
|
162
|
+
{
|
163
|
+
:id => id,
|
164
|
+
:size => size,
|
165
|
+
:checksum => md5_hash.downcase,
|
166
|
+
:url => "https://rapidshare.com/files/#{id}/#{URI::encode file_name}",
|
167
|
+
:already_exists? => already_exists
|
168
|
+
}
|
169
|
+
end
|
170
|
+
|
171
|
+
# Delete file
|
172
|
+
#
|
173
|
+
# @param [String] path
|
174
|
+
# @param [Hash] params
|
175
|
+
#
|
176
|
+
# api.remove_file("/putin/is/a/good/reason/to/live/abroad/ticket_to_Nikaragua.jpg")
|
177
|
+
def remove_file(path, params = {})
|
178
|
+
params = {
|
179
|
+
:files => file_id(path).to_s
|
180
|
+
}.merge params
|
181
|
+
|
182
|
+
deletefiles params
|
183
|
+
end
|
184
|
+
|
185
|
+
# Rename file
|
186
|
+
#
|
187
|
+
# @param [String] remote_path
|
188
|
+
# @param [String] name
|
189
|
+
# @param [Hash] params
|
190
|
+
#
|
191
|
+
# api.rename_file("/foo/bar.rar", "baz.rar")
|
192
|
+
def rename_file(remote_path, name, params = {})
|
193
|
+
file_id = file_id remote_path
|
194
|
+
|
195
|
+
params = {
|
196
|
+
:fileid => file_id,
|
197
|
+
:newname => name
|
198
|
+
}.merge params
|
199
|
+
|
200
|
+
renamefile params
|
201
|
+
# TODO: duplicates check
|
202
|
+
end
|
203
|
+
|
204
|
+
# Moves file to a specified folder
|
205
|
+
#
|
206
|
+
# @param [String] remote_path
|
207
|
+
# @param [Hash] params
|
208
|
+
# <tt>:to</tt>::
|
209
|
+
# Destination folder path, default: "/"
|
210
|
+
#
|
211
|
+
# api.move_file("/foo/bar/baz.rar", :to => "/foo")
|
212
|
+
# api.move_file("/foo/bar/baz.rar") # move to a root folder
|
213
|
+
def move_file(remote_path, params = {})
|
214
|
+
file_id = file_id remote_path
|
215
|
+
dest_path = path_trim(params.delete(:to) || '/')
|
216
|
+
|
217
|
+
params = {
|
218
|
+
:files => file_id,
|
219
|
+
:realfolder => folder_id(dest_path)
|
220
|
+
}.merge params
|
221
|
+
|
222
|
+
movefilestorealfolder params
|
223
|
+
end
|
224
|
+
|
225
|
+
# See #folders_hierarchy method
|
226
|
+
def folders_hierarchy!(params = {})
|
227
|
+
params[:force] = true
|
228
|
+
folders_hierarchy params
|
229
|
+
end
|
230
|
+
|
231
|
+
alias :reload! :folders_hierarchy!
|
232
|
+
|
233
|
+
# Build folders hierarchy in the following format:
|
234
|
+
# {
|
235
|
+
# <folder ID> => {
|
236
|
+
# :parent => <parent folder ID>,
|
237
|
+
# :name => <folder name>,
|
238
|
+
# :path => <folder absolute path>
|
239
|
+
# },
|
240
|
+
# ...
|
241
|
+
# }
|
242
|
+
#
|
243
|
+
# @param [Hash] params
|
244
|
+
# <tt>:force</tt>::
|
245
|
+
# Invalidate cached tree, default: false
|
246
|
+
# After each call of this method the generated tree will be saved as cache
|
247
|
+
# to avoid unnecessary queries to be performed fpr a future calls
|
248
|
+
# <tt>:consistent</tt>::
|
249
|
+
# Delete all found orphans, default: false
|
250
|
+
def folders_hierarchy(params = {})
|
251
|
+
force_load = params.delete :force
|
252
|
+
from_folder_path = path_trim(params.delete(:from) || '/')
|
253
|
+
remove_orphans = params.delete(:consistent)
|
254
|
+
|
255
|
+
if @tree && !force_load
|
256
|
+
if from_folder_path.empty?
|
257
|
+
return @tree
|
258
|
+
else
|
259
|
+
return slice_tree @tree, :from => from_folder_path
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
return @tree if @tree && !force_load # TODO: about slices here (:from parameter)
|
264
|
+
|
265
|
+
from_folder_id = folder_id from_folder_path
|
266
|
+
raise Exception, "Folder #{from_folder_path} could not be found" if from_folder_id.nil?
|
267
|
+
|
268
|
+
response = listrealfolders
|
269
|
+
|
270
|
+
if 'NONE' == response
|
271
|
+
@tree = {}
|
272
|
+
else
|
273
|
+
intermediate = response.split(' ').map do |str|
|
274
|
+
params = str.split ','
|
275
|
+
[params[0].to_i, {:parent => params[1].to_i, :name => params[2]}]
|
276
|
+
end
|
277
|
+
|
278
|
+
@tree = Hash[intermediate]
|
279
|
+
end
|
280
|
+
|
281
|
+
# Kill orphans
|
282
|
+
remove_orphans! if remove_orphans
|
283
|
+
|
284
|
+
# Validate folder tree consistency
|
285
|
+
@tree.each_pair do |folder_id, data|
|
286
|
+
parent_id = data[:parent]
|
287
|
+
if !parent_id.zero? && @tree[parent_id].nil?
|
288
|
+
|
289
|
+
error = "There is no parent folder with id ##{data[:parent]} for the folder \"#{data[:name]}\" [#{folder_id}]"
|
290
|
+
raise error
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
@tree.each_pair do |folder_id, data|
|
295
|
+
@tree[folder_id][:path] = folder_path folder_id
|
296
|
+
end
|
297
|
+
|
298
|
+
@tree = slice_tree @tree, :from => from_folder_path unless from_folder_path.empty?
|
299
|
+
@tree
|
300
|
+
end
|
301
|
+
|
302
|
+
# Build tree relative to a specified folder
|
303
|
+
# If the source tree is:
|
304
|
+
# tree = {
|
305
|
+
# 1 => {:parent => 0, :name => "a", :path => "a"},
|
306
|
+
# 2 => {:parent => 1, :name => "b", :path => "a/b"},
|
307
|
+
# 3 => {:parent => 2, :name => "c", :path => "a/b/c"},
|
308
|
+
# ...
|
309
|
+
# }
|
310
|
+
# slice_tree tree, :from => "/a"
|
311
|
+
# Result will be as follows:
|
312
|
+
# {
|
313
|
+
# 2 => {:parent => 1, :name => "b", :path => "b"},
|
314
|
+
# 3 => {:parent => 2, :name => "c", :path => "b/c"},
|
315
|
+
# ...
|
316
|
+
# }
|
317
|
+
def slice_tree(tree, params = {})
|
318
|
+
from_folder_path = path_trim(params.delete(:from) || '/')
|
319
|
+
|
320
|
+
result_tree = tree.dup
|
321
|
+
|
322
|
+
unless from_folder_path == ''
|
323
|
+
|
324
|
+
result_tree.keep_if do |folder_id, data|
|
325
|
+
data[:path].start_with? "#{from_folder_path}/"
|
326
|
+
end
|
327
|
+
|
328
|
+
result_tree.each_pair do |folder_id, data|
|
329
|
+
path = result_tree[folder_id][:path]
|
330
|
+
result_tree[folder_id][:path] = path.gsub /#{from_folder_path.gsub /\//, '\/'}\//, ''
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
result_tree
|
335
|
+
end
|
336
|
+
|
337
|
+
# Fix inconsistent folder tree (Yes, getting a broken folder hierarchy is possible with a stupid Rapidshare API)
|
338
|
+
# by deleting orphan folders (folders with no parent folder), this folders are invisible in Rapidshare File Manager
|
339
|
+
# So, this method deletes orphan folders
|
340
|
+
def remove_orphans!
|
341
|
+
@tree = folders_hierarchy
|
342
|
+
@tree.each_pair do |folder_id, data|
|
343
|
+
@tree.delete_if do |folder_id, data|
|
344
|
+
if orphan? folder_id
|
345
|
+
delrealfolder :realfolder => folder_id
|
346
|
+
true
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
# Places all existing orphan folders under the specific folder
|
353
|
+
# Orphan folder is a folder with non existing parent (yes, it's possible)
|
354
|
+
#
|
355
|
+
# Example:
|
356
|
+
# move_orphans :to => "/"
|
357
|
+
def move_orphans(params = {})
|
358
|
+
new_folder = folder_id params[:to].to_s
|
359
|
+
orphans = detect_gaps.join(',')
|
360
|
+
if orphans.any?
|
361
|
+
moverealfolder :realfolder => orphans.join(','), :newparent => new_folder
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
# Returns gap list between folders
|
366
|
+
# See #gap? for example
|
367
|
+
def detect_gaps
|
368
|
+
@tree = folders_hierarchy
|
369
|
+
@tree.keep_if do |folder_id, data|
|
370
|
+
gap? folder_id # This is wrong
|
371
|
+
end.keys
|
372
|
+
end
|
373
|
+
|
374
|
+
# The name speaks for itself
|
375
|
+
# WARNING!!! All data will be lost!!!
|
376
|
+
# Use it carefully
|
377
|
+
def erase_all_data!
|
378
|
+
@tree = folders_hierarchy
|
379
|
+
@tree.keys.each do |folder_id|
|
380
|
+
delrealfolder :realfolder => folder_id
|
381
|
+
end
|
382
|
+
folders_hierarchy!
|
383
|
+
end
|
384
|
+
|
385
|
+
# Check if folder with given id placed on the bottom of folder hierarchy
|
386
|
+
def root_folder?(folder_id)
|
387
|
+
@tree = folders_hierarchy
|
388
|
+
@tree[folder_id][:parent].zero?
|
389
|
+
end
|
390
|
+
|
391
|
+
# Check if the given folder has no parent
|
392
|
+
def gap?(folder_id)
|
393
|
+
@tree = folders_hierarchy
|
394
|
+
parent_id = @tree[folder_id][:parent]
|
395
|
+
@tree[parent_id].nil?
|
396
|
+
end
|
397
|
+
|
398
|
+
# Check if folder has any gaps in it hierarchy
|
399
|
+
# For example we have the following hierarchy:
|
400
|
+
#
|
401
|
+
# ROOT
|
402
|
+
# `-a <- if we remove just this folder then the folder "c" and "b" will become orphans
|
403
|
+
# `-b
|
404
|
+
# `-c
|
405
|
+
def orphan?(folder_id)
|
406
|
+
@tree = folders_hierarchy
|
407
|
+
parent_id = @tree[folder_id][:parent]
|
408
|
+
return false if root_folder? folder_id
|
409
|
+
return true if gap? folder_id
|
410
|
+
orphan?(parent_id)
|
411
|
+
end
|
412
|
+
|
413
|
+
# Translate folder ID to a human readable path
|
414
|
+
#
|
415
|
+
# api.folder_path(123) # -> "foo/bar/baz"
|
416
|
+
def folder_path(folder_id)
|
417
|
+
@tree = folders_hierarchy
|
418
|
+
parent_id = @tree[folder_id][:parent]
|
419
|
+
(folder_path(parent_id) if parent_id.nonzero?).to_s + ('/' if parent_id.nonzero?).to_s + @tree[folder_id][:name]
|
420
|
+
end
|
421
|
+
|
422
|
+
# Get folder ID by path
|
423
|
+
#
|
424
|
+
# api.folder_id("foo/bar/baz") # -> 123
|
425
|
+
def folder_id(folder_path)
|
426
|
+
folder_path = path_trim(folder_path)
|
427
|
+
return 0 if folder_path.empty?
|
428
|
+
|
429
|
+
@tree = folders_hierarchy
|
430
|
+
index = @tree.find_index do |folder_id, data|
|
431
|
+
data[:path] == folder_path
|
432
|
+
end
|
433
|
+
@tree.keys[index] unless index.nil?
|
434
|
+
end
|
435
|
+
|
436
|
+
# Get file info in the following format:
|
437
|
+
#
|
438
|
+
# {
|
439
|
+
# :downloads,
|
440
|
+
# :lastdownload,
|
441
|
+
# :filename,
|
442
|
+
# :size,
|
443
|
+
# :serverid,
|
444
|
+
# :type,
|
445
|
+
# :x,
|
446
|
+
# :y,
|
447
|
+
# :realfolder,
|
448
|
+
# :killdeadline,
|
449
|
+
# :uploadtime,
|
450
|
+
# :comment,
|
451
|
+
# :md5hex,
|
452
|
+
# :licids,
|
453
|
+
# :sentby
|
454
|
+
# }
|
455
|
+
# See http://images.rapidshare.com/apidoc.txt for more details
|
456
|
+
def file_info(file_path, params = {})
|
457
|
+
folder_path = File.dirname file_path
|
458
|
+
file_name = File.basename file_path
|
459
|
+
|
460
|
+
folder_id = folder_id folder_path
|
461
|
+
|
462
|
+
listfiles_params = {
|
463
|
+
:realfolder => folder_id,
|
464
|
+
:filename => "#{file_name}",
|
465
|
+
:fields => FILE_COLUMNS,
|
466
|
+
:parser => :csv
|
467
|
+
}.merge params
|
468
|
+
|
469
|
+
resp = listfiles(listfiles_params)[0]
|
470
|
+
return nil if "NONE" == resp[0]
|
471
|
+
|
472
|
+
response = {}
|
473
|
+
|
474
|
+
fields = listfiles_params[:fields].split(',')
|
475
|
+
fields.unshift "id"
|
476
|
+
fields.each_with_index do |value, index|
|
477
|
+
response[value.to_sym] = resp[index]
|
478
|
+
end
|
479
|
+
|
480
|
+
response
|
481
|
+
end
|
482
|
+
|
483
|
+
# Get file ID by absolute path
|
484
|
+
#
|
485
|
+
# api.file_id("foo/bar/baz/file.rar") # -> 456
|
486
|
+
def file_id(file_path, params = {})
|
487
|
+
params[:fields] = ""
|
488
|
+
file_info = file_info file_path, params
|
489
|
+
(file_info || {})[:id].to_i
|
490
|
+
end
|
491
|
+
|
492
|
+
protected
|
493
|
+
|
494
|
+
def path_trim(path)
|
495
|
+
path.gsub(/\A\/+/, '').gsub(/\/+\Z/, '')
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/rapidshare-ext/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "rapidshare-ext"
|
6
|
+
gem.version = Rapidshare::Ext::VERSION
|
7
|
+
gem.date = '2012-11-18'
|
8
|
+
gem.authors = ["odiszapc"]
|
9
|
+
gem.email = ["odiszapc@gmail.com"]
|
10
|
+
gem.description = %q{Makes your interactions with Rapidshare API more pleasant by providing new handy features: creating/moving/deleting files/folders in a user friendly way, upload files, etc}
|
11
|
+
gem.summary = %q{Simplifies interactions with Rapidshare API with handy features}
|
12
|
+
gem.homepage = "http://github.com/odiszapc/rapidshare-ext"
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($\)
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
|
19
|
+
|
20
|
+
gem.add_dependency('rapidshare', '~> 0.5.3')
|
21
|
+
gem.add_dependency('rest-client', '~> 1.6.7')
|
22
|
+
|
23
|
+
gem.add_development_dependency('test-unit')
|
24
|
+
gem.add_development_dependency('shoulda')
|
25
|
+
gem.add_development_dependency('simplecov')
|
26
|
+
gem.add_development_dependency('fakeweb')
|
27
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Test file for upload
|
@@ -0,0 +1,16 @@
|
|
1
|
+
accountid=12345
|
2
|
+
servertime=1217244932
|
3
|
+
addtime=127273393
|
4
|
+
username=valid_account
|
5
|
+
directstart=1
|
6
|
+
country=CZ
|
7
|
+
mailflags=
|
8
|
+
language=
|
9
|
+
jsconfig=1000
|
10
|
+
email=valid_account@email.com
|
11
|
+
curfiles=100
|
12
|
+
curspace=103994340
|
13
|
+
rapids=100
|
14
|
+
billeduntil=1320093121
|
15
|
+
nortuntil=1307123910
|
16
|
+
cookie=F0EEB41B38363A41F0D125102637DB7236468731F8DB760DC57934B4714C8D13
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'digest/md5'
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
|
4
|
+
|
5
|
+
class RapidshareExtTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
FakeWeb.allow_net_connect = true
|
9
|
+
@rs = Rapidshare::API.new :cookie => ENV['RAPIDSHARE_COOKIE']
|
10
|
+
@rs.erase_all_data!
|
11
|
+
end
|
12
|
+
|
13
|
+
context "Api" do
|
14
|
+
should "Upload file" do
|
15
|
+
assertion = ->(resp, size_local, digest_local, remote_filename) do
|
16
|
+
assert_instance_of Hash, resp
|
17
|
+
assert_kind_of Integer, resp[:id]
|
18
|
+
assert_kind_of Integer, resp[:size]
|
19
|
+
assert_equal size_local, resp[:size]
|
20
|
+
assert_instance_of String, resp[:checksum]
|
21
|
+
assert_match /[a-z0-9]{32}/, resp[:checksum]
|
22
|
+
assert_equal digest_local, resp[:checksum]
|
23
|
+
assert_instance_of String, resp[:url]
|
24
|
+
assert_equal "https://rapidshare.com/files/#{resp[:id]}/#{URI::encode(remote_filename)}", resp[:url]
|
25
|
+
end
|
26
|
+
|
27
|
+
file_info_assertion = ->(info, file_id, digest_local, size_local, remote_filename, remote_dir) do
|
28
|
+
assert_equal info[:filename], remote_filename
|
29
|
+
assert_equal info[:id].to_i, file_id
|
30
|
+
assert_equal info[:md5hex].downcase, digest_local
|
31
|
+
assert_equal info[:realfolder].to_i, @rs.folder_id(remote_dir)
|
32
|
+
assert_equal info[:size].to_i, size_local
|
33
|
+
end
|
34
|
+
|
35
|
+
local_path = File.expand_path(File.dirname(__FILE__) + "/../fixtures/files/upload1.txt")
|
36
|
+
remote_filename = "upload_file_1.txt"
|
37
|
+
remote_dir = "a/b/c"
|
38
|
+
remote_path = "#{remote_dir}/#{remote_filename}"
|
39
|
+
digest_local = Digest::MD5.hexdigest(File.read(local_path))
|
40
|
+
size_local = File.size local_path
|
41
|
+
|
42
|
+
# Initial upload
|
43
|
+
response = @rs.upload local_path, :as => remote_filename, :to => remote_dir
|
44
|
+
assertion.call response, size_local, digest_local, remote_filename
|
45
|
+
assert_false response[:already_exists?]
|
46
|
+
|
47
|
+
# Check file ID
|
48
|
+
file_id = @rs.file_id remote_path
|
49
|
+
assert_kind_of Integer, file_id
|
50
|
+
assert_equal file_id, response[:id]
|
51
|
+
|
52
|
+
# Check file info
|
53
|
+
info = @rs.file_info remote_path
|
54
|
+
file_info_assertion.call info, file_id, digest_local, size_local, remote_filename, remote_dir
|
55
|
+
|
56
|
+
# Upload the same file again
|
57
|
+
response = @rs.upload local_path, :as => remote_filename, :to => remote_dir
|
58
|
+
assertion.call response, size_local, digest_local, remote_filename
|
59
|
+
assert_true response[:already_exists?]
|
60
|
+
|
61
|
+
# Rename file
|
62
|
+
remote_filename_2 ="foo.txt"
|
63
|
+
remote_path_2 = "#{remote_dir}/#{remote_filename_2}"
|
64
|
+
@rs.rename_file remote_path, remote_filename_2
|
65
|
+
info = @rs.file_info remote_path_2
|
66
|
+
file_info_assertion.call info, @rs.file_id(remote_path_2), digest_local, size_local, remote_filename_2, remote_dir
|
67
|
+
|
68
|
+
# Move file
|
69
|
+
remote_dir_3 = "a/b"
|
70
|
+
remote_path_3 = "#{remote_dir_3}/#{remote_filename_2}"
|
71
|
+
@rs.move_file remote_path_2, :to => remote_dir_3
|
72
|
+
|
73
|
+
info = @rs.file_info remote_path_3
|
74
|
+
file_info_assertion.call info, @rs.file_id(remote_path_3), digest_local, size_local, remote_filename_2, remote_dir_3
|
75
|
+
|
76
|
+
# Delete file
|
77
|
+
@rs.remove_file remote_path_3
|
78
|
+
|
79
|
+
info = @rs.file_info remote_path_3
|
80
|
+
assert_nil info
|
81
|
+
end
|
82
|
+
|
83
|
+
should "Create folder" do
|
84
|
+
folder_id = @rs.add_folder "a/b/c"
|
85
|
+
assert_kind_of Integer, folder_id
|
86
|
+
assert_not_equal 0, folder_id
|
87
|
+
tree = @rs.folders_hierarchy
|
88
|
+
|
89
|
+
assert_equal 3, tree.count
|
90
|
+
assert_equal "a/b/c", tree[folder_id][:path]
|
91
|
+
assert_equal "a/b", tree[tree[folder_id][:parent]][:path]
|
92
|
+
assert_equal "a", tree[tree[tree[folder_id][:parent]][:parent]][:path]
|
93
|
+
end
|
94
|
+
|
95
|
+
should "Move folder" do
|
96
|
+
folder_id = @rs.add_folder "a/b/c"
|
97
|
+
assert_kind_of Integer, folder_id
|
98
|
+
assert_not_equal 0, folder_id
|
99
|
+
tree = @rs.folders_hierarchy
|
100
|
+
|
101
|
+
assert_equal 3, tree.count
|
102
|
+
assert_equal "a/b/c", tree[folder_id][:path]
|
103
|
+
assert_equal "a/b", tree[tree[folder_id][:parent]][:path]
|
104
|
+
assert_equal "a", tree[tree[tree[folder_id][:parent]][:parent]][:path]
|
105
|
+
|
106
|
+
@rs.move_folder "a/b/c", :to => 'a'
|
107
|
+
|
108
|
+
tree = @rs.reload!
|
109
|
+
|
110
|
+
assert_equal 3, tree.count
|
111
|
+
assert_equal "a/c", tree[folder_id][:path]
|
112
|
+
assert_equal @rs.folder_id("a"), tree[folder_id][:parent]
|
113
|
+
end
|
114
|
+
|
115
|
+
should "Build folder tree" do
|
116
|
+
# Create folder
|
117
|
+
folder_id = @rs.add_folder "a/b/c"
|
118
|
+
assert_kind_of Integer, folder_id
|
119
|
+
assert_not_equal 0, folder_id
|
120
|
+
tree = @rs.folders_hierarchy
|
121
|
+
|
122
|
+
# Validate tree
|
123
|
+
assert_equal 3, tree.count
|
124
|
+
assert_equal "a/b/c", tree[folder_id][:path]
|
125
|
+
assert_equal "a/b", tree[tree[folder_id][:parent]][:path]
|
126
|
+
assert_equal "a", tree[tree[tree[folder_id][:parent]][:parent]][:path]
|
127
|
+
|
128
|
+
# Validate subtree
|
129
|
+
sub_tree = @rs.folders_hierarchy :from => 'a/b'
|
130
|
+
assert_equal 1, sub_tree.count
|
131
|
+
assert_equal "c", sub_tree[folder_id][:path]
|
132
|
+
end
|
133
|
+
|
134
|
+
should "Remove folder" do
|
135
|
+
folder_id = @rs.add_folder "a/b/c"
|
136
|
+
assert_kind_of Integer, folder_id
|
137
|
+
assert_not_equal 0, folder_id
|
138
|
+
tree = @rs.folders_hierarchy
|
139
|
+
assert_equal 3, tree.count
|
140
|
+
|
141
|
+
@rs.remove_folder "a/b/c"
|
142
|
+
|
143
|
+
tree = @rs.folders_hierarchy!
|
144
|
+
assert_equal 2, tree.count
|
145
|
+
|
146
|
+
|
147
|
+
folder_id = @rs.add_folder "a/b/c"
|
148
|
+
assert_kind_of Integer, folder_id
|
149
|
+
assert_not_equal 0, folder_id
|
150
|
+
tree = @rs.folders_hierarchy!
|
151
|
+
assert_equal 3, tree.count
|
152
|
+
|
153
|
+
@rs.remove_folder "a"
|
154
|
+
tree = @rs.folders_hierarchy!
|
155
|
+
assert_equal 0, tree.count
|
156
|
+
end
|
157
|
+
|
158
|
+
should "Erase account" do
|
159
|
+
folder_id = @rs.add_folder "a/b/c"
|
160
|
+
assert_kind_of Integer, folder_id
|
161
|
+
|
162
|
+
folder_ids = @rs.folders_hierarchy.keys
|
163
|
+
assert_true folder_ids.count > 0
|
164
|
+
|
165
|
+
# Delete all data from account
|
166
|
+
@rs.erase_all_data!
|
167
|
+
|
168
|
+
folder_ids = @rs.folders_hierarchy.keys
|
169
|
+
assert_equal 0, folder_ids.count
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'shoulda'
|
3
|
+
require 'fakeweb'
|
4
|
+
|
5
|
+
require 'rapidshare-ext'
|
6
|
+
|
7
|
+
class Test::Unit::TestCase
|
8
|
+
|
9
|
+
# don't allow internet connections for testing (we should use fixtures, except
|
10
|
+
# integration testing)
|
11
|
+
FakeWeb.allow_net_connect = false
|
12
|
+
|
13
|
+
def read_fixture(filename, extension = 'txt')
|
14
|
+
# add extension to file unless it already has it
|
15
|
+
filename += ".#{extension}" unless (filename =~ /\.\w+$/)
|
16
|
+
|
17
|
+
File.read File.expand_path(File.dirname(__FILE__) + "/fixtures/#{filename}")
|
18
|
+
end
|
19
|
+
|
20
|
+
# general setup, can be overriden or extended in specific tests
|
21
|
+
#
|
22
|
+
def setup
|
23
|
+
@cookie = 'F0EEB41B38363A41F0D125102637DB7236468731F8DB760DC57934B4714C8D13'
|
24
|
+
|
25
|
+
# mock http requests for login into Rapidshare
|
26
|
+
#
|
27
|
+
FakeWeb.register_uri(:get,
|
28
|
+
'https://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=getaccountdetails&login=valid_login&password=valid_password&withcookie=1&cookie=',
|
29
|
+
:body => read_fixture('getaccountdetails_valid.txt')
|
30
|
+
)
|
31
|
+
|
32
|
+
FakeWeb.register_uri(:get,
|
33
|
+
"https://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=getaccountdetails&cookie=#{@cookie}",
|
34
|
+
:body => read_fixture('getaccountdetails_valid.txt')
|
35
|
+
)
|
36
|
+
|
37
|
+
@rs = Rapidshare::API.new(:login => 'valid_login', :password => 'valid_password')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class RapidshareExtTest < Test::Unit::TestCase
|
4
|
+
context "Interface" do
|
5
|
+
should "Respond to certain methods" do
|
6
|
+
assert_respond_to @rs, :add_folder
|
7
|
+
assert_respond_to @rs, :remove_folder
|
8
|
+
assert_respond_to @rs, :move_folder
|
9
|
+
assert_respond_to @rs, :upload
|
10
|
+
assert_respond_to @rs, :remove_file
|
11
|
+
assert_respond_to @rs, :rename_file
|
12
|
+
assert_respond_to @rs, :folders_hierarchy
|
13
|
+
assert_respond_to @rs, :folders_hierarchy!
|
14
|
+
assert_respond_to @rs, :slice_tree
|
15
|
+
assert_respond_to @rs, :remove_orphans!
|
16
|
+
assert_respond_to @rs, :move_orphans
|
17
|
+
assert_respond_to @rs, :detect_gaps
|
18
|
+
assert_respond_to @rs, :erase_all_data!
|
19
|
+
assert_respond_to @rs, :root_folder?
|
20
|
+
assert_respond_to @rs, :gap?
|
21
|
+
assert_respond_to @rs, :orphan?
|
22
|
+
assert_respond_to @rs, :folder_path
|
23
|
+
assert_respond_to @rs, :folder_id
|
24
|
+
assert_respond_to @rs, :file_info
|
25
|
+
assert_respond_to @rs, :file_id
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rapidshare-ext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- odiszapc
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rapidshare
|
16
|
+
requirement: &19166544 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.5.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *19166544
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rest-client
|
27
|
+
requirement: &19165800 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.6.7
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *19165800
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: test-unit
|
38
|
+
requirement: &19165332 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *19165332
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: shoulda
|
49
|
+
requirement: &19164948 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *19164948
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: simplecov
|
60
|
+
requirement: &19164600 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *19164600
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fakeweb
|
71
|
+
requirement: &19164180 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *19164180
|
80
|
+
description: ! 'Makes your interactions with Rapidshare API more pleasant by providing
|
81
|
+
new handy features: creating/moving/deleting files/folders in a user friendly way,
|
82
|
+
upload files, etc'
|
83
|
+
email:
|
84
|
+
- odiszapc@gmail.com
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files: []
|
88
|
+
files:
|
89
|
+
- .gitignore
|
90
|
+
- Gemfile
|
91
|
+
- History.md
|
92
|
+
- LICENSE
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- lib/rapidshare-base/api.rb
|
96
|
+
- lib/rapidshare-base/utils.rb
|
97
|
+
- lib/rapidshare-ext.rb
|
98
|
+
- lib/rapidshare-ext/api.rb
|
99
|
+
- lib/rapidshare-ext/version.rb
|
100
|
+
- rapidshare-ext.gemspec
|
101
|
+
- test/fixtures/files/upload1.txt
|
102
|
+
- test/fixtures/getaccountdetails_valid.txt
|
103
|
+
- test/integration/rapidshare-ext_test.rb
|
104
|
+
- test/test_helper.rb
|
105
|
+
- test/unit/rapidshare-ext_test.rb
|
106
|
+
homepage: http://github.com/odiszapc/rapidshare-ext
|
107
|
+
licenses: []
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ! '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project:
|
126
|
+
rubygems_version: 1.8.16
|
127
|
+
signing_key:
|
128
|
+
specification_version: 3
|
129
|
+
summary: Simplifies interactions with Rapidshare API with handy features
|
130
|
+
test_files:
|
131
|
+
- test/fixtures/files/upload1.txt
|
132
|
+
- test/fixtures/getaccountdetails_valid.txt
|
133
|
+
- test/integration/rapidshare-ext_test.rb
|
134
|
+
- test/test_helper.rb
|
135
|
+
- test/unit/rapidshare-ext_test.rb
|