comicbook 0.1.0 → 0.2.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 +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +18 -0
- data/README.md +42 -9
- data/Rakefile +4 -0
- data/SYSTEM.md +2 -2
- data/lib/comic_book/cb/archiver.rb +49 -0
- data/lib/comic_book/cb/extractor.rb +17 -0
- data/lib/comic_book/cb.rb +28 -0
- data/lib/comic_book/cb7/archiver.rb +6 -6
- data/lib/comic_book/cb7/extractor.rb +36 -21
- data/lib/comic_book/cb7.rb +13 -15
- data/lib/comic_book/cba.rb +17 -0
- data/lib/comic_book/cbr/extractor.rb +75 -0
- data/lib/comic_book/cbr.rb +36 -0
- data/lib/comic_book/cbt/archiver.rb +22 -31
- data/lib/comic_book/cbt/extractor.rb +38 -41
- data/lib/comic_book/cbt.rb +12 -14
- data/lib/comic_book/cbz/archiver.rb +6 -6
- data/lib/comic_book/cbz/extractor.rb +30 -19
- data/lib/comic_book/cbz.rb +10 -14
- data/lib/comic_book/cli.rb +68 -27
- data/lib/comic_book/cli_helpers.rb +37 -10
- data/lib/comic_book/vendor/macos/lsar +0 -0
- data/lib/comic_book/vendor/macos/unar +0 -0
- data/lib/comic_book/version.rb +1 -1
- data/lib/comicbook.rb +19 -5
- metadata +11 -7
- data/lib/comic_book/vendor/linux/lsar +0 -0
- data/lib/comic_book/vendor/linux/unar +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a0e1f16bc54c8073078765c5edd09bf2e886ee042a859e6f6ec7c601876fc010
|
|
4
|
+
data.tar.gz: c7fbaa136dc9705ef955dd272c83a22864fc541200b9b435a34c850afedea34b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3ad1f9e9e8d24c143e6dfb22a293e62d758ce6a865e19f7bf324e908e339f7557d303e873d0cc5448378e190214ce9e8c18bed3743480203fa708e9f313fb3a9
|
|
7
|
+
data.tar.gz: 8f7e8f708e4ff746e132d94a6a6fec8406196cabe246c2769ae1600684a2dfb7c2fe4d7dab32cd5f9c70e22967e35d942b2a649cc1784bea2734702c04036ac6
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2025-01-17
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- CBR extraction support using vendored `unar`/`lsar` binaries
|
|
8
|
+
- `--delete-original` CLI option for both extract and archive commands
|
|
9
|
+
- `--images-only` CLI option for extract command
|
|
10
|
+
- `images_only` option for Ruby API extraction
|
|
11
|
+
- `delete_original` option for Ruby API extraction and archiving
|
|
12
|
+
- CLI validation for unsupported archive output formats (CBR, CBA)
|
|
13
|
+
|
|
3
14
|
## [0.1.0] - 2025-10-26
|
|
4
15
|
|
|
16
|
+
### Added
|
|
17
|
+
|
|
5
18
|
- Initial release
|
|
19
|
+
- CBZ support (extract and archive)
|
|
20
|
+
- CB7 support (extract and archive)
|
|
21
|
+
- CBT support (extract and archive)
|
|
22
|
+
- CLI tool with `extract` and `archive` commands
|
|
23
|
+
- Ruby API with `ComicBook.extract`, `ComicBook.new().archive`, and `ComicBook.new().pages`
|
data/README.md
CHANGED
|
@@ -7,14 +7,15 @@ A Ruby library and CLI tool for managing comic books archives.
|
|
|
7
7
|
|
|
8
8
|
**`archive`** — to create a `.cb*` file (default: `.cbz`).
|
|
9
9
|
|
|
10
|
-
Currently supported formats
|
|
10
|
+
Currently supported formats for `archive` and `extract`:
|
|
11
11
|
- CB7 — [7zip](https://en.wikipedia.org/wiki/7-Zip)
|
|
12
12
|
- CBT — [Tar](https://en.wikipedia.org/wiki/Tar_(computing))
|
|
13
13
|
- CBZ — [Zip](https://en.wikipedia.org/wiki/ZIP_(file_format))
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Currently supported formats for `extract` only:
|
|
16
|
+
- **CBR** — [RAR](https://en.wikipedia.org/wiki/WinRAR) is proprietary without an open source implementation license. Extracting support is provided using vendored [`unar`](https://theunarchiver.com/command-line) binaries because a large number of comic books are archived in .cbr/.rar format. No support for creating `.cbr` files will ever be added until RAR is open source (or reverse engineered).
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
Planned formats for `extract` only:
|
|
18
19
|
- **CBA** — [ACE](https://en.wikipedia.org/wiki/WinAce) is both proprietary and very old/outdated/unsupported. ACE extracting support is provided for historical posterity and completeness.
|
|
19
20
|
|
|
20
21
|
## Installation
|
|
@@ -33,17 +34,49 @@ gem install comicbook
|
|
|
33
34
|
|
|
34
35
|
## Usage
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
### CLI
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
```sh
|
|
40
|
+
# Extract a comic book archive
|
|
41
|
+
comicbook extract path/to/archive.cbz
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
# Extract to a specific destination
|
|
44
|
+
comicbook extract path/to/archive.cbz --to path/to/output
|
|
45
|
+
|
|
46
|
+
# Extract only image files (exclude metadata like ComicInfo.xml)
|
|
47
|
+
comicbook extract path/to/archive.cbz --images-only
|
|
48
|
+
|
|
49
|
+
# Create a comic book archive from a folder
|
|
50
|
+
comicbook archive path/to/folder
|
|
51
|
+
|
|
52
|
+
# Create archive at a specific destination
|
|
53
|
+
comicbook archive path/to/folder --to path/to/output.cbz
|
|
54
|
+
|
|
55
|
+
# Show help
|
|
56
|
+
comicbook --help
|
|
42
57
|
```
|
|
43
|
-
|
|
58
|
+
|
|
59
|
+
### Ruby API
|
|
44
60
|
|
|
45
61
|
```ruby
|
|
46
|
-
|
|
62
|
+
# Extract a comic book archive (extracts all files by default)
|
|
63
|
+
ComicBook.extract 'path/to/archive.cbz'
|
|
64
|
+
|
|
65
|
+
# Extract to a specific destination
|
|
66
|
+
ComicBook.extract 'path/to/archive.cbz', to: 'path/to/output'
|
|
67
|
+
|
|
68
|
+
# Extract only image files (exclude metadata like ComicInfo.xml)
|
|
69
|
+
ComicBook.extract 'path/to/archive.cbz', images_only: true
|
|
70
|
+
|
|
71
|
+
# Create a comic book archive from a folder (creates .cbz by default)
|
|
72
|
+
ComicBook.new('path/to/folder').archive
|
|
73
|
+
|
|
74
|
+
# Create archive at a specific destination
|
|
75
|
+
ComicBook.new('path/to/folder').archive to: 'path/to/output.cbz'
|
|
76
|
+
|
|
77
|
+
# Get pages from an archive
|
|
78
|
+
comic = ComicBook.new 'path/to/archive.cbz'
|
|
79
|
+
comic.pages # => [#<ComicBook::Page>, ...]
|
|
47
80
|
```
|
|
48
81
|
|
|
49
82
|
## Development
|
data/Rakefile
CHANGED
data/SYSTEM.md
CHANGED
|
@@ -230,6 +230,6 @@ ComicBook::Error < StandardError
|
|
|
230
230
|
The adapter pattern makes it easy to add new formats or extend existing ones without modifying core functionality.
|
|
231
231
|
|
|
232
232
|
## Version Information
|
|
233
|
-
- **Current Version**: 0.
|
|
234
|
-
- **Ruby Requirement**: >=
|
|
233
|
+
- **Current Version**: 0.2.0
|
|
234
|
+
- **Ruby Requirement**: >= 4.0.0
|
|
235
235
|
- **License**: MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
class ComicBook
|
|
2
|
+
class CB < Adapter
|
|
3
|
+
class Archiver
|
|
4
|
+
def initialize source_path
|
|
5
|
+
@source_path = File.expand_path source_path
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def archive options = {}
|
|
9
|
+
output_path = options[:to] || determine_output_path
|
|
10
|
+
|
|
11
|
+
validate_destination! output_path
|
|
12
|
+
|
|
13
|
+
if File.directory? source_path
|
|
14
|
+
archive_folder output_path
|
|
15
|
+
else
|
|
16
|
+
archive_file output_path
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
output_path
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
attr_reader :source_path
|
|
25
|
+
|
|
26
|
+
def determine_output_path
|
|
27
|
+
base_name = File.basename source_path, '.*'
|
|
28
|
+
dir_name = File.dirname source_path
|
|
29
|
+
|
|
30
|
+
File.expand_path File.join(dir_name, "#{base_name}.cb")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def validate_destination! output_path
|
|
34
|
+
return unless File.exist? output_path
|
|
35
|
+
|
|
36
|
+
raise ComicBook::Error, "Destination already exists: #{output_path}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def archive_folder output_path
|
|
40
|
+
FileUtils.mv source_path, output_path
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def archive_file output_path
|
|
44
|
+
FileUtils.mkdir_p output_path
|
|
45
|
+
FileUtils.mv source_path, output_path
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class ComicBook
|
|
2
|
+
class CB < Adapter
|
|
3
|
+
class Extractor
|
|
4
|
+
def initialize archive_path
|
|
5
|
+
@archive_path = File.expand_path archive_path
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def extract
|
|
9
|
+
raise ComicBook::Error, '.cb folders are already extracted (they are uncompressed folders)'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
attr_reader :archive_path
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require_relative 'adapter'
|
|
2
|
+
require_relative 'cb/archiver'
|
|
3
|
+
require_relative 'cb/extractor'
|
|
4
|
+
|
|
5
|
+
class ComicBook
|
|
6
|
+
class CB < Adapter
|
|
7
|
+
def archive options = {}
|
|
8
|
+
Archiver.new(path).archive options
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def extract _options = {}
|
|
12
|
+
Extractor.new(path).extract
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def pages
|
|
16
|
+
pattern = ComicBook::IMAGE_GLOB_PATTERN
|
|
17
|
+
search_path = File.join path, '**', pattern
|
|
18
|
+
image_files = Dir.glob search_path, File::FNM_CASEFOLD
|
|
19
|
+
|
|
20
|
+
image_files.sort.map do |file|
|
|
21
|
+
relative_path = Pathname.new(file).relative_path_from(Pathname.new(path)).to_s
|
|
22
|
+
basename = File.basename file
|
|
23
|
+
|
|
24
|
+
ComicBook::Page.new relative_path, basename
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -10,7 +10,7 @@ class ComicBook
|
|
|
10
10
|
delete_original = options.fetch :delete_original, false
|
|
11
11
|
|
|
12
12
|
output_path = options[:to] || determine_output_path(extension)
|
|
13
|
-
|
|
13
|
+
create_archive output_path
|
|
14
14
|
cleanup_source_folder if delete_original
|
|
15
15
|
|
|
16
16
|
output_path
|
|
@@ -27,11 +27,11 @@ class ComicBook
|
|
|
27
27
|
File.expand_path File.join(dir_name, "#{base_name}.#{extension}")
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
def
|
|
30
|
+
def create_archive output_path
|
|
31
31
|
File.open(output_path, 'wb') do |file|
|
|
32
|
-
SevenZipRuby::Writer.open(file) do |
|
|
32
|
+
SevenZipRuby::Writer.open(file) do |writer|
|
|
33
33
|
find_image_files.each do |image_file|
|
|
34
|
-
|
|
34
|
+
add_file writer, image_file
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
end
|
|
@@ -42,12 +42,12 @@ class ComicBook
|
|
|
42
42
|
Dir.glob(pattern, File::FNM_CASEFOLD).sort
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
def
|
|
45
|
+
def add_file writer, file
|
|
46
46
|
file_path = Pathname.new file
|
|
47
47
|
source_path = Pathname.new source_folder
|
|
48
48
|
relative_path = file_path.relative_path_from source_path
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
writer.add_file file, as: relative_path.to_s
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def cleanup_source_folder
|
|
@@ -2,16 +2,17 @@ class ComicBook
|
|
|
2
2
|
class CB7 < Adapter
|
|
3
3
|
class Extractor
|
|
4
4
|
def initialize archive_path
|
|
5
|
-
@archive_path = File.expand_path
|
|
5
|
+
@archive_path = File.expand_path archive_path
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def extract options = {}
|
|
9
|
-
extension
|
|
10
|
-
delete_original
|
|
9
|
+
extension = options.fetch :extension, :cb
|
|
10
|
+
delete_original = options.fetch :delete_original, false
|
|
11
11
|
destination_folder = options[:to]
|
|
12
12
|
|
|
13
13
|
destination = destination_folder || determine_extract_path(extension)
|
|
14
|
-
|
|
14
|
+
create_destination_directory destination
|
|
15
|
+
extract_contents destination, options
|
|
15
16
|
cleanup_archive_file if delete_original
|
|
16
17
|
|
|
17
18
|
destination
|
|
@@ -21,9 +22,13 @@ class ComicBook
|
|
|
21
22
|
|
|
22
23
|
attr_reader :archive_path
|
|
23
24
|
|
|
25
|
+
def create_destination_directory destination
|
|
26
|
+
FileUtils.mkdir_p destination
|
|
27
|
+
end
|
|
28
|
+
|
|
24
29
|
def determine_extract_path extension
|
|
25
30
|
base_name = File.basename archive_path, '.*'
|
|
26
|
-
dir_name = File.dirname
|
|
31
|
+
dir_name = File.dirname archive_path
|
|
27
32
|
archive_name = base_name
|
|
28
33
|
|
|
29
34
|
archive_name << ".#{extension}" if extension
|
|
@@ -32,33 +37,43 @@ class ComicBook
|
|
|
32
37
|
File.expand_path full_path
|
|
33
38
|
end
|
|
34
39
|
|
|
35
|
-
def
|
|
40
|
+
def image_file? filename
|
|
41
|
+
ComicBook::IMAGE_EXTENSIONS.include? File.extname(filename.downcase)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def cleanup_archive_file
|
|
45
|
+
File.delete archive_path
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def create_parent_directory file_path
|
|
49
|
+
parent_dir = File.dirname file_path
|
|
50
|
+
FileUtils.mkdir_p parent_dir
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def extract_contents destination, options
|
|
36
54
|
FileUtils.mkdir_p destination
|
|
37
55
|
|
|
38
56
|
File.open(archive_path, 'rb') do |file|
|
|
39
|
-
SevenZipRuby::Reader.open(file) do |
|
|
40
|
-
|
|
41
|
-
next unless entry.file? && image_file?(entry.path)
|
|
42
|
-
|
|
43
|
-
extract_single_file entry, destination, szr
|
|
44
|
-
end
|
|
57
|
+
SevenZipRuby::Reader.open(file) do |seven_zip_reader|
|
|
58
|
+
extract_files destination, options, seven_zip_reader
|
|
45
59
|
end
|
|
46
60
|
end
|
|
47
61
|
end
|
|
48
62
|
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
def extract_files destination, options, seven_zip_reader
|
|
64
|
+
seven_zip_reader.entries.each do |entry|
|
|
65
|
+
next unless entry.file?
|
|
66
|
+
next if options[:images_only] && !image_file?(entry.path)
|
|
52
67
|
|
|
53
|
-
|
|
68
|
+
extract_single_file entry, destination, seven_zip_reader
|
|
69
|
+
end
|
|
54
70
|
end
|
|
55
71
|
|
|
56
|
-
def
|
|
57
|
-
File.
|
|
58
|
-
|
|
72
|
+
def extract_single_file entry, destination, seven_zip_reader
|
|
73
|
+
file_path = File.join destination, entry.path
|
|
74
|
+
create_parent_directory file_path
|
|
59
75
|
|
|
60
|
-
|
|
61
|
-
ComicBook::IMAGE_EXTENSIONS.include? File.extname(filename.downcase)
|
|
76
|
+
File.binwrite(file_path, seven_zip_reader.extract_data(entry))
|
|
62
77
|
end
|
|
63
78
|
end
|
|
64
79
|
end
|
data/lib/comic_book/cb7.rb
CHANGED
|
@@ -13,34 +13,32 @@ class ComicBook
|
|
|
13
13
|
Extractor.new(path).extract options
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def pages
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
def collect_pages_from_7z
|
|
21
|
-
pages = []
|
|
16
|
+
def pages
|
|
17
|
+
entries = []
|
|
22
18
|
|
|
23
19
|
File.open(path, 'rb') do |file|
|
|
24
|
-
SevenZipRuby::Reader.open(file) do |
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
pages << create_page_from_entry(entry)
|
|
20
|
+
SevenZipRuby::Reader.open(file) do |reader|
|
|
21
|
+
reader.entries.each do |entry|
|
|
22
|
+
entries << entry.path if entry.file?
|
|
29
23
|
end
|
|
30
24
|
end
|
|
31
25
|
end
|
|
32
26
|
|
|
33
|
-
|
|
27
|
+
entries.select { image_file? it }
|
|
28
|
+
.map { create_page_from_entry it }
|
|
29
|
+
.sort_by(&:name)
|
|
34
30
|
end
|
|
35
31
|
|
|
32
|
+
private
|
|
33
|
+
|
|
36
34
|
def create_page_from_entry entry
|
|
37
|
-
basename = File.basename
|
|
35
|
+
basename = File.basename entry
|
|
38
36
|
|
|
39
|
-
ComicBook::Page.new entry
|
|
37
|
+
ComicBook::Page.new entry, basename
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
def image_file? filename
|
|
43
|
-
extension = File.extname
|
|
41
|
+
extension = File.extname filename.downcase
|
|
44
42
|
|
|
45
43
|
ComicBook::IMAGE_EXTENSIONS.include? extension
|
|
46
44
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require_relative 'adapter'
|
|
2
|
+
|
|
3
|
+
class ComicBook
|
|
4
|
+
class CBA < Adapter
|
|
5
|
+
def archive _options = {}
|
|
6
|
+
raise Error, 'CBA archiving not supported (ACE is proprietary)'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def extract _options = {}
|
|
10
|
+
raise Error, 'CBA extraction not yet implemented'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def pages
|
|
14
|
+
raise Error, 'CBA page listing not yet implemented'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
class ComicBook
|
|
2
|
+
class CBR < Adapter
|
|
3
|
+
class Extractor
|
|
4
|
+
def initialize archive_path
|
|
5
|
+
@archive_path = File.expand_path archive_path
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def extract options = {}
|
|
9
|
+
extension = options.fetch :extension, :cb
|
|
10
|
+
delete_original = options.fetch :delete_original, false
|
|
11
|
+
destination_folder = options[:to]
|
|
12
|
+
|
|
13
|
+
destination = destination_folder || determine_extract_path(extension)
|
|
14
|
+
create_destination_directory destination
|
|
15
|
+
extract_contents destination, options
|
|
16
|
+
cleanup_archive_file if delete_original
|
|
17
|
+
|
|
18
|
+
destination
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
attr_reader :archive_path
|
|
24
|
+
|
|
25
|
+
def create_destination_directory destination
|
|
26
|
+
FileUtils.mkdir_p destination
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def determine_extract_path extension
|
|
30
|
+
base_name = File.basename archive_path, '.*'
|
|
31
|
+
dir_name = File.dirname archive_path
|
|
32
|
+
archive_name = base_name
|
|
33
|
+
|
|
34
|
+
archive_name << ".#{extension}" if extension
|
|
35
|
+
|
|
36
|
+
full_path = File.join dir_name, archive_name
|
|
37
|
+
File.expand_path full_path
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def image_file? filename
|
|
41
|
+
ComicBook::IMAGE_EXTENSIONS.include? File.extname(filename.downcase)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def cleanup_archive_file
|
|
45
|
+
File.delete archive_path
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def create_parent_directory file_path
|
|
49
|
+
parent_dir = File.dirname file_path
|
|
50
|
+
FileUtils.mkdir_p parent_dir
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def extract_contents destination, options
|
|
54
|
+
FileUtils.mkdir_p destination
|
|
55
|
+
extract_files destination, options
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def extract_files destination, options
|
|
59
|
+
CLIHelpers.unar_extract archive_path, destination
|
|
60
|
+
delete_non_images destination if options[:images_only]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def delete_non_images destination
|
|
64
|
+
archive_entries = CLIHelpers.lsar_list archive_path
|
|
65
|
+
|
|
66
|
+
archive_entries.each do |entry|
|
|
67
|
+
next if image_file? entry
|
|
68
|
+
|
|
69
|
+
file_path = File.join(destination, entry)
|
|
70
|
+
FileUtils.rm_f file_path
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'shellwords'
|
|
2
|
+
require_relative 'adapter'
|
|
3
|
+
require_relative 'cbr/extractor'
|
|
4
|
+
|
|
5
|
+
class ComicBook
|
|
6
|
+
class CBR < Adapter
|
|
7
|
+
def archive _options = {}
|
|
8
|
+
raise Error, 'CBR archiving not supported (RAR is proprietary)'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def extract options = {}
|
|
12
|
+
Extractor.new(path).extract options
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def pages
|
|
16
|
+
CLIHelpers.lsar_list(path)
|
|
17
|
+
.select { image_file? it }
|
|
18
|
+
.map { create_page_from_entry it }
|
|
19
|
+
.sort_by(&:name)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def create_page_from_entry entry
|
|
25
|
+
basename = File.basename entry
|
|
26
|
+
|
|
27
|
+
ComicBook::Page.new entry, basename
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def image_file? filename
|
|
31
|
+
extension = File.extname filename.downcase
|
|
32
|
+
|
|
33
|
+
ComicBook::IMAGE_EXTENSIONS.include? extension
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -6,14 +6,14 @@ class ComicBook
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def archive options = {}
|
|
9
|
-
extension
|
|
10
|
-
destination = options[:to] || determine_output_path(extension)
|
|
9
|
+
extension = options.fetch :extension, :cbt
|
|
11
10
|
delete_original = options.fetch :delete_original, false
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
output_path = options[:to] || determine_output_path(extension)
|
|
13
|
+
create_archive output_path
|
|
14
14
|
cleanup_source_folder if delete_original
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
output_path
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
private
|
|
@@ -27,43 +27,34 @@ class ComicBook
|
|
|
27
27
|
File.expand_path File.join(dir_name, "#{base_name}.#{extension}")
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
def
|
|
31
|
-
File.open(
|
|
32
|
-
Gem::Package::TarWriter.new(file) do |
|
|
33
|
-
|
|
30
|
+
def create_archive output_path
|
|
31
|
+
File.open(output_path, 'wb') do |file|
|
|
32
|
+
Gem::Package::TarWriter.new(file) do |writer|
|
|
33
|
+
find_image_files.each do |image_file|
|
|
34
|
+
add_file writer, image_file
|
|
35
|
+
end
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
full_path = File.join(folder, entry)
|
|
43
|
-
tar_path = prefix.empty? ? entry : File.join(prefix, entry)
|
|
44
|
-
|
|
45
|
-
if File.directory?(full_path)
|
|
46
|
-
add_files_to_tar tar, full_path, tar_path
|
|
47
|
-
elsif image_file?(entry)
|
|
48
|
-
add_file_to_tar tar, full_path, tar_path
|
|
49
|
-
end
|
|
50
|
-
end
|
|
40
|
+
def find_image_files
|
|
41
|
+
pattern = File.join(source_folder, '**', ComicBook::IMAGE_GLOB_PATTERN)
|
|
42
|
+
Dir.glob(pattern, File::FNM_CASEFOLD).sort
|
|
51
43
|
end
|
|
52
44
|
|
|
53
|
-
def
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
def add_file writer, file
|
|
46
|
+
file_path = Pathname.new file
|
|
47
|
+
source_path = Pathname.new source_folder
|
|
48
|
+
relative_path = file_path.relative_path_from source_path
|
|
49
|
+
|
|
50
|
+
stat = File.stat file
|
|
51
|
+
writer.add_file(relative_path.to_s, stat.mode) do |io|
|
|
52
|
+
File.open(file, 'rb') do |f|
|
|
53
|
+
io.write f.read
|
|
58
54
|
end
|
|
59
55
|
end
|
|
60
56
|
end
|
|
61
57
|
|
|
62
|
-
def image_file? filename
|
|
63
|
-
extension = File.extname(filename.downcase)
|
|
64
|
-
ComicBook::IMAGE_EXTENSIONS.include? extension
|
|
65
|
-
end
|
|
66
|
-
|
|
67
58
|
def cleanup_source_folder
|
|
68
59
|
FileUtils.rm_rf source_folder
|
|
69
60
|
end
|