ytdl 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.
- checksums.yaml +7 -0
- data/lib/youtube_dl.rb +8 -0
- data/lib/youtube_dl/command.rb +49 -0
- data/lib/youtube_dl/listener.rb +17 -0
- data/lib/youtube_dl/output_parser.rb +128 -0
- data/lib/youtube_dl/runner.rb +58 -0
- data/lib/youtube_dl/state.rb +28 -0
- data/lib/youtube_dl/version.rb +3 -0
- data/lib/ytdl.rb +1 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7ff16ab36991f68eb0ed450552918d2875c1b1d54c995d1dfe489975c3e263a0
|
4
|
+
data.tar.gz: 949f1257581559b86ce257b65f4bf3f7a1e9bd8c3ce678f00c58e43b3e88961e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3bb295a1865bbd86332f0c36e57cd27a13e116af371eb21177c837b765c07a0a9f2c2477028e15c5a77f69fbdfe538399ff48259cbe88a32ac013462068515a5
|
7
|
+
data.tar.gz: 4fb9df0465aed1b3e8a96ffa4a6852dfad4fe3d393a58c04d4d475dd6b9fad24de6c57823732fd24faf349f3a9a61941b94d69d617c295875ccdf1ba81f10b7b
|
data/lib/youtube_dl.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'dry/configurable'
|
3
|
+
|
4
|
+
module YoutubeDL
|
5
|
+
class Command
|
6
|
+
extend Dry::Configurable
|
7
|
+
|
8
|
+
def config
|
9
|
+
self.class.config
|
10
|
+
end
|
11
|
+
|
12
|
+
setting :executable, 'youtube-dl'
|
13
|
+
setting :default_options, {}
|
14
|
+
setting :forced_options, {
|
15
|
+
newline: true,
|
16
|
+
color: false,
|
17
|
+
write_info_json: true,
|
18
|
+
playlist: false,
|
19
|
+
}
|
20
|
+
|
21
|
+
def initialize(url, **options)
|
22
|
+
@url = url
|
23
|
+
@options =
|
24
|
+
config.default_options
|
25
|
+
.merge(options)
|
26
|
+
.merge(config.forced_options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def arguments
|
30
|
+
@options.flat_map do |option, value|
|
31
|
+
option = option.to_s.gsub('_', '-')
|
32
|
+
case value
|
33
|
+
when [] then nil
|
34
|
+
when true then "--#{option}"
|
35
|
+
when false then "--no-#{option}"
|
36
|
+
else ["--#{option}", value]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_a
|
42
|
+
[config.executable] + arguments + [@url]
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
Shellwords.join(to_a)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module YoutubeDL
|
2
|
+
class Listener
|
3
|
+
def initialize
|
4
|
+
@callbacks = Hash.new { |h, k| h[k] = [] }
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(event, state:, line: nil)
|
8
|
+
(@callbacks[event] + @callbacks[:any]).each do |cb|
|
9
|
+
cb.call(state: state, line: line)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def register(event, &block)
|
14
|
+
@callbacks[event] << block
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'filesize'
|
2
|
+
require 'youtube_dl/state'
|
3
|
+
|
4
|
+
module YoutubeDL
|
5
|
+
class OutputParser
|
6
|
+
def initialize
|
7
|
+
@state = State.new
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :state
|
11
|
+
|
12
|
+
def process(line)
|
13
|
+
line = line.strip
|
14
|
+
|
15
|
+
m = regex.match(line)
|
16
|
+
return :unparsable if m.nil?
|
17
|
+
|
18
|
+
if m[:destination]
|
19
|
+
state.destination = Pathname(m[:destination])
|
20
|
+
return :destination
|
21
|
+
end
|
22
|
+
|
23
|
+
if m[:info_json]
|
24
|
+
state.info_json = Pathname(m[:info_json]) if m[:info_json]
|
25
|
+
return :info_json
|
26
|
+
end
|
27
|
+
|
28
|
+
if m[:progress]
|
29
|
+
if m[:progress]
|
30
|
+
if m[:progress] == '100'
|
31
|
+
state.progress = 100
|
32
|
+
else
|
33
|
+
state.progress = m[:progress].to_f
|
34
|
+
end
|
35
|
+
end
|
36
|
+
state.total_size = Filesize.from("#{m[:total_size]} #{m[:total_size_unit]}") if m[:total_size]
|
37
|
+
state.speed = Filesize.from("#{m[:speed]} #{m[:speed_unit]}") if m[:speed]
|
38
|
+
return :progress
|
39
|
+
end
|
40
|
+
|
41
|
+
if m[:error]
|
42
|
+
state.error = m[:error] if m[:error]
|
43
|
+
return :error
|
44
|
+
end
|
45
|
+
|
46
|
+
raise 'Not sure how I got here...'
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def regex
|
52
|
+
%r{
|
53
|
+
#{progress_regex} |
|
54
|
+
#{destination_regex} |
|
55
|
+
#{existing_destination_regex} |
|
56
|
+
#{info_json_regex} |
|
57
|
+
#{error_regex}
|
58
|
+
}x
|
59
|
+
end
|
60
|
+
|
61
|
+
def progress_regex
|
62
|
+
%r{
|
63
|
+
\[download\] \s+
|
64
|
+
#{num_regex('progress')}%
|
65
|
+
(
|
66
|
+
\s+ of \s+
|
67
|
+
#{num_with_unit_regex('total_size')}
|
68
|
+
(
|
69
|
+
\s+ at \s+
|
70
|
+
#{num_with_unit_regex('speed')}
|
71
|
+
)?
|
72
|
+
)?
|
73
|
+
}x
|
74
|
+
end
|
75
|
+
|
76
|
+
def destination_regex
|
77
|
+
%r{
|
78
|
+
\[download\] \s+ Destination: \s+
|
79
|
+
(?<destination>.*)
|
80
|
+
}x
|
81
|
+
end
|
82
|
+
|
83
|
+
def existing_destination_regex
|
84
|
+
%r{
|
85
|
+
\[download\] \s
|
86
|
+
(?<destination>.*?) \s
|
87
|
+
has \s already \s been \s downloaded
|
88
|
+
}x
|
89
|
+
end
|
90
|
+
|
91
|
+
def info_json_regex
|
92
|
+
%r{
|
93
|
+
\[info\] \s Writing \s video \s description \s metadata \s as \s JSON \s to: \s
|
94
|
+
(?<info_json>.*)
|
95
|
+
}x
|
96
|
+
end
|
97
|
+
|
98
|
+
def error_regex
|
99
|
+
%r{
|
100
|
+
ERROR: \s
|
101
|
+
(?<error>.*)
|
102
|
+
}x
|
103
|
+
end
|
104
|
+
|
105
|
+
def num_regex(name)
|
106
|
+
%r{
|
107
|
+
(?<#{name}>
|
108
|
+
\d+(\.\d+)?
|
109
|
+
)
|
110
|
+
}x
|
111
|
+
end
|
112
|
+
|
113
|
+
def unit_regex(name)
|
114
|
+
%r{
|
115
|
+
(?<#{name}_unit>
|
116
|
+
\w+
|
117
|
+
)
|
118
|
+
}x
|
119
|
+
end
|
120
|
+
|
121
|
+
def num_with_unit_regex(name)
|
122
|
+
%r{
|
123
|
+
#{num_regex(name)}
|
124
|
+
#{unit_regex(name)}
|
125
|
+
}x
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'pty'
|
2
|
+
require 'youtube_dl/listener'
|
3
|
+
require 'youtube_dl/output_parser'
|
4
|
+
|
5
|
+
module YoutubeDL
|
6
|
+
class Runner
|
7
|
+
def initialize(command, listener: Listener.new)
|
8
|
+
@command = command
|
9
|
+
@listener = listener
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
parser = OutputParser.new
|
14
|
+
run(command: @command, parser: parser)
|
15
|
+
|
16
|
+
if parser.state.complete?
|
17
|
+
parser.state.load_and_delete_info_json
|
18
|
+
@listener.call(:complete, state: parser.state)
|
19
|
+
elsif parser.state.error?
|
20
|
+
@listener.call(:error, state: parser.state)
|
21
|
+
else
|
22
|
+
@listener.call(:unclear_exit_state, state: parser.state)
|
23
|
+
end
|
24
|
+
|
25
|
+
parser.state
|
26
|
+
end
|
27
|
+
|
28
|
+
def on(event, &block)
|
29
|
+
@listener.register(event, &block)
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def respond_to_missing?(method, *)
|
34
|
+
method.to_s.start_with?('on_') || super
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_missing(method, &block)
|
38
|
+
return super unless method.to_s.start_with?('on_')
|
39
|
+
|
40
|
+
event = method.to_s.sub(/^on_/, '').to_sym
|
41
|
+
on(event, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def run(command:, parser:)
|
47
|
+
PTY.spawn(command.to_s) do |stdout, stdin, pid|
|
48
|
+
begin
|
49
|
+
stdout.each do |line|
|
50
|
+
type = parser.process(line)
|
51
|
+
@listener.call(type, state: parser.state, line: line)
|
52
|
+
end
|
53
|
+
rescue Errno::EIO
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module YoutubeDL
|
4
|
+
class State
|
5
|
+
attr_accessor(
|
6
|
+
:progress,
|
7
|
+
:destination,
|
8
|
+
:total_size,
|
9
|
+
:speed,
|
10
|
+
:error,
|
11
|
+
:info_json,
|
12
|
+
:info,
|
13
|
+
)
|
14
|
+
|
15
|
+
def error?
|
16
|
+
!error.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
def complete?
|
20
|
+
destination&.exist? && (info || info_json&.exist?)
|
21
|
+
end
|
22
|
+
|
23
|
+
def load_and_delete_info_json
|
24
|
+
self.info = JSON.parse(info_json.read())
|
25
|
+
info_json.unlink()
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/ytdl.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'youtube_dl'
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ytdl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Max Hollmann
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-configurable
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.11.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.11.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: filesize
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.2.0
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- maxhollmann@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- lib/youtube_dl.rb
|
49
|
+
- lib/youtube_dl/command.rb
|
50
|
+
- lib/youtube_dl/listener.rb
|
51
|
+
- lib/youtube_dl/output_parser.rb
|
52
|
+
- lib/youtube_dl/runner.rb
|
53
|
+
- lib/youtube_dl/state.rb
|
54
|
+
- lib/youtube_dl/version.rb
|
55
|
+
- lib/ytdl.rb
|
56
|
+
homepage: https://github.com/maxhollmann/ruby-ytdl
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata:
|
60
|
+
source_code_uri: https://github.com/maxhollmann/ruby-ytdl
|
61
|
+
bug_tracker_uri: https://github.com/maxhollmann/ruby-ytdl/issues
|
62
|
+
changelog_uri: https://github.com/maxhollmann/ruby-ytdl/releases
|
63
|
+
homepage_uri: https://github.com/maxhollmann/ruby-ytdl
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 2.3.0
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubygems_version: 3.1.2
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: A wrapper for youtube-dl with progress callbacks
|
83
|
+
test_files: []
|