mangdown 0.20.8 → 0.21.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,26 +3,26 @@
3
3
  module Mangdown
4
4
  # Mangdown chapter object, which holds pages
5
5
  class Chapter
6
+ extend Forwardable
7
+
6
8
  include Equality
7
- include Enumerable
8
9
 
9
- attr_reader :uri, :pages, :name, :manga, :chapter
10
- attr_accessor :adapter
10
+ attr_reader :chapter
11
+
12
+ def_delegators :chapter, :url, :name, :number
13
+
14
+ alias uri url
11
15
 
12
- def initialize(uri, name, manga, chapter = nil)
13
- @name = name
14
- @manga = manga
16
+ def initialize(chapter)
15
17
  @chapter = chapter
16
- @uri = Addressable::URI.escape(uri)
17
- @pages = []
18
18
  end
19
19
 
20
- def each(&block)
21
- @pages.each(&block)
20
+ def pages
21
+ @pages ||= chapter.pages.map { |page| Mangdown.page(page) }
22
22
  end
23
23
 
24
- def to_chapter
25
- self
24
+ def manga
25
+ @manga ||= Mangdown.manga(chapter.manga)
26
26
  end
27
27
 
28
28
  def path
@@ -31,8 +31,8 @@ module Mangdown
31
31
  alias to_path path
32
32
 
33
33
  def setup_path(dir = nil)
34
- dir ||= File.join(DOWNLOAD_DIR, manga)
35
- path = File.join(dir, name)
34
+ dir ||= manga.path
35
+ path = Tools.file_join(dir, name)
36
36
  path = Tools.valid_path_name(path)
37
37
  @path = Tools.relative_or_absolute_path(path)
38
38
  end
@@ -41,8 +41,11 @@ module Mangdown
41
41
  CBZ.one(dir)
42
42
  end
43
43
 
44
+ # rubocop:disable Metrics/AbcSize
45
+ # rubocop:disable Metrics/CyclomaticComplexity
46
+ # rubocop:disable Metrics/MethodLength
47
+ # rubocop:disable Metrics/PerceivedComplexity
44
48
  def download_to(dir = nil, opts = { force_download: false })
45
- pages = map(&:to_page)
46
49
  failed = []
47
50
  succeeded = []
48
51
  skipped = []
@@ -53,10 +56,13 @@ module Mangdown
53
56
  setup_download_dir!(dir)
54
57
  end
55
58
 
56
- Tools.hydra_streaming(pages, adapter.hydra_opts) do |stage, page, data = nil|
59
+ Tools.hydra_streaming(
60
+ pages,
61
+ chapter.hydra_opts
62
+ ) do |stage, page, data = nil|
57
63
  case stage
58
64
  when :failed
59
- failed << page
65
+ failed << [page, data]
60
66
  when :succeeded
61
67
  succeeded << page
62
68
  when :before
@@ -72,13 +78,10 @@ module Mangdown
72
78
 
73
79
  { failed: failed, succeeded: succeeded, skipped: skipped }
74
80
  end
75
-
76
- def load_pages
77
- return @pages if @pages.any?
78
-
79
- fetch_each_page { |page| @pages << page }
80
- @pages.sort_by!(&:name)
81
- end
81
+ # rubocop:enable Metrics/AbcSize
82
+ # rubocop:enable Metrics/CyclomaticComplexity
83
+ # rubocop:enable Metrics/MethodLength
84
+ # rubocop:enable Metrics/PerceivedComplexity
82
85
 
83
86
  private
84
87
 
@@ -86,38 +89,5 @@ module Mangdown
86
89
  setup_path(dir)
87
90
  FileUtils.mkdir_p(to_path) unless Dir.exist?(to_path)
88
91
  end
89
-
90
- def fetch_each_page
91
- pages = build_page_hashes
92
- page_data = Hash.new { |h, k| h[k] = +'' }
93
- Tools.hydra_streaming(pages, adapter.hydra_opts) do |status, page, data = nil|
94
- case status
95
- when :before
96
- true
97
- when :body
98
- page_data[page] << data
99
- when :complete
100
- page = get_page(page.uri, Nokogiri::HTML(page_data[page]))
101
- yield(page)
102
- end
103
- end
104
- end
105
-
106
- def build_page_hashes
107
- adapter.page_list.map do |page|
108
- page[:chapter] = name
109
- page[:manga] = manga
110
- MDHash.new(page)
111
- end
112
- end
113
-
114
- def get_page(uri, doc)
115
- adapter = Mangdown.adapter!(uri, nil, doc)
116
- page = adapter.page
117
- page[:chapter] = name
118
- page[:manga] = manga
119
-
120
- MDHash.new(page)
121
- end
122
92
  end
123
93
  end
@@ -2,21 +2,24 @@
2
2
 
3
3
  require_relative '../mangdown'
4
4
 
5
- # Simple client for Mangdown
6
- module M
7
- DATA_FILE_PATH = Dir.home + '/.manga_list.yml'
8
- HELP_FILE_PATH = File.expand_path(
9
- '../../README.md', File.dirname(__FILE__)
10
- )
5
+ require_relative 'db'
11
6
 
12
- DEFAULT_MANGA_PAGES = ['https://www.mangareader.net/alphabetical'].freeze
7
+ module Mangdown
8
+ # Simple client for Mangdown
9
+ module Client
10
+ class <<self
11
+ include Logging
12
+ end
13
+
14
+ module_function
13
15
 
14
- class << self
15
16
  # return a list of hash with :uri and :name of mangas found in list
16
17
  def find(search)
17
- search = Regexp.new(/^#{search}$/) if search.respond_to?(:to_str)
18
-
19
- current_manga_list.select { |manga| manga[:name] =~ search }
18
+ filter = Sequel.lit('LOWER(name) LIKE ?', "%#{search.downcase}%")
19
+ order = Sequel[:name]
20
+ Mangdown::DB::Manga.where(filter).order(order).map do |manga|
21
+ Mangdown.manga(manga.url)
22
+ end
20
23
  end
21
24
 
22
25
  # cbz all subdirectories in a directory
@@ -26,51 +29,25 @@ module M
26
29
  raise Mangdown::Error, "Failed to package #{dir}: #{error.message}"
27
30
  end
28
31
 
29
- # display help file
30
- def help
31
- puts File.read(HELP_FILE_PATH)
32
- end
33
-
34
- # delete data file
35
- def clean_up
36
- File.delete(DATA_FILE_PATH) if File.exist?(DATA_FILE_PATH)
37
- end
38
-
39
- def manga_pages
40
- @manga_pages ||= DEFAULT_MANGA_PAGES.dup
41
- end
42
-
43
- private
44
-
45
- # convenience method to access the data file path
46
- def path
47
- DATA_FILE_PATH
48
- end
49
-
50
- # check if the data file is current
51
- def file_current?(file)
52
- File.exist?(file) && File.mtime(file) > (Time.now - 604_800)
53
- end
32
+ # rubocop:disable Metrics/MethodLength
33
+ # load manga into sqlite db
34
+ def index_manga
35
+ count_before = Mangdown::DB::Manga.count
54
36
 
55
- # attempt to get the list from the data file
56
- def data_from_file
57
- YAML.load(File.read(path)) if file_current?(path)
58
- end
37
+ Mangdown.adapters.each do |name, adapters|
38
+ adapters.manga_list.each do |manga|
39
+ Mangdown::DB::Manga.find_or_create(
40
+ adapter: name,
41
+ url: manga.url,
42
+ name: manga.name
43
+ )
44
+ end
45
+ end
59
46
 
60
- # get saved current manga list, if data is less than a week old
61
- # otherwise fetch new data and write it to the data file
62
- def current_manga_list
63
- data = data_from_file
64
- return Mangdown::MangaList.from_data(data) if data
47
+ count_after = Mangdown::DB::Manga.count
65
48
 
66
- list = manga_pages.inject([]) do |manga, uri|
67
- list = Mangdown::MDHash.new(uri: uri).to_manga_list
68
- list.merge(manga)
69
- end
70
- File.open(path, 'w+') { |f| f.write(list.to_yaml) }
71
- list
72
- rescue StandardError => error
73
- raise Mangdown::Error, "#{path} may be corrupt: #{error.message}"
49
+ logger.info("#{count_after} manga, #{count_after - count_before} new")
74
50
  end
51
+ # rubocop:enable Metrics/MethodLength
75
52
  end
76
53
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+ require 'sqlite3'
5
+
6
+ module Mangdown
7
+ # DB Connection
8
+ module DB
9
+ DB_MIGRATE = File.expand_path('../../db/migrate', __dir__)
10
+ DB_FILE = File.expand_path('../../db/mangdown.db', __dir__)
11
+
12
+ unless File.exist?(DB_FILE)
13
+ begin
14
+ SQLite3::Database.new(DB_FILE)
15
+ rescue StandardError
16
+ File.delete(DB_FILE)
17
+ raise
18
+ end
19
+ end
20
+
21
+ CONNECTION = Sequel.connect("sqlite://#{DB_FILE}")
22
+ Sequel.extension(:migration)
23
+ Sequel::Migrator.run(CONNECTION, DB_MIGRATE)
24
+ end
25
+ end
26
+
27
+ require_relative 'db/manga'
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mangdown
4
+ module DB
5
+ # DB model for manga
6
+ class Manga < Sequel::Model(Mangdown::DB::CONNECTION[:manga])
7
+ end
8
+ end
9
+ end
@@ -3,17 +3,25 @@
3
3
  module Mangdown
4
4
  # Mangdown manga object, which holds chapters
5
5
  class Manga
6
+ extend Forwardable
7
+
6
8
  include Equality
7
- include Enumerable
8
9
  include Logging
9
10
 
10
- attr_reader :uri, :chapters, :name
11
- attr_accessor :adapter
11
+ attr_accessor :manga
12
+
13
+ def_delegators :manga, :url, :name
12
14
 
13
- def initialize(uri, name)
14
- @name = name
15
- @uri = Addressable::URI.escape(uri)
16
- @chapters = []
15
+ alias uri url
16
+
17
+ def initialize(manga)
18
+ @manga = manga
19
+ end
20
+
21
+ def chapters
22
+ @chapters ||= manga
23
+ .chapters
24
+ .map { |chapter| Mangdown.chapter(chapter) }
17
25
  end
18
26
 
19
27
  def cbz
@@ -24,7 +32,8 @@ module Mangdown
24
32
  download_to(nil, *args)
25
33
  end
26
34
 
27
- # download using enumerable
35
+ # rubocop:disable Metrics/AbcSize
36
+ # rubocop:disable Metrics/MethodLength
28
37
  def download_to(dir, start = 0, stop = -1, opts = { force_download: false })
29
38
  start, stop = validate_indeces!(start, stop)
30
39
  setup_download_dir!(dir)
@@ -32,16 +41,15 @@ module Mangdown
32
41
  succeeded = []
33
42
  skipped = []
34
43
 
35
- chapters[start..stop].each do |md_hash|
36
- chapter = md_hash.to_chapter
44
+ chapters[start..stop].each do |chapter|
37
45
  chapter_result = chapter.download_to(to_path, opts)
38
46
 
39
47
  if chapter_result[:failed].any?
40
- failed << chapter
48
+ failed << [chapter, chapter_result]
41
49
  elsif chapter_result[:succeeded].any?
42
- succeeded << chapter
50
+ succeeded << [chapter, chapter_result]
43
51
  elsif chapter_result[:skipped].any?
44
- skipped << chapter
52
+ skipped << [chapter, chapter_result]
45
53
  end
46
54
 
47
55
  next unless chapter_result[:failed].any?
@@ -52,12 +60,11 @@ module Mangdown
52
60
  chapter: chapter.name
53
61
  }.to_s)
54
62
  end
55
- { failed: failed, succeeded: succeeded, skipped: skipped }
56
- end
57
63
 
58
- def to_manga
59
- self
64
+ { failed: failed, succeeded: succeeded, skipped: skipped }
60
65
  end
66
+ # rubocop:enable Metrics/AbcSize
67
+ # rubocop:enable Metrics/MethodLength
61
68
 
62
69
  def path
63
70
  @path ||= setup_path
@@ -66,21 +73,10 @@ module Mangdown
66
73
 
67
74
  def setup_path(dir = nil)
68
75
  dir ||= DOWNLOAD_DIR
69
- path = File.join(dir, name)
76
+ path = Tools.file_join(dir, name)
70
77
  @path = Tools.relative_or_absolute_path(path)
71
78
  end
72
79
 
73
- def each(&block)
74
- @chapters.each(&block)
75
- end
76
-
77
- def load_chapters
78
- @chapters += adapter.chapter_list.map do |chapter|
79
- chapter[:manga] = name
80
- MDHash.new(chapter)
81
- end
82
- end
83
-
84
80
  private
85
81
 
86
82
  def chapter_indeces(start, stop)
@@ -3,21 +3,23 @@
3
3
  module Mangdown
4
4
  # Mangdown page
5
5
  class Page
6
+ extend Forwardable
7
+
6
8
  include Equality
7
9
  include Logging
8
10
 
9
- attr_reader :uri, :name, :manga, :chapter
11
+ attr_reader :page
12
+
13
+ def_delegators :page, :url, :name
14
+
15
+ alias uri url
10
16
 
11
- def initialize(uri, name, manga, chapter)
12
- @name = Tools.valid_path_name(name)
13
- @chapter = chapter
14
- @manga = manga
15
- @uri = Addressable::URI.escape(uri)
17
+ def initialize(page)
18
+ @page = page
16
19
  end
17
20
 
18
- # explicit conversion to page
19
- def to_page
20
- self
21
+ def chapter
22
+ @chapter ||= Mangdown.chapter(page.chapter)
21
23
  end
22
24
 
23
25
  def path
@@ -29,15 +31,16 @@ module Mangdown
29
31
  # without file extension if file is not found. File extensions
30
32
  # are appended only after the file has been downloaded.
31
33
  def setup_path(dir = nil)
32
- dir ||= File.join(manga, chapter)
34
+ dir ||= chapter.path
33
35
  dir = Tools.valid_path_name(dir)
36
+ name = self.name.tr('/', '')
34
37
  file = Dir.entries(dir).find { |f| f[name] } if Dir.exist?(dir)
35
- path = File.join(dir, file || name)
38
+ path = Tools.file_join(dir, file || name)
36
39
  @path = Tools.relative_or_absolute_path(path)
37
40
  end
38
41
 
39
- # downloads to specified directory
40
- def download_to(dir = Dir.pwd, force_download: false)
42
+ # rubocop:disable Metrics/MethodLength
43
+ def download_to(dir = Dir.pwd, opts = { force_download: false })
41
44
  delete_files!(dir) if opts[:force_download]
42
45
 
43
46
  return if file_exist?(dir)
@@ -56,6 +59,7 @@ module Mangdown
56
59
  backtrace: error.backtrace
57
60
  }.to_s)
58
61
  end
62
+ # rubocop:enable Metrics/MethodLength
59
63
 
60
64
  def append_file_data(_dir, data)
61
65
  File.open(to_path, 'ab') { |file| file.write(data) }
@@ -29,10 +29,9 @@ module Mangdown
29
29
 
30
30
  ::Zip::File.open(zip_filename, ::Zip::File::CREATE) do |zip|
31
31
  file_matcher = File.join(dir, '**', '**')
32
- dir << '/'
33
32
 
34
33
  Dir.glob(file_matcher).each do |file|
35
- filename = file.sub(dir, '')
34
+ filename = file.sub("#{dir}/", '')
36
35
  zip.add(filename, file)
37
36
  end
38
37
  end