yt_downloader 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 409be4bc22c3acb2663067d21e58eb7195ada02f40bceaa4698ba92283fa491b
4
+ data.tar.gz: 4a0b0c19181defffa2c8ecd21c827f0209ee3ec3af3d3bbf416d8b7c4c9c45c0
5
+ SHA512:
6
+ metadata.gz: 5b02b839bc4f03848f92c8b66a2aabaed9ab8865e1b3a0bbfa6e4d78f84e9be5f659f6b08a6012aae74803b269fb32dc2baf53a62ae6cd6c0ef65cebb3cc94b0
7
+ data.tar.gz: 0ab9cad470141fc49dd2b51d6db413ad6190599567eb155face71057c8a5b2f942f324fa49d1148435d09ba17a0f560066710234a1ed79a11b0c0b1fe73b45b2
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # yt_downloader
2
+
3
+ ## Installation
4
+
5
+ ```shell
6
+ $ gem install yt_downloader
7
+ ```
8
+
9
+ ## Usage
10
+
11
+ ```shell
12
+ $ yt_downloader --help
13
+ Commands:
14
+ yt_downloader download
15
+ ```
16
+
17
+ ```shell
18
+ $ yt_downloader download --help
19
+ Command:
20
+ yt_downloader download
21
+
22
+ Usage:
23
+ yt_downloader download
24
+
25
+ Description:
26
+ Download audio from you tube video
27
+
28
+ Options:
29
+ --source=VALUE # Chrome json path
30
+ --parser=VALUE # Chrome json path: (chrome), default: "chrome"
31
+ --bookmark-tabs=VALUE # Chrome json path, default: "music"
32
+ --destination=VALUE # Download folder, default: "./yt_downloader/audios"
33
+ --logger-path=VALUE # Logger path, default: "./yt_downloader/logs/successful.txt"
34
+ --audio-format=VALUE # Audio format: (mp4/flac), default: "mp3"
35
+ --help, -h # Print this help
36
+
37
+ Examples:
38
+ yt_downloader download --source=/path --parser=chrome --bookmark-tabs=example,example --destination=/path --logger-path=/path audio_format=mp3
39
+ ```
40
+
41
+ ```shell
42
+ $ yt_downloader download
43
+ ```
44
+
45
+ ## Development
46
+
47
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
48
+
49
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
50
+
51
+ ## Contributing
52
+
53
+ Bug reports and pull requests are welcome on GitHub at https://github.com/radicm/yt_downloader.
54
+
55
+ ## Copyright
56
+
57
+ [RadicM](https://github.com/radicm) © 2019 - Released under the MIT License
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: :spec
data/exe/yt_downloader ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require "bundler/setup"
6
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
7
+ end
8
+
9
+ require "yt_downloader"
10
+
11
+ YtDownloader::CLI.new.call
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hanami/cli'
4
+ require 'pathname'
5
+
6
+ require 'yt_downloader/version'
7
+ require 'yt_downloader/logger'
8
+ require 'yt_downloader/config'
9
+ require 'yt_downloader/converter'
10
+ require 'yt_downloader/parser'
11
+ require 'yt_downloader/downloader'
12
+ require 'yt_downloader/downloader/yt_dl'
13
+ require 'yt_downloader/parser/chrome'
14
+
15
+ module YtDownloader
16
+ class CLI
17
+ def call(*args)
18
+ Hanami::CLI.new(Commands).call(*args)
19
+ end
20
+
21
+ module Commands
22
+ extend Hanami::CLI::Registry
23
+
24
+ class Download < Hanami::CLI::Command
25
+ desc 'Download audio from you tube video'
26
+
27
+ option :source, default: nil, desc: 'Chrome json path'
28
+ option :parser, default: YtDownloader::Parser::CHROME, values: [YtDownloader::Parser::CHROME], desc: 'Chrome json path'
29
+ option :bookmark_tabs, default: 'music', desc: 'Chrome json path'
30
+ option :destination, default: YtDownloader::Config.destination_path, desc: 'Download folder'
31
+ option :logger_path, default: YtDownloader::Config.logger_path, desc: 'Logger path'
32
+ option :audio_format, default: YtDownloader::Config.audio_format, values: %w[mp4 flac], desc: 'Audio format'
33
+
34
+ example [
35
+ '--source=/path --parser=chrome --bookmark-tabs=example,example --destination=/path --logger-path=/path audio_format=mp3 '
36
+ ]
37
+
38
+ def call(**options)
39
+ # make sure dir structure exists
40
+ Pathname(options.fetch(:destination)).dirname.mkpath
41
+ Pathname(options.fetch(:logger_path)).dirname.mkpath
42
+
43
+ bookmark_tabs = options.fetch(:bookmark_tabs).split(',')
44
+ downloader = Downloader.new(Downloader::YTDL, destination: options.fetch(:destination), audio_format: options.fetch(:audio_format))
45
+
46
+ Converter.call(downloader: downloader,
47
+ parser: Parser.new(options.fetch(:parser)),
48
+ source: options.fetch(:source, nil),
49
+ bookmark_tabs: bookmark_tabs,
50
+ logger: Logger.new(options.fetch(:logger_path)))
51
+ end
52
+ end
53
+
54
+ register 'download', Download, aliases: ['d']
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,31 @@
1
+ module YtDownloader
2
+ class Config
3
+ MP3_FORMAT = 'mp3'.freeze
4
+ MP4_FORMAT = 'mp4'.freeze
5
+ FLAC_FORMAT = 'flac'.freeze
6
+
7
+ class << self
8
+ #TODO add support for storing config in .yml
9
+
10
+ # @return [String]
11
+ def destination_path
12
+ './yt_downloader/audios'
13
+ end
14
+
15
+ # @return [String]
16
+ def logger_path
17
+ './yt_downloader/logs/successful.txt'
18
+ end
19
+
20
+ # @return [String]
21
+ def audio_format
22
+ MP3_FORMAT
23
+ end
24
+
25
+ # @return [Array][String]
26
+ def supported_audio_formats
27
+ [MP3_FORMAT, MP4_FORMAT, FLAC_FORMAT]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ module YtDownloader
2
+ class Converter
3
+
4
+ # @param [String] audio_format
5
+ # @param [Parser] parser
6
+ # @param [String] source
7
+ # @param [String] destination
8
+ # @param [Array][String] bookmark_tabs
9
+ # @param [Logger] logger
10
+ def self.call(downloader:, parser:, source:, bookmark_tabs:, logger:)
11
+ logger.info('Parsing bookmark urls')
12
+ bookmarks = parser.call(bookmark_tabs, source)
13
+
14
+ bookmarks.each_with_index do |bookmark, i|
15
+ logger.console_log("[#{i + 1}/#{bookmarks.count}] #{bookmark.name} - #{bookmark.url}")
16
+ logger.info("Starting download of #{bookmark.name} - #{bookmark.url}")
17
+
18
+ downloader.call(bookmark.url)
19
+ end
20
+ logger.console_log('Finished!')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module YtDownloader
2
+ class Downloader
3
+
4
+ # @param [String] downloader
5
+ # @return [Downloader]
6
+ def initialize(downloader, *args)
7
+ @parser = case downloader
8
+ when YtDownloader::Downloader::YTDL
9
+ YtDownloader::Downloader::YtDl.new(*args)
10
+ else
11
+ raise "Unsupported #{downloader} parser!"
12
+ end
13
+ end
14
+
15
+ # @param [String] url
16
+ def call(url)
17
+ @parser.call(url)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ module YtDownloader
2
+ class Downloader
3
+ class Base
4
+ def call
5
+ raise('Override this method!')
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ require 'yt_downloader/downloader/base'
2
+
3
+ module YtDownloader
4
+ class Downloader
5
+ YTDL = 'ytdl'.freeze
6
+
7
+ class YtDl < Base
8
+ def initialize(**options)
9
+ @destination = options.fetch(:destination)
10
+ @audio_format = options.fetch(:audio_format)
11
+ end
12
+
13
+ def call(url)
14
+ # `youtube-dl -x -o #{destination}/%\\(title\\)s.%\\(ext\\)s --audio-format #{format} -f best #{bookmark.url}`
15
+ `youtube-dl -x -o #{@destination}/%\\(title\\)s.%\\(ext\\)s --audio-format #{@audio_format} -f best --external-downloader aria2c --external-downloader-args '-c -j 3 -x 3 -s 3 -k 1M' #{url}`
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ require 'logger'
2
+
3
+ module YtDownloader
4
+ class Logger
5
+ attr_reader :logger
6
+
7
+ # @param [String] file_path
8
+ # @return [Logger]
9
+ def initialize(file_path)
10
+ @logger = ::Logger.new(file_path, File::APPEND, datetime_format: '%Y-%m-%d %H:%M:%S')
11
+ end
12
+
13
+ # @param [String] message
14
+ def console_log(message)
15
+ puts message
16
+ end
17
+
18
+ # @param [String] message
19
+ def info(message)
20
+ @logger.info(message)
21
+ end
22
+
23
+ # @param [String] message
24
+ def debug(message)
25
+ @logger.debug(message)
26
+ end
27
+
28
+ # @param [String] message
29
+ def warn(message)
30
+ @logger.warn(message)
31
+ end
32
+
33
+ # @param [String] message
34
+ def error(message)
35
+ @logger.error(message)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ module YtDownloader
2
+ class Parser
3
+
4
+ # @param [String] parser
5
+ # @return [Parser]
6
+ def initialize(parser)
7
+ @parser = case parser
8
+ when YtDownloader::Parser::CHROME
9
+ YtDownloader::Parser::Chrome
10
+ else
11
+ raise "Unsupported #{parser} parser!"
12
+ end
13
+ end
14
+
15
+ # @param [Array][String] bookmark_tabs
16
+ # @param [String] source
17
+ def call(bookmark_tabs, source)
18
+ @parser.call(bookmark_tabs, source)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module YtDownloader
2
+ class Parser
3
+ class Base
4
+
5
+ # @param [Array][String] bookmark_tabs
6
+ # @param [String] bookmark_path
7
+ def self.call(bookmark_tabs, bookmark_path)
8
+ raise 'Override this method!'
9
+ end
10
+ end
11
+
12
+ class Bookmark < Struct.new(:url, :name, :tab);
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,75 @@
1
+ require 'yt_downloader/parser/base'
2
+ require 'json'
3
+
4
+ module YtDownloader
5
+ class Parser
6
+
7
+ CHROME = 'chrome'.freeze
8
+
9
+ class Chrome < Base
10
+ MAC_OSX = 'Darwin'.freeze
11
+ LINUX_OS = 'Linux'.freeze
12
+
13
+ # @param [Array][String] bookmark_tabs
14
+ # @param [String] bookmark_path
15
+ def self.call(bookmark_tabs, bookmark_path)
16
+ bookmark_path ||= bookmark_json_path
17
+ bookmark_json = JSON.parse(File.read(bookmark_path), { symbolize_names: true })
18
+ bookmarks = bookmark_json.dig(:roots, :bookmark_bar, :children)
19
+
20
+ extract_urls(bookmarks, bookmark_tabs)
21
+ end
22
+
23
+ private
24
+
25
+ # @param [Array][Hash] bookmarks
26
+ # @param [Array][String] tabs
27
+ def self.extract_urls(bookmarks, tabs)
28
+ bookmarks.inject([]) do |acc, bookmark|
29
+ if tabs.empty?
30
+ acc.concat(aggregate_bookmarks(bookmark))
31
+ else
32
+ tabs.each do |tab|
33
+ acc.concat(aggregate_bookmarks(bookmark)) if bookmark[:name] == tab
34
+ end
35
+ end
36
+
37
+ acc
38
+ end
39
+ end
40
+
41
+ # @return [String]
42
+ def self.bookmark_json_path
43
+ case os
44
+ when LINUX_OS
45
+ "/home/#{whoami}/.config/google-chrome/Default/Bookmarks"
46
+ when MAC_OSX
47
+ "/Users/#{whoami}/Library/Application Support/Google/Chrome/Default/Bookmarks"
48
+ else
49
+ raise "Unsupported #{os} os!"
50
+ end
51
+ end
52
+
53
+ # @param [Hash] bookmark
54
+ # @return [Array][Bookmark]
55
+ def self.aggregate_bookmarks(bookmark)
56
+ return [] if bookmark[:children].nil?
57
+
58
+ bookmark[:children].map { |b| Bookmark.new(*(b.values_at(:url, :name) << bookmark[:name])) }
59
+ end
60
+
61
+ # NOTE: Stub methods for testing
62
+ #
63
+ #
64
+ # @return [String]
65
+ def self.os
66
+ `echo $(uname -s)`.strip
67
+ end
68
+
69
+ # @return [String]
70
+ def self.whoami
71
+ `whoami`.strip
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YtDownloader
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,34 @@
1
+
2
+ # frozen_string_literal: true
3
+
4
+ lib = File.expand_path("../lib", __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require "yt_downloader/version"
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "yt_downloader"
10
+ spec.version = YtDownloader::VERSION
11
+ spec.authors = ["RadicM"]
12
+ spec.email = ["milosrt2011@gmail.com"]
13
+
14
+ spec.summary = "You tube audio downloader"
15
+ spec.description = "Gem that helps you easly download audios from you tube"
16
+ # spec.homepage = "https://lucaguidi.com"
17
+ spec.license = "MIT"
18
+
19
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
20
+
21
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
22
+ f.match(%r{^(test|spec|features)/})
23
+ end
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.add_dependency "hanami-cli"
29
+
30
+ spec.add_development_dependency "bundler"
31
+ spec.add_development_dependency "rake"
32
+ spec.add_development_dependency "rspec"
33
+ spec.add_development_dependency "pry"
34
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yt_downloader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - RadicM
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-06-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hanami-cli
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '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'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Gem that helps you easly download audios from you tube
84
+ email:
85
+ - milosrt2011@gmail.com
86
+ executables:
87
+ - yt_downloader
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - README.md
94
+ - Rakefile
95
+ - exe/yt_downloader
96
+ - lib/yt_downloader.rb
97
+ - lib/yt_downloader/config.rb
98
+ - lib/yt_downloader/converter.rb
99
+ - lib/yt_downloader/downloader.rb
100
+ - lib/yt_downloader/downloader/base.rb
101
+ - lib/yt_downloader/downloader/yt_dl.rb
102
+ - lib/yt_downloader/logger.rb
103
+ - lib/yt_downloader/parser.rb
104
+ - lib/yt_downloader/parser/base.rb
105
+ - lib/yt_downloader/parser/chrome.rb
106
+ - lib/yt_downloader/version.rb
107
+ - yt_downloader.gemspec
108
+ homepage:
109
+ licenses:
110
+ - MIT
111
+ metadata:
112
+ allowed_push_host: https://rubygems.org
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.7.6
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: You tube audio downloader
133
+ test_files: []