novel-downloader 1.3.3__tar.gz → 1.4.1__tar.gz
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.
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/PKG-INFO +69 -35
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/README.md +61 -29
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/__init__.py +1 -1
- novel_downloader-1.4.1/novel_downloader/cli/clean.py +145 -0
- novel_downloader-1.4.1/novel_downloader/cli/config.py +177 -0
- novel_downloader-1.4.1/novel_downloader/cli/download.py +173 -0
- novel_downloader-1.4.1/novel_downloader/cli/export.py +77 -0
- novel_downloader-1.4.1/novel_downloader/cli/main.py +36 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/config/__init__.py +1 -25
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/config/adapter.py +32 -31
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/config/loader.py +3 -3
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/config/site_rules.py +1 -2
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/__init__.py +3 -6
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/downloaders/__init__.py +10 -13
- novel_downloader-1.4.1/novel_downloader/core/downloaders/base.py +233 -0
- novel_downloader-1.4.1/novel_downloader/core/downloaders/biquge.py +27 -0
- novel_downloader-1.4.1/novel_downloader/core/downloaders/common.py +414 -0
- novel_downloader-1.4.1/novel_downloader/core/downloaders/esjzone.py +27 -0
- novel_downloader-1.4.1/novel_downloader/core/downloaders/linovelib.py +27 -0
- novel_downloader-1.4.1/novel_downloader/core/downloaders/qianbi.py +27 -0
- novel_downloader-1.4.1/novel_downloader/core/downloaders/qidian.py +352 -0
- novel_downloader-1.4.1/novel_downloader/core/downloaders/sfacg.py +27 -0
- novel_downloader-1.4.1/novel_downloader/core/downloaders/yamibo.py +27 -0
- novel_downloader-1.4.1/novel_downloader/core/exporters/__init__.py +37 -0
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/base.py +73 -39
- novel_downloader-1.4.1/novel_downloader/core/exporters/biquge.py +25 -0
- novel_downloader-1.4.1/novel_downloader/core/exporters/common/__init__.py +12 -0
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/common/epub.py +22 -22
- novel_downloader-1.3.3/novel_downloader/core/savers/common/main_saver.py → novel_downloader-1.4.1/novel_downloader/core/exporters/common/main_exporter.py +35 -40
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/common/txt.py +20 -23
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/epub_utils/__init__.py +8 -3
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/epub_utils/css_builder.py +2 -2
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/epub_utils/image_loader.py +46 -4
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/epub_utils/initializer.py +6 -4
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/epub_utils/text_to_html.py +3 -3
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/epub_utils/volume_intro.py +2 -2
- novel_downloader-1.4.1/novel_downloader/core/exporters/esjzone.py +25 -0
- novel_downloader-1.4.1/novel_downloader/core/exporters/linovelib/__init__.py +10 -0
- novel_downloader-1.4.1/novel_downloader/core/exporters/linovelib/epub.py +449 -0
- novel_downloader-1.4.1/novel_downloader/core/exporters/linovelib/main_exporter.py +127 -0
- novel_downloader-1.4.1/novel_downloader/core/exporters/linovelib/txt.py +129 -0
- novel_downloader-1.4.1/novel_downloader/core/exporters/qianbi.py +25 -0
- {novel_downloader-1.3.3/novel_downloader/core/savers → novel_downloader-1.4.1/novel_downloader/core/exporters}/qidian.py +8 -8
- novel_downloader-1.4.1/novel_downloader/core/exporters/sfacg.py +25 -0
- novel_downloader-1.4.1/novel_downloader/core/exporters/yamibo.py +25 -0
- novel_downloader-1.4.1/novel_downloader/core/factory/__init__.py +20 -0
- novel_downloader-1.4.1/novel_downloader/core/factory/downloader.py +76 -0
- novel_downloader-1.4.1/novel_downloader/core/factory/exporter.py +58 -0
- novel_downloader-1.4.1/novel_downloader/core/factory/fetcher.py +96 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/factory/parser.py +17 -12
- {novel_downloader-1.3.3/novel_downloader/core/requesters → novel_downloader-1.4.1/novel_downloader/core/fetchers}/__init__.py +22 -15
- {novel_downloader-1.3.3/novel_downloader/core/requesters → novel_downloader-1.4.1/novel_downloader/core/fetchers}/base/__init__.py +2 -4
- novel_downloader-1.4.1/novel_downloader/core/fetchers/base/browser.py +383 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/base/rate_limiter.py +86 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/base/session.py +419 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/biquge/__init__.py +14 -0
- novel_downloader-1.3.3/novel_downloader/core/requesters/biquge/async_session.py → novel_downloader-1.4.1/novel_downloader/core/fetchers/biquge/browser.py +18 -6
- {novel_downloader-1.3.3/novel_downloader/core/requesters → novel_downloader-1.4.1/novel_downloader/core/fetchers}/biquge/session.py +23 -30
- novel_downloader-1.4.1/novel_downloader/core/fetchers/common/__init__.py +14 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/common/browser.py +79 -0
- novel_downloader-1.3.3/novel_downloader/core/requesters/common/async_session.py → novel_downloader-1.4.1/novel_downloader/core/fetchers/common/session.py +8 -25
- novel_downloader-1.4.1/novel_downloader/core/fetchers/esjzone/__init__.py +14 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/esjzone/browser.py +202 -0
- novel_downloader-1.3.3/novel_downloader/core/requesters/esjzone/async_session.py → novel_downloader-1.4.1/novel_downloader/core/fetchers/esjzone/session.py +62 -42
- novel_downloader-1.4.1/novel_downloader/core/fetchers/linovelib/__init__.py +14 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/linovelib/browser.py +193 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/linovelib/session.py +193 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/qianbi/__init__.py +14 -0
- novel_downloader-1.3.3/novel_downloader/core/requesters/qianbi/session.py → novel_downloader-1.4.1/novel_downloader/core/fetchers/qianbi/browser.py +30 -48
- novel_downloader-1.3.3/novel_downloader/core/requesters/qianbi/async_session.py → novel_downloader-1.4.1/novel_downloader/core/fetchers/qianbi/session.py +18 -6
- novel_downloader-1.4.1/novel_downloader/core/fetchers/qidian/__init__.py +14 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/qidian/browser.py +266 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/qidian/session.py +326 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/sfacg/__init__.py +14 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/sfacg/browser.py +189 -0
- novel_downloader-1.3.3/novel_downloader/core/requesters/sfacg/async_session.py → novel_downloader-1.4.1/novel_downloader/core/fetchers/sfacg/session.py +43 -73
- novel_downloader-1.4.1/novel_downloader/core/fetchers/yamibo/__init__.py +14 -0
- novel_downloader-1.4.1/novel_downloader/core/fetchers/yamibo/browser.py +229 -0
- novel_downloader-1.3.3/novel_downloader/core/requesters/yamibo/async_session.py → novel_downloader-1.4.1/novel_downloader/core/fetchers/yamibo/session.py +62 -44
- novel_downloader-1.4.1/novel_downloader/core/interfaces/__init__.py +27 -0
- novel_downloader-1.4.1/novel_downloader/core/interfaces/downloader.py +54 -0
- novel_downloader-1.3.3/novel_downloader/core/interfaces/saver.py → novel_downloader-1.4.1/novel_downloader/core/interfaces/exporter.py +12 -12
- novel_downloader-1.4.1/novel_downloader/core/interfaces/fetcher.py +162 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/interfaces/parser.py +6 -7
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/__init__.py +5 -6
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/base.py +9 -13
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/biquge/main_parser.py +12 -13
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/common/helper.py +3 -3
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/common/main_parser.py +39 -34
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/esjzone/main_parser.py +20 -14
- novel_downloader-1.4.1/novel_downloader/core/parsers/linovelib/__init__.py +10 -0
- novel_downloader-1.4.1/novel_downloader/core/parsers/linovelib/main_parser.py +210 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/qianbi/main_parser.py +21 -15
- novel_downloader-1.4.1/novel_downloader/core/parsers/qidian/__init__.py +10 -0
- novel_downloader-1.4.1/novel_downloader/core/parsers/qidian/book_info_parser.py +113 -0
- {novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/browser → novel_downloader-1.4.1/novel_downloader/core/parsers/qidian}/chapter_encrypted.py +162 -135
- novel_downloader-1.4.1/novel_downloader/core/parsers/qidian/chapter_normal.py +150 -0
- {novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/session → novel_downloader-1.4.1/novel_downloader/core/parsers/qidian}/chapter_router.py +15 -15
- {novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/session → novel_downloader-1.4.1/novel_downloader/core/parsers/qidian}/main_parser.py +48 -42
- novel_downloader-1.4.1/novel_downloader/core/parsers/qidian/utils/__init__.py +27 -0
- novel_downloader-1.4.1/novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py +145 -0
- {novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/shared → novel_downloader-1.4.1/novel_downloader/core/parsers/qidian/utils}/helpers.py +41 -68
- {novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/session → novel_downloader-1.4.1/novel_downloader/core/parsers/qidian/utils}/node_decryptor.py +64 -50
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/sfacg/main_parser.py +12 -12
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/yamibo/main_parser.py +10 -10
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/locales/en.json +18 -2
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/locales/zh.json +18 -2
- novel_downloader-1.4.1/novel_downloader/models/__init__.py +64 -0
- novel_downloader-1.4.1/novel_downloader/models/browser.py +21 -0
- novel_downloader-1.4.1/novel_downloader/models/chapter.py +25 -0
- novel_downloader-1.4.1/novel_downloader/models/config.py +100 -0
- novel_downloader-1.4.1/novel_downloader/models/login.py +20 -0
- novel_downloader-1.4.1/novel_downloader/models/site_rules.py +99 -0
- novel_downloader-1.4.1/novel_downloader/models/tasks.py +33 -0
- novel_downloader-1.4.1/novel_downloader/models/types.py +15 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/resources/config/settings.toml +31 -25
- novel_downloader-1.4.1/novel_downloader/resources/json/linovelib_font_map.json +3573 -0
- novel_downloader-1.4.1/novel_downloader/tui/__init__.py +7 -0
- novel_downloader-1.4.1/novel_downloader/tui/app.py +32 -0
- novel_downloader-1.4.1/novel_downloader/tui/main.py +17 -0
- novel_downloader-1.4.1/novel_downloader/tui/screens/__init__.py +14 -0
- novel_downloader-1.4.1/novel_downloader/tui/screens/home.py +191 -0
- novel_downloader-1.4.1/novel_downloader/tui/screens/login.py +74 -0
- novel_downloader-1.4.1/novel_downloader/tui/styles/home_layout.tcss +79 -0
- novel_downloader-1.4.1/novel_downloader/tui/widgets/richlog_handler.py +24 -0
- novel_downloader-1.4.1/novel_downloader/utils/__init__.py +6 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/chapter_storage.py +25 -38
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/constants.py +11 -5
- novel_downloader-1.4.1/novel_downloader/utils/cookies.py +66 -0
- novel_downloader-1.4.1/novel_downloader/utils/crypto_utils.py +71 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/fontocr/ocr_v1.py +2 -1
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/fontocr/ocr_v2.py +2 -2
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/hash_store.py +10 -18
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/hash_utils.py +3 -2
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/logger.py +2 -3
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/network.py +2 -1
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/text_utils/chapter_formatting.py +6 -1
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/text_utils/font_mapping.py +1 -1
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/text_utils/text_cleaning.py +1 -1
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/time_utils/datetime_utils.py +3 -3
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/time_utils/sleep_utils.py +1 -1
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader.egg-info/PKG-INFO +69 -35
- novel_downloader-1.4.1/novel_downloader.egg-info/SOURCES.txt +173 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader.egg-info/entry_points.txt +1 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader.egg-info/requires.txt +5 -4
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/pyproject.toml +11 -7
- novel_downloader-1.3.3/novel_downloader/cli/clean.py +0 -126
- novel_downloader-1.3.3/novel_downloader/cli/download.py +0 -128
- novel_downloader-1.3.3/novel_downloader/cli/interactive.py +0 -66
- novel_downloader-1.3.3/novel_downloader/cli/main.py +0 -43
- novel_downloader-1.3.3/novel_downloader/cli/settings.py +0 -177
- novel_downloader-1.3.3/novel_downloader/config/models.py +0 -187
- novel_downloader-1.3.3/novel_downloader/core/downloaders/base/__init__.py +0 -14
- novel_downloader-1.3.3/novel_downloader/core/downloaders/base/base_async.py +0 -153
- novel_downloader-1.3.3/novel_downloader/core/downloaders/base/base_sync.py +0 -208
- novel_downloader-1.3.3/novel_downloader/core/downloaders/biquge/__init__.py +0 -14
- novel_downloader-1.3.3/novel_downloader/core/downloaders/biquge/biquge_async.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/biquge/biquge_sync.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/common/__init__.py +0 -14
- novel_downloader-1.3.3/novel_downloader/core/downloaders/common/common_async.py +0 -210
- novel_downloader-1.3.3/novel_downloader/core/downloaders/common/common_sync.py +0 -202
- novel_downloader-1.3.3/novel_downloader/core/downloaders/esjzone/__init__.py +0 -14
- novel_downloader-1.3.3/novel_downloader/core/downloaders/esjzone/esjzone_async.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/esjzone/esjzone_sync.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/qianbi/__init__.py +0 -14
- novel_downloader-1.3.3/novel_downloader/core/downloaders/qianbi/qianbi_async.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/qianbi/qianbi_sync.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/qidian/__init__.py +0 -10
- novel_downloader-1.3.3/novel_downloader/core/downloaders/qidian/qidian_sync.py +0 -219
- novel_downloader-1.3.3/novel_downloader/core/downloaders/sfacg/__init__.py +0 -14
- novel_downloader-1.3.3/novel_downloader/core/downloaders/sfacg/sfacg_async.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/sfacg/sfacg_sync.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/yamibo/__init__.py +0 -14
- novel_downloader-1.3.3/novel_downloader/core/downloaders/yamibo/yamibo_async.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/downloaders/yamibo/yamibo_sync.py +0 -27
- novel_downloader-1.3.3/novel_downloader/core/factory/__init__.py +0 -32
- novel_downloader-1.3.3/novel_downloader/core/factory/downloader.py +0 -178
- novel_downloader-1.3.3/novel_downloader/core/factory/requester.py +0 -144
- novel_downloader-1.3.3/novel_downloader/core/factory/saver.py +0 -56
- novel_downloader-1.3.3/novel_downloader/core/interfaces/__init__.py +0 -31
- novel_downloader-1.3.3/novel_downloader/core/interfaces/async_downloader.py +0 -36
- novel_downloader-1.3.3/novel_downloader/core/interfaces/async_requester.py +0 -84
- novel_downloader-1.3.3/novel_downloader/core/interfaces/sync_downloader.py +0 -36
- novel_downloader-1.3.3/novel_downloader/core/interfaces/sync_requester.py +0 -82
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/__init__.py +0 -19
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/browser/__init__.py +0 -12
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/browser/chapter_normal.py +0 -93
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/browser/chapter_router.py +0 -71
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/browser/main_parser.py +0 -125
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/session/__init__.py +0 -12
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/session/chapter_encrypted.py +0 -443
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/session/chapter_normal.py +0 -115
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/shared/__init__.py +0 -37
- novel_downloader-1.3.3/novel_downloader/core/parsers/qidian/shared/book_info_parser.py +0 -150
- novel_downloader-1.3.3/novel_downloader/core/requesters/base/async_session.py +0 -410
- novel_downloader-1.3.3/novel_downloader/core/requesters/base/browser.py +0 -337
- novel_downloader-1.3.3/novel_downloader/core/requesters/base/session.py +0 -378
- novel_downloader-1.3.3/novel_downloader/core/requesters/biquge/__init__.py +0 -14
- novel_downloader-1.3.3/novel_downloader/core/requesters/common/__init__.py +0 -17
- novel_downloader-1.3.3/novel_downloader/core/requesters/common/session.py +0 -113
- novel_downloader-1.3.3/novel_downloader/core/requesters/esjzone/__init__.py +0 -13
- novel_downloader-1.3.3/novel_downloader/core/requesters/esjzone/session.py +0 -235
- novel_downloader-1.3.3/novel_downloader/core/requesters/qianbi/__init__.py +0 -13
- novel_downloader-1.3.3/novel_downloader/core/requesters/qidian/__init__.py +0 -21
- novel_downloader-1.3.3/novel_downloader/core/requesters/qidian/broswer.py +0 -307
- novel_downloader-1.3.3/novel_downloader/core/requesters/qidian/session.py +0 -290
- novel_downloader-1.3.3/novel_downloader/core/requesters/sfacg/__init__.py +0 -13
- novel_downloader-1.3.3/novel_downloader/core/requesters/sfacg/session.py +0 -242
- novel_downloader-1.3.3/novel_downloader/core/requesters/yamibo/__init__.py +0 -13
- novel_downloader-1.3.3/novel_downloader/core/requesters/yamibo/session.py +0 -237
- novel_downloader-1.3.3/novel_downloader/core/savers/__init__.py +0 -34
- novel_downloader-1.3.3/novel_downloader/core/savers/biquge.py +0 -25
- novel_downloader-1.3.3/novel_downloader/core/savers/common/__init__.py +0 -12
- novel_downloader-1.3.3/novel_downloader/core/savers/esjzone.py +0 -25
- novel_downloader-1.3.3/novel_downloader/core/savers/qianbi.py +0 -25
- novel_downloader-1.3.3/novel_downloader/core/savers/sfacg.py +0 -25
- novel_downloader-1.3.3/novel_downloader/core/savers/yamibo.py +0 -25
- novel_downloader-1.3.3/novel_downloader/resources/config/rules.toml +0 -196
- novel_downloader-1.3.3/novel_downloader/utils/__init__.py +0 -0
- novel_downloader-1.3.3/novel_downloader/utils/crypto_utils.py +0 -144
- novel_downloader-1.3.3/novel_downloader.egg-info/SOURCES.txt +0 -169
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/LICENSE +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/cli/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/biquge/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/common/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/esjzone/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/qianbi/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/sfacg/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/core/parsers/yamibo/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/resources/css_styles/main.css +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/resources/css_styles/volume-intro.css +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/resources/images/volume_border.png +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/resources/js_scripts/qidian_decrypt_node.js +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/resources/json/replace_word_map.json +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/resources/text/blacklist.txt +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/cache.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/file_utils/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/file_utils/io.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/file_utils/normalize.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/file_utils/sanitize.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/fontocr/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/i18n.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/model_loader.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/state.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/text_utils/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/text_utils/diff_display.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader/utils/time_utils/__init__.py +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader.egg-info/dependency_links.txt +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/novel_downloader.egg-info/top_level.txt +0 -0
- {novel_downloader-1.3.3 → novel_downloader-1.4.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: novel-downloader
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.4.1
|
4
4
|
Summary: A command-line tool for downloading Chinese web novels from Qidian and similar platforms.
|
5
5
|
Author-email: Saudade Z <saudadez217@gmail.com>
|
6
6
|
License: MIT License
|
@@ -34,19 +34,18 @@ Classifier: License :: OSI Approved :: MIT License
|
|
34
34
|
Classifier: Natural Language :: Chinese (Simplified)
|
35
35
|
Classifier: Topic :: Utilities
|
36
36
|
Classifier: Programming Language :: Python :: 3
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
37
38
|
Classifier: Programming Language :: Python :: 3.12
|
38
39
|
Classifier: Programming Language :: Python :: 3.13
|
39
|
-
Requires-Python: >=3.
|
40
|
+
Requires-Python: >=3.11
|
40
41
|
Description-Content-Type: text/markdown
|
41
42
|
License-File: LICENSE
|
43
|
+
Requires-Dist: textual
|
42
44
|
Requires-Dist: requests
|
43
45
|
Requires-Dist: aiohttp
|
44
|
-
Requires-Dist:
|
45
|
-
Requires-Dist: DrissionPage
|
46
|
-
Requires-Dist: opencv-python
|
46
|
+
Requires-Dist: playwright
|
47
47
|
Requires-Dist: lxml
|
48
48
|
Requires-Dist: platformdirs
|
49
|
-
Requires-Dist: click
|
50
49
|
Requires-Dist: ebooklib
|
51
50
|
Provides-Extra: dev
|
52
51
|
Requires-Dist: black; extra == "dev"
|
@@ -55,6 +54,8 @@ Requires-Dist: ruff; extra == "dev"
|
|
55
54
|
Requires-Dist: pytest; extra == "dev"
|
56
55
|
Requires-Dist: pytest-cov; extra == "dev"
|
57
56
|
Requires-Dist: pytest-mock; extra == "dev"
|
57
|
+
Requires-Dist: types-requests; extra == "dev"
|
58
|
+
Requires-Dist: types-PyYAML; extra == "dev"
|
58
59
|
Requires-Dist: pre-commit; extra == "dev"
|
59
60
|
Requires-Dist: commitizen; extra == "dev"
|
60
61
|
Provides-Extra: font-recovery
|
@@ -63,32 +64,19 @@ Requires-Dist: numpy; extra == "font-recovery"
|
|
63
64
|
Requires-Dist: tinycss2; extra == "font-recovery"
|
64
65
|
Requires-Dist: fonttools; extra == "font-recovery"
|
65
66
|
Requires-Dist: brotli; extra == "font-recovery"
|
67
|
+
Requires-Dist: opencv-python; extra == "font-recovery"
|
66
68
|
Requires-Dist: pillow; extra == "font-recovery"
|
67
69
|
Requires-Dist: huggingface_hub; extra == "font-recovery"
|
68
70
|
Dynamic: license-file
|
69
71
|
|
70
72
|
# novel-downloader
|
71
73
|
|
72
|
-
一个基于 [
|
74
|
+
一个基于 [playwright](https://playwright.dev/) 和 [aiohttp](https://github.com/aio-libs/aiohttp) 的小说下载工具/库。
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
## 项目简介
|
77
|
-
|
78
|
-
**novel-downloader** 支持多种小说网站的章节抓取与合并导出,
|
79
|
-
- **轻量化抓取**: 绝大多数站点仅依赖 `requests` 实现 HTTP 请求, 无需额外浏览器驱动
|
80
|
-
- 对于起点中文网 (Qidian), 可在配置中选择:
|
81
|
-
- `mode: session` : 纯 Requests 模式
|
82
|
-
- `mode: browser` : 基于 `DrissionPage` 驱动 Chrome 的浏览器模式 (可处理更复杂的 JS/加密)。
|
83
|
-
- **自动登录** (可选)
|
84
|
-
- 配置 `login_required: true` 后自动检测并重用历史 Cookie
|
85
|
-
- 首次登录或 Cookie 失效时:
|
86
|
-
- **browser** 模式: 在程序打开的浏览器窗口登录, 登录后回车继续
|
87
|
-
- **session** 模式: 根据提示粘贴浏览器中已登录的 Cookie (参考 [复制 Cookies](https://github.com/BowenZ217/novel-downloader/blob/main/docs/copy-cookies.md))
|
76
|
+
> 本项目开发环境为 Python 3.12, 需确保运行环境为 Python 3.11 及以上版本
|
88
77
|
|
89
78
|
## 功能特性
|
90
79
|
|
91
|
-
- 抓取起点中文网免费及已订阅章节内容
|
92
80
|
- 支持断点续爬, 自动续传未完成任务
|
93
81
|
- 自动整合所有章节并导出为:
|
94
82
|
- TXT
|
@@ -101,25 +89,71 @@ Dynamic: license-file
|
|
101
89
|
|
102
90
|
## 快速开始
|
103
91
|
|
92
|
+
### 安装
|
93
|
+
|
94
|
+
使用 `pip` 安装:
|
95
|
+
|
104
96
|
```bash
|
105
|
-
# 克隆 + 安装
|
106
97
|
pip install novel-downloader
|
98
|
+
```
|
99
|
+
|
100
|
+
如需使用浏览器模式 (即 `mode: browser`), 请确保已安装 Playwright 依赖:
|
107
101
|
|
108
|
-
|
109
|
-
|
102
|
+
```bash
|
103
|
+
playwright install
|
104
|
+
```
|
110
105
|
|
106
|
+
如需启用字体解密功能 (`decode_font`, 用于处理起点中文网对近一个月更新章节所采用的字体混淆技术), 请使用扩展安装方式:
|
107
|
+
|
108
|
+
```bash
|
109
|
+
pip install novel-downloader[font-recovery]
|
110
|
+
```
|
111
|
+
|
112
|
+
---
|
113
|
+
|
114
|
+
### CLI 模式
|
115
|
+
|
116
|
+
```bash
|
111
117
|
# 初始化默认配置 (生成 settings.toml)
|
112
|
-
novel-cli
|
118
|
+
novel-cli config init
|
113
119
|
|
114
120
|
# 编辑 ./settings.toml 完成 site/book_ids 等
|
115
|
-
# 可查看 docs/
|
121
|
+
# 可查看 docs/3-settings-schema.md
|
116
122
|
|
117
|
-
#
|
123
|
+
# 执行下载任务
|
118
124
|
novel-cli download 123456
|
119
125
|
```
|
120
126
|
|
121
|
-
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/
|
122
|
-
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/
|
127
|
+
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
128
|
+
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/6-cli-usage-examples.md)
|
129
|
+
|
130
|
+
---
|
131
|
+
|
132
|
+
### TUI 模式 (终端用户界面)
|
133
|
+
|
134
|
+
**注意**: TUI 模式仍在开发中, 目前尚未实现登录和修改设置等功能。建议优先使用稳定的 CLI 模式。
|
135
|
+
|
136
|
+
```bash
|
137
|
+
# 初始化默认配置 (生成 settings.toml)
|
138
|
+
novel-cli config init
|
139
|
+
|
140
|
+
# 编辑 ./settings.toml 修改网络配置
|
141
|
+
# 可查看 docs/3-settings-schema.md
|
142
|
+
|
143
|
+
# 启动 TUI 界面
|
144
|
+
novel-tui
|
145
|
+
```
|
146
|
+
|
147
|
+
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
148
|
+
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-tui-usage-examples.md)
|
149
|
+
|
150
|
+
---
|
151
|
+
|
152
|
+
### GUI 模式 (图形界面)
|
153
|
+
|
154
|
+
尚未实现
|
155
|
+
|
156
|
+
---
|
123
157
|
|
124
158
|
## 从 GitHub 安装 (开发版)
|
125
159
|
|
@@ -139,11 +173,11 @@ pip install .
|
|
139
173
|
|
140
174
|
- [项目简介](#项目简介)
|
141
175
|
- [安装](https://github.com/BowenZ217/novel-downloader/blob/main/docs/1-installation.md)
|
142
|
-
- [
|
143
|
-
- [
|
144
|
-
- [
|
145
|
-
- [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-usage-examples.md)
|
146
|
-
- [
|
176
|
+
- [配置](https://github.com/BowenZ217/novel-downloader/blob/main/docs/2-configuration.md)
|
177
|
+
- [settings.toml 配置说明](https://github.com/BowenZ217/novel-downloader/blob/main/docs/3-settings-schema.md)
|
178
|
+
- [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
179
|
+
- [TUI 使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-tui-usage-examples.md)
|
180
|
+
- [CLI 使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/6-cli-usage-examples.md)
|
147
181
|
- [复制 Cookies](https://github.com/BowenZ217/novel-downloader/blob/main/docs/copy-cookies.md)
|
148
182
|
- [文件保存](https://github.com/BowenZ217/novel-downloader/blob/main/docs/file-saving.md)
|
149
183
|
- [TODO](https://github.com/BowenZ217/novel-downloader/blob/main/docs/todo.md)
|
@@ -1,25 +1,11 @@
|
|
1
1
|
# novel-downloader
|
2
2
|
|
3
|
-
一个基于 [
|
3
|
+
一个基于 [playwright](https://playwright.dev/) 和 [aiohttp](https://github.com/aio-libs/aiohttp) 的小说下载工具/库。
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
## 项目简介
|
8
|
-
|
9
|
-
**novel-downloader** 支持多种小说网站的章节抓取与合并导出,
|
10
|
-
- **轻量化抓取**: 绝大多数站点仅依赖 `requests` 实现 HTTP 请求, 无需额外浏览器驱动
|
11
|
-
- 对于起点中文网 (Qidian), 可在配置中选择:
|
12
|
-
- `mode: session` : 纯 Requests 模式
|
13
|
-
- `mode: browser` : 基于 `DrissionPage` 驱动 Chrome 的浏览器模式 (可处理更复杂的 JS/加密)。
|
14
|
-
- **自动登录** (可选)
|
15
|
-
- 配置 `login_required: true` 后自动检测并重用历史 Cookie
|
16
|
-
- 首次登录或 Cookie 失效时:
|
17
|
-
- **browser** 模式: 在程序打开的浏览器窗口登录, 登录后回车继续
|
18
|
-
- **session** 模式: 根据提示粘贴浏览器中已登录的 Cookie (参考 [复制 Cookies](https://github.com/BowenZ217/novel-downloader/blob/main/docs/copy-cookies.md))
|
5
|
+
> 本项目开发环境为 Python 3.12, 需确保运行环境为 Python 3.11 及以上版本
|
19
6
|
|
20
7
|
## 功能特性
|
21
8
|
|
22
|
-
- 抓取起点中文网免费及已订阅章节内容
|
23
9
|
- 支持断点续爬, 自动续传未完成任务
|
24
10
|
- 自动整合所有章节并导出为:
|
25
11
|
- TXT
|
@@ -32,25 +18,71 @@
|
|
32
18
|
|
33
19
|
## 快速开始
|
34
20
|
|
21
|
+
### 安装
|
22
|
+
|
23
|
+
使用 `pip` 安装:
|
24
|
+
|
35
25
|
```bash
|
36
|
-
# 克隆 + 安装
|
37
26
|
pip install novel-downloader
|
27
|
+
```
|
28
|
+
|
29
|
+
如需使用浏览器模式 (即 `mode: browser`), 请确保已安装 Playwright 依赖:
|
38
30
|
|
39
|
-
|
40
|
-
|
31
|
+
```bash
|
32
|
+
playwright install
|
33
|
+
```
|
41
34
|
|
35
|
+
如需启用字体解密功能 (`decode_font`, 用于处理起点中文网对近一个月更新章节所采用的字体混淆技术), 请使用扩展安装方式:
|
36
|
+
|
37
|
+
```bash
|
38
|
+
pip install novel-downloader[font-recovery]
|
39
|
+
```
|
40
|
+
|
41
|
+
---
|
42
|
+
|
43
|
+
### CLI 模式
|
44
|
+
|
45
|
+
```bash
|
42
46
|
# 初始化默认配置 (生成 settings.toml)
|
43
|
-
novel-cli
|
47
|
+
novel-cli config init
|
44
48
|
|
45
49
|
# 编辑 ./settings.toml 完成 site/book_ids 等
|
46
|
-
# 可查看 docs/
|
50
|
+
# 可查看 docs/3-settings-schema.md
|
47
51
|
|
48
|
-
#
|
52
|
+
# 执行下载任务
|
49
53
|
novel-cli download 123456
|
50
54
|
```
|
51
55
|
|
52
|
-
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/
|
53
|
-
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/
|
56
|
+
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
57
|
+
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/6-cli-usage-examples.md)
|
58
|
+
|
59
|
+
---
|
60
|
+
|
61
|
+
### TUI 模式 (终端用户界面)
|
62
|
+
|
63
|
+
**注意**: TUI 模式仍在开发中, 目前尚未实现登录和修改设置等功能。建议优先使用稳定的 CLI 模式。
|
64
|
+
|
65
|
+
```bash
|
66
|
+
# 初始化默认配置 (生成 settings.toml)
|
67
|
+
novel-cli config init
|
68
|
+
|
69
|
+
# 编辑 ./settings.toml 修改网络配置
|
70
|
+
# 可查看 docs/3-settings-schema.md
|
71
|
+
|
72
|
+
# 启动 TUI 界面
|
73
|
+
novel-tui
|
74
|
+
```
|
75
|
+
|
76
|
+
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
77
|
+
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-tui-usage-examples.md)
|
78
|
+
|
79
|
+
---
|
80
|
+
|
81
|
+
### GUI 模式 (图形界面)
|
82
|
+
|
83
|
+
尚未实现
|
84
|
+
|
85
|
+
---
|
54
86
|
|
55
87
|
## 从 GitHub 安装 (开发版)
|
56
88
|
|
@@ -70,11 +102,11 @@ pip install .
|
|
70
102
|
|
71
103
|
- [项目简介](#项目简介)
|
72
104
|
- [安装](https://github.com/BowenZ217/novel-downloader/blob/main/docs/1-installation.md)
|
73
|
-
- [
|
74
|
-
- [
|
75
|
-
- [
|
76
|
-
- [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-usage-examples.md)
|
77
|
-
- [
|
105
|
+
- [配置](https://github.com/BowenZ217/novel-downloader/blob/main/docs/2-configuration.md)
|
106
|
+
- [settings.toml 配置说明](https://github.com/BowenZ217/novel-downloader/blob/main/docs/3-settings-schema.md)
|
107
|
+
- [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
108
|
+
- [TUI 使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-tui-usage-examples.md)
|
109
|
+
- [CLI 使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/6-cli-usage-examples.md)
|
78
110
|
- [复制 Cookies](https://github.com/BowenZ217/novel-downloader/blob/main/docs/copy-cookies.md)
|
79
111
|
- [文件保存](https://github.com/BowenZ217/novel-downloader/blob/main/docs/file-saving.md)
|
80
112
|
- [TODO](https://github.com/BowenZ217/novel-downloader/blob/main/docs/todo.md)
|
@@ -0,0 +1,145 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
novel_downloader.cli.clean
|
4
|
+
--------------------------
|
5
|
+
|
6
|
+
CLI subcommands for clean resources.
|
7
|
+
"""
|
8
|
+
|
9
|
+
import shutil
|
10
|
+
from argparse import Namespace, _SubParsersAction
|
11
|
+
from pathlib import Path
|
12
|
+
|
13
|
+
from novel_downloader.utils.constants import (
|
14
|
+
CONFIG_DIR,
|
15
|
+
DATA_DIR,
|
16
|
+
JS_SCRIPT_DIR,
|
17
|
+
LOGGER_DIR,
|
18
|
+
MODEL_CACHE_DIR,
|
19
|
+
REC_CHAR_MODEL_REPO,
|
20
|
+
)
|
21
|
+
from novel_downloader.utils.i18n import t
|
22
|
+
|
23
|
+
|
24
|
+
def register_clean_subcommand(subparsers: _SubParsersAction) -> None: # type: ignore
|
25
|
+
parser = subparsers.add_parser("clean", help=t("help_clean"))
|
26
|
+
|
27
|
+
parser.add_argument("--logs", action="store_true", help=t("clean_logs"))
|
28
|
+
parser.add_argument("--cache", action="store_true", help=t("clean_cache"))
|
29
|
+
parser.add_argument("--data", action="store_true", help=t("clean_data"))
|
30
|
+
parser.add_argument("--config", action="store_true", help=t("clean_config"))
|
31
|
+
parser.add_argument("--models", action="store_true", help=t("clean_models"))
|
32
|
+
parser.add_argument("--all", action="store_true", help=t("clean_all"))
|
33
|
+
parser.add_argument("-y", "--yes", action="store_true", help=t("clean_yes"))
|
34
|
+
|
35
|
+
parser.add_argument("--hf-cache", action="store_true", help=t("clean_hf_cache"))
|
36
|
+
parser.add_argument(
|
37
|
+
"--hf-cache-all", action="store_true", help=t("clean_hf_cache_all")
|
38
|
+
)
|
39
|
+
|
40
|
+
parser.set_defaults(func=handle_clean)
|
41
|
+
|
42
|
+
|
43
|
+
def handle_clean(args: Namespace) -> None:
|
44
|
+
targets: list[Path] = []
|
45
|
+
|
46
|
+
if args.hf_cache_all:
|
47
|
+
try:
|
48
|
+
if _clean_model_repo_cache(all=True):
|
49
|
+
print(t("clean_hf_cache_all_done"))
|
50
|
+
except Exception as e:
|
51
|
+
print(t("clean_hf_cache_all_fail", err=str(e)))
|
52
|
+
elif args.hf_cache:
|
53
|
+
try:
|
54
|
+
if _clean_model_repo_cache(repo_id=REC_CHAR_MODEL_REPO):
|
55
|
+
print(t("clean_hf_model_done", repo=REC_CHAR_MODEL_REPO))
|
56
|
+
else:
|
57
|
+
print(t("clean_hf_model_not_found", repo=REC_CHAR_MODEL_REPO))
|
58
|
+
except Exception as e:
|
59
|
+
print(t("clean_hf_model_fail", err=str(e)))
|
60
|
+
|
61
|
+
if args.all:
|
62
|
+
if not args.yes:
|
63
|
+
confirm = prompt(t("clean_confirm"), default="n")
|
64
|
+
if confirm.lower() != "y":
|
65
|
+
print(t("clean_cancelled"))
|
66
|
+
return
|
67
|
+
targets = [
|
68
|
+
LOGGER_DIR,
|
69
|
+
JS_SCRIPT_DIR,
|
70
|
+
DATA_DIR,
|
71
|
+
CONFIG_DIR,
|
72
|
+
MODEL_CACHE_DIR,
|
73
|
+
]
|
74
|
+
else:
|
75
|
+
if args.logs:
|
76
|
+
targets.append(LOGGER_DIR)
|
77
|
+
if args.cache:
|
78
|
+
targets.append(JS_SCRIPT_DIR)
|
79
|
+
if args.data:
|
80
|
+
targets.append(DATA_DIR)
|
81
|
+
if args.config:
|
82
|
+
targets.append(CONFIG_DIR)
|
83
|
+
if args.models:
|
84
|
+
targets.append(MODEL_CACHE_DIR)
|
85
|
+
|
86
|
+
if not targets and not args.hf_cache and not args.hf_cache_all:
|
87
|
+
print(t("clean_nothing"))
|
88
|
+
return
|
89
|
+
|
90
|
+
for path in targets:
|
91
|
+
_delete_path(path)
|
92
|
+
|
93
|
+
|
94
|
+
def prompt(message: str, default: str = "n") -> str:
|
95
|
+
"""
|
96
|
+
Prompt the user for input with a default option.
|
97
|
+
|
98
|
+
:param message: The prompt message to display to the user.
|
99
|
+
:param default: The default value to use if the user provides no input ("y" or "n").
|
100
|
+
:return: The user's input (lowercased), or the default value if no input is given.
|
101
|
+
"""
|
102
|
+
try:
|
103
|
+
full_prompt = f"{message} [{'Y/n' if default.lower() == 'y' else 'y/N'}]: "
|
104
|
+
response = input(full_prompt).strip().lower()
|
105
|
+
return response if response else default.lower()
|
106
|
+
except (KeyboardInterrupt, EOFError):
|
107
|
+
print("\n" + "Cancelled.")
|
108
|
+
return default.lower()
|
109
|
+
|
110
|
+
|
111
|
+
def _delete_path(p: Path) -> None:
|
112
|
+
if p.exists():
|
113
|
+
if p.is_file():
|
114
|
+
p.unlink()
|
115
|
+
else:
|
116
|
+
shutil.rmtree(p, ignore_errors=True)
|
117
|
+
print(f"[clean] {t('clean_deleted')}: {p}")
|
118
|
+
else:
|
119
|
+
print(f"[clean] {t('clean_not_found')}: {p}")
|
120
|
+
|
121
|
+
|
122
|
+
def _clean_model_repo_cache(
|
123
|
+
repo_id: str | None = None,
|
124
|
+
all: bool = False,
|
125
|
+
) -> bool:
|
126
|
+
"""
|
127
|
+
Delete Hugging Face cache for a specific repo.
|
128
|
+
"""
|
129
|
+
from huggingface_hub import scan_cache_dir
|
130
|
+
|
131
|
+
cache_info = scan_cache_dir()
|
132
|
+
|
133
|
+
if all:
|
134
|
+
targets = cache_info.repos
|
135
|
+
elif repo_id:
|
136
|
+
targets = [r for r in cache_info.repos if r.repo_id == repo_id]
|
137
|
+
else:
|
138
|
+
return False
|
139
|
+
|
140
|
+
strategy = cache_info.delete_revisions(
|
141
|
+
*[rev.commit_hash for r in targets for rev in r.revisions]
|
142
|
+
)
|
143
|
+
print(f"[clean] Will free {strategy.expected_freed_size_str}")
|
144
|
+
strategy.execute()
|
145
|
+
return True
|
@@ -0,0 +1,177 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
novel_downloader.cli.config
|
4
|
+
---------------------------
|
5
|
+
|
6
|
+
CLI subcommands for configuration management.
|
7
|
+
"""
|
8
|
+
|
9
|
+
import shutil
|
10
|
+
from argparse import Namespace, _SubParsersAction
|
11
|
+
from importlib.resources import as_file
|
12
|
+
from pathlib import Path
|
13
|
+
|
14
|
+
from novel_downloader.config import save_config_file, save_rules_as_json
|
15
|
+
from novel_downloader.utils.constants import DEFAULT_SETTINGS_PATHS
|
16
|
+
from novel_downloader.utils.i18n import t
|
17
|
+
from novel_downloader.utils.logger import setup_logging
|
18
|
+
from novel_downloader.utils.state import state_mgr
|
19
|
+
|
20
|
+
# from novel_downloader.utils.hash_store import img_hash_store
|
21
|
+
|
22
|
+
|
23
|
+
def register_config_subcommand(subparsers: _SubParsersAction) -> None: # type: ignore
|
24
|
+
parser = subparsers.add_parser("config", help=t("help_config"))
|
25
|
+
config_subparsers = parser.add_subparsers(dest="subcommand", required=True)
|
26
|
+
|
27
|
+
_register_init(config_subparsers)
|
28
|
+
_register_set_lang(config_subparsers)
|
29
|
+
_register_set_config(config_subparsers)
|
30
|
+
_register_update_rules(config_subparsers)
|
31
|
+
_register_set_cookies(config_subparsers)
|
32
|
+
# _register_add_hash(config_subparsers)
|
33
|
+
|
34
|
+
|
35
|
+
def _register_init(subparsers: _SubParsersAction) -> None: # type: ignore
|
36
|
+
parser = subparsers.add_parser("init", help=t("settings_init_help"))
|
37
|
+
parser.add_argument(
|
38
|
+
"--force", action="store_true", help=t("settings_init_force_help")
|
39
|
+
)
|
40
|
+
parser.set_defaults(func=_handle_init)
|
41
|
+
|
42
|
+
|
43
|
+
def _register_set_lang(subparsers: _SubParsersAction) -> None: # type: ignore
|
44
|
+
parser = subparsers.add_parser("set-lang", help=t("settings_set_lang_help"))
|
45
|
+
parser.add_argument("lang", choices=["zh", "en"], help="Language code")
|
46
|
+
parser.set_defaults(func=_handle_set_lang)
|
47
|
+
|
48
|
+
|
49
|
+
def _register_set_config(subparsers: _SubParsersAction) -> None: # type: ignore
|
50
|
+
parser = subparsers.add_parser("set-config", help=t("settings_set_config_help"))
|
51
|
+
parser.add_argument("path", type=str, help="Path to YAML config file")
|
52
|
+
parser.set_defaults(func=_handle_set_config)
|
53
|
+
|
54
|
+
|
55
|
+
def _register_update_rules(subparsers: _SubParsersAction) -> None: # type: ignore
|
56
|
+
parser = subparsers.add_parser("update-rules", help=t("settings_update_rules_help"))
|
57
|
+
parser.add_argument("path", type=str, help="Path to TOML/YAML/JSON rule file")
|
58
|
+
parser.set_defaults(func=_handle_update_rules)
|
59
|
+
|
60
|
+
|
61
|
+
def _register_set_cookies(subparsers: _SubParsersAction) -> None: # type: ignore
|
62
|
+
parser = subparsers.add_parser("set-cookies", help=t("settings_set_cookies_help"))
|
63
|
+
parser.add_argument("site", nargs="?", help="Site identifier")
|
64
|
+
parser.add_argument("cookies", nargs="?", help="Cookies string")
|
65
|
+
parser.set_defaults(func=_handle_set_cookies)
|
66
|
+
|
67
|
+
|
68
|
+
# def _register_add_hash(subparsers: _SubParsersAction) -> None: # type: ignore
|
69
|
+
# parser = subparsers.add_parser("add-hash", help=t("settings_add_hash_help"))
|
70
|
+
# parser.add_argument("--path", type=str, help=t("settings_add_hash_path_help"))
|
71
|
+
# parser.set_defaults(func=_handle_add_hash)
|
72
|
+
|
73
|
+
|
74
|
+
def _handle_init(args: Namespace) -> None:
|
75
|
+
setup_logging()
|
76
|
+
cwd = Path.cwd()
|
77
|
+
|
78
|
+
for resource in DEFAULT_SETTINGS_PATHS:
|
79
|
+
target_path = cwd / resource.name
|
80
|
+
should_copy = True
|
81
|
+
|
82
|
+
if target_path.exists():
|
83
|
+
if args.force:
|
84
|
+
print(t("settings_init_overwrite", filename=resource.name))
|
85
|
+
else:
|
86
|
+
print(t("settings_init_exists", filename=resource.name))
|
87
|
+
resp = (
|
88
|
+
input(
|
89
|
+
t("settings_init_confirm_overwrite", filename=resource.name)
|
90
|
+
+ " [y/N]: "
|
91
|
+
)
|
92
|
+
.strip()
|
93
|
+
.lower()
|
94
|
+
)
|
95
|
+
should_copy = resp == "y"
|
96
|
+
|
97
|
+
if not should_copy:
|
98
|
+
print(t("settings_init_skip", filename=resource.name))
|
99
|
+
continue
|
100
|
+
|
101
|
+
try:
|
102
|
+
with as_file(resource) as actual_path:
|
103
|
+
shutil.copy(actual_path, target_path)
|
104
|
+
print(t("settings_init_copy", filename=resource.name))
|
105
|
+
except Exception as e:
|
106
|
+
print(t("settings_init_error", filename=resource.name, err=str(e)))
|
107
|
+
raise
|
108
|
+
|
109
|
+
|
110
|
+
def _handle_set_lang(args: Namespace) -> None:
|
111
|
+
state_mgr.set_language(args.lang)
|
112
|
+
print(t("settings_set_lang", lang=args.lang))
|
113
|
+
|
114
|
+
|
115
|
+
def _handle_set_config(args: Namespace) -> None:
|
116
|
+
try:
|
117
|
+
save_config_file(args.path)
|
118
|
+
print(t("settings_set_config", path=args.path))
|
119
|
+
except Exception as e:
|
120
|
+
print(t("settings_set_config_fail", err=str(e)))
|
121
|
+
raise
|
122
|
+
|
123
|
+
|
124
|
+
def _handle_update_rules(args: Namespace) -> None:
|
125
|
+
try:
|
126
|
+
save_rules_as_json(args.path)
|
127
|
+
print(t("settings_update_rules", path=args.path))
|
128
|
+
except Exception as e:
|
129
|
+
print(t("settings_update_rules_fail", err=str(e)))
|
130
|
+
raise
|
131
|
+
|
132
|
+
|
133
|
+
def _handle_set_cookies(args: Namespace) -> None:
|
134
|
+
site = args.site or input(t("settings_set_cookies_prompt_site") + ": ").strip()
|
135
|
+
cookies = (
|
136
|
+
args.cookies or input(t("settings_set_cookies_prompt_payload") + ": ").strip()
|
137
|
+
)
|
138
|
+
|
139
|
+
try:
|
140
|
+
state_mgr.set_cookies(site, cookies)
|
141
|
+
print(t("settings_set_cookies_success", site=site))
|
142
|
+
except Exception as e:
|
143
|
+
print(t("settings_set_cookies_fail", err=str(e)))
|
144
|
+
raise
|
145
|
+
|
146
|
+
|
147
|
+
# def _handle_add_hash(args: Namespace) -> None:
|
148
|
+
# if args.path:
|
149
|
+
# try:
|
150
|
+
# img_hash_store.add_from_map(args.path)
|
151
|
+
# img_hash_store.save()
|
152
|
+
# print(t("settings_add_hash_loaded", path=args.path))
|
153
|
+
# except Exception as e:
|
154
|
+
# print(t("settings_add_hash_load_fail", err=str(e)))
|
155
|
+
# raise
|
156
|
+
# else:
|
157
|
+
# print(t("settings_add_hash_prompt_tip"))
|
158
|
+
# while True:
|
159
|
+
# img_path = input(t("settings_add_hash_prompt_img") + ": ").strip()
|
160
|
+
# if not img_path or img_path.lower() in {"exit", "quit"}:
|
161
|
+
# break
|
162
|
+
# if not Path(img_path).exists():
|
163
|
+
# print(t("settings_add_hash_path_invalid"))
|
164
|
+
# continue
|
165
|
+
|
166
|
+
# label = input(t("settings_add_hash_prompt_label") + ": ").strip()
|
167
|
+
# if not label or label.lower() in {"exit", "quit"}:
|
168
|
+
# break
|
169
|
+
|
170
|
+
# try:
|
171
|
+
# img_hash_store.add_image(img_path, label)
|
172
|
+
# print(t("settings_add_hash_added", img=img_path, label=label))
|
173
|
+
# except Exception as e:
|
174
|
+
# print(t("settings_add_hash_failed", err=str(e)))
|
175
|
+
|
176
|
+
# img_hash_store.save()
|
177
|
+
# print(t("settings_add_hash_saved"))
|