mangdown 0.14.0 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
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'