subfinder 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.circleci/config.yml +55 -0
- data/.gitignore +9 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +62 -0
- data/LICENSE.txt +21 -0
- data/README.md +104 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/subfinder +5 -0
- data/fixtures/vcr_cassettes/download_subtitle.yml +5071 -0
- data/fixtures/vcr_cassettes/integration_test.yml +1537 -0
- data/fixtures/vcr_cassettes/wrong_download_url.yml +112 -0
- data/lib/subfinder.rb +19 -0
- data/lib/subfinder/config.rb +8 -0
- data/lib/subfinder/logger.rb +22 -0
- data/lib/subfinder/main.rb +20 -0
- data/lib/subfinder/parser/args.rb +41 -0
- data/lib/subfinder/parser/download.rb +35 -0
- data/lib/subfinder/parser/files.rb +40 -0
- data/lib/subfinder/parser/subscene.rb +93 -0
- data/lib/subfinder/subtitle.rb +59 -0
- data/lib/subfinder/version.rb +3 -0
- data/movies_list_creator.rb +23 -0
- data/subfinder.gemspec +35 -0
- metadata +215 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://subscene.com/subtitles/english-text/MGNU9jG42CkOL8vcxVwLzwaKhIvuPAE0Bb7OqO62gY8-mFppv1EKkdjJVrTFiRBfXA2sxFE5E8je3FtYz11K6jGRckMYNf6S5LznnuUB5aV_PjsPghQ
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- "*/*"
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- rest-client/2.0.2 (darwin18 x86_64) ruby/2.3.7p456
|
16
|
+
Host:
|
17
|
+
- subscene.com
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Date:
|
24
|
+
- Fri, 25 Jan 2019 13:12:49 GMT
|
25
|
+
Content-Type:
|
26
|
+
- text/html; charset=utf-8
|
27
|
+
Transfer-Encoding:
|
28
|
+
- chunked
|
29
|
+
Connection:
|
30
|
+
- keep-alive
|
31
|
+
Set-Cookie:
|
32
|
+
- __cfduid=d54bf78588c18d70a094eac3fc7e5ce8a1548421969; expires=Sat, 25-Jan-20
|
33
|
+
13:12:49 GMT; path=/; domain=.subscene.com; HttpOnly; Secure
|
34
|
+
Cache-Control:
|
35
|
+
- private
|
36
|
+
Vary:
|
37
|
+
- Accept-Encoding
|
38
|
+
Expect-Ct:
|
39
|
+
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
|
40
|
+
Server:
|
41
|
+
- cloudflare
|
42
|
+
Cf-Ray:
|
43
|
+
- 49eafe5f2f01730d-AMS
|
44
|
+
Content-Encoding:
|
45
|
+
- gzip
|
46
|
+
body:
|
47
|
+
encoding: ASCII-8BIT
|
48
|
+
string: !binary |-
|
49
|
+
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
|
109
|
+
HAAA
|
110
|
+
http_version:
|
111
|
+
recorded_at: Fri, 25 Jan 2019 13:12:50 GMT
|
112
|
+
recorded_with: VCR 4.0.0
|
data/lib/subfinder.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'colorize'
|
3
|
+
require 'logger'
|
4
|
+
require 'optparse'
|
5
|
+
require 'zip'
|
6
|
+
|
7
|
+
require_relative 'subfinder/version'
|
8
|
+
require_relative 'subfinder/subtitle'
|
9
|
+
require_relative 'subfinder/config'
|
10
|
+
require_relative 'subfinder/main'
|
11
|
+
require_relative 'subfinder/logger'
|
12
|
+
|
13
|
+
require_relative 'subfinder/parser/args'
|
14
|
+
require_relative 'subfinder/parser/files'
|
15
|
+
require_relative 'subfinder/parser/subscene'
|
16
|
+
require_relative 'subfinder/parser/download'
|
17
|
+
|
18
|
+
module Subfinder
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Subfinder
|
2
|
+
class Logger < ::Logger
|
3
|
+
class << self
|
4
|
+
def setting
|
5
|
+
logger = Logger.new STDOUT
|
6
|
+
logger.level = Logger::INFO
|
7
|
+
logger.formatter = proc do |_severity, _datetime, _progname, msg|
|
8
|
+
"#{msg}\n"
|
9
|
+
end
|
10
|
+
@logger = logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def info(str)
|
14
|
+
@logger.info(str)
|
15
|
+
end
|
16
|
+
|
17
|
+
def debug(str)
|
18
|
+
@logger.info(str) if Config.debug
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Subfinder
|
2
|
+
class Main
|
3
|
+
class << self
|
4
|
+
def run(args)
|
5
|
+
Subfinder::Logger.setting
|
6
|
+
Logger.info welcome_message
|
7
|
+
Subfinder::Parser::Args.new args
|
8
|
+
Subfinder::Subtitle.new.match
|
9
|
+
end
|
10
|
+
|
11
|
+
def welcome_message
|
12
|
+
'''
|
13
|
+
|
14
|
+
welcome to subfinder Gem!
|
15
|
+
|
16
|
+
'''.green
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Subfinder
|
2
|
+
module Parser
|
3
|
+
class Args
|
4
|
+
def initialize(args)
|
5
|
+
@args = args
|
6
|
+
parse_args
|
7
|
+
validate_required_args
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse_args
|
11
|
+
opts = OptionParser.new
|
12
|
+
opts.banner = usage_msg
|
13
|
+
opts.separator ''
|
14
|
+
opts.separator 'options:'
|
15
|
+
opts.on('-u', '--url url', 'Set subscene url page') { |url| Config.url = url }
|
16
|
+
opts.on('-l', '--language language', 'Set subtitle language') { |language| Config.language = language }
|
17
|
+
opts.on('-v', '--version', 'Show the Compare Crypto version') { puts("compare-crypto #{CompareCrypto::VERSION}"); exit }
|
18
|
+
opts.on('-h', '--help', 'Show this message') { puts(opts); exit }
|
19
|
+
opts.on('-d', '--debug', 'debug') { Config.debug = true }
|
20
|
+
|
21
|
+
opts.parse!(@args)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def validate_required_args
|
27
|
+
Config.language ||= 'en'
|
28
|
+
Config.working_dir = Dir.pwd
|
29
|
+
end
|
30
|
+
|
31
|
+
def usage_msg
|
32
|
+
usage = '
|
33
|
+
Usage:
|
34
|
+
subfinder [options]
|
35
|
+
See https://github.com/sizief/subfinder for more information. Emm, nothing there really, just source code, if you want to improve the code or report a bug visit the page.
|
36
|
+
'
|
37
|
+
usage
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
module Subfinder
|
3
|
+
module Parser
|
4
|
+
class Download
|
5
|
+
def initialize(url)
|
6
|
+
@url = url
|
7
|
+
end
|
8
|
+
|
9
|
+
def save
|
10
|
+
res = RestClient.get @url
|
11
|
+
return false unless response_is_healthy? res
|
12
|
+
|
13
|
+
file_name = res.headers[:content_disposition].split('=')[1]
|
14
|
+
File.write("#{Config.working_dir}/#{file_name}", res.body)
|
15
|
+
Logger.info "Downloaded to #{Config.working_dir}/#{file_name}"
|
16
|
+
true
|
17
|
+
rescue StandardError => e
|
18
|
+
Logger.info "Error when downloading '#{@url}'\n Error message: #{e}\n".red
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def response_is_healthy?(res)
|
23
|
+
if res.code != 200
|
24
|
+
Logger.info "Error when downloading '#{@url}'\n Error message: resposnse code is #{res.code}\n".red
|
25
|
+
false
|
26
|
+
elsif res.body.include? 'An error occurred while processing your request.'
|
27
|
+
Logger.info "Error when downloading '#{@url}'\n Error message: 'An error occurred while processing your request.'\n".red
|
28
|
+
false
|
29
|
+
else
|
30
|
+
true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Subfinder
|
2
|
+
module Parser
|
3
|
+
class Files
|
4
|
+
class << self
|
5
|
+
def list
|
6
|
+
prepare_file_list
|
7
|
+
Dir["#{Config.working_dir}/*"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def prepare_file_list
|
11
|
+
files = Dir["#{Config.working_dir}/*"]
|
12
|
+
compressed_files = files.select { |file| ['.zip', '.rar'].include? File.extname(file) }
|
13
|
+
extract_all compressed_files
|
14
|
+
move_compressed_files compressed_files
|
15
|
+
end
|
16
|
+
|
17
|
+
def extract_all(array_list)
|
18
|
+
array_list.each do |file|
|
19
|
+
Zip::File.open(file) do |zip_file|
|
20
|
+
zip_file.each do |entry|
|
21
|
+
file_path = Config.working_dir + '/' + entry.name
|
22
|
+
unless File.exist? file_path
|
23
|
+
Logger.info "Extracting #{entry.name}"
|
24
|
+
entry.extract(file_path)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def move_compressed_files(compressed_files)
|
32
|
+
unless compressed_files.empty?
|
33
|
+
Dir.mkdir(Config.working_dir + '/compressed') unless File.exist?(Config.working_dir + '/compressed')
|
34
|
+
compressed_files.each { |f| File.rename(f, File.dirname(f) + '/compressed/' + File.basename(f)) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module Subfinder
|
5
|
+
module Parser
|
6
|
+
class Subscene
|
7
|
+
attr_reader :link
|
8
|
+
DOMAIN = 'https://subscene.com'.freeze
|
9
|
+
|
10
|
+
def initialize(file_name)
|
11
|
+
@file_name = file_name
|
12
|
+
end
|
13
|
+
|
14
|
+
def get
|
15
|
+
target_uri = find_link(create_links_list(open_online_document(Config.url)))
|
16
|
+
Subfinder::Parser::Download.new(find_download_link(open_online_document(DOMAIN + target_uri))).save
|
17
|
+
end
|
18
|
+
|
19
|
+
def open_online_document(url)
|
20
|
+
open url
|
21
|
+
rescue StandardError => e
|
22
|
+
Logger.info "Error when connecting to '#{url}'\n Error message: #{e}\n".red
|
23
|
+
abort('Check your internet connection or VPN and try again')
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_download_link(page)
|
27
|
+
doc = Nokogiri::HTML(page)
|
28
|
+
download_link = nil
|
29
|
+
doc.css('.download').each do |link|
|
30
|
+
download_link = link.xpath('./a/@href').to_s.strip # link
|
31
|
+
end
|
32
|
+
Logger.debug "download_link: #{download_link}"
|
33
|
+
DOMAIN + download_link
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_link(links)
|
37
|
+
max_match_point = 0
|
38
|
+
winner = ''
|
39
|
+
|
40
|
+
links.each do |link|
|
41
|
+
next if link[0] != Config.language
|
42
|
+
|
43
|
+
match_point = match_point_for link[1]
|
44
|
+
if match_point > max_match_point
|
45
|
+
max_match_point = match_point
|
46
|
+
winner = link[2]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
Logger.debug "winner is #{winner}"
|
50
|
+
winner
|
51
|
+
end
|
52
|
+
|
53
|
+
def match_point_for(target)
|
54
|
+
point = 0
|
55
|
+
file_name_array = @file_name.split('.')
|
56
|
+
# next we want to know if name of the sub is seprataed by . or space
|
57
|
+
target_array = target.split('.').size > target.split(' ').size ? target.split('.') : target.split(' ')
|
58
|
+
target_array = target_array.map(&:downcase)
|
59
|
+
|
60
|
+
file_name_array.each do |word|
|
61
|
+
point += 1 if target_array.include? word.downcase
|
62
|
+
end
|
63
|
+
(point * 100) / file_name_array.size
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_links_list(page)
|
67
|
+
array = []
|
68
|
+
doc = Nokogiri::HTML(page)
|
69
|
+
doc.xpath('//table//tr').each do |link|
|
70
|
+
next if link.xpath('./td/a/span/text()')[0].nil? # language
|
71
|
+
|
72
|
+
array << [convert_to_code(link.xpath('./td/a/span/text()')[0].to_s.strip), # language
|
73
|
+
link.xpath('./td/a/span/text()')[1].to_s.strip, # name
|
74
|
+
link.xpath('./td/a/@href')[0].to_s.strip] # link
|
75
|
+
end
|
76
|
+
Logger.debug "array_list: #{array}"
|
77
|
+
array
|
78
|
+
end
|
79
|
+
|
80
|
+
def convert_to_code(language)
|
81
|
+
case language
|
82
|
+
when 'Farsi/Persian'
|
83
|
+
'fa'
|
84
|
+
when 'English'
|
85
|
+
'en'
|
86
|
+
else
|
87
|
+
language
|
88
|
+
end
|
89
|
+
# TODO: add other languages codes
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Subfinder
|
2
|
+
class Subtitle
|
3
|
+
def initialize
|
4
|
+
@success = 0
|
5
|
+
@failure = 0
|
6
|
+
end
|
7
|
+
|
8
|
+
def match
|
9
|
+
Subfinder::Parser::Files.list.each do |video_file|
|
10
|
+
next unless Subfinder::Config.video_formats.include? File.extname(video_file)
|
11
|
+
next if subtitle_exists? video_file
|
12
|
+
|
13
|
+
if episode_number(video_file).nil?
|
14
|
+
Logger.info "Can not find the episode and season number for: #{File.basename(video_file)}".red
|
15
|
+
@failure += 1
|
16
|
+
next
|
17
|
+
else
|
18
|
+
find_subtitle_for video_file
|
19
|
+
end
|
20
|
+
end
|
21
|
+
Logger.info "Sub added: #{@success}, Sub not found: #{@failure}, Total file proccessed: #{@failure + @success}".green
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def episode_number(video_file)
|
27
|
+
video_file.scan(/[a-zA-Z]+\d+\d+[a-zA-Z]+\d+\d/).first.downcase
|
28
|
+
end
|
29
|
+
|
30
|
+
def subtitle_exists?(video_file)
|
31
|
+
return true if Subfinder::Parser::Files.list.include? video_file.split('.')[0..-2].join('.') + '.srt'
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_subtitle_for(video_file)
|
35
|
+
subtitles = Subfinder::Parser::Files.list.select { |item| item[/#{episode_number(video_file)}/i] && item[/.srt/] }
|
36
|
+
if subtitles.empty?
|
37
|
+
Logger.info "Subtitle for #{File.basename(video_file)} is not exists on disk "
|
38
|
+
subscene = Subfinder::Parser::Subscene.new(video_file)
|
39
|
+
if !Config.url.nil? && subscene.get
|
40
|
+
Subfinder::Parser::Files.prepare_file_list
|
41
|
+
Logger.info "Subtitle downloaded for #{File.basename(video_file)}"
|
42
|
+
else
|
43
|
+
Logger.info "Subtitle can not found on Subscene for #{File.basename(video_file)}".red
|
44
|
+
Logger.info 'Please provide a url with "-u" siwtch'.red if Config.url.nil?
|
45
|
+
@failure += 1
|
46
|
+
return
|
47
|
+
end
|
48
|
+
end
|
49
|
+
rename_subtitle video_file
|
50
|
+
end
|
51
|
+
|
52
|
+
def rename_subtitle(video_file)
|
53
|
+
subtitles = Subfinder::Parser::Files.list.select { |item| item[/#{episode_number(video_file)}/i] && item[/.srt/] }
|
54
|
+
File.rename(subtitles.first, File.dirname(subtitles.first) + '/' + File.basename(video_file).split('.')[0..-2].join('.') + '.srt')
|
55
|
+
Logger.info "Subtitle renamed for: #{File.basename(video_file)}"
|
56
|
+
@success += 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|