Add mark as non-linear division mannally
This commit is contained in:
@@ -63,6 +63,10 @@ class Config:
|
|||||||
def db(self):
|
def db(self):
|
||||||
return self.get_arg('db', 'cwm.db')
|
return self.get_arg('db', 'cwm.db')
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def division_id(self):
|
||||||
|
return getattr(self._args, 'division_id', None)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def export_book_template(self):
|
def export_book_template(self):
|
||||||
return self.get_arg('export_book_template', 'exported/<book_name> - <author_name>.<ext>') # noqa: E501
|
return self.get_arg('export_book_template', 'exported/<book_name> - <author_name>.<ext>') # noqa: E501
|
||||||
@@ -116,6 +120,10 @@ class Config:
|
|||||||
def key(self):
|
def key(self):
|
||||||
return self.get_arg('key', None)
|
return self.get_arg('key', None)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def linear(self):
|
||||||
|
return getattr(self._args, 'linear', False)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def page_size(self):
|
def page_size(self):
|
||||||
return self.get_arg('page_size', 10)
|
return self.get_arg('page_size', 10)
|
||||||
|
|||||||
26
db.py
26
db.py
@@ -14,12 +14,17 @@ user_id INT,
|
|||||||
key TEXT,
|
key TEXT,
|
||||||
PRIMARY KEY (chapter_id, user_id)
|
PRIMARY KEY (chapter_id, user_id)
|
||||||
);'''
|
);'''
|
||||||
|
DIVISION_TABLE = '''CREATE TABLE division(
|
||||||
|
division_id INT,
|
||||||
|
is_linear BOOL,
|
||||||
|
PRIMARY KEY(division_id)
|
||||||
|
);'''
|
||||||
|
|
||||||
|
|
||||||
class CwmDb:
|
class CwmDb:
|
||||||
def __init__(self, db_path):
|
def __init__(self, db_path):
|
||||||
self._db = sqlite3.connect(db_path, check_same_thread=False)
|
self._db = sqlite3.connect(db_path, check_same_thread=False)
|
||||||
self.version = Version(0, 0, 0, 0)
|
self.version = Version(0, 0, 0, 1)
|
||||||
if not self.__check_database():
|
if not self.__check_database():
|
||||||
self.__create_table()
|
self.__create_table()
|
||||||
|
|
||||||
@@ -29,6 +34,8 @@ class CwmDb:
|
|||||||
if v is None:
|
if v is None:
|
||||||
return False
|
return False
|
||||||
if v < self.version:
|
if v < self.version:
|
||||||
|
if v < Version(0, 0, 0, 1):
|
||||||
|
self._db.execute(DIVISION_TABLE)
|
||||||
self.__update_exists_tables()
|
self.__update_exists_tables()
|
||||||
self.__write_version()
|
self.__write_version()
|
||||||
return True
|
return True
|
||||||
@@ -44,6 +51,7 @@ class CwmDb:
|
|||||||
def __write_version(self):
|
def __write_version(self):
|
||||||
self._db.execute('INSERT OR REPLACE INTO version VALUES (?, ?);', [
|
self._db.execute('INSERT OR REPLACE INTO version VALUES (?, ?);', [
|
||||||
'main', str(self.version)])
|
'main', str(self.version)])
|
||||||
|
self._db.commit()
|
||||||
|
|
||||||
def __read_version(self) -> Optional[Version]:
|
def __read_version(self) -> Optional[Version]:
|
||||||
if 'version' not in self._exist_tables:
|
if 'version' not in self._exist_tables:
|
||||||
@@ -71,7 +79,23 @@ class CwmDb:
|
|||||||
cur = self._db.execute('SELECT chapter_id, user_id, key FROM key;')
|
cur = self._db.execute('SELECT chapter_id, user_id, key FROM key;')
|
||||||
return {f'{i[0]}{i[1]}': i[2] for i in cur}
|
return {f'{i[0]}{i[1]}': i[2] for i in cur}
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
self._db.commit()
|
||||||
|
|
||||||
def get_key(self, chapter_id: int) -> List[str]:
|
def get_key(self, chapter_id: int) -> List[str]:
|
||||||
cur = self._db.execute('SELECT key FROM key WHERE chapter_id = ?;', [
|
cur = self._db.execute('SELECT key FROM key WHERE chapter_id = ?;', [
|
||||||
chapter_id])
|
chapter_id])
|
||||||
return [i[0] for i in cur]
|
return [i[0] for i in cur]
|
||||||
|
|
||||||
|
def get_mark(self, division_id: int):
|
||||||
|
cur = self._db.execute(
|
||||||
|
'SELECT is_linear FROM division WHERE division_id = ?;',
|
||||||
|
[division_id])
|
||||||
|
for i in cur:
|
||||||
|
return bool(i[0])
|
||||||
|
return True
|
||||||
|
|
||||||
|
def set_mark(self, division_id: int, is_linear: bool):
|
||||||
|
self._db.execute('INSERT OR REPLACE INTO division VALUES (?, ?);', [
|
||||||
|
division_id, is_linear])
|
||||||
|
self._db.commit()
|
||||||
|
|||||||
12
epub.py
12
epub.py
@@ -344,7 +344,8 @@ class EpubFile:
|
|||||||
self.epub.spine.append(intro)
|
self.epub.spine.append(intro)
|
||||||
self.last_division_name = ''
|
self.last_division_name = ''
|
||||||
|
|
||||||
def add_chapter(self, chapter, content: str, division_name: str):
|
def add_chapter(self, chapter, content: str, division_name: str,
|
||||||
|
is_linear: bool):
|
||||||
chapter_title = chapter['chapter_title']
|
chapter_title = chapter['chapter_title']
|
||||||
chapter_id = chapter['chapter_id']
|
chapter_id = chapter['chapter_id']
|
||||||
ch = epub.EpubHtml(
|
ch = epub.EpubHtml(
|
||||||
@@ -353,8 +354,7 @@ class EpubFile:
|
|||||||
lang='zh-CN',
|
lang='zh-CN',
|
||||||
uid=f'ch{chapter_id}',
|
uid=f'ch{chapter_id}',
|
||||||
)
|
)
|
||||||
if division_name == '作品相关':
|
ch.is_linear = is_linear
|
||||||
ch.is_linear = False
|
|
||||||
parser = ContentParser(self.cfg)
|
parser = ContentParser(self.cfg)
|
||||||
contents = content.splitlines()
|
contents = content.splitlines()
|
||||||
try:
|
try:
|
||||||
@@ -392,7 +392,8 @@ class EpubFile:
|
|||||||
self.EpubList.append(ch)
|
self.EpubList.append(ch)
|
||||||
self.epub.spine.append(ch)
|
self.epub.spine.append(ch)
|
||||||
|
|
||||||
def add_nodownload_chapter(self, chapter, division_name: str):
|
def add_nodownload_chapter(self, chapter, division_name: str,
|
||||||
|
is_linear: bool):
|
||||||
chapter_title = chapter['chapter_title']
|
chapter_title = chapter['chapter_title']
|
||||||
chapter_id = chapter['chapter_id']
|
chapter_id = chapter['chapter_id']
|
||||||
ch = epub.EpubHtml(
|
ch = epub.EpubHtml(
|
||||||
@@ -401,8 +402,7 @@ class EpubFile:
|
|||||||
lang='zh-CN',
|
lang='zh-CN',
|
||||||
uid=f'ch{chapter_id}',
|
uid=f'ch{chapter_id}',
|
||||||
)
|
)
|
||||||
if division_name == '作品相关':
|
ch.is_linear = is_linear
|
||||||
ch.is_linear = False
|
|
||||||
ch.content = f'<h1 style="text-align: center;">{chapter_title}</h1>\n<p>本章未下载</p>' # noqa: E501
|
ch.content = f'<h1 style="text-align: center;">{chapter_title}</h1>\n<p>本章未下载</p>' # noqa: E501
|
||||||
self.epub.add_item(ch)
|
self.epub.add_item(ch)
|
||||||
if self.last_division_name != division_name:
|
if self.last_division_name != division_name:
|
||||||
|
|||||||
160
export.py
160
export.py
@@ -94,6 +94,7 @@ def export_book(ncw: NovelCiwei, db: CwmDb, cfg: Config, bn: BooksNew,
|
|||||||
for division in divisions:
|
for division in divisions:
|
||||||
division_name = division['division_name']
|
division_name = division['division_name']
|
||||||
division_id = division['division_id']
|
division_id = division['division_id']
|
||||||
|
is_linear = db.get_mark(division_id)
|
||||||
if cfg.export_txt:
|
if cfg.export_txt:
|
||||||
txt.write(f"第{division['division_index']}卷 {division_name}\n")
|
txt.write(f"第{division['division_index']}卷 {division_name}\n")
|
||||||
if division['description']:
|
if division['description']:
|
||||||
@@ -113,13 +114,15 @@ def export_book(ncw: NovelCiwei, db: CwmDb, cfg: Config, bn: BooksNew,
|
|||||||
txt.write(f"第{chapter_index}章 {chapter_title}\n")
|
txt.write(f"第{chapter_index}章 {chapter_title}\n")
|
||||||
txt.write(content + '\n\n')
|
txt.write(content + '\n\n')
|
||||||
if cfg.export_epub:
|
if cfg.export_epub:
|
||||||
epub.add_chapter(chapter, content, division_name)
|
epub.add_chapter(chapter, content, division_name,
|
||||||
|
is_linear)
|
||||||
count += 1
|
count += 1
|
||||||
elif cfg.export_nodownload:
|
elif cfg.export_nodownload:
|
||||||
if cfg.export_txt:
|
if cfg.export_txt:
|
||||||
txt.write(f"第{chapter_index}章 {chapter_title} (未下载)\n\n") # noqa: E501
|
txt.write(f"第{chapter_index}章 {chapter_title} (未下载)\n\n") # noqa: E501
|
||||||
if cfg.export_epub:
|
if cfg.export_epub:
|
||||||
epub.add_nodownload_chapter(chapter, division_name)
|
epub.add_nodownload_chapter(chapter, division_name,
|
||||||
|
is_linear)
|
||||||
chapter_index += 1
|
chapter_index += 1
|
||||||
print(f'Exported {count} chapters.')
|
print(f'Exported {count} chapters.')
|
||||||
finally:
|
finally:
|
||||||
@@ -139,49 +142,114 @@ def export_all(ncw: NovelCiwei, db: CwmDb, cfg: Config, bn: BooksNew):
|
|||||||
print(f'Failed to export book {book_id}: {e}')
|
print(f'Failed to export book {book_id}: {e}')
|
||||||
|
|
||||||
|
|
||||||
def export(ncw: NovelCiwei, db: CwmDb, cfg: Config, bn: BooksNew):
|
class ExportCli:
|
||||||
action = ask_choice(cfg, [], '请选择要导出的类型:', extra=[
|
def __init__(self, ncw: NovelCiwei, db: CwmDb, cfg: Config, bn: BooksNew):
|
||||||
('b', '整本书', 'book'), ('c', '单章', 'chapter'),
|
self.ncw = ncw
|
||||||
('a', '所有书', 'all')])
|
self.db = db
|
||||||
if action == 'all':
|
self.cfg = cfg
|
||||||
export_all(ncw, db, cfg, bn)
|
self.bn = bn
|
||||||
return
|
self.action = None
|
||||||
books = ncw.get_books()
|
self.shelf = None
|
||||||
shelfs = {}
|
self.shelfs = None
|
||||||
for book in books:
|
self.book = None
|
||||||
shelf_id = book['shelf_id']
|
self.book_id = None
|
||||||
if shelf_id in shelfs:
|
self.division_id = None
|
||||||
shelfs[shelf_id].append(book)
|
self.fns = [self.ask_action]
|
||||||
else:
|
|
||||||
shelfs[shelf_id] = [book]
|
|
||||||
|
|
||||||
def show_shelf(shelf: str):
|
def ask_action(self):
|
||||||
data = f"{shelf} ({len(shelfs[shelf])} 本书)"
|
self.action = ask_choice(self.cfg, [], '请选择要导出的类型:', extra=[
|
||||||
book = json.loads(choice(shelfs[shelf])['book_info'])
|
('b', '整本书', 'book'), ('c', '单章', 'chapter'), ('a', '所有书', 'all'),
|
||||||
data += f"\n书架内有 {book['book_name']} - {book['author_name']}"
|
('m', '标记为非线性卷', 'mark')])
|
||||||
return data
|
if self.action == 'all':
|
||||||
shelf = ask_choice(cfg, [i for i in shelfs.keys()], '请选择书架:', show_shelf,
|
export_all(self.ncw, self.db, self.cfg, self.bn)
|
||||||
[('r', '阅读历史', 'readhistory'), ('a', '所有书', 'all')])
|
return
|
||||||
if shelf == 'readhistory':
|
self.fns.append(self.ask_shelf)
|
||||||
books = [json.loads(b['book_info']) for b in ncw.get_read_history()]
|
|
||||||
elif shelf == 'all':
|
def ask_book(self):
|
||||||
bookids = [int(b[0]) for b in ncw.get_all_books()]
|
if self.shelf == 'readhistory':
|
||||||
books = []
|
books = [json.loads(b['book_info']) for b in self.ncw.get_read_history()] # noqa: E501
|
||||||
for bid in bookids:
|
elif self.shelf == 'all':
|
||||||
book = ncw.get_book_in_shelf(bid) or ncw.get_book_in_readhistory(bid) # noqa: E501
|
bookids = [int(b[0]) for b in self.ncw.get_all_books()]
|
||||||
if book:
|
books = []
|
||||||
books.append(book)
|
for bid in bookids:
|
||||||
else:
|
book = self.ncw.get_book_in_shelf(bid) or self.ncw.get_book_in_readhistory(bid) # noqa: E501
|
||||||
books = [json.loads(b['book_info']) for b in shelfs[shelf]]
|
if book:
|
||||||
book = ask_choice(cfg, books, '请选择书:', lambda b: f"{b['book_name']} - {b['author_name']}") # noqa: E501
|
books.append(book)
|
||||||
book_id = int(book['book_id'])
|
else:
|
||||||
if action == 'book':
|
books = [json.loads(b['book_info']) for b in self.shelfs[self.shelf]] # noqa: E501
|
||||||
export_book(ncw, db, cfg, bn, book_id)
|
self.book = ask_choice(self.cfg, books, '请选择书:', lambda b: f"{b['book_name']} - {b['author_name']}", [('b', '返回', 'back')]) # noqa: E501
|
||||||
elif action == 'chapter':
|
if self.book == 'back':
|
||||||
divisions = ncw.get_divisions_with_bookid(book_id)
|
self.fns.append(self.ask_shelf)
|
||||||
division = ask_choice(cfg, divisions, '请选择卷:', lambda b: b['division_name']) # noqa: E501
|
return
|
||||||
division_id = int(division['division_id'])
|
self.book_id = int(self.book['book_id'])
|
||||||
chapters = ncw.get_chapter_with_bookid_division(book_id, division_id)
|
if self.action == 'book':
|
||||||
chapter = ask_choice(cfg, chapters, '请选择章节:', lambda b: b['chapter_title']) # noqa: E501
|
export_book(self.ncw, self.db, self.cfg, self.bn, self.book_id)
|
||||||
|
return
|
||||||
|
self.fns.append(self.ask_division)
|
||||||
|
|
||||||
|
def ask_chapter(self):
|
||||||
|
chapters = self.ncw.get_chapter_with_bookid_division(self.book_id, self.division_id) # noqa: E501
|
||||||
|
chapter = ask_choice(self.cfg, chapters, '请选择章节:', lambda b: b['chapter_title'], [('b', '返回', 'back')]) # noqa: E501
|
||||||
|
if chapter == 'back':
|
||||||
|
self.fns.append(self.ask_division)
|
||||||
|
return
|
||||||
chapter_id = int(chapter['chapter_id'])
|
chapter_id = int(chapter['chapter_id'])
|
||||||
export_chapter(ncw, db, cfg, bn, chapter_id)
|
export_chapter(self.ncw, self.db, self.cfg, self.bn, chapter_id)
|
||||||
|
|
||||||
|
def ask_division(self):
|
||||||
|
divisions = self.ncw.get_divisions_with_bookid(self.book_id)
|
||||||
|
extras = [('b', '返回', 'back')]
|
||||||
|
if self.action == 'mark':
|
||||||
|
extras.append(('q', '退出', 'quit'))
|
||||||
|
|
||||||
|
def show_division(division):
|
||||||
|
name = division['division_name']
|
||||||
|
if self.action == 'mark':
|
||||||
|
division_id = int(division['division_id'])
|
||||||
|
if not self.db.get_mark(division_id):
|
||||||
|
name += ' (非线性卷)'
|
||||||
|
return name
|
||||||
|
division = ask_choice(self.cfg, divisions, '请选择卷:', show_division, extras) # noqa: E501
|
||||||
|
if division == 'back':
|
||||||
|
self.fns.append(self.ask_book)
|
||||||
|
return
|
||||||
|
if division == 'quit':
|
||||||
|
return
|
||||||
|
self.division_id = int(division['division_id'])
|
||||||
|
if self.action == 'mark':
|
||||||
|
now = self.db.get_mark(self.division_id)
|
||||||
|
self.db.set_mark(self.division_id, not now)
|
||||||
|
self.fns.append(self.ask_division)
|
||||||
|
return
|
||||||
|
self.fns.append(self.ask_chapter)
|
||||||
|
|
||||||
|
def ask_shelf(self):
|
||||||
|
books = self.ncw.get_books()
|
||||||
|
self.shelfs = {}
|
||||||
|
for book in books:
|
||||||
|
shelf_id = book['shelf_id']
|
||||||
|
if shelf_id in self.shelfs:
|
||||||
|
self.shelfs[shelf_id].append(book)
|
||||||
|
else:
|
||||||
|
self.shelfs[shelf_id] = [book]
|
||||||
|
|
||||||
|
def show_shelf(shelf: str):
|
||||||
|
data = f"{shelf} ({len(self.shelfs[shelf])} 本书)"
|
||||||
|
book = json.loads(choice(self.shelfs[shelf])['book_info'])
|
||||||
|
data += f"\n书架内有 {book['book_name']} - {book['author_name']}"
|
||||||
|
return data
|
||||||
|
self.shelf = ask_choice(self.cfg, [i for i in self.shelfs.keys()],
|
||||||
|
'请选择书架:', show_shelf,
|
||||||
|
[('r', '阅读历史', 'readhistory'),
|
||||||
|
('a', '所有书', 'all'),
|
||||||
|
('b', '返回', 'back')])
|
||||||
|
if self.shelf == 'back':
|
||||||
|
self.fns.append(self.ask_action)
|
||||||
|
return
|
||||||
|
self.fns.append(self.ask_book)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
while True:
|
||||||
|
if len(self.fns) == 0:
|
||||||
|
break
|
||||||
|
self.fns.pop(0)()
|
||||||
|
|||||||
2
key.py
2
key.py
@@ -43,6 +43,6 @@ def import_keys(key: str, db: CwmDb, force=False):
|
|||||||
count += 1
|
count += 1
|
||||||
print(f'Imported {count} keys.')
|
print(f'Imported {count} keys.')
|
||||||
finally:
|
finally:
|
||||||
db._db.commit()
|
db.commit()
|
||||||
if is_zip:
|
if is_zip:
|
||||||
z.close()
|
z.close()
|
||||||
|
|||||||
13
main.py
13
main.py
@@ -23,7 +23,9 @@ parser.add_argument('-s', '--page-size', help='Maximum size of a page when askin
|
|||||||
parser.add_argument('-a', '--export-nodownload', help='export not downloaded chapter when exporting book.', type=parse_bool, metavar='BOOL') # noqa: E501
|
parser.add_argument('-a', '--export-nodownload', help='export not downloaded chapter when exporting book.', type=parse_bool, metavar='BOOL') # noqa: E501
|
||||||
parser.add_argument('-i', '--image-type', help='How to handle images in EPUB. Available types: inline, footnote. Default: inline', choices=['inline', 'footnote'], metavar='TYPE') # noqa: E501
|
parser.add_argument('-i', '--image-type', help='How to handle images in EPUB. Available types: inline, footnote. Default: inline', choices=['inline', 'footnote'], metavar='TYPE') # noqa: E501
|
||||||
parser.add_argument('-f', '--force', help='Force import keys.', action='store_true') # noqa: E501
|
parser.add_argument('-f', '--force', help='Force import keys.', action='store_true') # noqa: E501
|
||||||
parser.add_argument('action', help='The action to do.', choices=['importkey', 'exportchapter', 'exportbook', 'export', 'exportall', 'ik', 'ec', 'eb', 'e', 'ea'], nargs='?', default='export') # noqa: E501
|
parser.add_argument('-D', '--division-id', help='The division id.', type=int, metavar='ID') # noqa: E501
|
||||||
|
parser.add_argument('-l', '--linear', help='Mark as linear.', type=parse_bool, metavar='BOOL', default=False) # noqa: E501
|
||||||
|
parser.add_argument('action', help='The action to do.', choices=['importkey', 'exportchapter', 'exportbook', 'export', 'exportall', 'markaslinear', 'ik', 'ec', 'eb', 'e', 'ea', 'mal'], nargs='?', default='export') # noqa: E501
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
@@ -75,8 +77,9 @@ def main(args=None):
|
|||||||
bn = BooksNew(cfg.booksnew)
|
bn = BooksNew(cfg.booksnew)
|
||||||
if not cfg.export_epub and not cfg.export_txt:
|
if not cfg.export_epub and not cfg.export_txt:
|
||||||
raise ValueError('At least one export type should be specified.') # noqa: E501
|
raise ValueError('At least one export type should be specified.') # noqa: E501
|
||||||
from export import export
|
from export import ExportCli
|
||||||
export(ncw, db, cfg, bn)
|
export = ExportCli(ncw, db, cfg, bn)
|
||||||
|
export.start()
|
||||||
elif arg.action == "exportall" or arg.action == "ea":
|
elif arg.action == "exportall" or arg.action == "ea":
|
||||||
if cfg.cwmdb is None:
|
if cfg.cwmdb is None:
|
||||||
raise ValueError('The cwmdb is not specified.')
|
raise ValueError('The cwmdb is not specified.')
|
||||||
@@ -88,6 +91,10 @@ def main(args=None):
|
|||||||
raise ValueError('At least one export type should be specified.') # noqa: E501
|
raise ValueError('At least one export type should be specified.') # noqa: E501
|
||||||
from export import export_all
|
from export import export_all
|
||||||
export_all(ncw, db, cfg, bn)
|
export_all(ncw, db, cfg, bn)
|
||||||
|
elif arg.action == 'markaslinear' or arg.action == 'mal':
|
||||||
|
if cfg.division_id is None:
|
||||||
|
raise ValueError('The division id is not specified.')
|
||||||
|
db.set_mark(cfg.division_id, cfg.linear)
|
||||||
finally:
|
finally:
|
||||||
cfg.save()
|
cfg.save()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user