youtube-dl.rb 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7c86b235fb38c06bc33f5984e8993d166da84c8
4
- data.tar.gz: 3711e90fbc95e01c0f1175ccdf2833c1f188908d
3
+ metadata.gz: 1c86f76bf2febd54113c84142274c4c496855ebf
4
+ data.tar.gz: 0da55077bb17767338d0bde1ae75ed1fc1d9e78d
5
5
  SHA512:
6
- metadata.gz: aad917d66ff21d4ecb11bf1f8228c1091dd9b618ab56cded145ed0bac9ef4685d6098860cbeb06cf5c66d7abd651259fe76fc157af82934ab1cc02e4f34b8795
7
- data.tar.gz: dea3940ed3ef94ad31e38f177c4b6824ec11f086038d014e590425d15d5760767b29614ca01948bf4b406854c60e5c8b7932b0f302367d31ef18b9826d5c57bb
6
+ metadata.gz: ef750607464a9a53882193569508b45b5f59d9b8c60fa30166bcded52a7a4ef1ae46223849aded5de47cbef64960a4958c78591d15528a46971465ca5d545d7a
7
+ data.tar.gz: b18889569bf6401ee10bffc6edab536d0f066cd3379cd487b65f2038b743ec1a7509f333e01c492d0dd81791df8c070d53e7b4de9dc9eb1a967d292b8ef0cc2d
@@ -1,7 +1,9 @@
1
1
  require 'youtube-dl/version'
2
2
  require 'youtube-dl/support'
3
3
  require 'youtube-dl/options'
4
+ require 'youtube-dl/output'
4
5
  require 'youtube-dl/runner'
6
+ require 'youtube-dl/video'
5
7
 
6
8
  module YoutubeDL
7
9
  extend self
@@ -12,22 +14,33 @@ module YoutubeDL
12
14
  # @param urls [String, Array] URLs to download
13
15
  # @param options [Hash] Downloader options
14
16
  def download(urls, options={})
15
- # force convert urls to array
16
- urls = [urls] unless urls.is_a? Array
17
-
18
- urls.each do |url|
19
- runner = YoutubeDL::Runner.new(url, YoutubeDL::Options.new(options))
20
- runner.run
17
+ if urls.is_a? Array
18
+ urls.map { |url| YoutubeDL::Video.get(url, options) }
19
+ else
20
+ YoutubeDL::Video.get(urls, options) # Urls should be singular but oh well. url = urls. There. Go cry in a corner.
21
21
  end
22
22
  end
23
23
 
24
24
  alias_method :get, :download
25
25
 
26
+ # Lists extractors
27
+ #
28
+ # @return [Array] list of extractors
26
29
  def extractors
27
- Cocaine::CommandLine.new(usable_executable_path_for('youtube-dl'), '--list-extractors').run.split("\n")
30
+ @extractors ||= cocaine_line('--list-extractors').run.split("\n")
28
31
  end
29
32
 
33
+ # Returns youtube-dl's version
34
+ #
35
+ # @return [String] youtube-dl version
30
36
  def binary_version
31
- Cocaine::CommandLine.new(usable_executable_path_for('youtube-dl'), '--version').run.chomp
37
+ @binary_version ||= cocaine_line('--version').run.strip
38
+ end
39
+
40
+ # Returns user agent
41
+ #
42
+ # @return [String] user agent
43
+ def user_agent
44
+ @user_agent ||= cocaine_line('--dump-user-agent').run.strip
32
45
  end
33
46
  end
@@ -6,7 +6,11 @@ module YoutubeDL
6
6
  #
7
7
  # @param options [Hash] a hash of options
8
8
  def initialize(options={})
9
- @store = options
9
+ if options.is_a? Hash
10
+ @store = options
11
+ else
12
+ @store = options.to_h
13
+ end
10
14
  end
11
15
 
12
16
  # Returns options as a hash
@@ -40,9 +44,8 @@ module YoutubeDL
40
44
  # Set options using a block
41
45
  #
42
46
  # @yield [config] self
43
- # TODO: support calling without arguments
44
- def configure(&block)
45
- block.call(self)
47
+ def configure
48
+ yield(self) if block_given?
46
49
  end
47
50
 
48
51
  # Get option with brackets syntax
@@ -0,0 +1,51 @@
1
+ module YoutubeDL
2
+ # A class of voodoo methods for parsing youtube-dl output
3
+ class Output < Struct.new(:output)
4
+ # Takes the output of '--list-formats'
5
+ #
6
+ # @return [Array] Array of supported formats
7
+ def supported_formats
8
+ # WARNING: This shit won't be documented or even properly tested. It's almost 3 in the morning and I have no idea what I'm doing.
9
+ header_index = output.index('format code')
10
+ return nil if header_index.nil?
11
+
12
+ formats = []
13
+ output.slice(header_index..-1).split("\n").each do |line|
14
+ format = {}
15
+ format[:format_code], format[:extension], format[:resolution], format[:note] = line.scan(/\A(\d+)\s+(\w+)\s+(\S+)\s(.*)/)[0]
16
+ formats.push format
17
+ end
18
+ formats.shift # The first line is just headers
19
+ formats.map do |format|
20
+ format[:note].strip! # Get rid of any trailing whitespace on the note.
21
+ format[:format_code] = format[:format_code].to_i # convert format code to integer
22
+ format
23
+ end
24
+ end
25
+
26
+ # Takes the output of a download
27
+ #
28
+ # @return [String] filename saved, nil if no match
29
+ def filename
30
+ # Check to see if file was already downloaded
31
+ if already_downloaded?
32
+ output.scan(/\[download\]\s(.*)\shas already been downloaded/)[0][0]
33
+ else
34
+ if output.include? 'Merging formats into'
35
+ output.scan(/Merging formats into \"(.*)\"/)[0][0]
36
+ else
37
+ output.scan(/\[download\] Destination:\s(.*)$/)[0][0]
38
+ end
39
+ end
40
+ rescue NoMethodError # There wasn't a match somewhere. Kill it with fire
41
+ nil
42
+ end
43
+
44
+ # Takes the output of a download
45
+ #
46
+ # @return [Boolean] Has the file already been downloaded?
47
+ def already_downloaded?
48
+ output.include? 'has already been downloaded'
49
+ end
50
+ end
51
+ end
@@ -4,18 +4,33 @@ module YoutubeDL
4
4
  class Runner
5
5
  include YoutubeDL::Support
6
6
 
7
+ # [String] URL to download
7
8
  attr_accessor :url
9
+
10
+ # [YoutubeDL::Options] Options access.
8
11
  attr_accessor :options
9
- attr_accessor :executable_path
12
+
13
+ # [String] Executable path
14
+ attr_reader :executable_path
15
+
16
+ # [String] Executable name to use
17
+ attr_accessor :executable
10
18
 
11
19
  # Command Line runner initializer
12
20
  #
13
21
  # @param url [String] URL to pass to youtube-dl executable
14
22
  # @param options [Hash, Options] options to pass to the executable. Automatically converted to Options if it isn't already
15
- def initialize(url, options=YoutubeDL::Options.new)
23
+ def initialize(url, options = {})
16
24
  @url = url
17
- @options = YoutubeDL::Options.new(options.to_hash)
18
- @executable_path = usable_executable_path_for('youtube-dl')
25
+ @options = YoutubeDL::Options.new(options)
26
+ @executable = 'youtube-dl'
27
+ end
28
+
29
+ # Returns usable executable path for youtube-dl
30
+ #
31
+ # @return [String] usable executable path for youtube-dl
32
+ def executable_path
33
+ @executable_path ||= usable_executable_path_for(@executable)
19
34
  end
20
35
 
21
36
  # Returns Cocaine's runner engine
@@ -28,6 +43,7 @@ module YoutubeDL
28
43
  # Sets Cocaine's runner engine
29
44
  #
30
45
  # @param [CommandLineRunner] backend runner class
46
+ # @return [Object] whatever Cocaine::CommandLine.runner= returns.
31
47
  def backend_runner=(cocaine_runner)
32
48
  Cocaine::CommandLine.runner = cocaine_runner
33
49
  end
@@ -41,30 +57,25 @@ module YoutubeDL
41
57
  alias_method :command, :to_command
42
58
 
43
59
  # Runs the command
60
+ #
61
+ # @return [String] the output of youtube-dl
44
62
  def run
45
63
  cocaine_line(options_to_commands).run(@options.store)
46
64
  end
47
65
  alias_method :download, :run
48
66
 
49
- # Returns a list of supported formats for the video in the form of
50
- # [{:format_code => '000', :extension => 'avi', :resolution => '320x240', :note => 'More details about the format'}]
51
- #
52
- # @return [Array] Format list
53
- def formats
54
- # TODO: Move formats to its own model?
55
- parse_format_output(cocaine_line("--list-formats #{quoted(url)}").run)
56
- end
57
-
58
- private
67
+ private
59
68
 
60
69
  # Parses options and converts them to Cocaine's syntax
61
70
  #
62
71
  # @return [String] commands ready to do cocaine
63
72
  def options_to_commands
64
73
  commands = []
65
- options.sanitize_keys.each_paramized_key do |key, paramized_key|
66
- if options[key].to_s == 'true'
74
+ @options.sanitize_keys.each_paramized_key do |key, paramized_key|
75
+ if @options[key].to_s == 'true'
67
76
  commands.push "--#{paramized_key}"
77
+ elsif @options[key].to_s == 'false'
78
+ commands.push "--no-#{paramized_key}"
68
79
  else
69
80
  commands.push "--#{paramized_key} :#{key}"
70
81
  end
@@ -72,37 +83,5 @@ module YoutubeDL
72
83
  commands.push quoted(url)
73
84
  commands.join(' ')
74
85
  end
75
-
76
- # Helper to add quotes to beginning and end of a URL.
77
- #
78
- # @param url [String] Raw URL
79
- # @return [String] Quoted URL
80
- def quoted(url)
81
- "\"#{url}\""
82
- end
83
-
84
- # Helper for doing lines of cocaine (initializing, auto executable stuff, etc)
85
- #
86
- # @param command [String] command switches to run
87
- # @return [Cocaine::CommandLine] initialized Cocaine instance
88
- def cocaine_line(command)
89
- Cocaine::CommandLine.new(@executable_path, command)
90
- end
91
-
92
- # Do you like voodoo?
93
- #
94
- # @param format_output [String] output from youtube-dl --list-formats
95
- # @return [Array] Magic.
96
- def parse_format_output(format_output)
97
- # WARNING: This shit won't be documented or even properly tested. It's almost 3 in the morning and I have no idea what I'm doing.
98
- this_shit = []
99
- format_output.slice(format_output.index('format code')..-1).split("\n").each do |line|
100
- a = {}
101
- a[:format_code], a[:extension], a[:resolution], a[:note] = line.scan(/\A(\d+)\s+(\w+)\s+(\S+)\s(.*)/)[0]
102
- this_shit.push a
103
- end
104
- this_shit.shift
105
- this_shit.map { |gipo| gipo[:note].strip!; gipo }
106
- end
107
86
  end
108
87
  end
@@ -11,11 +11,31 @@ module YoutubeDL
11
11
  if $?.exitstatus == 0 # $? is an object with information on that last command run with backticks.
12
12
  system_path.strip
13
13
  else
14
- # TODO: Search vendor bin for executable before just saying it's there.
14
+ # TODO: Search vendor bin for executable before just saying it's there.
15
15
  vendor_path = File.absolute_path("#{__FILE__}/../../../vendor/bin/#{exe}")
16
16
  File.chmod(775, vendor_path) unless File.executable?(vendor_path) # Make sure vendor binary is executable
17
17
  vendor_path
18
18
  end
19
19
  end
20
+
21
+ alias_method :executable_path_for, :usable_executable_path_for
22
+
23
+ # Helper for doing lines of cocaine (initializing, auto executable stuff, etc)
24
+ #
25
+ # @param command [String] command switches to run
26
+ # @param executable_path [String] executable to run. Defaults to usable youtube-dl.
27
+ # @return [Cocaine::CommandLine] initialized Cocaine instance
28
+ def cocaine_line(command, executable_path = nil)
29
+ executable_path = executable_path_for('youtube-dl') if executable_path.nil?
30
+ Cocaine::CommandLine.new(executable_path, command)
31
+ end
32
+
33
+ # Helper to add quotes to beginning and end of a URL or whatever you want....
34
+ #
35
+ # @param url [String] Raw URL
36
+ # @return [String] Quoted URL
37
+ def quoted(url)
38
+ "\"#{url}\""
39
+ end
20
40
  end
21
41
  end
@@ -1,3 +1,3 @@
1
1
  module YoutubeDL
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,60 @@
1
+ module YoutubeDL
2
+ # Video model
3
+ class Video < Runner
4
+ class << self
5
+ # Instantiate a new Video model and download the video
6
+ #
7
+ # @param url [String] URL to use and download
8
+ # @param options [Hash] Options to pass in
9
+ # @return [YoutubeDL::Video] new Video model
10
+ def download(url, options={})
11
+ video = new(url, options)
12
+ video.download
13
+ video
14
+ end
15
+
16
+ alias_method :get, :download
17
+ end
18
+
19
+ # [YoutubeDL::Options] Download Options for the last download
20
+ attr_reader :download_options
21
+
22
+ # Instantiate new model
23
+ #
24
+ # @param url [String] URL to initialize with
25
+ # @param options [Hash] Options to populate the everything with
26
+ def initialize(url, options={})
27
+ @url = url
28
+ @options = YoutubeDL::Options.new(options)
29
+ end
30
+
31
+ # Download the video.
32
+ def download
33
+ @download_options = YoutubeDL::Options.new(runner_options)
34
+ @last_download_output = YoutubeDL::Runner.new(url, @download_options).run
35
+ end
36
+
37
+ alias_method :get, :download
38
+
39
+ # Returns a list of supported formats for the video in the form of
40
+ # [{:format_code => '000', :extension => 'avi', :resolution => '320x240', :note => 'More details about the format'}]
41
+ #
42
+ # @return [Array] Format list
43
+ def formats
44
+ @formats ||= YoutubeDL::Output.new(cocaine_line("--list-formats #{quoted(url)}").run).supported_formats
45
+ end
46
+
47
+ # @return [String] Filename downloaded to
48
+ def filename
49
+ @filename ||= YoutubeDL::Output.new(@last_download_output).filename
50
+ end
51
+
52
+ private
53
+ # Add in other default options here.
54
+ def runner_options
55
+ {
56
+ no_color: true
57
+ }.merge(@options)
58
+ end
59
+ end
60
+ end
@@ -24,7 +24,7 @@ TEST_FORMAT = "5"
24
24
  TEST_GLOB = "nope*"
25
25
 
26
26
  def remove_downloaded_files
27
- Dir.glob("**/nope*").each do |nope|
27
+ Dir.glob("**/*nope*").each do |nope|
28
28
  File.delete(nope)
29
29
  end
30
30
  end
@@ -5,87 +5,141 @@ describe YoutubeDL::Options do
5
5
  @options = YoutubeDL::Options.new
6
6
  end
7
7
 
8
- it 'should symbolize option keys' do
9
- @options.store['key'] = "value"
10
- @options.sanitize_keys!
11
- assert_equal({key: 'value'}, @options.store)
8
+ describe '#initialize' do
9
+ it 'should symbolize option keys' do
10
+ @options.store['key'] = "value"
11
+ @options.sanitize_keys!
12
+ assert_equal({key: 'value'}, @options.store)
13
+ end
14
+
15
+ it 'should accept a parent Options as a param' do
16
+ parent = YoutubeDL::Options.new(parent_key: 'parent value')
17
+ child = YoutubeDL::Options.new(parent)
18
+ assert_equal parent.store, child.store
19
+ end
20
+
21
+ it 'should accept a Hash as a param' do
22
+ hash = {parent_key: 'parent value'}
23
+ options = YoutubeDL::Options.new(hash)
24
+ assert_equal hash, options.store
25
+ end
12
26
  end
13
27
 
14
- it 'should be able to set options with method_missing' do
15
- @options.test = true
28
+ describe '#to_hash, #to_h' do
29
+ before do
30
+ @options.store[:key] = "value"
31
+ end
16
32
 
17
- assert @options.store[:test]
33
+ it 'should return a hash' do
34
+ assert_instance_of Hash, @options.to_hash
35
+ end
36
+
37
+ it 'should be equal to store' do
38
+ assert_equal @options.store, @options.to_hash
39
+ end
18
40
  end
19
41
 
20
- it 'should be able to retrieve options with method_missing' do
21
- @options.store[:walrus] = 'haswalrus'
42
+ describe '#each_paramized' do
43
+ it 'should properly paramize keys and not values' do
44
+ @options.some_key = "some value"
22
45
 
23
- assert @options.walrus == 'haswalrus'
46
+ @options.each_paramized do |key, value|
47
+ assert_equal key, 'some-key'
48
+ assert_equal value, 'some value'
49
+ end
50
+ end
24
51
  end
25
52
 
26
- it 'should be able to use brackets' do
27
- @options[:mtn] = :dew
28
- assert @options[:mtn] == :dew
53
+ describe '#each_paramized_key' do
54
+ it 'should properly paramize keys' do # TODO: Write a better test name
55
+ @options.some_key = "some value"
56
+
57
+ @options.each_paramized_key do |key, paramized_key|
58
+ assert_equal :some_key, key
59
+ assert_equal 'some-key', paramized_key
60
+ end
61
+ end
29
62
  end
30
63
 
31
- it 'should be able to use a configuration block' do
32
- @options.configure do |c|
33
- c.get_operator = true
34
- c['get_index'] = true
64
+ describe '#configure' do
65
+ it 'should be able to use an explicit configuration block' do
66
+ @options.configure do |c|
67
+ c.get_operator = true
68
+ c['get_index'] = true
69
+ end
70
+
71
+ assert @options.store[:get_operator], "Actual: #{@options.store[:get_operator]}"
72
+ assert @options.store[:get_index], "Actual: #{@options.store[:get_index]}"
35
73
  end
36
74
 
37
- assert @options.store[:get_operator], "Actual: #{@options.store[:get_operator]}"
38
- assert @options.store[:get_index], "Actual: #{@options.store[:get_index]}"
75
+ it 'should not override parent configuration' do
76
+ opts = YoutubeDL::Options.new(parent: 'value')
77
+ opts.configure do |c|
78
+ c.child = 'vlaue'
79
+ end
80
+
81
+ assert_equal opts.store[:parent], 'value'
82
+ assert_equal opts.store[:child], 'vlaue'
83
+ end
39
84
  end
40
85
 
41
- it 'should automatically symbolize keys' do
42
- @options.get_operator = true
43
- @options['get_index'] = true
86
+ describe '#[], #[]==' do
87
+ it 'should be able to use brackets' do
88
+ @options[:mtn] = :dew
89
+ assert @options[:mtn] == :dew
90
+ end
91
+
92
+ it 'should automatically symbolize keys' do
93
+ @options.get_operator = true
94
+ @options['get_index'] = true
44
95
 
45
- [:get_operator, :get_index].each do |d|
46
- assert @options.store.keys.include?(d), "keys not symbolizing automatically: #{d}"
96
+ [:get_operator, :get_index].each do |d|
97
+ assert @options.store.keys.include?(d), "keys not symbolizing automatically: #{d}"
98
+ end
47
99
  end
48
100
  end
49
101
 
50
- it 'should properly paramize keys and not values' do
51
- @options.some_key = "some value"
102
+ describe '#method_missing' do
103
+ it 'should be able to set options with method_missing' do
104
+ @options.test = true
52
105
 
53
- @options.each_paramized do |key, value|
54
- assert_equal key, 'some-key'
55
- assert_equal value, 'some value'
106
+ assert @options.store[:test]
56
107
  end
57
- end
58
108
 
59
- it 'should make each_paramized_key work' do # TODO: Write a better test name
60
- @options.some_key = "some value"
109
+ it 'should be able to retrieve options with method_missing' do
110
+ @options.store[:walrus] = 'haswalrus'
61
111
 
62
- @options.each_paramized_key do |key, paramized_key|
63
- assert_equal :some_key, key
64
- assert_equal 'some-key', paramized_key
112
+ assert @options.walrus == 'haswalrus'
65
113
  end
66
114
  end
67
115
 
68
- it 'should convert hyphens to underscores in keys' do # See issue #9
69
- @options.store[:"hyphenated-key"] = 'value'
70
- @options.sanitize_keys!
71
- assert_equal({hyphenated_key: 'value'}, @options.to_h)
116
+ describe '#manipulate_keys!' do
117
+ it 'should manipulate keys' do
118
+ @options.some_key = 'value'
119
+ @options.manipulate_keys! do |key|
120
+ key.to_s.upcase
121
+ end
122
+ assert_equal({'SOME_KEY' => 'value'}, @options.store)
123
+ end
72
124
  end
73
125
 
74
- it 'should not modify the original by calling sanitize_keys without bang' do
75
- @options.store['some-key'] = "some_value"
76
- refute_equal @options.sanitize_keys, @options
126
+ describe '#sanitize_keys!' do
127
+ it 'should convert hyphens to underscores in keys' do # See issue #9
128
+ @options.store[:"hyphenated-key"] = 'value'
129
+ @options.sanitize_keys!
130
+ assert_equal({hyphenated_key: 'value'}, @options.to_h)
131
+ end
77
132
  end
78
133
 
79
- it 'should return instance of Options when calling sanitize_keys' do
80
- @options.store['some-key'] = "some_value"
81
- assert_instance_of YoutubeDL::Options, @options.sanitize_keys
82
- end
134
+ describe '#sanitize_keys' do
135
+ it 'should not modify the original by calling sanitize_keys without bang' do
136
+ @options.store['some-key'] = "some_value"
137
+ refute_equal @options.sanitize_keys, @options
138
+ end
83
139
 
84
- it 'should manipulate keys' do
85
- @options.some_key = 'value'
86
- @options.manipulate_keys! do |key|
87
- key.to_s.upcase
140
+ it 'should return instance of Options when calling sanitize_keys' do
141
+ @options.store['some-key'] = "some_value"
142
+ assert_instance_of YoutubeDL::Options, @options.sanitize_keys
88
143
  end
89
- assert_equal({'SOME_KEY' => 'value'}, @options.store)
90
144
  end
91
145
  end
@@ -0,0 +1,100 @@
1
+ require_relative '../test_helper'
2
+
3
+ module OutputFactory
4
+ extend self
5
+ extend YoutubeDL::Support
6
+
7
+ def download
8
+ remove_downloaded_files # Make sure there isn't a file there
9
+ @download ||= cocaine_line(quoted(TEST_URL)).run
10
+ end
11
+
12
+ def download_exists
13
+ @download_exists ||= lambda do
14
+ cocaine_line(quoted(TEST_URL)).run # two times to make sure it's there.
15
+ cocaine_line(quoted(TEST_URL)).run
16
+ end.call
17
+ end
18
+
19
+ def list_formats
20
+ @list_formats ||= cocaine_line("--list-formats #{quoted(TEST_URL)}").run
21
+ end
22
+ end
23
+
24
+ # For debugging
25
+ # puts
26
+ # puts " --------------- OutputFactory.download --------------- "
27
+ # puts OutputFactory.download
28
+ # puts
29
+ # puts " --------------- OutputFactory.download_exists --------------- "
30
+ # puts OutputFactory.download_exists
31
+ # puts
32
+ # puts " --------------- OutputFactory.list_formats --------------- "
33
+ # puts OutputFactory.list_formats
34
+ # puts
35
+
36
+ describe YoutubeDL::Output do
37
+ describe '#initialize' do
38
+ it 'should set the output variable' do
39
+ sample_output = "some sample output\n\n"
40
+ parser = YoutubeDL::Output.new(sample_output)
41
+ assert_equal sample_output, parser.output
42
+ end
43
+ end
44
+
45
+ describe '#supported_formats' do
46
+ before do
47
+ @parser = YoutubeDL::Output.new(OutputFactory.list_formats)
48
+ end
49
+
50
+ it 'should find a match given the correct output' do
51
+ refute_nil @parser.supported_formats
52
+ end
53
+
54
+ it 'should find the correct match and in the correct format' do
55
+ assert_includes(@parser.supported_formats, {format_code: 5, extension: 'flv', resolution: '400x240', note: 'small'})
56
+ end
57
+
58
+ it 'should return nil if no match or wrong log format' do
59
+ bad_parser = YoutubeDL::Output.new(OutputFactory.download)
60
+ assert_nil bad_parser.supported_formats
61
+ end
62
+ end
63
+
64
+ describe '#filename' do
65
+ before do
66
+ @parser_download = YoutubeDL::Output.new(OutputFactory.download)
67
+ @parser_download_exists = YoutubeDL::Output.new(OutputFactory.download_exists)
68
+ end
69
+
70
+ it 'should find a match given the correct output' do
71
+ refute_nil @parser_download.filename
72
+ refute_nil @parser_download_exists.filename
73
+ end
74
+
75
+ it 'should find the correct match' do
76
+ assert_equal 'nope.avi-gvdf5n-zI14.mp4', @parser_download.filename
77
+ assert_equal 'nope.avi-gvdf5n-zI14.mp4', @parser_download_exists.filename
78
+ end
79
+
80
+ it 'should return nil if no match or wrong log format' do
81
+ bad_parser = YoutubeDL::Output.new(OutputFactory.list_formats)
82
+ assert_nil bad_parser.filename
83
+ end
84
+ end
85
+
86
+ describe '#already_downloaded?' do
87
+ before do
88
+ @parser_download = YoutubeDL::Output.new(OutputFactory.download)
89
+ @parser_download_exists = YoutubeDL::Output.new(OutputFactory.download_exists)
90
+ end
91
+
92
+ it 'should return a truthy value if true' do
93
+ assert @parser_download_exists.already_downloaded?
94
+ end
95
+
96
+ it 'should return a falsy value if false' do
97
+ refute @parser_download.already_downloaded?
98
+ end
99
+ end
100
+ end
@@ -9,75 +9,68 @@ describe YoutubeDL::Runner do
9
9
  remove_downloaded_files
10
10
  end
11
11
 
12
- it 'should set cocaine runner' do
13
- @runner.backend_runner = Cocaine::CommandLine::BackticksRunner.new
14
- assert_instance_of Cocaine::CommandLine::BackticksRunner, @runner.backend_runner
15
-
16
- @runner.backend_runner = Cocaine::CommandLine::PopenRunner.new
17
- assert_instance_of Cocaine::CommandLine::PopenRunner, @runner.backend_runner
12
+ describe '#initialize' do
13
+ it 'should take options as a hash yet still have configuration blocks work' do
14
+ r = YoutubeDL::Runner.new(TEST_URL, {some_key: 'some value'})
15
+ r.options.configure do |c|
16
+ c.another_key = 'another_value'
17
+ end
18
+
19
+ assert_includes r.to_command, "--some-key"
20
+ assert_includes r.to_command, "--another-key"
21
+ end
18
22
  end
19
23
 
20
- it 'should set executable path automatically' do
21
- assert_match 'youtube-dl', @runner.executable_path
22
- end
24
+ describe '#executable_path' do
25
+ it 'should set executable path automatically' do
26
+ assert_match 'youtube-dl', @runner.executable_path
27
+ end
23
28
 
24
- it 'should not have a newline char in the executable_path' do
25
- assert_match /youtube-dl\z/, @runner.executable_path
29
+ it 'should not have a newline char in the executable_path' do
30
+ assert_match /youtube-dl\z/, @runner.executable_path
31
+ end
26
32
  end
27
33
 
28
- it 'should not have newline char in to_command' do
29
- assert_match /youtube-dl\s/, @runner.to_command
34
+ describe '#backend_runner=, #backend_runner' do
35
+ it 'should set cocaine runner' do
36
+ @runner.backend_runner = Cocaine::CommandLine::BackticksRunner.new
37
+ assert_instance_of Cocaine::CommandLine::BackticksRunner, @runner.backend_runner
38
+
39
+ @runner.backend_runner = Cocaine::CommandLine::PopenRunner.new
40
+ assert_instance_of Cocaine::CommandLine::PopenRunner, @runner.backend_runner
41
+ end
30
42
  end
31
43
 
32
- it 'should parse key-values from options' do
33
- @runner.options.some_key = "a value"
44
+ describe '#to_command' do
45
+ it 'should parse key-values from options' do
46
+ @runner.options.some_key = "a value"
34
47
 
35
- refute_nil @runner.to_command.match(/--some-key\s.*a value.*/)
36
- end
48
+ refute_nil @runner.to_command.match(/--some-key\s.*a value.*/)
49
+ end
37
50
 
38
- it 'should not include the value if value is true' do
39
- @runner.options.some_key = true
51
+ it 'should handle true boolean values' do
52
+ @runner.options.truthy_value = true
40
53
 
41
- refute @runner.to_command.include?("--some-key 'true'"), "adding true to boolean key >:("
42
- end
54
+ assert_match /youtube-dl .*--truthy-value\s--|\"http.*/, @runner.to_command
55
+ end
43
56
 
44
- it 'should run commands' do
45
- @runner.options.output = TEST_FILENAME
46
- @runner.options.format = TEST_FORMAT
47
- @runner.run
48
- assert File.exists? TEST_FILENAME
49
- end
57
+ it 'should handle false boolean values' do
58
+ @runner.options.false_value = false
50
59
 
51
- it 'should take options as a hash yet still have configuration blocks work' do
52
- r = YoutubeDL::Runner.new(TEST_URL, {some_key: 'some value'})
53
- r.options.configure do |c|
54
- c.another_key = 'another_value'
60
+ assert_match /youtube-dl .*--no-false-value\s--|\"http.*/, @runner.to_command
55
61
  end
56
62
 
57
- assert_includes r.to_command, "--some-key"
58
- assert_includes r.to_command, "--another-key"
63
+ it 'should not have newline char in to_command' do
64
+ assert_match /youtube-dl\s/, @runner.to_command
65
+ end
59
66
  end
60
67
 
61
- it 'might list formats' do
62
- formats = @runner.formats
63
- assert_instance_of Array, formats
64
- assert_instance_of Hash, formats.first
65
- assert_equal 4, formats.first.size
66
- [:format_code, :resolution, :extension, :note].each do |key|
67
- assert_includes formats.first, key
68
- assert_includes formats.last, key
68
+ describe '#run' do
69
+ it 'should run commands' do
70
+ @runner.options.output = TEST_FILENAME
71
+ @runner.options.format = TEST_FORMAT
72
+ @runner.run
73
+ assert File.exists? TEST_FILENAME
69
74
  end
70
75
  end
71
-
72
- it 'should handle strangely-formatted options correctly' do # See issue #9
73
- options = {
74
- format: 'bestaudio',
75
- :"prefer-ffmpeg" => "true",
76
- :"extract-audio" => true,
77
- :"audio-format" => "mp3"
78
- }
79
-
80
- @runner.options = YoutubeDL::Options.new(options)
81
- assert_match /youtube-dl --format 'bestaudio' --prefer-ffmpeg --extract-audio --audio-format 'mp3'/, @runner.to_command
82
- end
83
76
  end
@@ -33,4 +33,26 @@ describe YoutubeDL::Support do
33
33
  assert_match /youtube-dl\z/, @klass.executable_path
34
34
  end
35
35
  end
36
+
37
+ describe '#cocaine_line' do
38
+ it 'should return a Cocaine::CommandLine instance' do
39
+ assert_instance_of Cocaine::CommandLine, @klass.cocaine_line('')
40
+ end
41
+
42
+ it 'should be able to override the executable' do
43
+ line = @klass.cocaine_line('hello', 'echo')
44
+ assert_equal "echo hello", line.command
45
+ end
46
+
47
+ it 'should default to youtube-dl' do
48
+ line = @klass.cocaine_line(@klass.quoted(TEST_URL))
49
+ assert_includes line.command, "youtube-dl \"#{TEST_URL}\""
50
+ end
51
+ end
52
+
53
+ describe '#quoted' do
54
+ it 'should add quotes' do
55
+ assert_equal "\"#{TEST_URL}\"", @klass.quoted(TEST_URL)
56
+ end
57
+ end
36
58
  end
@@ -0,0 +1,89 @@
1
+ require_relative '../test_helper'
2
+
3
+ describe YoutubeDL::Video do
4
+ before do
5
+ @video = YoutubeDL::Video.new TEST_URL
6
+ end
7
+
8
+ after do
9
+ remove_downloaded_files
10
+ end
11
+
12
+ describe '.download' do
13
+ it 'should download videos without options' do
14
+ YoutubeDL::Video.download TEST_URL
15
+ assert_equal 1, Dir.glob(TEST_GLOB).length
16
+ end
17
+
18
+ it 'should download videos with options' do
19
+ YoutubeDL::Video.download TEST_URL, output: TEST_FILENAME, format: TEST_FORMAT
20
+ assert File.exist? TEST_FILENAME
21
+ end
22
+
23
+ it 'should return an instance of YoutubeDL::Video' do
24
+ video = YoutubeDL::Video.download TEST_URL
25
+ assert_instance_of YoutubeDL::Video, video
26
+ end
27
+ end
28
+
29
+ describe '.get' do
30
+ it 'should download videos, exactly like .download' do
31
+ YoutubeDL::Video.get TEST_URL
32
+ assert_equal Dir.glob(TEST_GLOB).length, 1
33
+ end
34
+ end
35
+
36
+ describe '#initialize' do
37
+ it 'should return an instance of YoutubeDL::Video' do
38
+ assert_instance_of YoutubeDL::Video, @video
39
+ end
40
+
41
+ it 'should not download anything' do
42
+ assert_empty Dir.glob(TEST_GLOB)
43
+ end
44
+ end
45
+
46
+ describe '#download' do
47
+ it 'should download the file' do
48
+ assert_equal 0, Dir.glob(TEST_GLOB).length
49
+ @video.download
50
+ assert_equal 1, Dir.glob(TEST_GLOB).length
51
+ end
52
+
53
+ it 'should set model variables accordingly' do
54
+ @video.download
55
+ assert_equal Dir.glob(TEST_GLOB).first, @video.filename
56
+ end
57
+ end
58
+
59
+ describe '#formats' do
60
+ before do
61
+ @formats = @video.formats
62
+ end
63
+
64
+ it 'should be an Array' do
65
+ assert_instance_of Array, @formats
66
+ end
67
+
68
+ it 'should be an Array of Hashes' do
69
+ assert_instance_of Hash, @formats.first
70
+ end
71
+
72
+ it 'should have a hash size of 4' do
73
+ assert_equal 4, @formats.first.size
74
+ end
75
+
76
+ it 'should include the correct information' do
77
+ [:format_code, :resolution, :extension, :note].each do |key|
78
+ assert_includes @formats.first, key
79
+ assert_includes @formats.last, key
80
+ end
81
+ end
82
+
83
+ it 'should not have any whitespace in the notes' do
84
+ @formats.each do |format|
85
+ assert_nil format[:note].strip!
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,84 @@
1
+ require_relative './test_helper'
2
+
3
+ describe YoutubeDL do
4
+ describe '.download' do
5
+ after do
6
+ remove_downloaded_files
7
+ end
8
+
9
+ it 'should download videos without options' do
10
+ YoutubeDL.download TEST_URL
11
+ assert_equal 1, Dir.glob(TEST_GLOB).length
12
+ end
13
+
14
+ it 'should download videos with options' do
15
+ YoutubeDL.download TEST_URL, output: TEST_FILENAME, format: TEST_FORMAT
16
+ assert File.exist? TEST_FILENAME
17
+ end
18
+
19
+ it 'should download multiple videos without options' do
20
+ YoutubeDL.download [TEST_URL, TEST_URL2]
21
+ assert_equal 2, Dir.glob(TEST_GLOB).length
22
+ end
23
+
24
+ it 'should download multiple videos with options' do
25
+ YoutubeDL.download [TEST_URL, TEST_URL2], output: 'test_%(title)s-%(id)s.%(ext)s'
26
+ assert_equal 2, Dir.glob('test_' + TEST_GLOB).length
27
+ end
28
+ end
29
+
30
+ describe '.get' do
31
+ after do
32
+ remove_downloaded_files
33
+ end
34
+
35
+ it 'should download videos, exactly like .download' do
36
+ YoutubeDL.get TEST_URL
37
+ assert_equal Dir.glob(TEST_GLOB).length, 1
38
+ end
39
+ end
40
+
41
+ describe '.extractors' do
42
+ before do
43
+ @extractors = YoutubeDL.extractors
44
+ end
45
+
46
+ it 'should return an Array' do
47
+ assert_instance_of Array, @extractors
48
+ end
49
+
50
+ it 'should include the youtube extractors' do
51
+ ['youtube', 'youtube:channel', 'youtube:search', 'youtube:show', 'youtube:user', 'youtube:playlist'].each do |e|
52
+ assert_includes @extractors, e
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '.binary_version' do
58
+ before do
59
+ @version = YoutubeDL.binary_version
60
+ end
61
+
62
+ it 'should return a string' do
63
+ assert_instance_of String, @version
64
+ end
65
+
66
+ it 'should be a specific format with no newlines' do
67
+ assert_match /\d+.\d+.\d+\z/, @version
68
+ end
69
+ end
70
+
71
+ describe '.user_agent' do
72
+ before do
73
+ @user_agent = YoutubeDL.user_agent
74
+ end
75
+
76
+ it 'should return a string' do
77
+ assert_instance_of String, @user_agent
78
+ end
79
+
80
+ it 'should be a specific format with no newlines' do
81
+ assert_match /Mozilla\/5\.0\s.*\)\z/, @user_agent
82
+ end
83
+ end
84
+ end
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_development_dependency "bundler", ">= 1.6"
24
24
  spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "m"
25
26
  spec.add_development_dependency "rake", "~> 10.0"
26
27
  spec.add_development_dependency "minitest", "~> 5.5.1"
27
28
  spec.add_development_dependency "purdytest"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: youtube-dl.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sapslaj
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-09-06 00:00:00.000000000 Z
12
+ date: 2015-09-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cocaine
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: m
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: rake
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -125,14 +139,18 @@ files:
125
139
  - Rakefile
126
140
  - lib/youtube-dl.rb
127
141
  - lib/youtube-dl/options.rb
142
+ - lib/youtube-dl/output.rb
128
143
  - lib/youtube-dl/runner.rb
129
144
  - lib/youtube-dl/support.rb
130
145
  - lib/youtube-dl/version.rb
146
+ - lib/youtube-dl/video.rb
131
147
  - test/test_helper.rb
132
148
  - test/youtube-dl/options_test.rb
149
+ - test/youtube-dl/output_test.rb
133
150
  - test/youtube-dl/runner_test.rb
134
151
  - test/youtube-dl/support_test.rb
135
- - test/youtube-dl/youtube-dl_test.rb
152
+ - test/youtube-dl/video_test.rb
153
+ - test/youtube-dl_test.rb
136
154
  - vendor/bin/youtube-dl
137
155
  - vendor/bin/youtube-dl.exe
138
156
  - youtube-dl.rb.gemspec
@@ -163,6 +181,8 @@ summary: youtube-dl wrapper for Ruby
163
181
  test_files:
164
182
  - test/test_helper.rb
165
183
  - test/youtube-dl/options_test.rb
184
+ - test/youtube-dl/output_test.rb
166
185
  - test/youtube-dl/runner_test.rb
167
186
  - test/youtube-dl/support_test.rb
168
- - test/youtube-dl/youtube-dl_test.rb
187
+ - test/youtube-dl/video_test.rb
188
+ - test/youtube-dl_test.rb
@@ -1,41 +0,0 @@
1
- require_relative '../test_helper'
2
-
3
- describe YoutubeDL do
4
- describe '.download' do
5
- after do
6
- remove_downloaded_files
7
- end
8
-
9
- it 'should download videos' do
10
- YoutubeDL.get TEST_URL, output: TEST_FILENAME, format: TEST_FORMAT
11
- assert File.exist? TEST_FILENAME
12
- end
13
-
14
- it 'should download multiple videos' do
15
- YoutubeDL.download [TEST_URL, TEST_URL2]
16
- assert_equal Dir.glob('nope*').length, 2
17
- end
18
- end
19
-
20
- describe '.extractors' do
21
- it 'should return an Array of Strings' do
22
- extractors = YoutubeDL.extractors
23
- assert_instance_of Array, extractors
24
- assert_instance_of String, extractors.first
25
- end
26
- end
27
-
28
- describe '.binary_version' do
29
- before do
30
- @version = YoutubeDL.binary_version
31
- end
32
-
33
- it 'should return a string' do
34
- assert_instance_of String, @version
35
- end
36
-
37
- it 'should be a specific format with no newlines' do
38
- assert_match /\d+.\d+.\d+\z/, @version
39
- end
40
- end
41
- end