rapidshare-ext 0.0.1
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/.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
|