novel-downloader 1.4.4__tar.gz → 1.5.0__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.
Files changed (211) hide show
  1. {novel_downloader-1.4.4/src/novel_downloader.egg-info → novel_downloader-1.5.0}/PKG-INFO +2 -2
  2. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/README.md +1 -1
  3. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/pyproject.toml +1 -1
  4. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/__init__.py +1 -1
  5. novel_downloader-1.5.0/src/novel_downloader/cli/config.py +95 -0
  6. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/cli/download.py +4 -5
  7. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/cli/export.py +4 -1
  8. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/cli/main.py +2 -0
  9. novel_downloader-1.5.0/src/novel_downloader/cli/search.py +123 -0
  10. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/config/__init__.py +3 -10
  11. novel_downloader-1.5.0/src/novel_downloader/config/adapter.py +360 -0
  12. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/config/loader.py +2 -3
  13. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/__init__.py +13 -13
  14. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/downloaders/__init__.py +10 -11
  15. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/downloaders/base.py +152 -26
  16. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/downloaders/biquge.py +5 -1
  17. novel_downloader-1.5.0/src/novel_downloader/core/downloaders/common.py +227 -0
  18. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/downloaders/esjzone.py +5 -1
  19. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/downloaders/linovelib.py +5 -1
  20. novel_downloader-1.5.0/src/novel_downloader/core/downloaders/qianbi.py +312 -0
  21. novel_downloader-1.5.0/src/novel_downloader/core/downloaders/qidian.py +290 -0
  22. novel_downloader-1.5.0/src/novel_downloader/core/downloaders/registry.py +67 -0
  23. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/downloaders/sfacg.py +5 -1
  24. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/downloaders/yamibo.py +5 -1
  25. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/__init__.py +10 -11
  26. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/base.py +87 -7
  27. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/biquge.py +5 -8
  28. novel_downloader-1.5.0/src/novel_downloader/core/exporters/common/epub.py +193 -0
  29. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/common/main_exporter.py +0 -60
  30. novel_downloader-1.5.0/src/novel_downloader/core/exporters/common/txt.py +141 -0
  31. novel_downloader-1.5.0/src/novel_downloader/core/exporters/epub_util.py +185 -0
  32. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/esjzone.py +5 -8
  33. novel_downloader-1.5.0/src/novel_downloader/core/exporters/linovelib/epub.py +351 -0
  34. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/linovelib/main_exporter.py +2 -59
  35. novel_downloader-1.5.0/src/novel_downloader/core/exporters/linovelib/txt.py +133 -0
  36. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/qianbi.py +5 -8
  37. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/qidian.py +14 -4
  38. novel_downloader-1.5.0/src/novel_downloader/core/exporters/registry.py +53 -0
  39. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/sfacg.py +5 -8
  40. novel_downloader-1.5.0/src/novel_downloader/core/exporters/txt_util.py +67 -0
  41. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/yamibo.py +5 -8
  42. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/__init__.py +19 -24
  43. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/base/browser.py +23 -4
  44. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/base/session.py +30 -5
  45. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/biquge/browser.py +5 -0
  46. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/biquge/session.py +6 -1
  47. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/esjzone/browser.py +5 -0
  48. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/esjzone/session.py +6 -1
  49. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/linovelib/browser.py +6 -1
  50. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/linovelib/session.py +6 -1
  51. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/qianbi/browser.py +5 -0
  52. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/qianbi/session.py +5 -0
  53. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/qidian/browser.py +12 -4
  54. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/qidian/session.py +11 -3
  55. novel_downloader-1.5.0/src/novel_downloader/core/fetchers/registry.py +71 -0
  56. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/sfacg/browser.py +5 -0
  57. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/sfacg/session.py +5 -0
  58. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/yamibo/browser.py +5 -0
  59. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/yamibo/session.py +6 -1
  60. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/interfaces/__init__.py +7 -5
  61. novel_downloader-1.5.0/src/novel_downloader/core/interfaces/searcher.py +18 -0
  62. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/__init__.py +10 -11
  63. novel_downloader-1.4.4/src/novel_downloader/core/parsers/biquge/main_parser.py → novel_downloader-1.5.0/src/novel_downloader/core/parsers/biquge.py +7 -2
  64. novel_downloader-1.4.4/src/novel_downloader/core/parsers/esjzone/main_parser.py → novel_downloader-1.5.0/src/novel_downloader/core/parsers/esjzone.py +7 -2
  65. novel_downloader-1.4.4/src/novel_downloader/core/parsers/linovelib/main_parser.py → novel_downloader-1.5.0/src/novel_downloader/core/parsers/linovelib.py +7 -2
  66. novel_downloader-1.4.4/src/novel_downloader/core/parsers/qianbi/main_parser.py → novel_downloader-1.5.0/src/novel_downloader/core/parsers/qianbi.py +7 -2
  67. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/chapter_encrypted.py +23 -21
  68. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/chapter_normal.py +1 -1
  69. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/main_parser.py +10 -21
  70. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py +5 -6
  71. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/utils/node_decryptor.py +2 -2
  72. novel_downloader-1.5.0/src/novel_downloader/core/parsers/registry.py +68 -0
  73. novel_downloader-1.4.4/src/novel_downloader/core/parsers/sfacg/main_parser.py → novel_downloader-1.5.0/src/novel_downloader/core/parsers/sfacg.py +7 -2
  74. novel_downloader-1.4.4/src/novel_downloader/core/parsers/yamibo/main_parser.py → novel_downloader-1.5.0/src/novel_downloader/core/parsers/yamibo.py +7 -2
  75. novel_downloader-1.5.0/src/novel_downloader/core/searchers/__init__.py +20 -0
  76. novel_downloader-1.5.0/src/novel_downloader/core/searchers/base.py +92 -0
  77. novel_downloader-1.5.0/src/novel_downloader/core/searchers/biquge.py +83 -0
  78. novel_downloader-1.5.0/src/novel_downloader/core/searchers/esjzone.py +84 -0
  79. novel_downloader-1.5.0/src/novel_downloader/core/searchers/qianbi.py +131 -0
  80. novel_downloader-1.5.0/src/novel_downloader/core/searchers/qidian.py +87 -0
  81. novel_downloader-1.5.0/src/novel_downloader/core/searchers/registry.py +63 -0
  82. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/locales/en.json +12 -4
  83. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/locales/zh.json +12 -4
  84. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/models/__init__.py +4 -30
  85. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/models/config.py +12 -6
  86. novel_downloader-1.5.0/src/novel_downloader/models/search.py +16 -0
  87. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/models/types.py +0 -2
  88. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/resources/config/settings.toml +31 -4
  89. novel_downloader-1.5.0/src/novel_downloader/resources/css_styles/intro.css +83 -0
  90. novel_downloader-1.5.0/src/novel_downloader/resources/css_styles/main.css +45 -0
  91. novel_downloader-1.5.0/src/novel_downloader/utils/__init__.py +58 -0
  92. novel_downloader-1.5.0/src/novel_downloader/utils/chapter_storage.py +347 -0
  93. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/constants.py +1 -21
  94. novel_downloader-1.5.0/src/novel_downloader/utils/epub/__init__.py +34 -0
  95. novel_downloader-1.5.0/src/novel_downloader/utils/epub/builder.py +377 -0
  96. novel_downloader-1.5.0/src/novel_downloader/utils/epub/constants.py +77 -0
  97. novel_downloader-1.5.0/src/novel_downloader/utils/epub/documents.py +403 -0
  98. novel_downloader-1.5.0/src/novel_downloader/utils/epub/models.py +134 -0
  99. novel_downloader-1.5.0/src/novel_downloader/utils/epub/utils.py +212 -0
  100. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/file_utils/__init__.py +10 -14
  101. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/file_utils/io.py +20 -51
  102. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/file_utils/sanitize.py +2 -3
  103. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/fontocr/__init__.py +5 -5
  104. {novel_downloader-1.4.4/src/novel_downloader/utils → novel_downloader-1.5.0/src/novel_downloader/utils/fontocr}/hash_store.py +4 -3
  105. {novel_downloader-1.4.4/src/novel_downloader/utils → novel_downloader-1.5.0/src/novel_downloader/utils/fontocr}/hash_utils.py +2 -2
  106. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/fontocr/ocr_v1.py +13 -1
  107. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/fontocr/ocr_v2.py +13 -1
  108. novel_downloader-1.5.0/src/novel_downloader/utils/fontocr/ocr_v3.py +744 -0
  109. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/i18n.py +2 -0
  110. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/logger.py +2 -0
  111. novel_downloader-1.5.0/src/novel_downloader/utils/network.py +159 -0
  112. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/state.py +1 -0
  113. novel_downloader-1.5.0/src/novel_downloader/utils/text_utils/__init__.py +34 -0
  114. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/text_utils/diff_display.py +4 -5
  115. novel_downloader-1.5.0/src/novel_downloader/utils/text_utils/numeric_conversion.py +253 -0
  116. novel_downloader-1.5.0/src/novel_downloader/utils/text_utils/text_cleaner.py +179 -0
  117. novel_downloader-1.5.0/src/novel_downloader/utils/text_utils/truncate_utils.py +62 -0
  118. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/time_utils/datetime_utils.py +4 -5
  119. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/time_utils/sleep_utils.py +2 -3
  120. {novel_downloader-1.4.4 → novel_downloader-1.5.0/src/novel_downloader.egg-info}/PKG-INFO +2 -2
  121. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader.egg-info/SOURCES.txt +34 -35
  122. novel_downloader-1.4.4/src/novel_downloader/cli/config.py +0 -177
  123. novel_downloader-1.4.4/src/novel_downloader/config/adapter.py +0 -224
  124. novel_downloader-1.4.4/src/novel_downloader/config/site_rules.py +0 -94
  125. novel_downloader-1.4.4/src/novel_downloader/core/downloaders/common.py +0 -448
  126. novel_downloader-1.4.4/src/novel_downloader/core/downloaders/qianbi.py +0 -25
  127. novel_downloader-1.4.4/src/novel_downloader/core/downloaders/qidian.py +0 -376
  128. novel_downloader-1.4.4/src/novel_downloader/core/exporters/common/epub.py +0 -277
  129. novel_downloader-1.4.4/src/novel_downloader/core/exporters/common/txt.py +0 -142
  130. novel_downloader-1.4.4/src/novel_downloader/core/exporters/epub_util.py +0 -1358
  131. novel_downloader-1.4.4/src/novel_downloader/core/exporters/linovelib/epub.py +0 -406
  132. novel_downloader-1.4.4/src/novel_downloader/core/exporters/linovelib/txt.py +0 -129
  133. novel_downloader-1.4.4/src/novel_downloader/core/factory/__init__.py +0 -20
  134. novel_downloader-1.4.4/src/novel_downloader/core/factory/downloader.py +0 -73
  135. novel_downloader-1.4.4/src/novel_downloader/core/factory/exporter.py +0 -58
  136. novel_downloader-1.4.4/src/novel_downloader/core/factory/fetcher.py +0 -96
  137. novel_downloader-1.4.4/src/novel_downloader/core/factory/parser.py +0 -86
  138. novel_downloader-1.4.4/src/novel_downloader/core/fetchers/common/__init__.py +0 -14
  139. novel_downloader-1.4.4/src/novel_downloader/core/fetchers/common/browser.py +0 -79
  140. novel_downloader-1.4.4/src/novel_downloader/core/fetchers/common/session.py +0 -79
  141. novel_downloader-1.4.4/src/novel_downloader/core/parsers/biquge/__init__.py +0 -10
  142. novel_downloader-1.4.4/src/novel_downloader/core/parsers/common/__init__.py +0 -13
  143. novel_downloader-1.4.4/src/novel_downloader/core/parsers/common/helper.py +0 -323
  144. novel_downloader-1.4.4/src/novel_downloader/core/parsers/common/main_parser.py +0 -106
  145. novel_downloader-1.4.4/src/novel_downloader/core/parsers/esjzone/__init__.py +0 -10
  146. novel_downloader-1.4.4/src/novel_downloader/core/parsers/linovelib/__init__.py +0 -10
  147. novel_downloader-1.4.4/src/novel_downloader/core/parsers/qianbi/__init__.py +0 -10
  148. novel_downloader-1.4.4/src/novel_downloader/core/parsers/sfacg/__init__.py +0 -10
  149. novel_downloader-1.4.4/src/novel_downloader/core/parsers/yamibo/__init__.py +0 -10
  150. novel_downloader-1.4.4/src/novel_downloader/models/browser.py +0 -21
  151. novel_downloader-1.4.4/src/novel_downloader/models/site_rules.py +0 -99
  152. novel_downloader-1.4.4/src/novel_downloader/models/tasks.py +0 -33
  153. novel_downloader-1.4.4/src/novel_downloader/resources/css_styles/main.css +0 -104
  154. novel_downloader-1.4.4/src/novel_downloader/resources/css_styles/volume-intro.css +0 -56
  155. novel_downloader-1.4.4/src/novel_downloader/resources/json/replace_word_map.json +0 -4
  156. novel_downloader-1.4.4/src/novel_downloader/resources/text/blacklist.txt +0 -22
  157. novel_downloader-1.4.4/src/novel_downloader/utils/__init__.py +0 -6
  158. novel_downloader-1.4.4/src/novel_downloader/utils/chapter_storage.py +0 -327
  159. novel_downloader-1.4.4/src/novel_downloader/utils/network.py +0 -300
  160. novel_downloader-1.4.4/src/novel_downloader/utils/text_utils/__init__.py +0 -33
  161. novel_downloader-1.4.4/src/novel_downloader/utils/text_utils/chapter_formatting.py +0 -46
  162. novel_downloader-1.4.4/src/novel_downloader/utils/text_utils/font_mapping.py +0 -28
  163. novel_downloader-1.4.4/src/novel_downloader/utils/text_utils/text_cleaning.py +0 -107
  164. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/LICENSE +0 -0
  165. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/setup.cfg +0 -0
  166. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/cli/__init__.py +2 -2
  167. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/cli/clean.py +0 -0
  168. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/common/__init__.py +2 -2
  169. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/exporters/linovelib/__init__.py +2 -2
  170. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/base/__init__.py +3 -3
  171. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/base/rate_limiter.py +0 -0
  172. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/biquge/__init__.py +3 -3
  173. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/esjzone/__init__.py +3 -3
  174. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/linovelib/__init__.py +3 -3
  175. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/qianbi/__init__.py +3 -3
  176. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/qidian/__init__.py +3 -3
  177. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/sfacg/__init__.py +3 -3
  178. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/fetchers/yamibo/__init__.py +3 -3
  179. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/interfaces/downloader.py +0 -0
  180. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/interfaces/exporter.py +0 -0
  181. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/interfaces/fetcher.py +0 -0
  182. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/interfaces/parser.py +0 -0
  183. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/base.py +0 -0
  184. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/__init__.py +2 -2
  185. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/book_info_parser.py +0 -0
  186. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/chapter_router.py +0 -0
  187. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/utils/__init__.py +11 -11
  188. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/core/parsers/qidian/utils/helpers.py +0 -0
  189. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/models/chapter.py +0 -0
  190. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/models/login.py +0 -0
  191. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/resources/images/volume_border.png +0 -0
  192. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/resources/js_scripts/qidian_decrypt_node.js +0 -0
  193. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/resources/json/linovelib_font_map.json +0 -0
  194. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/tui/__init__.py +0 -0
  195. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/tui/app.py +0 -0
  196. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/tui/main.py +0 -0
  197. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/tui/screens/__init__.py +0 -0
  198. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/tui/screens/home.py +0 -0
  199. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/tui/screens/login.py +0 -0
  200. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/tui/styles/home_layout.tcss +0 -0
  201. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/tui/widgets/richlog_handler.py +0 -0
  202. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/cache.py +0 -0
  203. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/cookies.py +0 -0
  204. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/crypto_utils.py +0 -0
  205. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/file_utils/normalize.py +2 -2
  206. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/fontocr/model_loader.py +0 -0
  207. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader/utils/time_utils/__init__.py +3 -3
  208. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader.egg-info/dependency_links.txt +0 -0
  209. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader.egg-info/entry_points.txt +0 -0
  210. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader.egg-info/requires.txt +0 -0
  211. {novel_downloader-1.4.4 → novel_downloader-1.5.0}/src/novel_downloader.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: novel-downloader
3
- Version: 1.4.4
3
+ Version: 1.5.0
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
@@ -83,7 +83,7 @@ Dynamic: license-file
83
83
  - EPUB (可选包含章节插图)
84
84
  - 支持活动广告过滤:
85
85
  - [x] 章节标题
86
- - [ ] 章节正文
86
+ - [x] 章节正文
87
87
 
88
88
  ---
89
89
 
@@ -12,7 +12,7 @@
12
12
  - EPUB (可选包含章节插图)
13
13
  - 支持活动广告过滤:
14
14
  - [x] 章节标题
15
- - [ ] 章节正文
15
+ - [x] 章节正文
16
16
 
17
17
  ---
18
18
 
@@ -116,7 +116,7 @@ testpaths = ["tests"]
116
116
 
117
117
  [tool.commitizen]
118
118
  name = "cz_conventional_commits"
119
- version = "1.4.4"
119
+ version = "1.5.0"
120
120
  version_files = [
121
121
  "src/novel_downloader/__init__.py"
122
122
  ]
@@ -6,7 +6,7 @@ novel_downloader
6
6
  Core package for the Novel Downloader project.
7
7
  """
8
8
 
9
- __version__ = "1.4.4"
9
+ __version__ = "1.5.0"
10
10
 
11
11
  __author__ = "Saudade Z"
12
12
  __email__ = "saudadez217@gmail.com"
@@ -0,0 +1,95 @@
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
15
+ from novel_downloader.utils.constants import DEFAULT_SETTINGS_PATHS
16
+ from novel_downloader.utils.i18n import t
17
+ from novel_downloader.utils.state import state_mgr
18
+
19
+
20
+ def register_config_subcommand(subparsers: _SubParsersAction) -> None: # type: ignore
21
+ parser = subparsers.add_parser("config", help=t("help_config"))
22
+ config_subparsers = parser.add_subparsers(dest="subcommand", required=True)
23
+
24
+ _register_init(config_subparsers)
25
+ _register_set_lang(config_subparsers)
26
+ _register_set_config(config_subparsers)
27
+
28
+
29
+ def _register_init(subparsers: _SubParsersAction) -> None: # type: ignore
30
+ parser = subparsers.add_parser("init", help=t("settings_init_help"))
31
+ parser.add_argument(
32
+ "--force", action="store_true", help=t("settings_init_force_help")
33
+ )
34
+ parser.set_defaults(func=_handle_init)
35
+
36
+
37
+ def _register_set_lang(subparsers: _SubParsersAction) -> None: # type: ignore
38
+ parser = subparsers.add_parser("set-lang", help=t("settings_set_lang_help"))
39
+ parser.add_argument("lang", choices=["zh", "en"], help="Language code")
40
+ parser.set_defaults(func=_handle_set_lang)
41
+
42
+
43
+ def _register_set_config(subparsers: _SubParsersAction) -> None: # type: ignore
44
+ parser = subparsers.add_parser("set-config", help=t("settings_set_config_help"))
45
+ parser.add_argument("path", type=str, help="Path to YAML config file")
46
+ parser.set_defaults(func=_handle_set_config)
47
+
48
+
49
+ def _handle_init(args: Namespace) -> None:
50
+ cwd = Path.cwd()
51
+
52
+ for resource in DEFAULT_SETTINGS_PATHS:
53
+ target_path = cwd / resource.name
54
+ should_copy = True
55
+
56
+ if target_path.exists():
57
+ if args.force:
58
+ print(t("settings_init_overwrite", filename=resource.name))
59
+ else:
60
+ print(t("settings_init_exists", filename=resource.name))
61
+ resp = (
62
+ input(
63
+ t("settings_init_confirm_overwrite", filename=resource.name)
64
+ + " [y/N]: "
65
+ )
66
+ .strip()
67
+ .lower()
68
+ )
69
+ should_copy = resp == "y"
70
+
71
+ if not should_copy:
72
+ print(t("settings_init_skip", filename=resource.name))
73
+ continue
74
+
75
+ try:
76
+ with as_file(resource) as actual_path:
77
+ shutil.copy(actual_path, target_path)
78
+ print(t("settings_init_copy", filename=resource.name))
79
+ except Exception as e:
80
+ print(t("settings_init_error", filename=resource.name, err=str(e)))
81
+ raise
82
+
83
+
84
+ def _handle_set_lang(args: Namespace) -> None:
85
+ state_mgr.set_language(args.lang)
86
+ print(t("settings_set_lang", lang=args.lang))
87
+
88
+
89
+ def _handle_set_config(args: Namespace) -> None:
90
+ try:
91
+ save_config_file(args.path)
92
+ print(t("settings_set_config", path=args.path))
93
+ except Exception as e:
94
+ print(t("settings_set_config_fail", err=str(e)))
95
+ raise
@@ -15,13 +15,13 @@ from pathlib import Path
15
15
  from typing import Any
16
16
 
17
17
  from novel_downloader.config import ConfigAdapter, load_config
18
- from novel_downloader.core.factory import (
18
+ from novel_downloader.core import (
19
+ FetcherProtocol,
19
20
  get_downloader,
20
21
  get_exporter,
21
22
  get_fetcher,
22
23
  get_parser,
23
24
  )
24
- from novel_downloader.core.interfaces import FetcherProtocol
25
25
  from novel_downloader.models import BookConfig, LoginField
26
26
  from novel_downloader.utils.cookies import resolve_cookies
27
27
  from novel_downloader.utils.i18n import t
@@ -44,8 +44,6 @@ def register_download_subcommand(subparsers: _SubParsersAction) -> None: # type
44
44
 
45
45
 
46
46
  def handle_download(args: Namespace) -> None:
47
- setup_logging()
48
-
49
47
  site: str = args.site
50
48
  config_path: Path | None = Path(args.config) if args.config else None
51
49
  book_ids: list[BookConfig] = _cli_args_to_book_configs(
@@ -143,10 +141,11 @@ async def _download(
143
141
  fetcher_cfg = adapter.get_fetcher_config()
144
142
  parser_cfg = adapter.get_parser_config()
145
143
  exporter_cfg = adapter.get_exporter_config()
144
+ log_level = adapter.get_log_level()
146
145
 
147
146
  parser = get_parser(site, parser_cfg)
148
147
  exporter = get_exporter(site, exporter_cfg)
149
- setup_logging()
148
+ setup_logging(log_level=log_level)
150
149
 
151
150
  async with get_fetcher(site, fetcher_cfg) as fetcher:
152
151
  if downloader_cfg.login_required and not await fetcher.load_state():
@@ -9,8 +9,9 @@ from argparse import Namespace, _SubParsersAction
9
9
  from pathlib import Path
10
10
 
11
11
  from novel_downloader.config import ConfigAdapter, load_config
12
- from novel_downloader.core.factory import get_exporter
12
+ from novel_downloader.core import get_exporter
13
13
  from novel_downloader.utils.i18n import t
14
+ from novel_downloader.utils.logger import setup_logging
14
15
 
15
16
 
16
17
  def register_export_subcommand(subparsers: _SubParsersAction) -> None: # type: ignore
@@ -57,7 +58,9 @@ def handle_export(args: Namespace) -> None:
57
58
 
58
59
  adapter = ConfigAdapter(config=config_data, site=site)
59
60
  exporter_cfg = adapter.get_exporter_config()
61
+ log_level = adapter.get_log_level()
60
62
  exporter = get_exporter(site, exporter_cfg)
63
+ setup_logging(log_level=log_level)
61
64
 
62
65
  for book_id in book_ids:
63
66
  print(t("export_processing", book_id=book_id, format=export_format))
@@ -14,6 +14,7 @@ from .clean import register_clean_subcommand
14
14
  from .config import register_config_subcommand
15
15
  from .download import register_download_subcommand
16
16
  from .export import register_export_subcommand
17
+ from .search import register_search_subcommand
17
18
 
18
19
 
19
20
  def cli_main() -> None:
@@ -24,6 +25,7 @@ def cli_main() -> None:
24
25
  register_config_subcommand(subparsers)
25
26
  register_download_subcommand(subparsers)
26
27
  register_export_subcommand(subparsers)
28
+ register_search_subcommand(subparsers)
27
29
 
28
30
  args = parser.parse_args()
29
31
  if hasattr(args, "func"):
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ novel_downloader.cli.search
4
+ ---------------------------
5
+
6
+ """
7
+
8
+ import asyncio
9
+ from argparse import Namespace, _SubParsersAction
10
+ from collections.abc import Sequence
11
+ from pathlib import Path
12
+
13
+ from novel_downloader.cli.download import _download
14
+ from novel_downloader.config import ConfigAdapter, load_config
15
+ from novel_downloader.core import search
16
+ from novel_downloader.models import BookConfig, SearchResult
17
+ from novel_downloader.utils.i18n import t
18
+
19
+
20
+ def register_search_subcommand(subparsers: _SubParsersAction) -> None: # type: ignore
21
+ parser = subparsers.add_parser("search", help=t("help_search"))
22
+
23
+ parser.add_argument(
24
+ "--site",
25
+ "-s",
26
+ action="append",
27
+ metavar="SITE",
28
+ help=t("help_search_sites"),
29
+ )
30
+ parser.add_argument(
31
+ "keyword",
32
+ help=t("help_search_keyword"),
33
+ )
34
+ parser.add_argument(
35
+ "--config",
36
+ type=str,
37
+ help=t("help_config"),
38
+ )
39
+ parser.add_argument(
40
+ "--limit",
41
+ "-l",
42
+ type=int,
43
+ default=10,
44
+ metavar="N",
45
+ help=t("help_search_limit"),
46
+ )
47
+ parser.add_argument(
48
+ "--site-limit",
49
+ type=int,
50
+ default=5,
51
+ metavar="M",
52
+ help=t("help_search_site_limit"),
53
+ )
54
+
55
+ parser.set_defaults(func=handle_search)
56
+
57
+
58
+ def handle_search(args: Namespace) -> None:
59
+ """
60
+ Handler for the `search` subcommand. Loads config, runs the search,
61
+ prompts the user to pick one result, then kicks off download.
62
+ """
63
+ sites: Sequence[str] | None = args.site or None
64
+ keyword: str = args.keyword
65
+ overall_limit = max(1, args.limit)
66
+ per_site_limit = max(1, args.site_limit)
67
+ config_path: Path | None = Path(args.config) if args.config else None
68
+
69
+ try:
70
+ config_data = load_config(config_path)
71
+ except Exception as e:
72
+ print(t("download_config_load_fail", err=str(e)))
73
+ return
74
+
75
+ results = search(
76
+ keyword=keyword,
77
+ sites=sites,
78
+ limit=overall_limit,
79
+ per_site_limit=per_site_limit,
80
+ )
81
+
82
+ chosen = _prompt_user_select(results)
83
+ if chosen is None:
84
+ # user cancelled or no valid choice
85
+ return
86
+
87
+ adapter = ConfigAdapter(config=config_data, site=chosen["site"])
88
+ books: list[BookConfig] = [{"book_id": chosen["book_id"]}]
89
+ asyncio.run(_download(adapter, chosen["site"], books))
90
+
91
+
92
+ def _prompt_user_select(
93
+ results: Sequence[SearchResult],
94
+ max_attempts: int = 3,
95
+ ) -> SearchResult | None:
96
+ """
97
+ Display a numbered list of results and prompt the user to pick one.
98
+
99
+ :param results: A list of SearchResult dicts.
100
+ :param max_attempts: How many bad inputs to tolerate before giving up.
101
+ :return: The chosen SearchResult, or None if cancelled/failed.
102
+ """
103
+ if not results:
104
+ print(t("no_results"))
105
+ return None
106
+
107
+ # Show choices
108
+ for i, r in enumerate(results, start=1):
109
+ print(f"[{i}] {r['title']} - {r['author']} ({r['site']}, id: {r['book_id']})")
110
+
111
+ attempts = 0
112
+ while attempts < max_attempts:
113
+ choice = input(t("prompt_select_index")).strip()
114
+ if choice == "":
115
+ return None
116
+ if choice.isdigit():
117
+ idx = int(choice)
118
+ if 1 <= idx <= len(results):
119
+ return results[idx - 1]
120
+ print(t("invalid_selection"))
121
+ attempts += 1
122
+
123
+ return None
@@ -8,20 +8,13 @@ Unified interface for loading and adapting configuration files.
8
8
  This module provides:
9
9
  - load_config: loads YAML config from file path with fallback support
10
10
  - ConfigAdapter: maps raw config + site name to structured config models
11
- - Configuration dataclasses: RequesterConfig, DownloaderConfig, etc.
12
11
  """
13
12
 
14
- from .adapter import ConfigAdapter
15
- from .loader import load_config, save_config_file
16
- from .site_rules import (
17
- load_site_rules,
18
- save_rules_as_json,
19
- )
20
-
21
13
  __all__ = [
22
14
  "load_config",
23
15
  "save_config_file",
24
16
  "ConfigAdapter",
25
- "load_site_rules",
26
- "save_rules_as_json",
27
17
  ]
18
+
19
+ from .adapter import ConfigAdapter
20
+ from .loader import load_config, save_config_file