my_manga 1.1.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/db/config.yml +3 -3
- data/db/connection.rb +16 -12
- data/db/migrate/002_add_zine_to_manga.rb +3 -0
- data/lib/my_manga.rb +12 -0
- data/lib/my_manga/cli.rb +2 -0
- data/lib/my_manga/list.rb +19 -11
- data/lib/my_manga/version.rb +1 -1
- data/lib/my_manga/zine.rb +112 -0
- data/test/features_test.rb +24 -19
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b196ef7ec4b300ded6dc4a9270fa49d49ff3cfd43dea8f8d233e89132cdd03ad
|
4
|
+
data.tar.gz: 9c6f245d09d9b6c0363f27b6f57c295e16f4f7c17bfb799c1eedb7e596528d5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 600db7c50191c5605d4a92a55fb54886a9fe43cbaae4c94e618d85fc4ba4381c5476cc72cd83f7644be0189064f5797c69b6cb75e442751016306ec98f853b74
|
7
|
+
data.tar.gz: 848b9553b785229c3043ae64293710d9dee26af9b629c00c25b6585b8eeb1c2891158137d235fba5db13d7a1b0877711ee1affd13051b037c189e83349e29693
|
data/db/config.yml
CHANGED
@@ -7,13 +7,13 @@ default: &default
|
|
7
7
|
host: <%= ENV["PG_HOST"] %>
|
8
8
|
reconnect: false
|
9
9
|
# Set these in .bashrc or .bash_profile
|
10
|
-
username: <%= ENV["PG_USER"] %>
|
10
|
+
username: <%= ENV["PG_USER"] %>
|
11
11
|
password: <%= ENV["PG_PASS"] %>
|
12
12
|
|
13
13
|
production:
|
14
14
|
<<: *default
|
15
|
-
database:
|
15
|
+
database: my_manga
|
16
16
|
|
17
17
|
test:
|
18
18
|
<<: *default
|
19
|
-
database:
|
19
|
+
database: my_manga_test
|
data/db/connection.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
module MyManga
|
2
|
-
|
2
|
+
module DB
|
3
3
|
MIGRATION_PATH = File.expand_path('../migrate', __FILE__)
|
4
4
|
CONFIG_PATH = File.expand_path('../config.yml', __FILE__)
|
5
5
|
CONFIG = YAML.load(ERB.new(File.read(CONFIG_PATH)).result)[MyManga.env]
|
6
6
|
|
7
|
-
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def establish_connection
|
8
10
|
ActiveRecord::Base.establish_connection(CONFIG)
|
9
|
-
end
|
11
|
+
end
|
10
12
|
|
11
|
-
def
|
13
|
+
def establish_base_connection
|
12
14
|
ActiveRecord::Base.establish_connection(
|
13
15
|
CONFIG.merge(
|
14
16
|
{
|
@@ -19,26 +21,28 @@ module MyManga
|
|
19
21
|
)
|
20
22
|
end
|
21
23
|
|
22
|
-
def
|
24
|
+
def connection
|
23
25
|
ActiveRecord::Base.connection
|
24
26
|
end
|
25
27
|
|
26
|
-
def
|
28
|
+
def create_database
|
27
29
|
connection.create_database(CONFIG["database"], CONFIG)
|
28
30
|
end
|
29
31
|
|
30
|
-
def
|
32
|
+
def drop_database
|
31
33
|
connection.drop_database(CONFIG["database"])
|
32
34
|
end
|
33
35
|
|
34
|
-
def
|
35
|
-
ActiveRecord::
|
36
|
+
def migrate
|
37
|
+
ActiveRecord::MigrationContext.new(MIGRATION_PATH).migrate
|
38
|
+
end
|
39
|
+
|
40
|
+
def restore
|
41
|
+
system("pg_restore --verbose --clean --no-acl --no-owner -d #{CONFIG["database"]} #{File.expand_path(__dir__)}/latest.dump")
|
36
42
|
end
|
37
43
|
|
38
|
-
def
|
44
|
+
def dump
|
39
45
|
system("pg_dump -Fc #{CONFIG["database"]} > #{File.expand_path(__dir__)}/latest.dump")
|
40
46
|
end
|
41
47
|
end
|
42
48
|
end
|
43
|
-
|
44
|
-
|
data/lib/my_manga.rb
CHANGED
@@ -30,6 +30,18 @@ module MyManga
|
|
30
30
|
Manga.pluck(:name)
|
31
31
|
end
|
32
32
|
|
33
|
+
def add_to_zine(names)
|
34
|
+
Manga.where(name: names).update(zine: true)
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_from_zine(names)
|
38
|
+
Manga.where(name: names).update(zine: false)
|
39
|
+
end
|
40
|
+
|
41
|
+
def zine
|
42
|
+
Manga.where(zine: true)
|
43
|
+
end
|
44
|
+
|
33
45
|
def add(uri)
|
34
46
|
return if Manga.find_by_uri(uri)
|
35
47
|
|
data/lib/my_manga/cli.rb
CHANGED
@@ -11,6 +11,7 @@ require_relative './update'
|
|
11
11
|
require_relative './mark'
|
12
12
|
require_relative './env'
|
13
13
|
require_relative './m_clean_up'
|
14
|
+
require_relative './zine'
|
14
15
|
|
15
16
|
module MyManga
|
16
17
|
module CLI
|
@@ -37,6 +38,7 @@ module MyManga
|
|
37
38
|
register 'mark', Mark
|
38
39
|
register 'env', Env, aliases: %w[-e --environment]
|
39
40
|
register 'm:clean_up', MCleanUp, aliases: %w[purge]
|
41
|
+
register 'zine', Zine
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
data/lib/my_manga/list.rb
CHANGED
@@ -13,46 +13,54 @@ module MyManga
|
|
13
13
|
names.one? ? list_detail(names.first) : list(names)
|
14
14
|
end
|
15
15
|
|
16
|
+
private
|
17
|
+
|
16
18
|
def list(names)
|
17
19
|
column_width = names.map(&:length).max || 10
|
18
20
|
|
19
21
|
puts 'Manga list'
|
20
22
|
puts '=========='
|
21
23
|
print pad('Name', column_width)
|
22
|
-
puts 'Chapters read/total (unread)'
|
24
|
+
puts 'Zine Chapters read/total (unread)'
|
23
25
|
|
24
26
|
names.sort.each do |name|
|
25
27
|
manga = MyManga[name]
|
26
28
|
read = manga.read_count
|
27
29
|
total = manga.total_count
|
28
30
|
unread = total - read
|
31
|
+
zine = check_box(manga.zine?)
|
29
32
|
|
30
33
|
print pad(name, column_width)
|
31
|
-
puts "#{read}/#{total} (#{unread}) #{manga.uri}"
|
34
|
+
puts "#{zine} #{read}/#{total} (#{unread}) #{manga.uri}"
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
35
38
|
def list_detail(name)
|
36
39
|
manga = MyManga[name]
|
37
40
|
header = %(Manga details for "#{manga.name}")
|
38
|
-
chapters = manga.
|
41
|
+
chapters = manga.chapters.reorder(number: :desc)
|
39
42
|
read = manga.read_count
|
40
43
|
total = manga.total_count
|
41
44
|
unread = total - read
|
45
|
+
zine = check_box(manga.zine?)
|
42
46
|
|
43
47
|
puts header
|
44
48
|
puts '=' * header.length
|
45
49
|
print pad('Name', name.length)
|
46
|
-
puts 'Chapters read/total (unread)'
|
47
|
-
puts "#{name} #{read}/#{total} (#{unread}) #{manga.uri}"
|
50
|
+
puts 'Zine Chapters read/total (unread)'
|
51
|
+
puts "#{name} #{zine} #{read}/#{total} (#{unread}) #{manga.uri}"
|
48
52
|
puts
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
+
|
54
|
+
|
55
|
+
puts 'Read Chapter'
|
56
|
+
puts '------------'
|
57
|
+
chapters.each do |chapter|
|
58
|
+
puts "#{chapter.read? ? ' [X]' : ' [ ]'} #{chapter.name}"
|
53
59
|
end
|
54
|
-
|
55
|
-
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_box(bool)
|
63
|
+
bool ? ' [X]' : ' [ ]'
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
data/lib/my_manga/version.rb
CHANGED
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module MyManga
|
6
|
+
module CLI
|
7
|
+
module Commands
|
8
|
+
# See desc
|
9
|
+
class Zine < MyManga::CLI::Command
|
10
|
+
desc 'Build a new zine'
|
11
|
+
argument :names, desc: 'Manga names (comma separated)'
|
12
|
+
|
13
|
+
option :add,
|
14
|
+
type: :boolean,
|
15
|
+
default: false,
|
16
|
+
desc: 'Add manga to zine'
|
17
|
+
option :remove,
|
18
|
+
type: :boolean,
|
19
|
+
default: false,
|
20
|
+
desc: 'Remove manga from zine'
|
21
|
+
option :size,
|
22
|
+
default: '10',
|
23
|
+
desc: 'Number of chapters to include in the zine'
|
24
|
+
option :filename,
|
25
|
+
desc: 'Filename for the zine, (default `zine-<timestamp>-<hash of chapters included>`)'
|
26
|
+
|
27
|
+
TMP_DIR = File.expand_path('../../tmp', __dir__)
|
28
|
+
|
29
|
+
def call(names: nil, **options)
|
30
|
+
names = manga_names(names)
|
31
|
+
filename = options.fetch(:filename) { nil }
|
32
|
+
size = options.fetch(:size).to_i
|
33
|
+
|
34
|
+
if options[:add] && options[:remove]
|
35
|
+
puts "--add and --remove are mutually exclusive"
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
if options[:add]
|
40
|
+
MyManga.add_to_zine(names)
|
41
|
+
puts %("#{names.join(', ')}" added to the zine!)
|
42
|
+
elsif options[:remove]
|
43
|
+
MyManga.remove_from_zine(names)
|
44
|
+
puts %("#{names.join(', ')}" removed from the zine!)
|
45
|
+
else
|
46
|
+
publish(filename, size)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def publish(filename, size)
|
53
|
+
FileUtils.rm_r(TMP_DIR) if Dir.exist?(TMP_DIR)
|
54
|
+
Dir.mkdir(TMP_DIR)
|
55
|
+
|
56
|
+
zine = zine_content(size)
|
57
|
+
serialized_name = []
|
58
|
+
zine.each do |chapter|
|
59
|
+
serialized_name << chapter.id
|
60
|
+
chapter.to_md.download_to(TMP_DIR)
|
61
|
+
MyManga.read!(chapter.manga, [chapter.number])
|
62
|
+
end
|
63
|
+
|
64
|
+
serialized_name = serialized_name.join.to_i.to_s(32)
|
65
|
+
filename ||= "zine-#{Time.now.to_i}-#{serialized_name}"
|
66
|
+
|
67
|
+
dir = File.join(MyManga.download_dir, filename)
|
68
|
+
|
69
|
+
cbz(dir)
|
70
|
+
|
71
|
+
FileUtils.rm_r(TMP_DIR)
|
72
|
+
|
73
|
+
puts "Pushlished a new zine (#{filename}) in #{MyManga.download_dir}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def zine_content(chapter_count)
|
77
|
+
manga = MyManga.zine
|
78
|
+
chapters = Chapter
|
79
|
+
.unread
|
80
|
+
.where(manga_id: manga.map(&:id))
|
81
|
+
.order(:number)
|
82
|
+
.group_by(&:manga)
|
83
|
+
.values
|
84
|
+
.sort_by(&:length)
|
85
|
+
.reverse
|
86
|
+
|
87
|
+
return if chapters.empty?
|
88
|
+
|
89
|
+
zine = chapters.first.zip(*chapters.drop(1)).flatten.compact
|
90
|
+
zine.first(chapter_count).sort_by do |chapter|
|
91
|
+
[chapter.manga_id, chapter.number]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def cbz(dir)
|
96
|
+
pages = Dir["#{TMP_DIR}/**/*.*"]
|
97
|
+
|
98
|
+
Dir.mkdir(dir) unless Dir.exist?(dir)
|
99
|
+
|
100
|
+
pages.each do |page|
|
101
|
+
filename = File.basename(page)
|
102
|
+
FileUtils.cp(page, File.join(dir, filename))
|
103
|
+
end
|
104
|
+
|
105
|
+
Mangdown::CBZ.one(dir, false)
|
106
|
+
|
107
|
+
FileUtils.rm_r(dir)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/test/features_test.rb
CHANGED
@@ -13,19 +13,19 @@ class FeaturesTest < Minitest::Test
|
|
13
13
|
name: 'Assassination Classroom',
|
14
14
|
read_count: 0,
|
15
15
|
total_count: 161,
|
16
|
-
uri: '
|
16
|
+
uri: 'https://www.mangareader.net/assassination-classroom'
|
17
17
|
},
|
18
18
|
{
|
19
19
|
name: 'Naruto',
|
20
20
|
read_count: 699,
|
21
21
|
total_count: 700,
|
22
|
-
uri: '
|
22
|
+
uri: 'https://www.mangareader.net/naruto'
|
23
23
|
},
|
24
24
|
{
|
25
25
|
name: 'Naruto Movie',
|
26
26
|
read_count: 10,
|
27
27
|
total_count: 10,
|
28
|
-
uri: '
|
28
|
+
uri: 'https://www.mangareader.net/naruto-movie'
|
29
29
|
}
|
30
30
|
]
|
31
31
|
)
|
@@ -63,7 +63,7 @@ class FeaturesTest < Minitest::Test
|
|
63
63
|
)
|
64
64
|
output = stdout.read
|
65
65
|
header = 'Manga found for "assassination classroom"'
|
66
|
-
url = '
|
66
|
+
url = 'https://www.mangareader.net/assassination-classroom'
|
67
67
|
|
68
68
|
assert_equal 0, wait_thr.value
|
69
69
|
assert_includes output, header
|
@@ -72,7 +72,7 @@ class FeaturesTest < Minitest::Test
|
|
72
72
|
|
73
73
|
def test_add
|
74
74
|
_, stdout, _, wait_thr = Open3.popen3(
|
75
|
-
'my_manga', 'add', '
|
75
|
+
'my_manga', 'add', 'https://www.mangareader.net/nisekoi'
|
76
76
|
)
|
77
77
|
output = stdout.each_line.to_a
|
78
78
|
expected = <<~EXP
|
@@ -106,10 +106,10 @@ class FeaturesTest < Minitest::Test
|
|
106
106
|
expected = <<~EXP
|
107
107
|
Manga list
|
108
108
|
==========
|
109
|
-
Name Chapters read/total (unread)
|
110
|
-
Assassination Classroom
|
111
|
-
Naruto
|
112
|
-
Naruto Movie
|
109
|
+
Name Zine Chapters read/total (unread)
|
110
|
+
Assassination Classroom [ ] 0/161 (161) https://www.mangareader.net/assassination-classroom
|
111
|
+
Naruto [ ] 699/700 (1) https://www.mangareader.net/naruto
|
112
|
+
Naruto Movie [ ] 10/10 (0) https://www.mangareader.net/naruto-movie
|
113
113
|
EXP
|
114
114
|
expected = expected.split("\n").map { |line| line << "\n" }
|
115
115
|
|
@@ -123,16 +123,21 @@ class FeaturesTest < Minitest::Test
|
|
123
123
|
expected = <<~EXP
|
124
124
|
Manga details for "Naruto Movie"
|
125
125
|
================================
|
126
|
-
Name Chapters read/total (unread)
|
127
|
-
Naruto Movie
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
126
|
+
Name Zine Chapters read/total (unread)
|
127
|
+
Naruto Movie [ ] 10/10 (0) https://www.mangareader.net/naruto-movie
|
128
|
+
|
129
|
+
Read Chapter
|
130
|
+
------------
|
131
|
+
[X] Naruto Movie 1
|
132
|
+
[X] Naruto Movie 2
|
133
|
+
[X] Naruto Movie 3
|
134
|
+
[X] Naruto Movie 4
|
135
|
+
[X] Naruto Movie 5
|
136
|
+
[X] Naruto Movie 6
|
137
|
+
[X] Naruto Movie 7
|
138
|
+
[X] Naruto Movie 8
|
139
|
+
[X] Naruto Movie 9
|
140
|
+
[X] Naruto Movie 10
|
136
141
|
EXP
|
137
142
|
expected = expected.split("\n").map { |line| line << "\n" }
|
138
143
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: my_manga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jphager2
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '5.
|
19
|
+
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '5.
|
26
|
+
version: '5.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: hanami-cli
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,28 +44,28 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.19.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.19.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: pg
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '1.1'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '1.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rubocop
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +108,7 @@ files:
|
|
108
108
|
- db/connection.rb
|
109
109
|
- db/environment.rb
|
110
110
|
- db/migrate/001_add_tables.rb
|
111
|
+
- db/migrate/002_add_zine_to_manga.rb
|
111
112
|
- lib/mangdown/adapters/manga_here.rb
|
112
113
|
- lib/my_manga.rb
|
113
114
|
- lib/my_manga/add.rb
|
@@ -122,6 +123,7 @@ files:
|
|
122
123
|
- lib/my_manga/remove.rb
|
123
124
|
- lib/my_manga/update.rb
|
124
125
|
- lib/my_manga/version.rb
|
126
|
+
- lib/my_manga/zine.rb
|
125
127
|
- models/chapter.rb
|
126
128
|
- models/manga.rb
|
127
129
|
- test/adapters_test.rb
|
@@ -147,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
149
|
version: '0'
|
148
150
|
requirements: []
|
149
151
|
rubyforge_project:
|
150
|
-
rubygems_version: 2.
|
152
|
+
rubygems_version: 2.7.7
|
151
153
|
signing_key:
|
152
154
|
specification_version: 4
|
153
155
|
summary: Manage Manga Downloads
|