fyt 1.0.0.pre
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/bin/fyt +17 -0
- data/lib/fyt/base.rb +15 -0
- data/lib/fyt/builder.rb +64 -0
- data/lib/fyt/config.rb +35 -0
- data/lib/fyt/parser.rb +18 -0
- data/lib/fyt/storage.rb +91 -0
- data/lib/fyt.rb +76 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 887c1039e232c88cea39f0ee81f91b5ad4016d27
|
4
|
+
data.tar.gz: 496085398da2655a31237eeffbe808d722c0500b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5afc811c1e1f7ebfa4b041974c10ad2d888bf2e6b87322425eccc14e9730aa1fad300ea290556b0b9b1da91c6836ec889fdeb067836e4d9a1773817112858000
|
7
|
+
data.tar.gz: e4c809f130ce2b717d1eaa060b42f40798ad2b5f150b08cc6f8968f7da42501622d26732c41588db55994be75e6f36e0549c99ef0459220da20e854f3d7984d3
|
data/bin/fyt
ADDED
data/lib/fyt/base.rb
ADDED
data/lib/fyt/builder.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module FYT
|
3
|
+
# processes the Youtube feed
|
4
|
+
class Builder < FYT::Base
|
5
|
+
def initialize(source_feed, storage, server_prefix)
|
6
|
+
@source_feed = source_feed
|
7
|
+
@storage = storage
|
8
|
+
@server_prefix = server_prefix
|
9
|
+
@maker = RSS::Maker['2.0'].new
|
10
|
+
end
|
11
|
+
|
12
|
+
def build
|
13
|
+
add_channel_data(@source_feed.link.href, @source_feed.title.content)
|
14
|
+
add_image(@source_feed.author.uri.content, @source_feed.title.content)
|
15
|
+
|
16
|
+
build_items
|
17
|
+
|
18
|
+
@maker.to_feed
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_items
|
24
|
+
@source_feed.items.each do |item|
|
25
|
+
filename = @storage.add(item)
|
26
|
+
|
27
|
+
add_item(item.link.href, item.title.content, filename)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_channel_data(link, title)
|
32
|
+
logger.debug "Title: #{title}"
|
33
|
+
|
34
|
+
@maker.channel.updated = Time.now.to_s
|
35
|
+
@maker.channel.link = link
|
36
|
+
@maker.channel.title = title
|
37
|
+
@maker.channel.description = 'Processed Youtube Feed'
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_image(youtube_url, title)
|
41
|
+
youtube_url = youtube_url.gsub('http:', 'https:')
|
42
|
+
|
43
|
+
open(youtube_url) do |file|
|
44
|
+
image_url =
|
45
|
+
file.read.scan(/<meta property=\"og:image\" content=\"(.*)\">/)
|
46
|
+
.flatten.first
|
47
|
+
|
48
|
+
@maker.image.url = image_url
|
49
|
+
@maker.image.title = title
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_item(link, title, filename)
|
54
|
+
@maker.items.new_item do |new_item|
|
55
|
+
new_item.link = link
|
56
|
+
new_item.title = title
|
57
|
+
new_item.updated = @storage.mtime(filename)
|
58
|
+
new_item.enclosure.url = "#{@server_prefix}/#{filename}"
|
59
|
+
new_item.enclosure.type = 'video/mp4'
|
60
|
+
new_item.enclosure.length = @storage.size(filename)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/fyt/config.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'yaml/store'
|
3
|
+
|
4
|
+
module FYT
|
5
|
+
# reads and prepares a youtube feed for further processing
|
6
|
+
class Config < FYT::Base
|
7
|
+
def initialize(path = nil)
|
8
|
+
path ||= File.join(Dir.home, '.fyt.config.yml')
|
9
|
+
@store = YAML::Store.new(path)
|
10
|
+
|
11
|
+
# populate defaults
|
12
|
+
@store.transaction do
|
13
|
+
@store[:storage_path] ||= 'storage'
|
14
|
+
@store[:server_prefix] ||= 'https://localhost:2017'
|
15
|
+
@store[:format_options] ||= '22+140'
|
16
|
+
@store[:output_format] ||= 'mp4'
|
17
|
+
@store[:feeds] ||= []
|
18
|
+
|
19
|
+
@store.commit
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](key)
|
24
|
+
@store.transaction { @store[key] }
|
25
|
+
end
|
26
|
+
|
27
|
+
def []=(key, value)
|
28
|
+
return if value.is_a?(String) && value.size.zero?
|
29
|
+
|
30
|
+
@store.transaction do
|
31
|
+
@store[key] = value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/fyt/parser.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rss'
|
4
|
+
|
5
|
+
module FYT
|
6
|
+
# reads and prepares a youtube feed for further processing
|
7
|
+
class Parser < FYT::Base
|
8
|
+
def initialize(url)
|
9
|
+
@url = url
|
10
|
+
end
|
11
|
+
|
12
|
+
def read
|
13
|
+
open(@url) do |rss|
|
14
|
+
return RSS::Parser.parse(rss, false)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/fyt/storage.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module FYT
|
3
|
+
# Manages file downloads and storage
|
4
|
+
class Storage < FYT::Base
|
5
|
+
def initialize(path, format_options, output_format, proxy = nil)
|
6
|
+
@path = path || ''
|
7
|
+
@format_options = format_options
|
8
|
+
@output_format = output_format
|
9
|
+
@proxy = proxy
|
10
|
+
@known_files = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add(item)
|
14
|
+
url = item.link.href
|
15
|
+
|
16
|
+
path = path_for(item)
|
17
|
+
download_file!(url, path)
|
18
|
+
@known_files << File.basename(path)
|
19
|
+
File.basename(path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_feed(name, feed)
|
23
|
+
logger.debug feed.to_s
|
24
|
+
logger.debug @known_files
|
25
|
+
|
26
|
+
File.join(@path, "#{name}.feed.rss20.xml").tap do |path|
|
27
|
+
File.write(path, feed)
|
28
|
+
|
29
|
+
@known_files << File.basename(path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def cleanup!
|
34
|
+
logger.debug 'Files to delete:'
|
35
|
+
logger.debug files_to_delete
|
36
|
+
|
37
|
+
files_to_delete.each do |filename|
|
38
|
+
delete_file! filename
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def mtime(filename)
|
43
|
+
File.mtime(File.join(@path, filename))
|
44
|
+
end
|
45
|
+
|
46
|
+
def size(filename)
|
47
|
+
File.size(File.join(@path, filename))
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def download_file!(url, output_path)
|
53
|
+
options = [
|
54
|
+
"-f '#{@format_options}'",
|
55
|
+
"--merge-output-format '#{@output_format}'",
|
56
|
+
"-o '#{output_path}'"
|
57
|
+
]
|
58
|
+
options << "--proxy '#{@proxy}'" if @proxy
|
59
|
+
options << "'#{url}'"
|
60
|
+
|
61
|
+
options_string = options.join(' ')
|
62
|
+
|
63
|
+
logger.debug "Executing: youtube-dl #{options_string}"
|
64
|
+
|
65
|
+
raise unless system("youtube-dl #{options_string}", out: $stdout, err: :out)
|
66
|
+
end
|
67
|
+
|
68
|
+
def delete_file!(filename)
|
69
|
+
File.join(@path, filename).tap do |path|
|
70
|
+
logger.debug "Deleting file: #{path}"
|
71
|
+
File.delete(path)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def filename_for(item)
|
76
|
+
"#{item.id.content}.mp4"
|
77
|
+
end
|
78
|
+
|
79
|
+
def path_for(item)
|
80
|
+
File.join(@path, filename_for(item))
|
81
|
+
end
|
82
|
+
|
83
|
+
def files_on_disk
|
84
|
+
Dir.entries(@path).reject { |filename| filename.start_with? '.' }
|
85
|
+
end
|
86
|
+
|
87
|
+
def files_to_delete
|
88
|
+
files_on_disk - @known_files
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/fyt.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'fyt/base'
|
3
|
+
require_relative 'fyt/builder'
|
4
|
+
require_relative 'fyt/config'
|
5
|
+
require_relative 'fyt/parser'
|
6
|
+
require_relative 'fyt/storage'
|
7
|
+
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
# handles the general behaviour of FYT
|
11
|
+
module FYT
|
12
|
+
def self.lock
|
13
|
+
lockfile = '~/.fyt/pid.lock'
|
14
|
+
dirname = File.dirname(lockfile)
|
15
|
+
|
16
|
+
FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
|
17
|
+
|
18
|
+
File.open(lockfile, ::File::CREAT | ::File::EXCL | ::File::WRONLY) do |f|
|
19
|
+
f.write(Process.pid.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
at_exit { File.delete(lockfile) if File.exist?(lockfile) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.run
|
26
|
+
config = FYT::Config.new
|
27
|
+
storage = FYT::Storage.new(
|
28
|
+
config[:storage_path],
|
29
|
+
config[:format_options],
|
30
|
+
config[:output_format],
|
31
|
+
config[:proxy]
|
32
|
+
)
|
33
|
+
|
34
|
+
config[:feeds].each do |feed_config|
|
35
|
+
source_feed = FYT::Parser.new(feed_config[:url]).read
|
36
|
+
|
37
|
+
new_feed = FYT::Builder.new(source_feed, storage, config[:server_prefix]).build
|
38
|
+
|
39
|
+
storage.add_feed(feed_config[:name], new_feed)
|
40
|
+
end
|
41
|
+
|
42
|
+
storage.cleanup!
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.config
|
46
|
+
config = FYT::Config.new
|
47
|
+
|
48
|
+
print "Please enter storage path [#{config[:storage_path]}]: "
|
49
|
+
config[:storage_path] = STDIN.gets.rstrip
|
50
|
+
|
51
|
+
print "Please enter server prefix [#{config[:server_prefix]}]: "
|
52
|
+
config[:server_prefix] = STDIN.gets.rstrip
|
53
|
+
|
54
|
+
print "Please enter format options [#{config[:format_options]}]: "
|
55
|
+
config[:format_options] = STDIN.gets.rstrip
|
56
|
+
|
57
|
+
print "Please enter output_format [#{config[:output_format]}]: "
|
58
|
+
config[:output_format] = STDIN.gets.rstrip
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.add
|
62
|
+
print 'Please name of the feed e.g. "My Favorite Videos": '
|
63
|
+
name = STDIN.gets.rstrip
|
64
|
+
|
65
|
+
print 'Please enter feed url e.g. "https://www.youtube.com/feeds/videos.xml?channel_id=AbCdEf1234567890aBcDeF00": '
|
66
|
+
url = STDIN.gets.rstrip
|
67
|
+
|
68
|
+
raise 'No name given' if name.size.zero?
|
69
|
+
raise 'No feed url given' if url.size.zero?
|
70
|
+
|
71
|
+
config = FYT::Config.new
|
72
|
+
feeds = config[:feeds]
|
73
|
+
feeds << { name: name, url: url }
|
74
|
+
config[:feeds] = feeds
|
75
|
+
end
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fyt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Steffen Schröder
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Downloads a youtube channel and its videos and stores themlocally as
|
14
|
+
a podcatcher-friendly feed
|
15
|
+
email: steffen@schröder.xyz
|
16
|
+
executables:
|
17
|
+
- fyt
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- bin/fyt
|
22
|
+
- lib/fyt.rb
|
23
|
+
- lib/fyt/base.rb
|
24
|
+
- lib/fyt/builder.rb
|
25
|
+
- lib/fyt/config.rb
|
26
|
+
- lib/fyt/parser.rb
|
27
|
+
- lib/fyt/storage.rb
|
28
|
+
homepage: https://github.com/ChaosSteffen/fyt
|
29
|
+
licenses:
|
30
|
+
- BSD-2-Clause
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">"
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.3.1
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 2.6.10
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: fyt
|
52
|
+
test_files: []
|