my-dropbox-api 1.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.
- checksums.yaml +7 -0
- data/lib/my-dropbox-api.rb +235 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: abbb20e06ab8d1fb51d2d2f46a59d4fb53a2dcd86f8a90354f6dda52b13519b2
|
4
|
+
data.tar.gz: c81c047a173b64c303d166b12c5861d76f46a7528f3a0fd6ad68b0e7105e95be
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 79283e682d26332777f34f90ed273ac70adace6bfb15db54b54661caf588bd76203ca210ef75d72a557b003c2a7251bbb641be0350967602d71c1c4b9f802dcb
|
7
|
+
data.tar.gz: 88abb7a05ad1452d6a1105b24c71c2670a8dd9b3b9d5488075ad73d34ee2a31b516c38ddda8b4516169bbb48c26da34739e0d22ca4e5f01e9c227df32a642049
|
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'json'
|
3
|
+
require 'blackstack-core'
|
4
|
+
|
5
|
+
module BlackStack
|
6
|
+
module DropBox
|
7
|
+
DROPBOX_APP_KEY = 'lnystcoayzse5at'
|
8
|
+
|
9
|
+
# ConnectionSphere API-KEY
|
10
|
+
@@connectionsphere_api_key = nil
|
11
|
+
@@connectionsphere_token_url = 'https://connectionsphere.com/api1.0/dropbox/get_access_token.json'
|
12
|
+
|
13
|
+
# mysaas end-user "refresh-token" to grab a new "access-code" every time is needed.
|
14
|
+
@@dropbox_refresh_token = nil
|
15
|
+
# list of folders and files to backup
|
16
|
+
@@destinations = []
|
17
|
+
|
18
|
+
# getters
|
19
|
+
def self.dropbox_refresh_token
|
20
|
+
@@dropbox_refresh_token
|
21
|
+
end
|
22
|
+
|
23
|
+
# getters
|
24
|
+
def self.destinations
|
25
|
+
@@destinations
|
26
|
+
end
|
27
|
+
|
28
|
+
# Setup the bakcup module.
|
29
|
+
def self.set(h)
|
30
|
+
@@dropbox_refresh_token = h[:dropbox_refresh_token]
|
31
|
+
@@destinations = h[:destinations]
|
32
|
+
@@connectionsphere_api_key = h[:connectionsphere_api_key]
|
33
|
+
end # set
|
34
|
+
|
35
|
+
# Get a short-live access code using the refresh token.
|
36
|
+
# This method is for internal usage only.
|
37
|
+
# End-users should not call this method.
|
38
|
+
#
|
39
|
+
def self.dropbox_get_access_token
|
40
|
+
# get the refresh token
|
41
|
+
begin
|
42
|
+
params = {
|
43
|
+
'api_key' => "#{@@connectionsphere_api_key}",
|
44
|
+
'refresh_token' => "#{@@dropbox_refresh_token}"
|
45
|
+
}
|
46
|
+
res = BlackStack::Netting::call_post(@@connectionsphere_token_url, params)
|
47
|
+
h = JSON.parse(res.body)
|
48
|
+
raise h['status'] if h['status']!='success'
|
49
|
+
|
50
|
+
h['access_token']
|
51
|
+
rescue Errno::ECONNREFUSED => e
|
52
|
+
raise "Errno::ECONNREFUSED:#{e.message}"
|
53
|
+
rescue => e2
|
54
|
+
raise "Exception:#{e2.message}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Create a folder into dropbox
|
59
|
+
#
|
60
|
+
# This method is for internal use only.
|
61
|
+
# End-users should use the BlackStack::Backup::backup method.
|
62
|
+
#
|
63
|
+
# use `2>&1 1>/dev/null` to suppress verbose output of shell command.
|
64
|
+
# reference: https://stackoverflow.com/questions/18525359/suppress-verbose-output-of-shell-command-in-python
|
65
|
+
def self.dropbox_create_folder(cloudfoldername)
|
66
|
+
s = "curl --silent -X POST https://api.dropboxapi.com/2/files/create_folder_v2 \\
|
67
|
+
--header \"Authorization: Bearer #{BlackStack::DropBox.dropbox_get_access_token}\" \\
|
68
|
+
--header \"Content-Type: application/json\" \\
|
69
|
+
--data \"{\\\"autorename\\\":false,\\\"path\\\":\\\"#{cloudfoldername}\\\"}\""
|
70
|
+
`#{s}`
|
71
|
+
end
|
72
|
+
|
73
|
+
# Upload a file to dropbox
|
74
|
+
#
|
75
|
+
# This method is for internal use only.
|
76
|
+
# End-users should use the BlackStack::Backup::backup method.
|
77
|
+
#
|
78
|
+
# use `2>&1 1>/dev/null` to suppress verbose output of shell command.
|
79
|
+
# reference: https://stackoverflow.com/questions/18525359/suppress-verbose-output-of-shell-command-in-python
|
80
|
+
def self.dropbox_upload_file(localfilename, cloudfilename)
|
81
|
+
s = "curl --silent -X POST https://content.dropboxapi.com/2/files/upload \\
|
82
|
+
--header \"Authorization: Bearer #{BlackStack::DropBox.dropbox_get_access_token}\" \\
|
83
|
+
--header \"Dropbox-API-Arg: {\\\"path\\\": \\\"#{cloudfilename}\\\", \\\"mode\\\": \\\"overwrite\\\"}\" \\
|
84
|
+
--header \"Content-Type: application/octet-stream\" \\
|
85
|
+
--data-binary @#{localfilename}"
|
86
|
+
return `#{s}`
|
87
|
+
end
|
88
|
+
|
89
|
+
# Upload a files and folders to dropbox
|
90
|
+
#
|
91
|
+
# This method is for internal use only.
|
92
|
+
# End-users should use the BlackStack::Backup::backup method.
|
93
|
+
#
|
94
|
+
# Iterate over directories and subdirectories recursively showing 'path/file'.
|
95
|
+
# reference: https://stackoverflow.com/questions/40016856/iterate-over-directories-and-subdirectories-recursively-showing-path-file-in-r
|
96
|
+
#
|
97
|
+
# localpath: pattern to list the files and folders to upload
|
98
|
+
# cloudpath: name of the cloud folder
|
99
|
+
#
|
100
|
+
# Return an array of each opeation performed, with the result of such operation.
|
101
|
+
#
|
102
|
+
def self.upload(localpath, cloudpath)
|
103
|
+
# drop last / from cloudpath
|
104
|
+
cloudpath.strip!
|
105
|
+
cloudpath.gsub!(/\/$/, '')
|
106
|
+
# get the path from the ls command
|
107
|
+
local_folder = localpath.gsub(/\/#{Regexp.escape(localpath.split('/').last)}$/, '')
|
108
|
+
ret = [] # array
|
109
|
+
Dir.glob(localpath).each do |file|
|
110
|
+
# hash descriptor of this operation
|
111
|
+
h = {}
|
112
|
+
h[:file] = file
|
113
|
+
# decide if it is a file or a folder
|
114
|
+
type = File.directory?(file) ? 'folder' : 'file'
|
115
|
+
# remove the source from the path
|
116
|
+
file.gsub!(/^#{Regexp.escape(local_folder)}\//, '')
|
117
|
+
if type == 'file'
|
118
|
+
h[:type] = 'file'
|
119
|
+
h[:result] = BlackStack::DropBox.dropbox_upload_file("#{local_folder}/\"#{file}\"", "#{cloudpath}/\"#{file}\"")
|
120
|
+
ret << h
|
121
|
+
else
|
122
|
+
h[:type] = 'folder'
|
123
|
+
h[:result] = BlackStack::DropBox.dropbox_create_folder("#{cloudpath}/#{file}")
|
124
|
+
ret << h
|
125
|
+
ret += BlackStack::DropBox.upload("#{local_folder}/#{file}/*", "#{cloudpath}/#{file}")
|
126
|
+
end # if type
|
127
|
+
end # Dir.glob
|
128
|
+
ret
|
129
|
+
end
|
130
|
+
|
131
|
+
# Run the backup process.
|
132
|
+
def self.backup(verbose=false, log=nil)
|
133
|
+
log = BlackStack::DummyLogger.new(nil) if log.nil?
|
134
|
+
timestamp = Time.now.getutc.to_s.gsub(/[^0-9a-zA-Z\.]/, '')
|
135
|
+
@@destinations.each { |d|
|
136
|
+
# parameters
|
137
|
+
foldername = d[:folder] # how to name this backup in dropbox
|
138
|
+
source = d[:source] # source folder to backup
|
139
|
+
|
140
|
+
# build a unique folder name using the current timestamp.
|
141
|
+
log.logs "#{foldername}... "
|
142
|
+
folder = "#{timestamp}.#{foldername}"
|
143
|
+
|
144
|
+
log.logs "Create folder #{folder}... "
|
145
|
+
BlackStack::DropBox::dropbox_create_folder(folder, verbose)
|
146
|
+
log.done
|
147
|
+
|
148
|
+
log.logs "Upload files... "
|
149
|
+
BlackStack::DropBox::upload(folder, source, verbose, log)
|
150
|
+
log.done
|
151
|
+
log.done
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
# Run the restore process
|
156
|
+
#
|
157
|
+
# NOTE: Download a folder from the user's Dropbox, as a zip file.
|
158
|
+
# The folder must be less than 20 GB in size and any single file within must be less than 4 GB in size.
|
159
|
+
# The resulting zip must have fewer than 10,000 total file and folder entries, including the top level folder.
|
160
|
+
# The input cannot be a single file. Note: this endpoint does not support HTTP range requests.
|
161
|
+
#
|
162
|
+
# Reference: https://www.dropbox.com/developers/documentation/http/documentation#files-download_zip
|
163
|
+
#
|
164
|
+
# Parameters:
|
165
|
+
# - cloudfoldername: name of the folder in dropbox to download. The zip file will be saved in the folder where the command is running.
|
166
|
+
# - zipfilename: name of the zip file to save.
|
167
|
+
# - unzip: activate thisf lag if you want to unzip the downloaded zip file.
|
168
|
+
# - destination: path of the local folder where you want to unzip.
|
169
|
+
# - deletezipfile: activate this if you want to delete the zip file after unzipping.
|
170
|
+
#
|
171
|
+
# Activate the unzip if you have installed the zip command.
|
172
|
+
# Reference: https://iq.direct/blog/49-how-to-unzip-file-on-ubuntu-linux.html
|
173
|
+
#
|
174
|
+
def self.restore(cloudfoldername, log=nil, zipfilename='temp.zip', unzip=false, destination=nil, deletezipfile=false)
|
175
|
+
log.logs 'Downloading backup folder... '
|
176
|
+
s = "curl --silent -X POST https://content.dropboxapi.com/2/files/download_zip \\
|
177
|
+
--header \"Authorization: Bearer #{BlackStack::DropBox.dropbox_get_access_token}\" \\
|
178
|
+
--header \"Dropbox-API-Arg: {\\\"path\\\":\\\"/#{cloudfoldername}/\\\"}\" --output #{zipfilename} 2>&1 1>/dev/null"
|
179
|
+
`#{s}`
|
180
|
+
|
181
|
+
log.done
|
182
|
+
|
183
|
+
if unzip
|
184
|
+
log.logs 'Unzipping backup folder... '
|
185
|
+
s = "
|
186
|
+
rmdir ./tempy 2>/dev/null;
|
187
|
+
mkdir ./tempy;
|
188
|
+
unzip #{zipfilename} -d ./tempy;
|
189
|
+
mv ./tempy/#{cloudfoldername}/* #{destination};
|
190
|
+
rm -rf ./tempy 2>/dev/null;
|
191
|
+
"
|
192
|
+
`#{s}`
|
193
|
+
log.done
|
194
|
+
if deletezipfile
|
195
|
+
log.logs 'Deleting zip file... '
|
196
|
+
`rm #{zipfilename}`
|
197
|
+
log.done
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end # def self.restore
|
201
|
+
|
202
|
+
def self.dropbox_download_file(cloudfoldername, cloudfilename, destination=nil)
|
203
|
+
s = "curl --silent -X POST https://content.dropboxapi.com/2/files/download \\
|
204
|
+
--header \"Authorization: Bearer #{BlackStack::DropBox.dropbox_get_access_token}\" \\
|
205
|
+
--header \"Dropbox-API-Arg: {\\\"path\\\":\\\"/#{cloudfoldername}/#{cloudfilename}\\\"}\" --output #{destination}/#{cloudfilename} 2>&1 1>/dev/null"
|
206
|
+
`#{s}`
|
207
|
+
end # def self.dropbox_download_file
|
208
|
+
|
209
|
+
# Reference: https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder
|
210
|
+
def self.dropbox_folder_files(cloudfoldername)
|
211
|
+
s = "curl --silent -X POST https://api.dropboxapi.com/2/files/list_folder \\
|
212
|
+
--header \"Authorization: Bearer #{BlackStack::DropBox.dropbox_get_access_token}\" \\
|
213
|
+
--header \"Content-Type: application/json\" \\
|
214
|
+
--data \"{\\\"include_deleted\\\":false,\\\"include_has_explicit_shared_members\\\":false,\\\"include_media_info\\\":false,\\\"include_mounted_folders\\\":true,\\\"include_non_downloadable_files\\\":true,\\\"path\\\":\\\"/#{cloudfoldername}/\\\"}\""
|
215
|
+
output = `#{s}`
|
216
|
+
ret = JSON.parse(output)
|
217
|
+
ret['entries'].map { |e| e['name'] }
|
218
|
+
end # def self.dropbox_folder_files
|
219
|
+
|
220
|
+
# Reference: https://www.dropbox.com/developers/documentation/http/documentation#sharing-create_shared_link_with_settings
|
221
|
+
def self.get_file_url(cloudfilename)
|
222
|
+
s = "curl --silent -X POST https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings \\
|
223
|
+
--header \"Authorization: Bearer #{BlackStack::DropBox.dropbox_get_access_token}\" \\
|
224
|
+
--header \"Content-Type: application/json\" \\
|
225
|
+
--data \"{\\\"path\\\":\\\"#{cloudfilename}\\\",\\\"settings\\\":{\\\"access\\\":\\\"viewer\\\",\\\"allow_download\\\":true,\\\"audience\\\":\\\"public\\\",\\\"requested_visibility\\\":\\\"public\\\"}}\""
|
226
|
+
output = JSON.parse(`#{s}`)
|
227
|
+
raise "Error: #{output['error_summary']}" if output.has_key?('error_summary')
|
228
|
+
url = output["url"]
|
229
|
+
url.gsub!('www.dropbox.com', 'dl.dropboxusercontent.com') # Gsub domain
|
230
|
+
url.gsub!('dl=0', 'dl=1') # Enable download
|
231
|
+
url
|
232
|
+
end # def self.get_file_url
|
233
|
+
|
234
|
+
end # module Extensions
|
235
|
+
end # module BlackStack
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: my-dropbox-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Leandro Daniel Sardi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.6.3
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.6.3
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.6.3
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.6.3
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: pry
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.14.2
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.14.2
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 0.14.2
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.14.2
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: blackstack-core
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.2.3
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.2.3
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.2.3
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.2.3
|
73
|
+
description: "\nThe **dropbox-api** is a Ruby gem for managing DropBox uploading,
|
74
|
+
downloading and sharing DropBox files and folders.\n\nThe main goals of building
|
75
|
+
this gem are:\n \n1. Simulate a **permanent access token**, since [Dropbox is moving
|
76
|
+
to \"short-term live access codes\"](https://www.dropboxforum.com/t5/Discuss-Dropbox-Developer-API/Permanent-access-token/td-p/592644);\n
|
77
|
+
\ \n2. Manage DropBox as an elastic-storage providers for [our SaaS projects](https://github.com/leandrosardi/mysaas),
|
78
|
+
allowing us to upload, download and share download links to files;\n \n3. Backup
|
79
|
+
and restore secret files of our projects that cannot be commited into the source
|
80
|
+
code repository (E.g.: database passwords, SSL certificates, private keys).\n "
|
81
|
+
email: leandro@connectionsphere.com
|
82
|
+
executables: []
|
83
|
+
extensions: []
|
84
|
+
extra_rdoc_files: []
|
85
|
+
files:
|
86
|
+
- lib/my-dropbox-api.rb
|
87
|
+
homepage: https://github.com/leandrosardi/my-dropbox-api
|
88
|
+
licenses:
|
89
|
+
- MIT
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubygems_version: 3.3.7
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: Ruby gem to manage some basic DropBox operations.
|
110
|
+
test_files: []
|