youtube-dl.rb 0.1.1 → 0.2.0

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 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