mangdown 0.12.2 → 0.13.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: a0ea88db18ac42922a837cb3ed76307d35af9bea
4
- data.tar.gz: c9594ac2a9dba91e307bda03ea3f3630a265591f
3
+ metadata.gz: 0d85a1d5f0bf974970fcc26e817583bfcf16226b
4
+ data.tar.gz: 9b8108fd038b01dd78eda987753c38a4e21c0f94
5
5
  SHA512:
6
- metadata.gz: c4d252007f729afbff7a8d6da1257feec608da2db20fdc7940cfa2f6f875b2e4766f83022dd2845b7a8925be09ae0c043e5ba74cad4edaf369e9392e65363531
7
- data.tar.gz: 528ec01731d20658013268171ea7c168235f0f8572a5fb3948e1c5bc52648a3151b4b8ba2a72feefd4909dde55b3dec2574fb8a8e707b00762b24936dc0e5491
6
+ metadata.gz: c61a0df176b08ed90f5f4a56a8215aa027af64a2f3ed89a7ae722c5cf8d7b32e005b2d8c4851b7ba23abfae80506651e8459b8ee2b66d4c761572cafc6406034
7
+ data.tar.gz: 638112e648008bde76e405c5309b19223cde0a9d684ee4827cfd0901b4170ca723edabab0374884799ef937f4b2e429144a30b7dcc4728f4a78ce999a0100608
@@ -4,7 +4,11 @@ require 'yaml'
4
4
  require 'zip'
5
5
  require 'filemagic'
6
6
 
7
- require_relative 'mangdown/mangdown'
7
+ module Mangdown
8
+ ADAPTERS = []
9
+
10
+ DOWNLOAD_DIR ||= Dir.home + '/manga'
11
+ end
8
12
 
9
13
  require_relative 'mangdown/adapter'
10
14
  adapters = "#{File.expand_path('../mangdown/adapter', __FILE__)}/*.rb"
@@ -12,18 +16,16 @@ Dir[adapters].each do |f|
12
16
  require_relative f
13
17
  end
14
18
 
19
+ require_relative 'mangdown/equality'
15
20
  require_relative 'mangdown/tools'
16
21
  require_relative 'mangdown/properties'
17
22
  require_relative 'mangdown/uri'
18
23
  require_relative 'mangdown/page'
19
24
  require_relative 'mangdown/chapter'
20
25
  require_relative 'mangdown/manga'
21
- require_relative 'mangdown/popular'
22
26
  require_relative 'mangdown/manga_list.rb'
23
27
  require_relative 'mangdown/cbz'
24
28
  require_relative 'mangdown/commands'
25
29
  require_relative 'mangdown/mangdown_hash'
26
30
 
27
- if $0 == __FILE__
28
- puts '*** Use "M.help" for commands ***'
29
- end
31
+
@@ -3,22 +3,43 @@ module Mangdown
3
3
  class Base
4
4
 
5
5
  attr_reader :root
6
- def initialize(uri, doc)
7
- @uri, @doc = uri, doc
8
- #@root = ''
9
- #@manga_list_css = ''
10
- #@chapter_list_css = ''
11
- #@manga_name_css = ''
12
- #@manga_list_uri = ''
13
- #@manga_link_prefix = ''
14
- #@reverse_chapters = true || false
15
- #@manga_uri_regex = /.*/i
16
- #@chapter_uri_regex = /.*/i
17
- #@page_uri_regex = /.*/i
6
+ def initialize(uri, doc, name)
7
+ @uri, @doc, @name = uri, doc, name
8
+ #@root = ''
9
+ #@manga_list_css = ''
10
+ #@chapter_list_css = ''
11
+ #@manga_name_css = ''
12
+ #@chapter_name_css = ''
13
+ #@chapter_manga_name_css = ''
14
+ #@chapter_number_css = ''
15
+ #@manga_list_uri = ''
16
+ #@manga_link_prefix = ''
17
+ #@reverse_chapters = true || false
18
+ #@manga_uri_regex = /.*/i
19
+ #@chapter_uri_regex = /.*/i
20
+ #@page_uri_regex = /.*/i
21
+ end
22
+
23
+ def self.type
24
+ name.split('::').last.downcase.to_sym
18
25
  end
19
26
 
20
27
  def type
21
- self.class.to_s.split('::').last.downcase.to_sym
28
+ self.class.type
29
+ end
30
+
31
+ # Override this if you want to use an adapter name for a site that is
32
+ # not matched in the site's url
33
+ # e.g. CoolAdapterName < Adapter::Base
34
+ # def site
35
+ # "mangareader"
36
+ # end
37
+ def self.site
38
+ type.to_s
39
+ end
40
+
41
+ def site
42
+ self.class.site
22
43
  end
23
44
 
24
45
  # Must return true/false if uri represents a manga for adapter
@@ -38,7 +59,36 @@ module Mangdown
38
59
 
39
60
  # Must return a string
40
61
  def manga_name
41
- doc.css(@manga_name_css).text
62
+ if is_manga?
63
+ doc.css(@manga_name_css).text
64
+ elsif is_chapter?
65
+ chapter_manga_name
66
+ end
67
+ end
68
+
69
+ def chapter_name
70
+ if @name
71
+ @name.sub(/\s(\d+)$/) { |num| ' ' + num.to_i.to_s.rjust(5, '0') }
72
+ else
73
+ doc.css(@chapter_name_css).text
74
+ end
75
+ end
76
+
77
+ def chapter_manga_name
78
+ if @name
79
+ @name.slice(/(^.+)\s/, 1)
80
+ else
81
+ doc.css(@chapter_manga_name_css).text
82
+ end
83
+ end
84
+
85
+ def chapter_number
86
+ raise NoMethodError, "Not a chapter" unless is_chapter?
87
+ if @name
88
+ @name.slice(/\d+\z/).to_i
89
+ else
90
+ doc.css(@chapter_number_css).text
91
+ end
42
92
  end
43
93
 
44
94
  # Must return a uri for a page given the arguments
@@ -61,11 +111,12 @@ module Mangdown
61
111
  # [manga_uri, manga_name, adapter_type]
62
112
  # If block given, then the block may alter this array
63
113
  # Only valid mangas should be returned (using is_manga?(uri))
64
- def manga_list
114
+ def collect_manga_list
65
115
  doc.css(@manga_list_css).map { |a|
66
- manga = ["#{@manga_link_prefix}#{a[:href]}",a.text.strip,type]
67
- next(nil) unless is_manga?(manga.first)
68
- block_given? ? yield(manga) : manga
116
+ manga = ["#{@manga_link_prefix}#{a[:href]}", a.text.strip, type]
117
+ if is_manga?(manga.first)
118
+ block_given? ? yield(manga) : manga
119
+ end
69
120
  }.compact
70
121
  end
71
122
 
@@ -75,9 +126,11 @@ module Mangdown
75
126
  # Only valid chapters should be returned (using is_chapter?(uri))
76
127
  def manga_chapters
77
128
  chapters = doc.css(@chapter_list_css).map { |a|
78
- chapter = [(root + a[:href].sub(root, '')),a.text.strip,type]
79
- next(nil) unless is_chapter?(chapter.first)
80
- block_given? ? yield(chapter) : chapter
129
+ link = root + a[:href].sub(root, '')
130
+ chapter = [link, a.text.strip, type]
131
+ if is_chapter?(chapter.first)
132
+ block_given? ? yield(chapter) : chapter
133
+ end
81
134
  }.compact
82
135
  @reverse_chapters ? chapters.reverse : chapters
83
136
  end
@@ -2,21 +2,21 @@ module Mangdown
2
2
  class Mangafox < Adapter::Base
3
3
  Mangdown::ADAPTERS << self
4
4
 
5
- def initialize(uri, doc)
5
+ def initialize(uri, doc, name)
6
6
  super
7
- @manga_list_css = 'div.manga_list li a'
8
- @chapter_list_css = 'a.tips'
9
- @root = 'http://mangafox.me'
7
+ @manga_list_css = 'div.manga_list li a'
8
+ @chapter_list_css = 'a.tips'
9
+ @root = 'http://mangafox.me'
10
10
  @manga_list_uri = "#{@root}/manga"
11
11
  @manga_name_css = "#title h1"
12
- @manga_link_prefix = ''
13
- @reverse_chapters = true
12
+ @manga_link_prefix = ''
13
+ @reverse_chapters = true
14
14
  @manga_uri_regex =
15
15
  /#{@root}\/manga\/[^\/]+?\//i
16
16
  @chapter_uri_regex =
17
17
  /#{@manga_uri_regex}(v\d+\/)?(c\d+\/)(1\.html)/i
18
18
  @page_uri_regex = /.+\.(png|jpg|jpeg)$/i
19
- end
19
+ end
20
20
 
21
21
  def manga_name
22
22
  CGI.unescapeHTML(super.sub(/ Manga/, '').downcase).upcase
@@ -2,21 +2,21 @@ module Mangdown
2
2
  class Mangahere < Adapter::Base
3
3
  Mangdown::ADAPTERS << self
4
4
 
5
- def initialize(uri, doc)
5
+ def initialize(uri, doc, name)
6
6
  super
7
- @root = 'http://www.mangahere.co'
8
- @manga_list_css = 'a.manga_info'
7
+ @root = 'http://www.mangahere.co'
8
+ @manga_list_css = 'a.manga_info'
9
9
  @manga_name_css = 'h1.title'
10
- @chapter_list_css = '.detail_list ul a'
10
+ @chapter_list_css = '.detail_list ul a'
11
11
  @manga_list_uri = "#{@root}/mangalist/"
12
- @manga_link_prefix = ''
13
- @reverse_chapters = true
12
+ @manga_link_prefix = ''
13
+ @reverse_chapters = true
14
14
  @manga_uri_regex =
15
15
  /#{@root}\/manga\/([^\/]+\/)?/i
16
16
  @chapter_uri_regex =
17
17
  /#{@manga_uri_regex}(v\d+\/)?(c\d+\/)(1\.html)?/i
18
18
  @page_uri_regex = /.+\.(png|jpg|jpeg)$/i
19
- end
19
+ end
20
20
 
21
21
  def manga_name
22
22
  CGI.unescapeHTML(super.downcase).upcase
@@ -4,7 +4,7 @@ module Mangdown
4
4
  class Mangapanda < Mangareader
5
5
  Mangdown::ADAPTERS << self
6
6
 
7
- def initialize(uri, doc)
7
+ def initialize(uri, doc, name)
8
8
  @root = 'http://www.mangapanda.com'
9
9
  super
10
10
  end
@@ -2,7 +2,7 @@ module Mangdown
2
2
  class Mangareader < Adapter::Base
3
3
  Mangdown::ADAPTERS << self
4
4
 
5
- def initialize(uri, doc)
5
+ def initialize(uri, doc, name)
6
6
  super
7
7
  @root ||= 'http://www.mangareader.net'
8
8
  @manga_list_css = 'ul.series_alpha li a'
@@ -23,7 +23,8 @@ module Mangdown
23
23
  end
24
24
 
25
25
  def build_page_uri(uri, manga, chapter, page_num)
26
- "#{root}/#{manga.gsub(' ', '-')}/#{chapter}/#{page_num}"
26
+ slug = slug(manga)
27
+ "#{root}/#{slug}/#{chapter}/#{page_num}"
27
28
  end
28
29
 
29
30
  def num_pages
@@ -45,6 +46,10 @@ module Mangdown
45
46
  def page_image
46
47
  doc.css('img')[0]
47
48
  end
49
+
50
+ def slug(string)
51
+ string.gsub(' ', '-').gsub(/[:,]/, '')
52
+ end
48
53
  end
49
54
  end
50
55
 
@@ -0,0 +1,9 @@
1
+ module Mangdown
2
+ module Adapter
3
+ class NoAdapterError < StandardError
4
+ def initialize(site)
5
+ super("Bad Site: No Properties Specified for Site: #{site.inspect}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -2,30 +2,30 @@ module Mangdown
2
2
  class Wiemanga < Adapter::Base
3
3
  Mangdown::ADAPTERS << self
4
4
 
5
- def initialize(uri, doc)
5
+ def initialize(uri, doc, name)
6
6
  super
7
- @root = 'http://www.wiemanga.com'
7
+ @root = 'http://www.wiemanga.com'
8
8
  @manga_list_uri =
9
9
  "#{@root}/search/?name_sel=contain&author_sel=contain" +
10
10
  "&completed_series=either"
11
11
  @manga_name_css = '.bookmessagebox h1'
12
- @manga_list_css = 'a.resultbookname'
13
- @chapter_list_css =
12
+ @manga_list_css = 'a.resultbookname'
13
+ @chapter_list_css =
14
14
  '.chapterlist tr:not(:first-child) .col1 a'
15
- @manga_link_prefix = ''
16
- @reverse_chapters = true
15
+ @manga_link_prefix = ''
16
+ @reverse_chapters = true
17
17
  @manga_uri_regex = /#{@root}\/manga\/([^\/]+)(\.html)?/i
18
18
  @chapter_uri_regex =
19
19
  /#{@root}\/chapter\/([^\/]+)\/(\d+)(\/|\.html)?/i
20
20
  @page_uri_regex = /.+\.(png|jpg|jpeg)$/i
21
- end
21
+ end
22
22
 
23
23
  def manga_name
24
24
  super.sub(/ Manga$/, "")
25
25
  end
26
26
 
27
27
  def build_page_uri(uri, manga, chapter, page_num)
28
- "#{uri}-#{page_num}.html"
28
+ "#{uri.sub(/\/+$/, '')}-#{page_num}.html"
29
29
  end
30
30
 
31
31
  def num_pages
@@ -4,56 +4,57 @@ module Mangdown
4
4
  extend ::Mangdown::Tools
5
5
 
6
6
  def all(main_dir)
7
- # Make sure all sub dirs are checked
8
- validate_file_or_dir_names(main_dir)
9
- # Make sure all sub dirs have files checked
10
- check_dir(main_dir) { |dir| validate_file_or_dir_names(dir)}
11
- # Create cbz files for all sub dirs
12
- cbz_sub_dirs(main_dir)
7
+ main_dir = String(main_dir)
8
+ # Make sure all sub dirs are checked
9
+ validate_file_or_dir_names(main_dir)
10
+ # Make sure all sub dirs have files checked
11
+ each_dir_or_page(main_dir) { |dir| validate_file_or_dir_names(dir)}
12
+ # Create cbz files for all sub dirs
13
+ cbz_sub_dirs(main_dir)
14
+ end
15
+
16
+ def one(dir)
17
+ dir = String(dir)
18
+ validate_file_or_dir_names(dir)
19
+ cbz_dir(dir)
13
20
  end
14
21
 
15
22
  private
16
23
  def cbz_dir(dir)
24
+ dir = dir.to_s.sub(/\/*$/, "")
25
+
17
26
  zip_file_name = dir + '.cbz'
18
- dir += '/' unless dir[-1] == '/'
27
+ return if File.exist?(zip_file_name)
19
28
 
20
29
  ::Zip::File.open(zip_file_name, ::Zip::File::CREATE) do |zip|
21
- Dir[File.join(dir, '**', '**')].each do |file|
22
- zip.add(file.sub(dir, ''), file)
30
+ file_matcher = File.join(dir, '**', '**')
31
+ dir << "/"
32
+
33
+ Dir.glob(file_matcher).each do |file|
34
+ filename = file.sub(dir, '')
35
+ zip.add(filename, file)
23
36
  end
24
37
  end
25
38
  end
26
39
 
27
40
  def cbz_sub_dirs(dir)
28
- check_dir(dir) do |sub_dir|
41
+ each_dir_or_page(dir) do |sub_dir|
29
42
  cbz_dir(sub_dir)
30
43
  end
31
44
  end
32
45
 
33
- def check_dir(dir)
34
- Dir.glob(dir + '/*').each do |file_name|
35
- #do block on each file name, but skip .cbz files
36
- next if file_name.include?('.cbz')
37
- yield(file_name)
46
+ def each_dir_or_page(dir)
47
+ Dir.glob(dir + '/*').each do |filename|
48
+ next if filename.include?('.cbz')
49
+ yield(filename)
38
50
  end
39
51
  end
40
52
 
41
53
  def validate_file_or_dir_names(dir)
42
- check_dir(dir) do |file_name|
43
- checked_name = check_file_or_dir_name(file_name)
54
+ each_dir_or_page(dir) do |file_name|
55
+ checked_name = Tools.valid_path_name(file_name)
44
56
  File.rename(file_name, checked_name)
45
57
  end
46
58
  end
47
-
48
- def check_file_or_dir_name(name)
49
- # slice the last number in the file or directory name,
50
- # which will be either the page number or the chapter number
51
- num = name.slice(/(\d+)(\.jpg)*\Z/, 1)
52
- return name unless num
53
-
54
- zeros_to_add = (3-num.length) > 0 ? (3-num.length) : 0
55
- num = "0" * zeros_to_add + num
56
- name.sub(/(\d+)(\.jpg)*\Z/, num + '\2')
57
- end
58
59
  end
59
60
  end
@@ -1,24 +1,33 @@
1
1
  module Mangdown
2
- class Chapter
2
+ class Chapter
3
3
 
4
4
  include Equality
5
5
  include Enumerable
6
- attr_reader :name, :uri, :pages, :manga, :chapter
7
6
 
8
- def initialize(name, uri)
7
+ attr_reader :uri, :pages
8
+
9
+ def initialize(uri, name = nil, manga = nil, chapter = nil)
9
10
  # use a valid name
10
- @name = name.sub(/\s(\d+)$/) { |num|
11
- ' ' + num.to_i.to_s.rjust(3, '0')
12
- }
13
- @manga = name.slice(/(^.+)\s/, 1)
14
- @chapter = name.slice(/\d+\z/).to_i
15
- @uri = Mangdown::Uri.new(uri)
16
- @properties = Properties.new(@uri)
17
- @pages = []
11
+ @name = name
12
+ @manga = manga
13
+ @chapter = chapter
14
+ @uri = Mangdown::Uri.new(uri)
15
+ @properties = Properties.new(@uri, nil, nil, name)
16
+
17
+ load_pages
18
+ end
19
+
20
+ def name
21
+ @name ||= @properties.chapter_name
22
+ end
23
+
24
+ def manga
25
+ @manga ||= @properties.manga_name
26
+ end
18
27
 
19
- get_pages
20
- @pages.sort_by! {|page| page.name}
21
- end
28
+ def chapter
29
+ @chapter ||= @properties.chapter_number
30
+ end
22
31
 
23
32
  def inspect
24
33
  "#<#{self.class} @name=#{name} @uri=#{uri} " +
@@ -28,76 +37,97 @@ module Mangdown
28
37
  alias_method :to_s, :inspect
29
38
 
30
39
  # enumerates through pages
31
- def each
32
- block_given? ? @pages.each { |page| yield(page) } : @pages.each
40
+ def each(&block)
41
+ @pages.each(&block)
42
+ end
43
+
44
+ # explicit conversion to chapter
45
+ def to_chapter
46
+ self
47
+ end
48
+
49
+ def to_path
50
+ @path ||= set_path
51
+ end
52
+
53
+ def set_path(dir = nil)
54
+ dir ||= File.join(DOWNLOAD_DIR, manga)
55
+ path = File.join(dir, name)
56
+ path = Tools.valid_path_name(path)
57
+ @path = Tools.relative_or_absolute_path(path)
33
58
  end
34
59
 
35
- # explicit conversion to chapter
36
- def to_chapter
37
- self
38
- end
60
+ def cbz(dir = to_path)
61
+ CBZ.one(dir)
62
+ end
39
63
 
40
- # download all pages in a chapter
41
- def download_to(dir)
42
- dir = Tools.relative_or_absolute_path(dir, @name)
43
- pages = map {|page| page.to_page}
44
- failed = []
64
+ # download all pages in a chapter
65
+ def download_to(dir = nil)
66
+ pages = map(&:to_page)
67
+ failed = []
45
68
  succeeded = []
46
69
 
47
- Dir.mkdir(dir) unless Dir.exists?(dir)
48
- Tools.hydra_streaming(pages) do |stage, page, data=nil|
70
+ setup_download_dir!(dir)
71
+
72
+ Tools.hydra_streaming(pages) do |stage, page, data = nil|
49
73
  case stage
50
74
  when :failed
51
75
  failed << page
52
76
  when :succeeded
53
77
  succeeded << page
54
78
  when :before
55
- path = page.file_path(dir)
56
- !File.exist?(path)
79
+ !page.file_exist?(to_path)
57
80
  when :body
58
- unless failed.include?(page)
59
- path = page.file_path(dir)
60
- File.open(path, 'ab') { |file| file.write(data) }
61
- end
81
+ page.append_file_data(to_path, data) unless failed.include?(page)
62
82
  when :complete
63
- unless failed.include?(page)
64
- path = page.file_path(dir)
65
- FileUtils.mv(path, "#{path}.#{Tools.file_type(path)}")
66
- end
83
+ page.append_file_ext(to_path) unless failed.include?(page)
67
84
  end
68
85
  end
69
- FileUtils.rm_rf(dir) if succeeded.empty?
70
86
 
71
- !succeeded.empty?
72
- end
87
+ FileUtils.rm_r(to_path) if succeeded.empty?
73
88
 
74
- private
75
- # get page objects for all pages in a chapter
76
- def get_pages
77
- pages = (1..@properties.num_pages).map {|num| get_page_hash(num)}
89
+ { failed: failed, succeeded: succeeded }
90
+ end
91
+
92
+ private
93
+ def setup_download_dir!(dir)
94
+ set_path(dir)
95
+ FileUtils.mkdir_p(to_path) unless Dir.exists?(to_path)
96
+ end
78
97
 
98
+ def load_pages
99
+ @pages ||= []
100
+
101
+ fetch_each_page do |page| @pages << page end
102
+ @pages.sort_by!(&:name)
103
+ end
104
+
105
+ # get page objects for all pages in a chapter
106
+ def fetch_each_page
107
+ pages = build_page_hashes
79
108
  Tools.hydra(pages) do |page, body|
80
- @pages << get_page(page.uri, Nokogiri::HTML(body))
109
+ page = get_page(page.uri, Nokogiri::HTML(body))
110
+ yield(page)
81
111
  end
82
112
  end
83
113
 
84
- # get the doc for a given page number
85
- def get_page_hash(num)
86
- uri_str = @properties.build_page_uri(uri, @manga, @chapter, num)
87
-
88
- MDHash.new(
89
- uri: Mangdown::Uri.new(uri_str).downcase, name: num
90
- )
114
+ # get the docs for number of pages
115
+ def build_page_hashes
116
+ (1..@properties.num_pages).map { |num|
117
+ uri_str = @properties.build_page_uri(uri, manga, chapter, num)
118
+ uri = Mangdown::Uri.new(uri_str).downcase
119
+ MDHash.new(uri: uri, name: num, chapter: name, manga: manga)
120
+ }
91
121
  end
92
122
 
93
123
  # get the page name and uri
94
124
  def get_page(uri, doc)
95
125
  properties = Properties.new(uri, nil, doc)
96
- MDHash.new(
97
- uri: properties.page_image_src,
98
- name: properties.page_image_name,
99
- site: properties.type
100
- )
126
+ uri = properties.page_image_src
127
+ page = properties.page_image_name
128
+ site = properties.type
129
+
130
+ MDHash.new(uri: uri, name: page, chapter: name, manga: manga, site: site)
101
131
  end
102
132
  end
103
133
  end