my-local-putio 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +24 -12
- data/bin/my-local-putio +2 -3
- data/lib/my-local-putio.rb +12 -0
- data/lib/my-local-putio/configuration.rb +16 -6
- data/lib/my-local-putio/fetcher.rb +43 -24
- data/lib/my-local-putio/logger.rb +1 -1
- data/lib/my-local-putio/putio_cli.rb +30 -13
- data/lib/my-local-putio/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9926010a7296b64e53e36469ca62e01f01e765b1fc8efdcab2681f45c0bc370
|
4
|
+
data.tar.gz: f8235be041d1639f3cc0e5b63fe8ffce9d4755cd1678250d43728763e608c5c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3325310547f3350073771a381ab300facf64e3a54af83e3494be7078a924eb8975e8f34aedd6f1f7a98bc07145e121ed20eebf26ff4e5d59ac701b2faa8544f
|
7
|
+
data.tar.gz: 82debad28c46401a321d8c6d2dadfa56a0b2beda08c905ce5aa7657552977f05eac488c4fe5cbc47e1fb3191b1ac93e0f2db31d907fd4985bd8ae4d5382d5e72
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# v3.0.0
|
2
|
+
|
3
|
+
- Introducing delete from remote after downloading
|
4
|
+
- Breaking changes parameters
|
5
|
+
- removed -d option for --debug. Now debug is only available as --debug
|
6
|
+
- introduced -d option for --delete-remote
|
7
|
+
- More code refactoring
|
8
|
+
|
1
9
|
# v2.1.0
|
2
10
|
|
3
11
|
- Introducing SOCKS5 support with `--socks5-proxy` option.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -11,10 +11,10 @@ For now the script only supports download the content from your account and keep
|
|
11
11
|
- Supports SOCKS5 proxy for an even more secure and anonymous transfer, with kill switch, so the application will stop if the proxy became unavailable. No leak connections.
|
12
12
|
- Resume broken/stopped downloads, so you don't have to start from the begin of your huge file.
|
13
13
|
- Simple and easy to run
|
14
|
+
- Option to delete the file from put.io after the download
|
14
15
|
|
15
16
|
#### Planned features:
|
16
17
|
|
17
|
-
- Option to delete the file on put.io after sync
|
18
18
|
- Option to download the subtitle if available in put.io list
|
19
19
|
|
20
20
|
#### Future or ideas: (Feel free to contribute to the list)
|
@@ -39,12 +39,13 @@ For now the script only supports download the content from your account and keep
|
|
39
39
|
my-local-putio -h
|
40
40
|
|
41
41
|
Usage: my-local-putio [options]
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
-t, --token TOKEN Put.io access token [REQUIRED]
|
43
|
+
-l, --local-destination PATH Local destination path [REQUIRED]
|
44
|
+
-d, --delete-remote Delete remote file/folder after the download
|
45
|
+
-v, --version Print my-local-putio version
|
46
|
+
-s, --silent Hide all messages and progress bar
|
47
|
+
--debug Debug mode [Developer mode]
|
48
|
+
--socks5-proxy hostname:port SOCKS5 hostname and port for proxy. Format: 127.0.0.1:1234
|
48
49
|
|
49
50
|
#### Required attributes:
|
50
51
|
* **-t** or **--token**: Your Put.io Token. This attribute becames optional if you set `PUTIO_TOKEN` env variable with your token (Can be inline or into your bash profile). Check examples below.
|
@@ -63,26 +64,37 @@ With Token variable (inline or exporting):
|
|
63
64
|
my-local-putio --local-destination Downloads/
|
64
65
|
|
65
66
|
#### Others attributes:
|
67
|
+
* **-d** or **--delete-remote**: Delete the remote file/folder from put.io after downloading
|
66
68
|
* **-h**: Print the help usage message
|
67
69
|
* **-v** or **--version**: Print the version of the application
|
68
70
|
* **-s** or **--silent**: Hide all messages and progress bar
|
69
|
-
*
|
71
|
+
* **--debug**: Developer mode: Prints everything and expose URLs with tokens for debug purposes.
|
70
72
|
* **--socks5-proxy**: Enable the SOCKS5 proxy. If enabled, all the connections for PUT.IO API and the downloads will be performed using this proxy. If the socks connection became unavailable, the application will raise an error and will stop.
|
71
73
|
|
72
74
|
Examples:
|
73
75
|
|
74
76
|
my-local-putio -h
|
75
|
-
my-local-putio -t 123 -l Downloads --silent
|
77
|
+
my-local-putio -t 123 -l Downloads --silent -d
|
76
78
|
my-local-putio -t 123 -l Downloads -s
|
77
79
|
my-local-putio --local-destination Downloads -t 123 --debug
|
78
80
|
my-local-putio --local-destination Downloads -t 123 --socks5-proxy 127.0.0.1:3333
|
79
81
|
|
80
82
|
Verbose output example:
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
my-local-putio -t 123 -l Downloads -d --socks5-proxy 127.0.0.1:3333
|
85
|
+
|
86
|
+
Starting My Local Put.io - version 3.0.0
|
87
|
+
https://github.com/rafaelbiriba/my-local-putio
|
88
|
+
=============================================
|
89
|
+
Full path of the local destination: /Users/user/Downloads
|
90
|
+
>>> Delete remote files enabled!
|
91
|
+
>>> SOCKS5 enabled with 127.0.0.1:3333
|
92
|
+
=============================================
|
93
|
+
[LOG][2019-07-18 11:11:30] Getting file list for /
|
94
|
+
[LOG][2019-07-18 11:11:31] Getting file list for /ubuntu
|
95
|
+
[LOG][2019-07-18 11:11:31] Downloading: /ubuntu/ubuntu-18.04.2-desktop-amd64.iso
|
85
96
|
######################################################################## 100.0%
|
97
|
+
[LOG][2019-07-18 11:11:33] Deleting remote file: /ubuntu/ubuntu-18.04.2-desktop-amd64.iso
|
86
98
|
|
87
99
|
#### Troubleshooting
|
88
100
|
|
data/bin/my-local-putio
CHANGED
@@ -9,6 +9,5 @@ unless open(__FILE__).flock(File::LOCK_EX | File::LOCK_NB)
|
|
9
9
|
end
|
10
10
|
|
11
11
|
configuration = MyLocalPutio::Configuration.new
|
12
|
-
|
13
|
-
|
14
|
-
MyLocalPutio::Fetcher.new(configuration, putio_cli, logger).run!
|
12
|
+
MyLocalPutio.print_introduction_msg(configuration)
|
13
|
+
MyLocalPutio::Fetcher.new(configuration).run!
|
data/lib/my-local-putio.rb
CHANGED
@@ -26,4 +26,16 @@ require "my-local-putio/putio_cli"
|
|
26
26
|
require "my-local-putio/fetcher"
|
27
27
|
|
28
28
|
module MyLocalPutio
|
29
|
+
def self.print_introduction_msg(configuration)
|
30
|
+
return if configuration.silent
|
31
|
+
puts "Starting My Local Put.io - version #{VERSION}"
|
32
|
+
puts "https://github.com/rafaelbiriba/my-local-putio"
|
33
|
+
puts "============================================="
|
34
|
+
puts "Full path of the local destination: #{File.realdirpath(configuration.local_destination)}"
|
35
|
+
puts ">>> Delete remote files enabled!" if configuration.delete_remote
|
36
|
+
puts ">>> SOCKS5 enabled with #{configuration.socks_host}:#{configuration.socks_port}" if configuration.socks_enabled?
|
37
|
+
puts ">>> DEBUG enabled! Hello Mr(s) developer :)" if configuration.debug
|
38
|
+
puts "============================================="
|
39
|
+
sleep 2 # In case the configurations are not correct, 2 seconds to kill the command line before run
|
40
|
+
end
|
29
41
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module MyLocalPutio
|
2
2
|
class Configuration
|
3
|
-
attr_reader :token, :local_destination, :silent, :debug, :socks_host, :socks_port
|
3
|
+
attr_reader :token, :local_destination, :silent, :debug, :socks_host, :socks_port, :delete_remote
|
4
4
|
def initialize
|
5
5
|
read_args_from_envs!
|
6
6
|
parse_args!
|
@@ -11,18 +11,23 @@ module MyLocalPutio
|
|
11
11
|
@socks_host || @socks_port
|
12
12
|
end
|
13
13
|
|
14
|
+
def logger
|
15
|
+
@logger ||= Logger.new(self)
|
16
|
+
end
|
17
|
+
|
14
18
|
private
|
15
19
|
def parse_args!
|
16
20
|
OptionParser.new do |opt|
|
17
21
|
opt.on("-t", "--token TOKEN", "Put.io access token [REQUIRED]") { |v| @token = v }
|
18
22
|
opt.on("-l", "--local-destination PATH", "Local destination path [REQUIRED]") { |v| @local_destination = v }
|
23
|
+
opt.on("-d", "--delete-remote", "Delete remote file/folder after the download") { |v| @delete_remote = true }
|
19
24
|
opt.on("-v", "--version", "Print my-local-putio version") do
|
20
25
|
puts MyLocalPutio::VERSION
|
21
26
|
exit
|
22
27
|
end
|
23
28
|
|
24
29
|
opt.on("-s", "--silent", "Hide all messages and progress bar") { |v| @silent = true }
|
25
|
-
opt.on("
|
30
|
+
opt.on("--debug", "Debug mode [Developer mode]") { |v| @debug = true }
|
26
31
|
opt.on("--socks5-proxy hostname:port", "SOCKS5 hostname and port for proxy. Format: 127.0.0.1:1234") do |v|
|
27
32
|
@socks_host, @socks_port = v.to_s.split(":")
|
28
33
|
end
|
@@ -40,10 +45,7 @@ module MyLocalPutio
|
|
40
45
|
exit
|
41
46
|
end
|
42
47
|
|
43
|
-
|
44
|
-
puts "Cannot write on the local destination path '#{@local_destination}'"
|
45
|
-
exit
|
46
|
-
end
|
48
|
+
destination_folder_checks!
|
47
49
|
|
48
50
|
if socks_enabled? && !port_is_open?(@socks_host, @socks_port)
|
49
51
|
puts "Cannot connect to socks using '#{@socks_host}:#{@socks_port}'"
|
@@ -51,6 +53,14 @@ module MyLocalPutio
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
56
|
+
def destination_folder_checks!
|
57
|
+
return if File.exists?(@local_destination) && File.writable?(@local_destination)
|
58
|
+
FileUtils.mkdir_p(@local_destination)
|
59
|
+
rescue Errno::EACCES
|
60
|
+
puts "Cannot write on the local destination path '#{@local_destination}'"
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
|
54
64
|
def read_args_from_envs!
|
55
65
|
@token ||= ENV["PUTIO_TOKEN"]
|
56
66
|
end
|
@@ -2,8 +2,10 @@ module MyLocalPutio
|
|
2
2
|
class Fetcher
|
3
3
|
attr_reader :configuration, :cli, :logger
|
4
4
|
|
5
|
-
def initialize(configuration
|
6
|
-
@configuration
|
5
|
+
def initialize(configuration)
|
6
|
+
@configuration = configuration
|
7
|
+
@logger = configuration.logger
|
8
|
+
@cli = PutioCli.new(@configuration)
|
7
9
|
end
|
8
10
|
|
9
11
|
def run!
|
@@ -12,42 +14,59 @@ module MyLocalPutio
|
|
12
14
|
|
13
15
|
protected
|
14
16
|
|
15
|
-
def fetch_files(id: nil, path:
|
16
|
-
|
17
|
-
logger.log "Getting files for #{path}"
|
17
|
+
def fetch_files(id: nil, path: "/")
|
18
|
+
logger.log "Getting file list for #{path}"
|
18
19
|
files = cli.get_files(id)["files"]
|
19
20
|
|
20
21
|
while files.any?
|
21
|
-
file = OpenStruct.new
|
22
|
-
|
23
|
-
fetch_files(id: file.id, path: File.join(path, file.name))
|
24
|
-
else
|
25
|
-
file_path = File.join(path, file.name)
|
26
|
-
if File.exists?(file_path) && File.size(file_path) == file.size
|
27
|
-
logger.log "File already downloaded #{file_path}"
|
28
|
-
else
|
29
|
-
url = cli.get_download_url file.id
|
30
|
-
logger.log "Downloading: #{file_path}"
|
31
|
-
if ! fetch(url, file_path)
|
32
|
-
raise "Unable to download #{file_path}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
22
|
+
file = OpenStruct.new(files.pop)
|
23
|
+
process_file(file, path)
|
36
24
|
end
|
37
25
|
end
|
38
26
|
|
39
|
-
def
|
27
|
+
def process_file(file, path)
|
28
|
+
local_file_path = File.join(path, file.name)
|
29
|
+
if file.content_type == "application/x-directory"
|
30
|
+
fetch_files(id: file.id, path: local_file_path)
|
31
|
+
else
|
32
|
+
download(file, local_file_path) unless file_exists?(local_file_path, file)
|
33
|
+
end
|
34
|
+
delete_file(local_file_path, file)
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete_file(local_file_path, file)
|
38
|
+
logger.log "Deleting remote file: #{local_file_path}"
|
39
|
+
cli.delete_file(file.id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def file_exists?(local_file_path, file)
|
43
|
+
file_exists = File.exists?(local_file_path) && File.size(local_file_path) == file.size
|
44
|
+
logger.log "File already downloaded #{local_file_path}" if file_exists
|
45
|
+
file_exists
|
46
|
+
end
|
47
|
+
|
48
|
+
def download_command(url, path)
|
49
|
+
destination = File.join(configuration.local_destination, path)
|
50
|
+
|
40
51
|
command = [
|
41
|
-
"curl", "--progress-bar", "-L", "--retry", "5", "-S", "-C", "-", "-o",
|
52
|
+
"curl", "--create-dirs", "--progress-bar", "-L", "--retry", "5", "-S", "-C", "-", "-o", destination, url.to_s
|
42
53
|
]
|
43
|
-
|
54
|
+
|
44
55
|
command.push("--silent") if logger.silent?
|
45
56
|
|
46
57
|
if configuration.socks_enabled?
|
47
58
|
command.push("--socks5-hostname", "#{configuration.socks_host}:#{configuration.socks_port}")
|
48
59
|
end
|
49
60
|
|
50
|
-
|
61
|
+
return command
|
62
|
+
end
|
63
|
+
|
64
|
+
def download(file, path)
|
65
|
+
url = cli.get_download_url(file.id)
|
66
|
+
command = download_command(url, path)
|
67
|
+
logger.log "Downloading: #{path}"
|
68
|
+
fetch_result = system(*command)
|
69
|
+
raise "Unable to download #{path}" unless fetch_result
|
51
70
|
end
|
52
71
|
end
|
53
72
|
end
|
@@ -3,11 +3,11 @@ module MyLocalPutio
|
|
3
3
|
ROOT = "https://api.put.io/v2/"
|
4
4
|
attr_reader :configuration, :endpoint, :http, :logger
|
5
5
|
|
6
|
-
def initialize(configuration
|
7
|
-
@configuration
|
8
|
-
@
|
9
|
-
@
|
10
|
-
|
6
|
+
def initialize(configuration)
|
7
|
+
@configuration = configuration
|
8
|
+
@logger = configuration.logger
|
9
|
+
@endpoint = URI(ROOT)
|
10
|
+
setup_connection
|
11
11
|
end
|
12
12
|
|
13
13
|
def get_files(parent_id=nil)
|
@@ -15,6 +15,17 @@ module MyLocalPutio
|
|
15
15
|
get("files/list", args)
|
16
16
|
end
|
17
17
|
|
18
|
+
def delete_file(id)
|
19
|
+
args = {file_ids: id}
|
20
|
+
post("files/delete", args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete_file_url
|
24
|
+
url = to_url("files/delete")
|
25
|
+
url.query = URI.encode_www_form to_args()
|
26
|
+
url
|
27
|
+
end
|
28
|
+
|
18
29
|
def get_download_url(id)
|
19
30
|
url = to_url("files/#{id}/download")
|
20
31
|
url.query = URI.encode_www_form to_args()
|
@@ -31,6 +42,12 @@ module MyLocalPutio
|
|
31
42
|
end
|
32
43
|
end
|
33
44
|
|
45
|
+
def setup_connection
|
46
|
+
@http = http_library.new(@endpoint.host, @endpoint.port)
|
47
|
+
@http.use_ssl = true
|
48
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
49
|
+
end
|
50
|
+
|
34
51
|
def get(path, args={})
|
35
52
|
url = to_url(path)
|
36
53
|
url.query = URI.encode_www_form to_args(args)
|
@@ -39,14 +56,14 @@ module MyLocalPutio
|
|
39
56
|
as_json http.request(req)
|
40
57
|
end
|
41
58
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
59
|
+
def post(path, args={})
|
60
|
+
url = to_url(path)
|
61
|
+
args = to_args(args)
|
62
|
+
logger.debug "POST #{url} -- #{args.inspect}"
|
63
|
+
req = Net::HTTP::Post.new(url)
|
64
|
+
req.set_form_data(args)
|
65
|
+
as_json http.request(req)
|
66
|
+
end
|
50
67
|
|
51
68
|
def to_url(path)
|
52
69
|
url = endpoint.dup
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: my-local-putio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafael Biriba
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|