cloudapp-export 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.rubocop.yml +5 -1
- data/lib/cloudapp_export/api.rb +15 -0
- data/lib/cloudapp_export/cli.rb +29 -11
- data/lib/cloudapp_export/exporter.rb +8 -2
- data/lib/cloudapp_export/item_list.rb +20 -6
- data/lib/cloudapp_export/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 76ec7d3deb5e44184022937ced41ddc7438bfebbb6729225de2476b7d647aa58
|
4
|
+
data.tar.gz: 1b967386965f333aa271ac6f2928c5c524849d4871379fa24b39392aae02a43c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c85a8fbcd7ccf4cc19fcf5fcccdd1d2685dab6439975613eee4c2ed585f9a4aa5dadf3ac6a7873c765a047df070d143bba5068cff4070ff8680e01c9835ccad
|
7
|
+
data.tar.gz: 8c871fdfe40a82e3cc04d18f40be11329714f31fe14dcb634c09ea781dae5f9ce9562cd73ae8ab89887a7f0e300ca3030b2d00c53f82676f3ca6bd1aff132cf9
|
data/.rubocop.yml
CHANGED
@@ -27,6 +27,10 @@ Style/MultilineTernaryOperator:
|
|
27
27
|
Style/RegexpLiteral:
|
28
28
|
Enabled: false
|
29
29
|
|
30
|
+
# TODO: Figure out how to do this without URI.encode
|
31
|
+
Lint/UriEscapeUnescape:
|
32
|
+
Enabled: false
|
33
|
+
|
30
34
|
# Screens are big, even when they're small
|
31
35
|
Metrics/LineLength:
|
32
36
|
Enabled: false
|
@@ -44,7 +48,7 @@ Style/ClassAndModuleChildren:
|
|
44
48
|
Exclude:
|
45
49
|
- '**/*_test.rb'
|
46
50
|
Metrics/MethodLength:
|
47
|
-
Max:
|
51
|
+
Max: 18
|
48
52
|
Exclude:
|
49
53
|
- '**/*_test.rb'
|
50
54
|
|
data/lib/cloudapp_export/api.rb
CHANGED
@@ -12,6 +12,13 @@ module CloudappExport
|
|
12
12
|
@options = options
|
13
13
|
end
|
14
14
|
|
15
|
+
def authenticate!
|
16
|
+
response = request("items?per_page=1")
|
17
|
+
return true if response.status_code == 200
|
18
|
+
# TODO: Use custom exception classes
|
19
|
+
raise response.body.strip
|
20
|
+
end
|
21
|
+
|
15
22
|
def request(path)
|
16
23
|
digest_auth = Net::HTTP::DigestAuth.new
|
17
24
|
uri = URI.parse("https://#{host}/v3/#{path}")
|
@@ -57,8 +64,16 @@ module CloudappExport
|
|
57
64
|
@http_response.body
|
58
65
|
end
|
59
66
|
|
67
|
+
def status_code
|
68
|
+
@http_response.code.to_i
|
69
|
+
end
|
70
|
+
|
60
71
|
def data
|
61
72
|
JSON.parse(@http_response.body)['data']
|
62
73
|
end
|
74
|
+
|
75
|
+
def meta
|
76
|
+
JSON.parse(@http_response.body)['meta']
|
77
|
+
end
|
63
78
|
end
|
64
79
|
end
|
data/lib/cloudapp_export/cli.rb
CHANGED
@@ -10,13 +10,18 @@ module CloudappExport
|
|
10
10
|
desc :all, "Export all data from your Cloudapp account"
|
11
11
|
option :limit, default: 5, type: :numeric
|
12
12
|
option :dir, default: "#{ENV['HOME']}/Downloads/CloudappExport", type: :string, desc: "Directory to download all files to"
|
13
|
-
option :cache, type: :boolean, default:
|
13
|
+
option :cache, type: :boolean, default: false
|
14
14
|
def all
|
15
|
+
authenticate!
|
16
|
+
|
15
17
|
items = CloudappExport::ItemList.new(
|
16
18
|
api,
|
17
19
|
'limit' => options['limit'],
|
18
|
-
'
|
20
|
+
'use_cache' => options['cache'],
|
21
|
+
'cache_key' => "#{username}:#{options['limit']}",
|
19
22
|
)
|
23
|
+
say("Account contains #{set_color items.total_count, :bold} items")
|
24
|
+
say("", nil, true)
|
20
25
|
|
21
26
|
exporter = ::CloudappExport::Exporter.new(
|
22
27
|
items,
|
@@ -29,27 +34,31 @@ module CloudappExport
|
|
29
34
|
end
|
30
35
|
|
31
36
|
# rubocop:disable Metrics/AbcSize
|
32
|
-
# rubocop:disable Layout/TrailingWhitespace
|
33
37
|
desc :stats, "Show stats for CloudApp items"
|
34
38
|
option :dir, default: "#{ENV['HOME']}/Downloads/CloudappExport", type: :string, desc: "Directory where your files were downloaded to"
|
35
|
-
option :cache, type: :boolean, default:
|
39
|
+
option :cache, type: :boolean, default: false
|
36
40
|
def stats
|
41
|
+
authenticate!
|
42
|
+
|
37
43
|
items = CloudappExport::ItemList.new(
|
38
44
|
api,
|
39
|
-
'cache' => options['cache'],
|
40
45
|
)
|
41
|
-
|
46
|
+
say("Account contains #{set_color items.total_count, :bold} items")
|
47
|
+
say("", nil, true)
|
48
|
+
|
49
|
+
say("Dir #{options['dir']}")
|
50
|
+
say("", nil, true)
|
51
|
+
|
52
|
+
# TODO: Just count files directly in local folder
|
42
53
|
downloaded_items = items.data.select { |item| File.exist?("#{options['dir']}/#{item.filename}") }
|
43
54
|
downloaded_items_size = downloaded_items.inject(0) { |sum, item| sum + File.size("#{options['dir']}/#{item.filename}") }
|
44
|
-
|
45
|
-
say("Dir #{options['dir']}")
|
46
|
-
say("Items #{items.count}")
|
55
|
+
|
47
56
|
say("Downloaded #{downloaded_items.count}")
|
48
57
|
say(" #{(downloaded_items_size.to_f / 1_000_000).round 2} mb")
|
49
58
|
end
|
50
59
|
# rubocop:enable Metrics/AbcSize
|
51
|
-
# rubocop:enable Layout/TrailingWhitespace
|
52
60
|
|
61
|
+
# rubocop:disable Metrics/BlockLength
|
53
62
|
no_commands do
|
54
63
|
def api
|
55
64
|
@api ||= begin
|
@@ -60,6 +69,14 @@ module CloudappExport
|
|
60
69
|
end
|
61
70
|
end
|
62
71
|
|
72
|
+
def authenticate!
|
73
|
+
api.authenticate!
|
74
|
+
say("Successfully authenticated!", :green)
|
75
|
+
rescue StandardError => error
|
76
|
+
say("Could not authenticate with Cloudapp (#{error.message})", :red)
|
77
|
+
Kernel.exit
|
78
|
+
end
|
79
|
+
|
63
80
|
def username
|
64
81
|
@username ||= begin
|
65
82
|
username = options['username']
|
@@ -74,10 +91,11 @@ module CloudappExport
|
|
74
91
|
@password ||= begin
|
75
92
|
password = options['password']
|
76
93
|
password ||= ENV['CLOUDAPP_PASSWORD']
|
77
|
-
password ||=
|
94
|
+
(password ||= ask("Password:", echo: false)) && say('*' * 20)
|
78
95
|
password || raise("Password is required")
|
79
96
|
end
|
80
97
|
end
|
81
98
|
end
|
99
|
+
# rubocop:enable Metrics/BlockLength
|
82
100
|
end
|
83
101
|
end
|
@@ -25,13 +25,16 @@ module CloudappExport
|
|
25
25
|
filepath = "#{download_dir}/#{item.filename}"
|
26
26
|
if File.exist?(filepath)
|
27
27
|
log " SK #{item_filesize_human(item)}"
|
28
|
+
elsif item['remote_url'].nil? || item['item_type'] == 'pending'
|
29
|
+
log " SK No Remote URL"
|
28
30
|
else
|
29
31
|
begin
|
30
32
|
log " DL"
|
31
33
|
copy_file(item['remote_url'], filepath)
|
32
34
|
log " #{item_filesize_human(item)}"
|
33
35
|
rescue StandardError => error
|
34
|
-
log " ER #{error.message}"
|
36
|
+
log " ER #{error.message}\n"
|
37
|
+
error.backtrace.each { |line| log " #{line}\n" }
|
35
38
|
end
|
36
39
|
end
|
37
40
|
log "\n"
|
@@ -44,10 +47,13 @@ module CloudappExport
|
|
44
47
|
protected
|
45
48
|
|
46
49
|
def copy_file(remote_url, local_path)
|
47
|
-
remote_uri = URI(remote_url)
|
50
|
+
remote_uri = URI.parse(URI.encode(remote_url, '[]'))
|
48
51
|
File.open(local_path, 'wb') do |file|
|
49
52
|
file << Net::HTTP.get(remote_uri)
|
50
53
|
end
|
54
|
+
rescue StandardError => error
|
55
|
+
File.delete(local_path)
|
56
|
+
raise error
|
51
57
|
end
|
52
58
|
|
53
59
|
def item_filesize(item)
|
@@ -1,11 +1,13 @@
|
|
1
1
|
require "json"
|
2
|
+
require "digest"
|
2
3
|
|
3
4
|
module CloudappExport
|
4
5
|
class ItemList
|
5
6
|
def initialize(api, options = {})
|
6
7
|
@api = api
|
7
8
|
@items = []
|
8
|
-
@
|
9
|
+
@cache_key = options['cache_key']
|
10
|
+
@use_cache = options['use_cache']
|
9
11
|
@limit = (options['limit'] || 999_999_999).to_i
|
10
12
|
@offset = (options['offset'] || 0).to_i
|
11
13
|
end
|
@@ -16,8 +18,12 @@ module CloudappExport
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def count
|
19
|
-
|
20
|
-
|
21
|
+
[total_count, @limit].min
|
22
|
+
end
|
23
|
+
|
24
|
+
def total_count
|
25
|
+
load_meta
|
26
|
+
@meta['count'].to_i
|
21
27
|
end
|
22
28
|
|
23
29
|
def each(&block)
|
@@ -42,9 +48,9 @@ module CloudappExport
|
|
42
48
|
if @use_cache && File.exist?(cache_file_path)
|
43
49
|
items = ::JSON.parse(::File.read(cache_file_path))
|
44
50
|
else
|
45
|
-
response = @api.request("items?per_page
|
51
|
+
response = @api.request("items?per_page=#{@limit}")
|
46
52
|
items = response.data
|
47
|
-
::File.write(cache_file_path, ::JSON.dump(items))
|
53
|
+
::File.write(cache_file_path, ::JSON.dump(items)) if @cache_key
|
48
54
|
end
|
49
55
|
items.map do |attributes|
|
50
56
|
::CloudappExport::Item.new(attributes)
|
@@ -52,8 +58,16 @@ module CloudappExport
|
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
61
|
+
def load_meta
|
62
|
+
@load_meta ||= begin
|
63
|
+
response = @api.request("items?per_page=1")
|
64
|
+
@meta = response.meta
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
55
68
|
def cache_file_path
|
56
|
-
|
69
|
+
hashed_cache_key = Digest::MD5.hexdigest(@cache_key)
|
70
|
+
"/tmp/cloudapp-export-items-cache-#{hashed_cache_key}.json"
|
57
71
|
end
|
58
72
|
end
|
59
73
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudapp-export
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc Qualie
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dotenv
|
@@ -155,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
155
|
version: '0'
|
156
156
|
requirements: []
|
157
157
|
rubyforge_project:
|
158
|
-
rubygems_version: 2.
|
158
|
+
rubygems_version: 2.7.3
|
159
159
|
signing_key:
|
160
160
|
specification_version: 4
|
161
161
|
summary: A quick way to export all the data you have stored in CloudApp
|