Add a choice

This commit is contained in:
2024-03-08 20:26:38 +08:00
parent 3982a2b9c2
commit 4a39c3afb6
6 changed files with 141 additions and 6 deletions

View File

@@ -8,3 +8,18 @@ python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
# Usage
## Termux
```shell
sudo python main.py -r
# Only export as txt file
sudo python main.py --type=txt -r
# Only export as epub file
sudo python main.py --type=epub -r
# Export all supported type
sudo python main.py --type=epub,txt -r
# Export single chapter with chapter id
sudo python main.py ec -C <chapterid>
# Export book with book id
sudo python main.py eb -B <bookid>
```

View File

@@ -21,6 +21,7 @@ class Config:
self._data['type'] = 'epub,txt'
self._data['export_book_template'] = 'exported/<book_name> - <author_name>.<ext>' # noqa: E501
self._data['export_chapter_template'] = 'exported/<book_id>/<chapter_id>.txt' # noqa: E501
self._data['page_size'] = 10
self.save()
def add_args(self, args: Namespace):
@@ -100,6 +101,10 @@ class Config:
def key(self):
return self.get_arg('key', None)
@cached_property
def page_size(self):
return self.get_arg('page_size', 10)
@cached_property
def save_to_config(self):
return getattr(self._args, 'save_to_config', True)

View File

@@ -7,6 +7,9 @@ from crypto import decrypt
from os.path import dirname
from os import makedirs
from epub import EpubFile
from utils import ask_choice
import json
from random import choice
key_imported = False
@@ -86,9 +89,9 @@ def export_book(ncw: NovelCiwei, db: CwmDb, cfg: Config, bn: BooksNew,
print('TODO: add division description to epub.')
chapter_index = 1
for chapter in maps[division['division_id']]:
chapter_id = chapter['chapter_id']
chapter_title = chapter['chapter_title']
if chapter['is_download']:
chapter_id = chapter['chapter_id']
chapter_title = chapter['chapter_title']
raw_content = bn.get_chapter(book_id, chapter_id)
content = try_decrypt(db, cfg, raw_content, chapter_id)
if cfg.export_txt:
@@ -107,3 +110,36 @@ def export_book(ncw: NovelCiwei, db: CwmDb, cfg: Config, bn: BooksNew,
txt.close()
if cfg.export_epub:
epub.save_epub_file()
def export(ncw: NovelCiwei, db: CwmDb, cfg: Config, bn: BooksNew):
action = ask_choice(cfg, [], '请选择要导出的类型:', extra=[
('b', '整本书', 'book'), ('c', '单章', 'chapter')])
books = ncw.get_books()
shelfs = {}
for book in books:
shelf_id = book['shelf_id']
if shelf_id in shelfs:
shelfs[shelf_id].append(book)
else:
shelfs[shelf_id] = [book]
def show_shelf(shelf: str):
data = f"{shelf} ({len(shelfs[shelf])} 本书)"
book = json.loads(choice(shelfs[shelf])['book_info'])
data += f"\n书架内有 {book['book_name']} - {book['author_name']}"
return data
shelf = ask_choice(cfg, [i for i in shelfs.keys()], '请选择书架:', show_shelf)
books = [json.loads(b['book_info']) for b in shelfs[shelf]]
book = ask_choice(cfg, books, '请选择书:', lambda b: f"{b['book_name']} - {b['author_name']}") # noqa: E501
book_id = int(book['book_id'])
if action == 'book':
export_book(ncw, db, cfg, bn, book_id)
elif action == 'chapter':
divisions = ncw.get_divisions_with_bookid(book_id)
division = ask_choice(cfg, divisions, '请选择卷:', lambda b: b['division_name']) # noqa: E501
division_id = int(division['division_id'])
chapters = ncw.get_chapter_with_bookid_division(book_id, division_id)
chapter = ask_choice(cfg, chapters, '请选择章节:', lambda b: b['chapter_title']) # noqa: E501
chapter_id = int(chapter['chapter_id'])
export_chapter(ncw, db, cfg, bn, chapter_id)

20
main.py
View File

@@ -18,7 +18,8 @@ parser.add_argument('-B', '--bid', '--book-id', help='The book id.', type=int)
parser.add_argument('-t', '--type', help='Export type. Available types: epub, txt. Default: epub,txt') # noqa: E501
parser.add_argument('--ebt', '--export-book-template', help='The template of the exported book. Available key: <ext>, <book_id>, <book_name>, <author_name> eta.') # noqa: E501
parser.add_argument('--icd', '--image-cache-dir', help='Path to image cache directory.') # noqa: E501
parser.add_argument('action', help='The action to do.', choices=['importkey', 'exportchapter', 'exportbook']) # noqa: E501
parser.add_argument('-s', '--page-size', help='Maximum size of a page when asking for choices.', type=int) # noqa: E501
parser.add_argument('action', help='The action to do.', choices=['importkey', 'exportchapter', 'exportbook', 'export', 'ik', 'ec', 'eb', 'e'], nargs='?', default='export') # noqa: E501
def main(args=None):
@@ -32,12 +33,12 @@ def main(args=None):
cfg.add_args(arg)
try:
db = CwmDb(cfg.db)
if arg.action == 'importkey':
if arg.action == 'importkey' or arg.action == 'ik':
if cfg.key is None:
raise ValueError('The key is not specified.')
from key import import_keys
import_keys(cfg.key, db)
elif arg.action == 'exportchapter':
elif arg.action == 'exportchapter' or arg.action == 'ec':
if cfg.cwmdb is None:
raise ValueError('The cwmdb is not specified.')
ncw = NovelCiwei(cfg.cwmdb)
@@ -48,7 +49,7 @@ def main(args=None):
raise ValueError('The chapter id is not specified.')
from export import export_chapter
export_chapter(ncw, db, cfg, bn, cfg.chapter_id)
elif arg.action == 'exportbook':
elif arg.action == 'exportbook' or arg.action == 'eb':
if cfg.cwmdb is None:
raise ValueError('The cwmdb is not specified.')
ncw = NovelCiwei(cfg.cwmdb)
@@ -61,6 +62,17 @@ def main(args=None):
raise ValueError('At least one export type should be specified.') # noqa: E501
from export import export_book
export_book(ncw, db, cfg, bn, cfg.book_id)
elif arg.action == 'export' or arg.action == 'e':
if cfg.cwmdb is None:
raise ValueError('The cwmdb is not specified.')
ncw = NovelCiwei(cfg.cwmdb)
if cfg.booksnew is None:
raise ValueError('The booksnew is not specified.')
bn = BooksNew(cfg.booksnew)
if not cfg.export_epub and not cfg.export_txt:
raise ValueError('At least one export type should be specified.') # noqa: E501
from export import export
export(ncw, db, cfg, bn)
finally:
cfg.save()

View File

@@ -13,6 +13,11 @@ class NovelCiwei:
for i in cur:
return json.loads(i[0])
def get_books(self):
cur = self._db.execute('SELECT * FROM shelf_book_info;')
cur.row_factory = sqlite3.Row
return cur.fetchall()
def get_chapter_with_bookid(self, book_id: int):
cur = self._db.execute(
'SELECT * FROM catalog1 WHERE book_id = ? ORDER BY chapter_index;',
@@ -20,6 +25,13 @@ class NovelCiwei:
cur.row_factory = sqlite3.Row
return cur.fetchall()
def get_chapter_with_bookid_division(self, book_id: int, division_id: int):
cur = self._db.execute(
'SELECT * FROM catalog1 WHERE book_id = ? AND division_id = ? AND is_download = 1 ORDER BY chapter_index;', # noqa: E501
[str(book_id), str(division_id)])
cur.row_factory = sqlite3.Row
return cur.fetchall()
def get_divisions_with_bookid(self, book_id: int):
cur = self._db.execute('SELECT * FROM division WHERE book_id = ? ORDER BY division_index;', [str(book_id)]) # noqa: E501
cur.row_factory = sqlite3.Row

55
utils.py Normal file
View File

@@ -0,0 +1,55 @@
from config import Config
from math import ceil
def ask_choice(cfg: Config, choices: list, prompt='请选择:', fn=None, extra=None):
count = len(choices)
total_pages = ceil(count / cfg.page_size)
page = 1
def show_page():
nonlocal page
base = (page - 1) * cfg.page_size
if total_pages > 1:
print(f"{page}/{total_pages}")
for i in range(cfg.page_size):
index = base + i
if index >= count:
break
s = fn(choices[index]) if fn else choices[index]
print(f"{i}. {s}")
if page > 1:
print("f. 第一页")
print("p. 上一页")
if page < total_pages:
print("n. 下一页")
print("l. 最后一页")
if extra is not None:
for t in extra:
print(f"{t[0]}. {t[1]}")
while True:
show_page()
s = input(prompt)
if s == "f":
page = 1
elif s == "p":
page = max(1, page - 1)
elif s == "n":
page = min(total_pages, page + 1)
elif s == "l":
page = total_pages
else:
if extra is not None:
for t in extra:
if t[0] == s:
return t[2]
try:
index = int(s)
except Exception:
continue
base = (page - 1) * cfg.page_size
index += base
if index < 0 or index >= count:
continue
return choices[index]