dmanga 0.0.7
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/.gitignore +16 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +172 -0
- data/Rakefile +23 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/dmanga.gemspec +40 -0
- data/exe/dmanga +52 -0
- data/lib/dmanga.rb +5 -0
- data/lib/dmanga/mangahost_parser.rb +95 -0
- data/lib/dmanga/options.rb +44 -0
- data/lib/dmanga/os.rb +8 -0
- data/lib/dmanga/site_parser_base.rb +185 -0
- data/lib/dmanga/util.rb +22 -0
- data/lib/dmanga/version.rb +3 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 956e283f79da7aaed40fd064c5b8e6afa33cbcb7
|
4
|
+
data.tar.gz: b4979c7c6412f405b9072ee1a00d3033c3c96f2f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 11a751afc3d705e8379bbde152eecbbb443b650e8a14fd096ddbb2135437fd2ab943bba5819d2772de3b03b2008197ac66068aa1c3124d822c009611f9eaec2c
|
7
|
+
data.tar.gz: b99c4a60f4003228438db30bc7c7b07f93aebcc06ae68cc6b09b0f48564163685a2c22c1882dfebecf72184481aad1754e2d5b34869c45eba7a5a48ccdbbf6af
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 David Endrew
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
# DManga
|
2
|
+
|
3
|
+
DManga é um script/programa ruby multiplataforma Window/Linux/Mac
|
4
|
+
para baixar mangas de mangahost.net. Com ele voce pode baixar
|
5
|
+
qualquer manga hospedado em mangahost.net (site br de hospedagem de
|
6
|
+
manga) de forma automatizada e sem restrição de quantidade. Basta
|
7
|
+
dizer o nome do manga e selecionar os capitulos que deseja baixar
|
8
|
+
e pronto o script fará os downloads do capitulos selecionados.
|
9
|
+
|
10
|
+
## Instalação
|
11
|
+
|
12
|
+
### Windows
|
13
|
+
Primeiro você precisa ter ruby instalado, você pode baixar ruby
|
14
|
+
deste [site](https://github.com/oneclick/rubyinstaller2/releases),
|
15
|
+
basta baixar um dos instaladores que estão abaixo do titulo 'Downloads',
|
16
|
+
algo com o nome similar a rubyinstaller-2.4.1-1rc3-x86.exe (pode ser uma
|
17
|
+
versão superior) para arquitetura 32 bits e rubyinstaller-2.4.1-1rc3-x64.exe para 64.
|
18
|
+
|
19
|
+
Com o ruby instalado. Abra o prompt de comando.
|
20
|
+
|
21
|
+
No prompt digite:
|
22
|
+
|
23
|
+
`gem install dmanga`
|
24
|
+
|
25
|
+
Digite Enter para executar o comando.
|
26
|
+
|
27
|
+
Com isso o script/programa será instalado.
|
28
|
+
|
29
|
+
### Linux (debian/ubuntu)
|
30
|
+
Abra o terminal.
|
31
|
+
|
32
|
+
Se voce não tem o ruby instalado:
|
33
|
+
|
34
|
+
`$ sudo apt-get install ruby`
|
35
|
+
|
36
|
+
Em seguida:
|
37
|
+
|
38
|
+
`$ gem install dmanga`
|
39
|
+
|
40
|
+
Obs: Eu não cheguei a testar em versões do ruby abaixo do 2.4.1,
|
41
|
+
em caso de problema procure na internet como instalar a versão do
|
42
|
+
ruby 2.4.1 ou superior.
|
43
|
+
|
44
|
+
## Uso
|
45
|
+
|
46
|
+
`dmanga [opões] <nome do manga>`
|
47
|
+
|
48
|
+
obs: o script/programa é executado no prompt.
|
49
|
+
|
50
|
+
Ex1:
|
51
|
+
|
52
|
+
`dmanga "one piece"`
|
53
|
+
|
54
|
+
Ex2:
|
55
|
+
|
56
|
+
`dmanga tomo-chan`
|
57
|
+
|
58
|
+
obs: A pasta padrão de destino dos downloads é a pasta Downloads mas
|
59
|
+
você pode dizer ao script a pasta de destino do downloads com a
|
60
|
+
opçao -d, veja [Opções](#opções) para mais detalhes.
|
61
|
+
|
62
|
+
obs: o nome do manga não precisa ser o nome exato, pode ser parte do
|
63
|
+
nome ou alguma palavra contida no nome, em todo caso o script/programa
|
64
|
+
fará uma busca no site com o nome passado.
|
65
|
+
|
66
|
+
obs: você pode cancelar a execução do script/program a qualquer hora
|
67
|
+
clicando ctrl-c no prompt.
|
68
|
+
|
69
|
+
**obs: se o nome do manga contiver mais de uma palavra coloque-o
|
70
|
+
entre aspas**.
|
71
|
+
|
72
|
+
O scrip/program mostará os mangas encontrados na busca no site
|
73
|
+
um de cada vez, selecione o que corresponde a sua busca.
|
74
|
+
|
75
|
+
Após será mostrada a lista de capitulos encontrados para aquele manga.
|
76
|
+
|
77
|
+
Quando ele perguntar "Quais capitulos você que baixar?", digite
|
78
|
+
uma das sequintes opções:
|
79
|
+
|
80
|
+
1. Para baixar todos so capitulos:
|
81
|
+
|
82
|
+
`todos`
|
83
|
+
|
84
|
+
Baixa todos os capitulos disponiveis.
|
85
|
+
|
86
|
+
2. Para selecionar um intervalo digite:
|
87
|
+
|
88
|
+
`inicio-fim`
|
89
|
+
|
90
|
+
Ex1:
|
91
|
+
|
92
|
+
`10-222`
|
93
|
+
|
94
|
+
Baixa do capitulo 10 ao 222.
|
95
|
+
|
96
|
+
Ex2:
|
97
|
+
|
98
|
+
`1-1l`
|
99
|
+
|
100
|
+
Baixa do capitulo 1 ao 11.
|
101
|
+
|
102
|
+
Se voce quiser baixar de um certo capitulo ao ultimo, basta digitar
|
103
|
+
no limite superior do intervalo um numero maior que o numero do
|
104
|
+
ultimo capitulo (ex: 999999).
|
105
|
+
|
106
|
+
3. Para selecionar capitulos especificos:
|
107
|
+
|
108
|
+
`numeroDoCapitulo,numeroDoCapitulo,numeroDoCapitulo`
|
109
|
+
|
110
|
+
Ex:
|
111
|
+
|
112
|
+
`2,5,130`
|
113
|
+
|
114
|
+
Baixa os capitulos 2, 5 e 130.
|
115
|
+
|
116
|
+
Obs: os numeros dos capitulos devem ser digitados separados por
|
117
|
+
virgula e **sem espaços**.
|
118
|
+
|
119
|
+
### Opções
|
120
|
+
|
121
|
+
`--version`
|
122
|
+
|
123
|
+
Mostra o numero da versao do programa e sai.
|
124
|
+
|
125
|
+
`-d <pasta de download>, --directory <pasta de download>`
|
126
|
+
|
127
|
+
A pasta de destino do downlaod.
|
128
|
+
|
129
|
+
`-h , --help`
|
130
|
+
|
131
|
+
Mostra a messagem de ajuda e sai.
|
132
|
+
|
133
|
+
`-v , --verbose`
|
134
|
+
|
135
|
+
Mostra detalhes da execução do programa.
|
136
|
+
|
137
|
+
### Exemplos
|
138
|
+
|
139
|
+
`dmanga -d "c:\window\users\images\manga e animes" "One piece"`
|
140
|
+
|
141
|
+
No windows, baixe 'One piece' para
|
142
|
+
'c:\window\users\images\manga e animes'
|
143
|
+
|
144
|
+
`dmanga "One punch man"`
|
145
|
+
|
146
|
+
Baixe 'One punch man' para 'Downloads'.
|
147
|
+
|
148
|
+
`dmanga -d /home/usuario/Images/mangas tomo-chan`
|
149
|
+
|
150
|
+
No linux baixe 'tomo-chan' para '/home/usuario/Images/mangas'.
|
151
|
+
|
152
|
+
### Exemplos de seleção de capitulos
|
153
|
+
|
154
|
+
`todos`
|
155
|
+
|
156
|
+
Baixa todos os capitulos.
|
157
|
+
|
158
|
+
`34-96`
|
159
|
+
|
160
|
+
Baixa do capitulos do 34 ao 96.
|
161
|
+
|
162
|
+
`1,3,55`
|
163
|
+
|
164
|
+
Baixa do capitulos 1, 2 e 55.
|
165
|
+
|
166
|
+
`34,124`
|
167
|
+
|
168
|
+
Baixa do capitulos 34 e 124.
|
169
|
+
|
170
|
+
## License
|
171
|
+
|
172
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
require_relative "lib/dmanga/version"
|
4
|
+
|
5
|
+
Rake::TestTask.new(:test) do |t|
|
6
|
+
t.libs << "test"
|
7
|
+
t.libs << "lib"
|
8
|
+
t.test_files = FileList['test/**/*_test.rb']
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => :test
|
12
|
+
|
13
|
+
desc "change to second branch"
|
14
|
+
task :second do system "git checkout second" end
|
15
|
+
|
16
|
+
desc "change to master branch"
|
17
|
+
task :master do system "git checkout master" end
|
18
|
+
|
19
|
+
desc "exec the app"
|
20
|
+
task :exe do system "ruby -Ilib exe/dmanga denki ga honya" end
|
21
|
+
|
22
|
+
desc "console with app loaded"
|
23
|
+
task :console do system "bundle exec bin/console" end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "dmanga"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
require "pry"
|
11
|
+
Pry.start
|
12
|
+
|
13
|
+
# require "irb"
|
14
|
+
# IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/dmanga.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dmanga/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "dmanga"
|
8
|
+
spec.version = DManga::VERSION
|
9
|
+
spec.authors = ["David Endrew"]
|
10
|
+
spec.email = ["david.edews@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Download any manga from mangahost.net"
|
13
|
+
spec.description = "Download any manga from mangahost.net with the option to search" +
|
14
|
+
" and select any chapters or range of chapters"
|
15
|
+
spec.homepage = "https://github.com/david-endrew/DManga"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
19
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
20
|
+
#if spec.respond_to?(:metadata)
|
21
|
+
#spec.metadata['allowed_push_host'] = "http://mygemserver.com'"
|
22
|
+
#else
|
23
|
+
#raise "RubyGems 2.0 or newer is required to protect against " \
|
24
|
+
#"public gem pushes."
|
25
|
+
#end
|
26
|
+
|
27
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
28
|
+
f.match(%r{^(test|spec|features)/})
|
29
|
+
end
|
30
|
+
spec.bindir = "exe"
|
31
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ["lib"]
|
33
|
+
|
34
|
+
spec.add_runtime_dependency "ruby-progressbar","~> 1.8"
|
35
|
+
spec.add_runtime_dependency "formatador", "~> 0.2"
|
36
|
+
spec.add_development_dependency "minitest","~> 5.10"
|
37
|
+
spec.add_development_dependency "webmock", "~> 3.0"
|
38
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
39
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
40
|
+
end
|
data/exe/dmanga
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
require 'net/http'
|
5
|
+
require 'dmanga/util'
|
6
|
+
require 'dmanga/mangahost_parser'
|
7
|
+
|
8
|
+
#main #############
|
9
|
+
begin
|
10
|
+
|
11
|
+
mangahost = DManga::MangaHostParser.new(ARGV)
|
12
|
+
mangahost.download
|
13
|
+
DManga::print_feedback "\nTodos os download concluidos"
|
14
|
+
|
15
|
+
rescue URI::InvalidURIError => uri_error
|
16
|
+
DManga::display_error("Nome do manga não deve conter acentos, cecedilha ou simbolos",
|
17
|
+
uri_error)
|
18
|
+
|
19
|
+
rescue Errno::ECONNRESET => con_error
|
20
|
+
DManga::display_error("Não foi possivel conectar a internet",
|
21
|
+
con_error)
|
22
|
+
|
23
|
+
rescue OpenURI::HTTPError => http_error
|
24
|
+
DManga::display_error("Servidor recusando conexao",
|
25
|
+
http_error)
|
26
|
+
|
27
|
+
rescue DManga::MangaNotFoundError => manga_error
|
28
|
+
DManga::display_warn "\t#{manga_error}"
|
29
|
+
DManga::display_feedback "\tExiting"
|
30
|
+
|
31
|
+
rescue Net::ReadTimeout => timeout_error
|
32
|
+
DManga::display_error("Site demorou demais para responder",
|
33
|
+
timeout_error)
|
34
|
+
|
35
|
+
rescue Net::OpenTimeout => timeout_error
|
36
|
+
DManga::display_error("Site demorou demais para responder",
|
37
|
+
timeout_error)
|
38
|
+
|
39
|
+
rescue SocketError => sock_error
|
40
|
+
DManga::display_error("Nao foi possivel conectar a internet",
|
41
|
+
sock_error)
|
42
|
+
|
43
|
+
rescue OpenSSL::SSL::SSLError => ssl_error
|
44
|
+
DManga::display_error("Não foi possivel conectar a internet",
|
45
|
+
ssl_error)
|
46
|
+
|
47
|
+
rescue Errno::ENETUNREACH => error
|
48
|
+
DManga::display_error("Não foi possivel conectar a internet",
|
49
|
+
error)
|
50
|
+
rescue Interrupt
|
51
|
+
DManga::display_feedback("\nBye")
|
52
|
+
end
|
data/lib/dmanga.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# require 'dmanga/site_parser_base'
|
2
|
+
require 'dmanga/site_parser_base'
|
3
|
+
module DManga
|
4
|
+
class MangaHostParser < SiteParserBase
|
5
|
+
|
6
|
+
# url used to search in the site
|
7
|
+
SEARCH_URL = "https://mangahost.net/find/"
|
8
|
+
|
9
|
+
# regex to extract url of found mangas
|
10
|
+
SEARCH_LINK_REGEX = /entry-title">\s*<a\s*href="(.*)?"\s*title="(.*)"/
|
11
|
+
|
12
|
+
# Regex to extract chapters' url from manga page.
|
13
|
+
# Manga host has two diferent manga pages.
|
14
|
+
# One to medium/short mangas and one to big mangas
|
15
|
+
# /capitulo['"]\stitle=['"]Ler Online\s+-\s+(.*?)['"]\s+href=['"](.*?)['"]/, # for short/medium mangas
|
16
|
+
CHAPTER_LINK_REGEX = [
|
17
|
+
/capitulo.*?Ler\s+Online\s+-\s+(.*?)['"]\s+href=['"](.*?)['"]/, # for short/medium mangas
|
18
|
+
/<a\s+href=['"](.*?)['"]\s+title=['"]Ler\s+Online\s+-\s+(.*?)\s+\[\]/ # for big mangas
|
19
|
+
]
|
20
|
+
|
21
|
+
# regex to extract images' url from chapter page
|
22
|
+
IMG_LINK_REGEX = [/img_\d+['"]\s+src=['"](.*?)['"]/,
|
23
|
+
/url['"]:['"](.*?)['"]\}/]
|
24
|
+
|
25
|
+
def download
|
26
|
+
|
27
|
+
# white space is not allowed in the search url.
|
28
|
+
guess_manga_name = @options.manga.gsub(/\s/, '+') # Replace ' ' by '+'
|
29
|
+
|
30
|
+
search("#{SEARCH_URL}#{guess_manga_name}", SEARCH_LINK_REGEX)
|
31
|
+
|
32
|
+
# puts "executing chapters".green ## DEBUG
|
33
|
+
# Due the organazation of the chapters page the chapters are
|
34
|
+
# extracted in reverse order
|
35
|
+
@chapters = parse(@manga_url, CHAPTER_LINK_REGEX[0]) do |resul, page|
|
36
|
+
|
37
|
+
# use long mangas regex if short mangas regex
|
38
|
+
# returns empty array
|
39
|
+
if resul.empty?
|
40
|
+
# Extract chapters name and url and
|
41
|
+
# swap chapter[0](name) with chapter[1](url)
|
42
|
+
# to conform with result from CHAPTER_LINK_REGEX[0]
|
43
|
+
page.scan(CHAPTER_LINK_REGEX[1]) {|chapter| resul << chapter.rotate}
|
44
|
+
end
|
45
|
+
resul
|
46
|
+
end
|
47
|
+
|
48
|
+
# correct utf-8 errors
|
49
|
+
correct_chapters_name
|
50
|
+
|
51
|
+
# prompt user to select chapters to download
|
52
|
+
select_chapters
|
53
|
+
|
54
|
+
# create manga directory
|
55
|
+
create_dir(@manga_name)
|
56
|
+
|
57
|
+
# download selected chapters
|
58
|
+
@chapters.reverse_each do |chapter|
|
59
|
+
imgs_url = parse(chapter[1], IMG_LINK_REGEX[0]) do |resul, page|
|
60
|
+
# use second pattern if the first returns a empty
|
61
|
+
# array
|
62
|
+
# binding.pry # DEBUG
|
63
|
+
if resul.empty?
|
64
|
+
page.scan(IMG_LINK_REGEX[1]) do |img|
|
65
|
+
resul << img[0].gsub!(%r{\\}, "")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
resul.each do |img|
|
70
|
+
# some images urls are incorrect and need to be corrected. For exemple:
|
71
|
+
# img.mangahost.net/br/images/img.png.webp => img.mangahost.net/br/mangas_files/img.png
|
72
|
+
img.sub!(/images/, "mangas_files")
|
73
|
+
img.sub!(/\.webp/, "")
|
74
|
+
end
|
75
|
+
resul
|
76
|
+
end
|
77
|
+
|
78
|
+
# create chapter directory relative to manga directory
|
79
|
+
chapter_name = "#{chapter[0]}"
|
80
|
+
chapter_dir = "#{@manga_name}/#{chapter_name}"
|
81
|
+
create_dir(chapter_dir)
|
82
|
+
|
83
|
+
DManga::display_feedback "\nBaixando #{chapter_name}"
|
84
|
+
imgs_donwload(chapter_dir, imgs_url)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
# Due to problems with open-uri and utf-8
|
90
|
+
# some chapters name need to be corrected
|
91
|
+
def correct_chapters_name
|
92
|
+
@chapters.each {|chapter| chapter[0].sub!(/[cC]ap.*?tulo/, "capitulo")}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'dmanga/version'
|
3
|
+
module DManga
|
4
|
+
class Options
|
5
|
+
DEFAULT_DOWNLOAD_DIR = "#{ENV['HOME']}/Downloads"
|
6
|
+
attr_reader :download_dir, :verbose, :site, :manga
|
7
|
+
def initialize(argv)
|
8
|
+
@download_dir = DEFAULT_DOWNLOAD_DIR
|
9
|
+
@verbose = false
|
10
|
+
@site = "mangahost.net"
|
11
|
+
parse(argv)
|
12
|
+
@manga = argv[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse(argv)
|
16
|
+
OptionParser.new do |opts|
|
17
|
+
opts.banner = "Uso: dmanga [opção] <nome do manga>"
|
18
|
+
opts.separator ""
|
19
|
+
opts.separator "Opções:"
|
20
|
+
|
21
|
+
opts.on('--version', 'Exibe o numero de versão do programa.') do
|
22
|
+
puts "version #{DManga::VERSION}"
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on('-v', '--verbose',
|
27
|
+
'Exibe informações da execução do programa.') do
|
28
|
+
@verbose = true
|
29
|
+
end
|
30
|
+
opts.on('-d', '--directory DIRETORIO',
|
31
|
+
'O diretorio de destino do download. Padrão é Downloads.') do |path|
|
32
|
+
@download_dir = path
|
33
|
+
end
|
34
|
+
opts.on('-h', '--help', 'Exibe esta tela.') do
|
35
|
+
puts opts
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
|
39
|
+
argv = ['-h'] if argv.empty?
|
40
|
+
opts.parse!(argv)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/dmanga/os.rb
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'dmanga/options'
|
2
|
+
require 'dmanga/os'
|
3
|
+
require 'ruby-progressbar'
|
4
|
+
require 'open-uri'
|
5
|
+
# require 'pry'
|
6
|
+
# require 'formatador'
|
7
|
+
|
8
|
+
module DManga
|
9
|
+
class SiteParserBase
|
10
|
+
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
|
11
|
+
|
12
|
+
attr_accessor :manga_name, :manga_url, :download_path,
|
13
|
+
:chapters, :verbose
|
14
|
+
|
15
|
+
def initialize(argv)
|
16
|
+
@options = Options.new(argv)
|
17
|
+
@manga_url = nil
|
18
|
+
@manga_name = nil
|
19
|
+
@chapters = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# Parse the html and colect the links that match the pattern.
|
23
|
+
# Can receive a block.
|
24
|
+
def parse(url, regex)
|
25
|
+
DManga::display_feedback "\nbuscando #{url}" if @options.verbose
|
26
|
+
result = []
|
27
|
+
open(url, "User-Agent" => USER_AGENT) do |response|
|
28
|
+
if response.status[1] == "OK"
|
29
|
+
DManga::display_feedback "parsing #{url}" if @options.verbose
|
30
|
+
page = response.read
|
31
|
+
page.scan(regex) do |r| # => try first regex
|
32
|
+
if r.length < 2
|
33
|
+
result << r[0]
|
34
|
+
else
|
35
|
+
result << r
|
36
|
+
end
|
37
|
+
end
|
38
|
+
# binding.pry # DEBUG
|
39
|
+
result = yield(result, page) if block_given?
|
40
|
+
else
|
41
|
+
DManga::display_error("ERRO: Servidor respondeu: #{response.status.inpect}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
def search(url, regex)
|
48
|
+
DManga::display_feedback "Iniciando busca em #{@options.site}"
|
49
|
+
search_result = parse(url, regex)
|
50
|
+
select_manga(search_result)
|
51
|
+
end
|
52
|
+
|
53
|
+
def select_manga(mangas)
|
54
|
+
puts # just a new line for better output
|
55
|
+
unless mangas.empty?
|
56
|
+
mangas.each do |manga|
|
57
|
+
DManga::display_prompt("Você quer baixar #{manga[1]} [s/n]? ")
|
58
|
+
res = $stdin.gets.chomp
|
59
|
+
if res == 's'
|
60
|
+
@manga_url = manga[0]
|
61
|
+
@manga_name = manga[1]
|
62
|
+
break
|
63
|
+
elsif res != 'n'
|
64
|
+
DManga::display_warn("\tOpção invalida")
|
65
|
+
DManga::display_feedback("\tSaindo")
|
66
|
+
exit(true)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
raise MangaNotFoundError, "manga não encontrado"
|
71
|
+
end
|
72
|
+
raise MangaNotFoundError, "manga não encontrado" if @manga_url.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
def select_chapters
|
76
|
+
DManga::display_feedback "\nCapítulos:"
|
77
|
+
@chapters.reverse_each.with_index do |chapter, index|
|
78
|
+
DManga::display_feedback "(#{index + 1})\t#{chapter[0]}"
|
79
|
+
end
|
80
|
+
answer = nil
|
81
|
+
DManga::display_feedback "\n#{@chapters.length} capitulos encontrados"
|
82
|
+
loop do
|
83
|
+
DManga::display_prompt("\nQuais capitulos você quer baixar [o-opções]? ")
|
84
|
+
answer = $stdin.gets.chomp
|
85
|
+
if answer == "o" || answer.empty?
|
86
|
+
DManga::display_prompt("\ttodos \t\t\t\t- baixar todos os capítulos")
|
87
|
+
DManga::display_prompt("\n\to \t\t\t\t- exibe opções")
|
88
|
+
DManga::display_prompt("\n\tinicio-fim \t\t\t- baixar intervalo selecionado")
|
89
|
+
DManga::display_prompt("\n\t\t\t\t\tEx: 0-10 - baixa do 0 ao 10")
|
90
|
+
DManga::display_prompt("\n\tcapitulo,capitulo,capitulo \t- baixar capitulos selecionados")
|
91
|
+
DManga::display_prompt("\n\t\t\t\t\tEx: 29,499,1 - ")
|
92
|
+
DManga::display_prompt("baixa capitulos 29, 499 e 1")
|
93
|
+
elsif answer == "todos"
|
94
|
+
DManga::display_feedback "Baixando todos os capítulos" if @options.verbose
|
95
|
+
break
|
96
|
+
elsif answer =~ /(\d+)-(\d+)/
|
97
|
+
b = Integer($2) <= @chapters.length ? Integer($2) * -1 : @chapters.length * -1
|
98
|
+
e = Integer($1) * -1
|
99
|
+
@chapters = @chapters[b..e]
|
100
|
+
DManga::display_feedback "Baixando capítulos do #{$1} ao #{$2}" if @options.verbose
|
101
|
+
break
|
102
|
+
elsif answer =~ /^(\d+,?)+$/
|
103
|
+
answer = answer.split(',')
|
104
|
+
aux = []
|
105
|
+
# downloads are processed in reverse order (to make
|
106
|
+
# it in crescent order)so the answer is reversed too
|
107
|
+
answer.reverse_each do |c|
|
108
|
+
chp = @chapters[Integer(c) * -1]
|
109
|
+
aux << chp unless chp.nil?
|
110
|
+
end
|
111
|
+
@chapters = aux
|
112
|
+
DManga::display_feedback "Baixando capítulos #{answer.to_s}" if @options.verbose
|
113
|
+
break
|
114
|
+
else
|
115
|
+
DManga::display_warn("\tOpção invalida")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def imgs_donwload(chp_path, imgs_urls)
|
121
|
+
imgs_urls.each do |url|
|
122
|
+
original_filename = url.slice(/(\w|[_-])+\.(png|jpg)/)
|
123
|
+
img_path = "#{@options.download_dir}/#{chp_path}/#{original_filename}"
|
124
|
+
unless File.exist? img_path
|
125
|
+
DManga::display_feedback "\n#{url}"
|
126
|
+
pbar = nil
|
127
|
+
open(url,
|
128
|
+
:content_length_proc => lambda {|size|
|
129
|
+
if size.nil?
|
130
|
+
if DManga::OS.windows?
|
131
|
+
pbar = ProgressBar.create(:title => 'Baixando',
|
132
|
+
:starting_at => 20,
|
133
|
+
:length => 70,
|
134
|
+
:total => nil)
|
135
|
+
else
|
136
|
+
pbar = ProgressBar.create(:title => 'Baixando',
|
137
|
+
:starting_at => 20,
|
138
|
+
:total => nil)
|
139
|
+
end
|
140
|
+
else
|
141
|
+
if DManga::OS.windows?
|
142
|
+
pbar = ProgressBar.create(:total => size / Integer(16384),
|
143
|
+
:format => '%a %B %p%% %r KB/sec',
|
144
|
+
:rate_scale => lambda { |rate|
|
145
|
+
rate / 1024 },
|
146
|
+
length: 70
|
147
|
+
)
|
148
|
+
else
|
149
|
+
pbar = ProgressBar.create(:total => size / Integer(16384),
|
150
|
+
:format => '%a %B %p%% %r KB/sec',
|
151
|
+
:rate_scale => lambda { |rate|
|
152
|
+
rate / 1024 }
|
153
|
+
)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
},
|
157
|
+
:progress_proc => lambda {|s|
|
158
|
+
pbar.increment
|
159
|
+
}) do |response|
|
160
|
+
if response.status[1] == "OK"
|
161
|
+
DManga::display_feedback "Salvando imagem em:'#{img_path}'" if @options.verbose
|
162
|
+
File.open(img_path, "wb") do |img|
|
163
|
+
img.puts response.read
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
puts
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# check if the directory exists and
|
173
|
+
# create a directory relative to download dir
|
174
|
+
def create_dir(name)
|
175
|
+
dir_path = "#{@options.download_dir}/#{name}"
|
176
|
+
DManga::display_feedback "\nCriando diretorio '#{name}' em '#{dir_path}'" if @options.verbose
|
177
|
+
unless Dir.exist? dir_path
|
178
|
+
Dir.mkdir(dir_path)
|
179
|
+
puts if @options.verbose ## just a blank line for prettier output
|
180
|
+
else
|
181
|
+
DManga::display_feedback "'#{name}' directorio ja existe" if @options.verbose
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/lib/dmanga/util.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'formatador'
|
2
|
+
module DManga
|
3
|
+
class MangaNotFoundError < RuntimeError
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.display_error(message, error)
|
7
|
+
Formatador.display_line("\t[_red_][white][bold]ERRO: #{message}.[/]")
|
8
|
+
Formatador.display_line("\t[_red_][white][bold]ERROR: #{error.message}.[/]")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.display_feedback(str)
|
12
|
+
Formatador.display_line("[magenta][bold]#{str}[/]")
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.display_prompt(str)
|
16
|
+
Formatador.display("[white][bold]#{str}[/]")
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.display_warn(str)
|
20
|
+
Formatador.display_line("[red][bold]#{str}[/]")
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dmanga
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Endrew
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-05-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ruby-progressbar
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: formatador
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: webmock
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '12.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '12.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.14'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.14'
|
97
|
+
description: Download any manga from mangahost.net with the option to search and select
|
98
|
+
any chapters or range of chapters
|
99
|
+
email:
|
100
|
+
- david.edews@gmail.com
|
101
|
+
executables:
|
102
|
+
- dmanga
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- ".gitignore"
|
107
|
+
- ".travis.yml"
|
108
|
+
- Gemfile
|
109
|
+
- LICENSE.txt
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- bin/console
|
113
|
+
- bin/setup
|
114
|
+
- dmanga.gemspec
|
115
|
+
- exe/dmanga
|
116
|
+
- lib/dmanga.rb
|
117
|
+
- lib/dmanga/mangahost_parser.rb
|
118
|
+
- lib/dmanga/options.rb
|
119
|
+
- lib/dmanga/os.rb
|
120
|
+
- lib/dmanga/site_parser_base.rb
|
121
|
+
- lib/dmanga/util.rb
|
122
|
+
- lib/dmanga/version.rb
|
123
|
+
homepage: https://github.com/david-endrew/DManga
|
124
|
+
licenses:
|
125
|
+
- MIT
|
126
|
+
metadata: {}
|
127
|
+
post_install_message:
|
128
|
+
rdoc_options: []
|
129
|
+
require_paths:
|
130
|
+
- lib
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
requirements: []
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 2.6.11
|
144
|
+
signing_key:
|
145
|
+
specification_version: 4
|
146
|
+
summary: Download any manga from mangahost.net
|
147
|
+
test_files: []
|