mangdown 0.14.0 → 0.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ceaa6642dfcb70513d084ec3b636d2c0855a9928
4
- data.tar.gz: e6f2920b7f48afb586aeb038543a2f32ac6e1267
3
+ metadata.gz: 087f4e2f6ce88163a9edb3f661b8cfaacdab3056
4
+ data.tar.gz: bb4f4ac0cd6c9b8197c99d982b7df0daf8826875
5
5
  SHA512:
6
- metadata.gz: e6ef238870bac0cd688769574919aea5ab8dffcd59b52f17ce1cbe315310179394c572972ffa34045a036a4f1d7eb200700a12ff9fb2e00756bb8b3afceddc8a
7
- data.tar.gz: f9c15ca24c70f1abd1eabbe33af7a90ed68f300fe5397877a8a76ab3ee1966d9cd2e2b4337871a637c0a0dcd3bbbbc6c86b6df7bd1feefe2dc3933849ae3f606
6
+ metadata.gz: f8e9352f01b656133205c0e3ae98f4f9f1cbe04313c2a8b4131d2bdf20016f495d90d6472e895c8e7e67f095f68cc88e35f4d34e291af6265861c914891fc331
7
+ data.tar.gz: 717a840d6823ae74e27be19c0eb95e916d572fdc248d25c19b5565c6e95bf34c60e55b316a88264025e24a6b906f3fa69e4ff74fc40dfdab0d8699ffca5c7c56
data/README.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ![Gitten badge](http://gittens.r15.railsrumble.com//badge/jphager2/mangdown)
2
2
 
3
+ ## Adapters [New]
4
+ Check out lib/mangdown/adapter.rb and lib/mangdown/adapters/mangareader.rb for examples of how to build an adapter.
5
+
6
+ ### Register an adapter
7
+
8
+ ```
9
+ # Register an adapter (AdapterClass) with the name :name
10
+ Mangdown.register_adapter(:name, AdpaterClass)
11
+ ```
12
+
13
+ ### Bundled adapters
14
+ There is only one adapter bundled with mangdown, but it is fairly simple to create one, so go ahead and give it a try. Feel free to file an issue if you have any problems.
15
+
3
16
  There is a simple built-in client, "M", that you can use for finding manga:
4
17
 
5
18
  ```ruby
@@ -64,7 +64,7 @@ module Mangdown
64
64
  (1..last_page).map { |page|
65
65
  slug = manga_name.gsub(' ', '-').gsub(/[:,]/, '')
66
66
  uri = "#{root}/#{slug}/#{chapter_number}/#{page}"
67
- uri = Mangdown::Uri.new(uri).downcase
67
+ uri = URI.escape(uri).downcase
68
68
 
69
69
  { uri: uri, name: page, site: site } }
70
70
  end
@@ -12,7 +12,7 @@ module Mangdown
12
12
  site ? @_site = site : @_site
13
13
  end
14
14
 
15
- attr_reader :uri, :doc, :name
15
+ attr_reader :uri, :name
16
16
  def initialize(uri, doc, name)
17
17
  @uri = uri
18
18
  @doc = doc
@@ -73,7 +73,6 @@ module Mangdown
73
73
  raise NotImplementedError
74
74
  end
75
75
 
76
- private
77
76
  def doc
78
77
  @doc ||= Tools.get_doc(uri)
79
78
  end
@@ -1,6 +1,5 @@
1
1
  module Mangdown
2
2
  class Chapter
3
-
4
3
  include Equality
5
4
  include Enumerable
6
5
 
@@ -11,7 +10,7 @@ module Mangdown
11
10
  @name = name
12
11
  @manga = manga
13
12
  @chapter = chapter
14
- @uri = Mangdown::Uri.new(uri)
13
+ @uri = URI.escape(uri)
15
14
  @pages = []
16
15
  end
17
16
 
@@ -22,12 +21,10 @@ module Mangdown
22
21
  end
23
22
  alias_method :to_s, :inspect
24
23
 
25
- # enumerates through pages
26
24
  def each(&block)
27
25
  @pages.each(&block)
28
26
  end
29
27
 
30
- # explicit conversion to chapter
31
28
  def to_chapter
32
29
  self
33
30
  end
@@ -47,7 +44,6 @@ module Mangdown
47
44
  CBZ.one(dir)
48
45
  end
49
46
 
50
- # download all pages in a chapter
51
47
  def download_to(dir = nil, opts = { force_download: false })
52
48
  pages = map(&:to_page)
53
49
  failed = []
@@ -88,30 +84,36 @@ module Mangdown
88
84
  end
89
85
 
90
86
  private
87
+
91
88
  def setup_download_dir!(dir)
92
89
  set_path(dir)
93
90
  FileUtils.mkdir_p(to_path) unless Dir.exists?(to_path)
94
91
  end
95
92
 
96
- # get page objects for all pages in a chapter
97
93
  def fetch_each_page
98
94
  pages = build_page_hashes
99
- Tools.hydra(pages) do |page, body|
100
- page = get_page(page.uri, Nokogiri::HTML(body))
101
- yield(page)
95
+ page_data = Hash.new { |h, k| h[k] = "" }
96
+ Tools.hydra_streaming(pages) do |status, page, data=nil|
97
+ case status
98
+ when :before
99
+ true
100
+ when :body
101
+ page_data[page] << data
102
+ when :complete
103
+ page = get_page(page.uri, Nokogiri::HTML(page_data[page]))
104
+ yield(page)
105
+ end
102
106
  end
103
107
  end
104
108
 
105
- # get the docs for number of pages
106
109
  def build_page_hashes
107
- adapter.page_list.map { |page|
110
+ adapter.page_list.map do |page|
108
111
  page.merge!(chapter: name, manga: manga)
109
- MDHash.new(page) }
112
+ MDHash.new(page)
113
+ end
110
114
  end
111
115
 
112
- # get the page name and uri
113
116
  def get_page(uri, doc)
114
- # Local binding for adapter
115
117
  adapter = Mangdown.adapter!(uri, nil, doc)
116
118
  page = adapter.page
117
119
  page.merge!(chapter: name, manga: manga)
@@ -1,18 +1,16 @@
1
- require 'progress_bar'
2
-
3
1
  module Mangdown
4
2
  # mangdown manga object, which holds chapters
5
3
  class Manga
6
-
7
4
  include Equality
8
5
  include Enumerable
6
+ include Logging
9
7
 
10
8
  attr_reader :uri, :chapters, :name
11
9
  attr_accessor :adapter
12
10
 
13
11
  def initialize(uri, name)
14
12
  @name = name
15
- @uri = Mangdown::Uri.new(uri)
13
+ @uri = URI.escape(uri)
16
14
  @chapters = []
17
15
  end
18
16
 
@@ -27,7 +25,6 @@ module Mangdown
27
25
  CBZ.all(to_path)
28
26
  end
29
27
 
30
- # download to current directory convenience method
31
28
  def download(*args)
32
29
  download_to(nil, *args)
33
30
  end
@@ -40,7 +37,6 @@ module Mangdown
40
37
  succeeded = []
41
38
  skipped = []
42
39
 
43
- bar = progress_bar(start, stop)
44
40
  chapters[start..stop].each do |md_hash|
45
41
  chapter = md_hash.to_chapter
46
42
  chapter_result = chapter.download_to(to_path, opts)
@@ -53,15 +49,12 @@ module Mangdown
53
49
  skipped << chapter
54
50
  end
55
51
  if chapter_result[:failed].any?
56
- STDERR.puts("error: #{chapter.name} was not fully downloaded")
57
- else
58
- bar.increment!
52
+ logger.error "#{chapter.name} was not fully downloaded"
59
53
  end
60
54
  end
61
55
  { failed: failed, succeeded: succeeded, skipped: skipped }
62
56
  end
63
57
 
64
- # explicit conversion to manga
65
58
  def to_manga
66
59
  self
67
60
  end
@@ -76,19 +69,19 @@ module Mangdown
76
69
  @path = Tools.relative_or_absolute_path(path)
77
70
  end
78
71
 
79
- # each for enumerating through chapters
80
72
  def each(&block)
81
73
  @chapters.each(&block)
82
74
  end
83
75
 
84
- # push MDHashes of manga chapters to @chapters
85
76
  def load_chapters
86
- @chapters += adapter.chapter_list.map { |chapter|
77
+ @chapters += adapter.chapter_list.map do |chapter|
87
78
  chapter.merge!(manga: name)
88
- MDHash.new(chapter) }
79
+ MDHash.new(chapter)
80
+ end
89
81
  end
90
82
 
91
83
  private
84
+
92
85
  def chapter_indeces(start, stop)
93
86
  length = chapters.length
94
87
  [start, stop].map { |i| i < 0 ? length + i : i }
@@ -112,10 +105,5 @@ module Mangdown
112
105
  end
113
106
  }
114
107
  end
115
-
116
- # create a progress bar object for start and stop indexes
117
- def progress_bar(start, stop)
118
- ProgressBar.new(stop - start + 1)
119
- end
120
108
  end
121
109
  end
@@ -8,6 +8,9 @@ module Mangdown
8
8
 
9
9
  attr_reader :manga
10
10
 
11
+ alias to_a manga
12
+ alias to_ary manga
13
+
11
14
  def initialize(manga = [])
12
15
  @manga = manga.map! { |hash| MDHash.new(hash) }
13
16
  end
@@ -28,12 +31,8 @@ module Mangdown
28
31
  merge(manga)
29
32
  end
30
33
 
31
- def to_a
32
- manga
33
- end
34
-
35
34
  def merge(other)
36
- @manga += other.to_a
35
+ @manga += other.to_ary
37
36
 
38
37
  return self
39
38
  end
@@ -7,83 +7,68 @@ module Mangdown
7
7
 
8
8
  def initialize(options = {})
9
9
  uri = options.fetch(:uri)
10
- name = options[:name]
11
10
  site = options[:site]
11
+
12
+ @name = options[:name]
13
+ @manga = options[:manga]
14
+ @chapter = options[:chapter]
15
+
12
16
  @adapter = Mangdown.adapter!(uri, site, nil, name)
13
17
 
14
- self.name = name
15
- self.uri = Mangdown::Uri.new(uri)
16
- self.site = @adapter.site
17
- self.manga = options[:manga]
18
- self.chapter = options[:chapter]
18
+ @uri = URI.escape(uri)
19
+ @site = adapter.site
19
20
  end
20
21
 
21
- # explicit conversion to manga list
22
22
  def to_manga_list
23
- # Seems weird to do it this way, but this is to intentially make it
24
- # more tedious to create a Mangadown::Manga object
25
- # (outsite of this method)
26
- #
27
- if @adapter.is_manga_list?
28
- list = MangaList.new
29
- list.load_manga(uri)
30
- list
31
- else
32
- raise NoMethodError, 'This is not a known manga list type'
33
- end
23
+ type_error('manga_list') unless adapter.is_manga_list?
24
+
25
+ list = MangaList.new
26
+ list.load_manga(uri)
27
+ list
34
28
  end
35
29
 
36
- # explicit conversion to manga
37
30
  def to_manga
38
- # Seems weird to do it this way, but this is to intentially make it
39
- # more tedious to create a Mangadown::Manga object
40
- # (outsite of this method)
41
- #
42
- if @adapter.is_manga?
43
- if name.to_s.empty?
44
- properties.merge!(@adapter.manga) { |_, before, after|
45
- before || after }
46
- end
47
-
48
- manga = Manga.new(uri, name)
49
- manga.adapter = @adapter
50
- manga.load_chapters
51
- manga
52
- else
53
- raise NoMethodError, 'This is not a known manga type'
31
+ type_error('manga') unless adapter.is_manga?
32
+
33
+ if name.to_s.empty?
34
+ fill_properties(adapter.manga)
54
35
  end
36
+
37
+ manga = Manga.new(uri, name)
38
+ manga.adapter = adapter
39
+ manga.load_chapters
40
+ manga
55
41
  end
56
42
 
57
- # explicit conversion to chapter
58
43
  def to_chapter
59
- # Seems weird to do it this way, but this is to intentially make it
60
- # more tedious to create a Mangadown::Chapter object
61
- # (outsite of this method)
62
- #
63
- if @adapter.is_chapter?
64
- if name.to_s.empty? || manga.to_s.empty? || chapter.to_s.empty?
65
- properties.merge!(@adapter.chapter) { |_, before, after|
66
- before || after }
67
- end
68
- # Get a local binding
69
- number = chapter
70
-
71
- chapter = Chapter.new(uri, name, manga, number)
72
- chapter.adapter = @adapter
73
- chapter.load_pages
74
- chapter
75
- else
76
- raise NoMethodError, 'This is not a known chapter type'
44
+ type_error('chapter') unless adapter.is_chapter?
45
+
46
+ if name.to_s.empty? || manga.to_s.empty? || chapter.to_s.empty?
47
+ fill_properties(adapter.chapter)
77
48
  end
49
+
50
+ number = chapter
51
+
52
+ chapter = Chapter.new(uri, name, manga, number)
53
+ chapter.adapter = adapter
54
+ chapter.load_pages
55
+ chapter
78
56
  end
79
57
 
80
- # explicit conversion to page
81
58
  def to_page
82
- if @adapter.is_page?
83
- Page.new(uri, name, manga, chapter)
84
- else
85
- raise NoMethodError, 'This is not a known page type'
86
- end
59
+ type_error('page') unless adapter.is_page?
60
+
61
+ Page.new(uri, name, manga, chapter)
87
62
  end
63
+
64
+ private
65
+
66
+ def adapter
67
+ @adapter
68
+ end
69
+
70
+ def type_error(type)
71
+ raise NoMethodError, "This is not a known #{type} type"
72
+ end
88
73
  end
89
74
  end
data/lib/mangdown/page.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Mangdown
2
2
  class Page
3
-
4
3
  include Equality
4
+ include Logging
5
5
 
6
6
  attr_reader :uri, :name, :manga, :chapter
7
7
 
@@ -9,7 +9,7 @@ module Mangdown
9
9
  @name = Tools.valid_path_name(name)
10
10
  @chapter = chapter
11
11
  @manga = manga
12
- @uri = Mangdown::Uri.new(uri)
12
+ @uri = URI.escape(uri)
13
13
  end
14
14
 
15
15
  # explicit conversion to page
@@ -46,7 +46,7 @@ module Mangdown
46
46
  append_file_data(dir, image)
47
47
  append_file_ext(dir)
48
48
  rescue => error # SocketError not defined?
49
- STDERR.puts( "#{error.message} | #{name} | #{uri}" )
49
+ logger.error "#{error.message} | #{name} | #{uri}"
50
50
  end
51
51
 
52
52
  def append_file_data(dir, data)
@@ -56,7 +56,7 @@ module Mangdown
56
56
  def append_file_ext(dir = nil)
57
57
  set_path(dir) if dir
58
58
  path = to_path
59
- ext = Tools.file_type(path)
59
+ ext = Tools.image_extension(path)
60
60
  filename = "#{path}.#{ext}"
61
61
 
62
62
  FileUtils.mv(path, filename)
@@ -0,0 +1,65 @@
1
+ module Mangdown
2
+ module CBZ
3
+ class << self
4
+ extend Tools
5
+
6
+ def all(main_dir)
7
+ main_dir = String(main_dir)
8
+ main_dir = validate_file_or_dir_names(main_dir)
9
+ each_dir_or_page(main_dir) { |dir| validate_file_or_dir_names(dir)}
10
+ cbz_sub_dirs(main_dir)
11
+ end
12
+
13
+ def one(dir)
14
+ dir = String(dir)
15
+ dir = validate_file_or_dir_names(dir)
16
+ cbz_dir(dir)
17
+ end
18
+
19
+ private
20
+
21
+ def cbz_dir(dir)
22
+ dir = dir.to_s.sub(/\/*$/, "")
23
+
24
+ zip_filename = dir + '.cbz'
25
+ return if File.exist?(zip_filename)
26
+
27
+ ::Zip::File.open(zip_filename, ::Zip::File::CREATE) do |zip|
28
+ file_matcher = File.join(dir, '**', '**')
29
+ dir << "/"
30
+
31
+ Dir.glob(file_matcher).each do |file|
32
+ filename = file.sub(dir, '')
33
+ zip.add(filename, file)
34
+ end
35
+ end
36
+ end
37
+
38
+ def cbz_sub_dirs(dir)
39
+ each_dir_or_page(dir) do |sub_dir|
40
+ cbz_dir(sub_dir)
41
+ end
42
+ end
43
+
44
+ def each_dir_or_page(dir)
45
+ Dir.glob(dir + '/*').each do |filename|
46
+ next if filename.include?('.cbz')
47
+ yield(filename)
48
+ end
49
+ end
50
+
51
+ def validate_file_or_dir_names(dir)
52
+ each_dir_or_page(dir) do |filename|
53
+ rename_with_valid_name(filename)
54
+ end
55
+ rename_with_valid_name(dir)
56
+ end
57
+
58
+ def rename_with_valid_name(filename)
59
+ checked_name = Tools.valid_path_name(filename)
60
+ File.rename(filename, checked_name)
61
+ checked_name
62
+ end
63
+ end
64
+ end
65
+ end
File without changes
@@ -0,0 +1,25 @@
1
+ require 'logger'
2
+
3
+ module Mangdown
4
+ module Logging
5
+
6
+ private
7
+
8
+ def logger
9
+ Mangdown.logger
10
+ end
11
+ end
12
+
13
+ class << self
14
+ def logger
15
+ @logger ||= configure_logger(file: STDOUT)
16
+ end
17
+
18
+ def configure_logger(options = {})
19
+ logger_args = options.fetch(:logger_args) { [options[:file]] }
20
+ @logger = Logger.new(*logger_args)
21
+ @logger.level = options.fetch(:level, Logger::DEBUG)
22
+ @logger
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ module Mangdown
2
+ module Properties
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ def properties
8
+ keys = self.class.property_names
9
+ values = keys.map { |name| self[name] }
10
+ Hash[keys.zip(values)]
11
+ end
12
+ alias to_hash properties
13
+
14
+ def fill_properties(other)
15
+ other.each do |property, value|
16
+ self[property] = value if self[property].to_s.empty?
17
+ end
18
+ end
19
+
20
+ def [](key)
21
+ instance_variable_get("@#{key}")
22
+ end
23
+
24
+ def []=(key, value)
25
+ instance_variable_set("@#{key}", value)
26
+ end
27
+
28
+ def inspect
29
+ properties.inspect
30
+ end
31
+
32
+ def to_s
33
+ properties.to_s
34
+ end
35
+
36
+ module ClassMethods
37
+ def properties(*names)
38
+ @properties = names
39
+ attr_accessor(*names)
40
+ end
41
+
42
+ def property_names
43
+ @properties || []
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,77 @@
1
+ require 'pathname'
2
+ require 'typhoeus'
3
+
4
+ module Mangdown
5
+ module Tools
6
+ class << self
7
+
8
+ def get_doc(uri)
9
+ data = get(uri)
10
+ @doc = ::Nokogiri::HTML(data)
11
+ end
12
+
13
+ def get(uri)
14
+ Typhoeus.get(uri).body
15
+ end
16
+
17
+ def get_root(uri)
18
+ uri = ::URI.parse(uri)
19
+ @root = "#{uri.scheme}://#{uri.host}"
20
+ end
21
+
22
+ def relative_or_absolute_path(*sub_paths)
23
+ Pathname.new(Dir.pwd).join(*sub_paths)
24
+ end
25
+
26
+ def valid_path_name(name)
27
+ name.to_s.sub(/(\d+)(\.\w+)*\Z/) do
28
+ digits, ext = Regexp.last_match[1..2]
29
+ digits.to_i.to_s.rjust(5, "0") + ext.to_s
30
+ end
31
+ end
32
+
33
+ def image_extension(path)
34
+ path = path.to_s
35
+
36
+ return unless File.exist?(path)
37
+
38
+ mime = FileMagic.new(:mime).file(path)
39
+ mime_to_extension(mime)
40
+ end
41
+
42
+ def hydra_streaming(objects)
43
+ hydra = Typhoeus::Hydra.hydra
44
+
45
+ requests = objects.map { |obj|
46
+ next unless yield(:before, obj)
47
+
48
+ request = Typhoeus::Request.new(obj.uri)
49
+ request.on_headers do |response|
50
+ status = response.success? ? :succeeded : :failed
51
+ yield(status, obj)
52
+ end
53
+ request.on_body do |chunk|
54
+ yield(:body, obj, chunk)
55
+ end
56
+ request.on_complete do |response|
57
+ yield(:complete, obj)
58
+ end
59
+
60
+ hydra.queue(request)
61
+ request
62
+ }.compact
63
+
64
+ hydra.run
65
+ requests
66
+ end
67
+
68
+ private
69
+
70
+ def mime_to_extension(mime)
71
+ return unless mime.start_with?('image')
72
+
73
+ mime.split(';').first.split('/').last
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,3 +1,3 @@
1
1
  module Mangdown
2
- VERSION = "0.14.0"
2
+ VERSION = "0.14.1"
3
3
  end
data/lib/mangdown.rb CHANGED
@@ -4,15 +4,15 @@ require 'yaml'
4
4
  require 'zip'
5
5
  require 'filemagic'
6
6
 
7
- require_relative 'mangdown/equality'
8
- require_relative 'mangdown/properties'
9
- require_relative 'mangdown/tools'
10
- require_relative 'mangdown/uri'
7
+ require_relative 'mangdown/support/logging'
8
+ require_relative 'mangdown/support/equality'
9
+ require_relative 'mangdown/support/properties'
10
+ require_relative 'mangdown/support/tools'
11
+ require_relative 'mangdown/support/cbz'
11
12
  require_relative 'mangdown/page'
12
13
  require_relative 'mangdown/chapter'
13
14
  require_relative 'mangdown/manga'
14
15
  require_relative 'mangdown/manga_list.rb'
15
- require_relative 'mangdown/cbz'
16
16
  require_relative 'mangdown/md_hash'
17
17
 
18
18
  require_relative 'mangdown/adapter'