codex 1.7.2__py3-none-any.whl → 1.7.3__py3-none-any.whl

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.

Potentially problematic release.


This version of codex might be problematic. Click here for more details.

Files changed (894) hide show
  1. codex/asgi.py +2 -1
  2. codex/choices.py +10 -11
  3. codex/choices_to_json.py +8 -8
  4. codex/db.py +2 -2
  5. codex/exceptions.py +5 -6
  6. codex/librarian/bookmark/bookmarkd.py +9 -6
  7. codex/librarian/bookmark/tasks.py +1 -1
  8. codex/librarian/bookmark/update.py +17 -31
  9. codex/librarian/covers/create.py +10 -8
  10. codex/librarian/covers/path.py +6 -5
  11. codex/librarian/covers/purge.py +2 -2
  12. codex/librarian/cron/crond.py +1 -1
  13. codex/librarian/importer/aggregate.py +2 -2
  14. codex/librarian/importer/cache.py +1 -4
  15. codex/librarian/importer/create_comics.py +2 -2
  16. codex/librarian/importer/create_covers.py +1 -1
  17. codex/librarian/importer/create_fks.py +4 -3
  18. codex/librarian/importer/deleted.py +3 -3
  19. codex/librarian/importer/extract.py +2 -2
  20. codex/librarian/importer/failed_imports.py +1 -1
  21. codex/librarian/importer/importer.py +3 -1
  22. codex/librarian/importer/importerd.py +3 -3
  23. codex/librarian/importer/link_comics.py +2 -1
  24. codex/librarian/importer/moved.py +2 -7
  25. codex/librarian/importer/query_fks.py +3 -6
  26. codex/librarian/importer/tasks.py +1 -1
  27. codex/librarian/janitor/integrity.py +27 -20
  28. codex/librarian/janitor/janitor.py +5 -2
  29. codex/librarian/janitor/latest_version.py +1 -1
  30. codex/librarian/janitor/update.py +2 -2
  31. codex/librarian/janitor/vacuum.py +1 -1
  32. codex/librarian/librariand.py +16 -15
  33. codex/librarian/notifier/notifierd.py +2 -1
  34. codex/librarian/search/optimize.py +1 -1
  35. codex/librarian/search/remove.py +1 -1
  36. codex/librarian/search/update.py +11 -7
  37. codex/librarian/telemeter/stats.py +7 -6
  38. codex/librarian/telemeter/telemeter.py +0 -1
  39. codex/librarian/watchdog/db_snapshot.py +3 -3
  40. codex/librarian/watchdog/dir_snapshot_diff.py +3 -4
  41. codex/librarian/watchdog/emitter.py +4 -4
  42. codex/librarian/watchdog/event_batcherd.py +2 -1
  43. codex/librarian/watchdog/events.py +1 -2
  44. codex/librarian/watchdog/observers.py +15 -10
  45. codex/logger/loggerd.py +40 -17
  46. codex/logger/logging.py +1 -1
  47. codex/memory.py +3 -2
  48. codex/migrations/0001_init.py +1 -2
  49. codex/migrations/0014_pdf_issue_suffix_remove_cover_image_sort_name.py +1 -2
  50. codex/migrations/0018_rename_userbookmark_bookmark.py +1 -2
  51. codex/migrations/0028_telemeter.py +1 -5
  52. codex/migrations/0031_adminflag_banner.py +50 -0
  53. codex/models/admin.py +4 -3
  54. codex/models/base.py +3 -1
  55. codex/models/bookmark.py +4 -7
  56. codex/models/comic.py +2 -2
  57. codex/models/functions.py +12 -5
  58. codex/models/groups.py +1 -1
  59. codex/models/library.py +1 -1
  60. codex/models/paths.py +4 -4
  61. codex/models/query.py +8 -4
  62. codex/models/util.py +1 -1
  63. codex/permissions.py +1 -1
  64. codex/run.py +1 -1
  65. codex/serializers/admin/flags.py +1 -1
  66. codex/serializers/admin/libraries.py +1 -3
  67. codex/serializers/auth.py +1 -0
  68. codex/serializers/browser/choices.py +2 -2
  69. codex/serializers/browser/mixins.py +5 -1
  70. codex/serializers/browser/settings.py +2 -2
  71. codex/serializers/fields.py +7 -7
  72. codex/serializers/models/base.py +1 -1
  73. codex/serializers/models/comic.py +2 -2
  74. codex/serializers/models/groups.py +0 -2
  75. codex/serializers/opds/authentication.py +2 -1
  76. codex/serializers/opds/v2/__init__.py +1 -0
  77. codex/serializers/opds/v2/facet.py +13 -0
  78. codex/serializers/opds/v2/feed.py +36 -0
  79. codex/serializers/opds/v2/links.py +75 -0
  80. codex/serializers/opds/v2/metadata.py +23 -0
  81. codex/serializers/opds/v2/progression.py +65 -0
  82. codex/serializers/opds/v2/publication.py +81 -0
  83. codex/serializers/opds/{v2_unused.py → v2/unused.py} +16 -9
  84. codex/serializers/route.py +2 -2
  85. codex/settings/settings.py +4 -3
  86. codex/signals/django_signals.py +1 -1
  87. codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js +1 -0
  88. codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js.br +0 -0
  89. codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js.gz +0 -0
  90. codex/static_root/assets/VCheckbox-Dv6fwaDb.js +1 -0
  91. codex/static_root/assets/VCheckbox-Dv6fwaDb.js.br +0 -0
  92. codex/static_root/assets/VCheckbox-Dv6fwaDb.js.gz +0 -0
  93. codex/static_root/assets/VCheckboxBtn-CNMFahfF.4ee9778a562e.js +1 -0
  94. codex/static_root/assets/VCheckboxBtn-CNMFahfF.4ee9778a562e.js.br +0 -0
  95. codex/static_root/assets/VCheckboxBtn-CNMFahfF.4ee9778a562e.js.gz +0 -0
  96. codex/static_root/assets/VCheckboxBtn-CNMFahfF.js +1 -0
  97. codex/static_root/assets/VCheckboxBtn-CNMFahfF.js.br +0 -0
  98. codex/static_root/assets/VCheckboxBtn-CNMFahfF.js.gz +0 -0
  99. codex/static_root/assets/VCombobox-DqBFki-9.2806f95c938d.js +1 -0
  100. codex/static_root/assets/VCombobox-DqBFki-9.2806f95c938d.js.br +0 -0
  101. codex/static_root/assets/VCombobox-DqBFki-9.2806f95c938d.js.gz +0 -0
  102. codex/static_root/assets/VCombobox-DqBFki-9.js +1 -0
  103. codex/static_root/assets/VCombobox-DqBFki-9.js.br +0 -0
  104. codex/static_root/assets/VCombobox-DqBFki-9.js.gz +0 -0
  105. codex/static_root/assets/VDialog-CQXjBvDZ.1a576c5e472f.js +1 -0
  106. codex/static_root/assets/VDialog-CQXjBvDZ.1a576c5e472f.js.br +0 -0
  107. codex/static_root/assets/VDialog-CQXjBvDZ.1a576c5e472f.js.gz +0 -0
  108. codex/static_root/assets/VDialog-CQXjBvDZ.js +1 -0
  109. codex/static_root/assets/VDialog-CQXjBvDZ.js.br +0 -0
  110. codex/static_root/assets/VDialog-CQXjBvDZ.js.gz +0 -0
  111. codex/static_root/assets/VDialog-DWos4S54.b07aca713774.css +1 -0
  112. codex/static_root/assets/VDialog-DWos4S54.b07aca713774.css.br +0 -0
  113. codex/static_root/assets/VDialog-DWos4S54.b07aca713774.css.gz +0 -0
  114. codex/static_root/assets/VDialog-DWos4S54.css +1 -0
  115. codex/static_root/assets/VDialog-DWos4S54.css.br +0 -0
  116. codex/static_root/assets/VDialog-DWos4S54.css.gz +0 -0
  117. codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css +1 -0
  118. codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css.br +0 -0
  119. codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css.gz +0 -0
  120. codex/static_root/assets/VDivider-DU47sRrT.css +1 -0
  121. codex/static_root/assets/VDivider-DU47sRrT.css.br +0 -0
  122. codex/static_root/assets/VDivider-DU47sRrT.css.gz +0 -0
  123. codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js +1 -0
  124. codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js.br +0 -0
  125. codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js.gz +0 -0
  126. codex/static_root/assets/VDivider-DUxQu-IZ.js +1 -0
  127. codex/static_root/assets/VDivider-DUxQu-IZ.js.br +0 -0
  128. codex/static_root/assets/VDivider-DUxQu-IZ.js.gz +0 -0
  129. codex/static_root/assets/VExpansionPanels-BaYzHUJp.5346826103eb.js +1 -0
  130. codex/static_root/assets/VExpansionPanels-BaYzHUJp.5346826103eb.js.br +0 -0
  131. codex/static_root/assets/VExpansionPanels-BaYzHUJp.5346826103eb.js.gz +0 -0
  132. codex/static_root/assets/VExpansionPanels-BaYzHUJp.js +1 -0
  133. codex/static_root/assets/VExpansionPanels-BaYzHUJp.js.br +0 -0
  134. codex/static_root/assets/VExpansionPanels-BaYzHUJp.js.gz +0 -0
  135. codex/static_root/assets/VForm-DxBt30-N.138c0b89b6fc.css +1 -0
  136. codex/static_root/assets/VForm-DxBt30-N.138c0b89b6fc.css.br +0 -0
  137. codex/static_root/assets/VForm-DxBt30-N.138c0b89b6fc.css.gz +0 -0
  138. codex/static_root/assets/VForm-DxBt30-N.css +1 -0
  139. codex/static_root/assets/VForm-DxBt30-N.css.br +0 -0
  140. codex/static_root/assets/VForm-DxBt30-N.css.gz +0 -0
  141. codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js +1 -0
  142. codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js.br +0 -0
  143. codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js.gz +0 -0
  144. codex/static_root/assets/VForm-hB4C5jVd.js +1 -0
  145. codex/static_root/assets/VForm-hB4C5jVd.js.br +0 -0
  146. codex/static_root/assets/VForm-hB4C5jVd.js.gz +0 -0
  147. codex/static_root/assets/VRadioGroup-DOjw38qB.cbf2922d05af.js +1 -0
  148. codex/static_root/assets/VRadioGroup-DOjw38qB.cbf2922d05af.js.br +0 -0
  149. codex/static_root/assets/VRadioGroup-DOjw38qB.cbf2922d05af.js.gz +0 -0
  150. codex/static_root/assets/VRadioGroup-DOjw38qB.js +1 -0
  151. codex/static_root/assets/VRadioGroup-DOjw38qB.js.br +0 -0
  152. codex/static_root/assets/VRadioGroup-DOjw38qB.js.gz +0 -0
  153. codex/static_root/assets/VSelect-CP_CVb8s.6309f7bf17bb.css +1 -0
  154. codex/static_root/assets/VSelect-CP_CVb8s.6309f7bf17bb.css.br +0 -0
  155. codex/static_root/assets/VSelect-CP_CVb8s.6309f7bf17bb.css.gz +0 -0
  156. codex/static_root/assets/VSelect-CP_CVb8s.css +1 -0
  157. codex/static_root/assets/VSelect-CP_CVb8s.css.br +0 -0
  158. codex/static_root/assets/VSelect-CP_CVb8s.css.gz +0 -0
  159. codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js +1 -0
  160. codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js.br +0 -0
  161. codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js.gz +0 -0
  162. codex/static_root/assets/VSelect-L4v_m3ag.js +1 -0
  163. codex/static_root/assets/VSelect-L4v_m3ag.js.br +0 -0
  164. codex/static_root/assets/VSelect-L4v_m3ag.js.gz +0 -0
  165. codex/static_root/assets/VSelectionControl-BqB1JeKa.2fb68a673402.js +1 -0
  166. codex/static_root/assets/VSelectionControl-BqB1JeKa.2fb68a673402.js.br +0 -0
  167. codex/static_root/assets/VSelectionControl-BqB1JeKa.2fb68a673402.js.gz +0 -0
  168. codex/static_root/assets/VSelectionControl-BqB1JeKa.js +1 -0
  169. codex/static_root/assets/VSelectionControl-BqB1JeKa.js.br +0 -0
  170. codex/static_root/assets/VSelectionControl-BqB1JeKa.js.gz +0 -0
  171. codex/static_root/assets/VSelectionControl-DPpfgCW2.cc18de4e83f6.css +1 -0
  172. codex/static_root/assets/VSelectionControl-DPpfgCW2.cc18de4e83f6.css.br +0 -0
  173. codex/static_root/assets/VSelectionControl-DPpfgCW2.cc18de4e83f6.css.gz +0 -0
  174. codex/static_root/assets/VSelectionControl-DPpfgCW2.css +1 -0
  175. codex/static_root/assets/VSelectionControl-DPpfgCW2.css.br +0 -0
  176. codex/static_root/assets/VSelectionControl-DPpfgCW2.css.gz +0 -0
  177. codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js +1 -0
  178. codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js.br +0 -0
  179. codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js.gz +0 -0
  180. codex/static_root/assets/VTable-CtorAbOx.js +1 -0
  181. codex/static_root/assets/VTable-CtorAbOx.js.br +0 -0
  182. codex/static_root/assets/VTable-CtorAbOx.js.gz +0 -0
  183. codex/static_root/assets/VWindowItem-Bl-fa3ss.334e6b813775.js +1 -0
  184. codex/static_root/assets/VWindowItem-Bl-fa3ss.334e6b813775.js.br +0 -0
  185. codex/static_root/assets/VWindowItem-Bl-fa3ss.334e6b813775.js.gz +0 -0
  186. codex/static_root/assets/VWindowItem-Bl-fa3ss.js +1 -0
  187. codex/static_root/assets/VWindowItem-Bl-fa3ss.js.br +0 -0
  188. codex/static_root/assets/VWindowItem-Bl-fa3ss.js.gz +0 -0
  189. codex/static_root/assets/admin-BAVKNREt.23c0966bd683.js +1 -0
  190. codex/static_root/assets/admin-BAVKNREt.23c0966bd683.js.br +0 -0
  191. codex/static_root/assets/admin-BAVKNREt.23c0966bd683.js.gz +0 -0
  192. codex/static_root/assets/admin-BAVKNREt.js +1 -0
  193. codex/static_root/assets/admin-BAVKNREt.js.br +0 -0
  194. codex/static_root/assets/admin-BAVKNREt.js.gz +0 -0
  195. codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css +1 -0
  196. codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css.br +0 -0
  197. codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css.gz +0 -0
  198. codex/static_root/assets/admin-C3iCIUnm.css +1 -0
  199. codex/static_root/assets/admin-C3iCIUnm.css.br +0 -0
  200. codex/static_root/assets/admin-C3iCIUnm.css.gz +0 -0
  201. codex/static_root/assets/admin-CHuFhx_t.a54700f97fc8.js +1 -0
  202. codex/static_root/assets/admin-CHuFhx_t.a54700f97fc8.js.br +0 -0
  203. codex/static_root/assets/admin-CHuFhx_t.a54700f97fc8.js.gz +0 -0
  204. codex/static_root/assets/admin-CHuFhx_t.js +1 -0
  205. codex/static_root/assets/admin-CHuFhx_t.js.br +0 -0
  206. codex/static_root/assets/admin-CHuFhx_t.js.gz +0 -0
  207. codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js +1 -0
  208. codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js.br +0 -0
  209. codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js.gz +0 -0
  210. codex/static_root/assets/admin-menu-T8WJ_x0C.js +1 -0
  211. codex/static_root/assets/admin-menu-T8WJ_x0C.js.br +0 -0
  212. codex/static_root/assets/admin-menu-T8WJ_x0C.js.gz +0 -0
  213. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js +1 -0
  214. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js.br +0 -0
  215. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js.gz +0 -0
  216. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.js +1 -0
  217. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.js.br +0 -0
  218. codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.js.gz +0 -0
  219. codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css +1 -0
  220. codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css.br +0 -0
  221. codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css.gz +0 -0
  222. codex/static_root/assets/browser-DNzQvgkY.css +1 -0
  223. codex/static_root/assets/browser-DNzQvgkY.css.br +0 -0
  224. codex/static_root/assets/browser-DNzQvgkY.css.gz +0 -0
  225. codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js +1 -0
  226. codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js.br +0 -0
  227. codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js.gz +0 -0
  228. codex/static_root/assets/browser-DdLCtUlr.js +1 -0
  229. codex/static_root/assets/browser-DdLCtUlr.js.br +0 -0
  230. codex/static_root/assets/browser-DdLCtUlr.js.gz +0 -0
  231. codex/static_root/assets/change-password-dialog-Cy1tU-tj.416ef5bdfd46.js +1 -0
  232. codex/static_root/assets/change-password-dialog-Cy1tU-tj.416ef5bdfd46.js.br +0 -0
  233. codex/static_root/assets/change-password-dialog-Cy1tU-tj.416ef5bdfd46.js.gz +0 -0
  234. codex/static_root/assets/change-password-dialog-Cy1tU-tj.js +1 -0
  235. codex/static_root/assets/change-password-dialog-Cy1tU-tj.js.br +0 -0
  236. codex/static_root/assets/change-password-dialog-Cy1tU-tj.js.gz +0 -0
  237. codex/static_root/assets/confirm-dialog-B_Y3KKiL.1070d18f6b2d.js +1 -0
  238. codex/static_root/assets/confirm-dialog-B_Y3KKiL.1070d18f6b2d.js.br +0 -0
  239. codex/static_root/assets/confirm-dialog-B_Y3KKiL.1070d18f6b2d.js.gz +0 -0
  240. codex/static_root/assets/confirm-dialog-B_Y3KKiL.js +1 -0
  241. codex/static_root/assets/confirm-dialog-B_Y3KKiL.js.br +0 -0
  242. codex/static_root/assets/confirm-dialog-B_Y3KKiL.js.gz +0 -0
  243. codex/static_root/assets/datetime-column-DVC0YqHC.03bb52c198e9.js +1 -0
  244. codex/static_root/assets/datetime-column-DVC0YqHC.03bb52c198e9.js.br +0 -0
  245. codex/static_root/assets/datetime-column-DVC0YqHC.03bb52c198e9.js.gz +0 -0
  246. codex/static_root/assets/datetime-column-DVC0YqHC.js +1 -0
  247. codex/static_root/assets/datetime-column-DVC0YqHC.js.br +0 -0
  248. codex/static_root/assets/datetime-column-DVC0YqHC.js.gz +0 -0
  249. codex/static_root/assets/{filter-ud5mPZpn.0f0a537959aa.js → filter-xcEcgcIx.be1bb4725c89.js} +1 -1
  250. codex/static_root/assets/filter-xcEcgcIx.be1bb4725c89.js.br +0 -0
  251. codex/static_root/assets/filter-xcEcgcIx.be1bb4725c89.js.gz +0 -0
  252. codex/static_root/assets/{filter-ud5mPZpn.js → filter-xcEcgcIx.js} +1 -1
  253. codex/static_root/assets/filter-xcEcgcIx.js.br +0 -0
  254. codex/static_root/assets/filter-xcEcgcIx.js.gz +0 -0
  255. codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js +1 -0
  256. codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js.br +0 -0
  257. codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js.gz +0 -0
  258. codex/static_root/assets/flag-tab-BOyQb0kr.js +1 -0
  259. codex/static_root/assets/flag-tab-BOyQb0kr.js.br +0 -0
  260. codex/static_root/assets/flag-tab-BOyQb0kr.js.gz +0 -0
  261. codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css +1 -0
  262. codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css.br +0 -0
  263. codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css.gz +0 -0
  264. codex/static_root/assets/flag-tab-D2MYXCHk.css +1 -0
  265. codex/static_root/assets/flag-tab-D2MYXCHk.css.br +0 -0
  266. codex/static_root/assets/flag-tab-D2MYXCHk.css.gz +0 -0
  267. codex/static_root/assets/forwardRefs-CFNX6kJ2.9b56b4459240.css +1 -0
  268. codex/static_root/assets/forwardRefs-CFNX6kJ2.9b56b4459240.css.br +0 -0
  269. codex/static_root/assets/forwardRefs-CFNX6kJ2.9b56b4459240.css.gz +0 -0
  270. codex/static_root/assets/forwardRefs-CFNX6kJ2.css +1 -0
  271. codex/static_root/assets/forwardRefs-CFNX6kJ2.css.br +0 -0
  272. codex/static_root/assets/forwardRefs-CFNX6kJ2.css.gz +0 -0
  273. codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js +1 -0
  274. codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js.br +0 -0
  275. codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js.gz +0 -0
  276. codex/static_root/assets/forwardRefs-D1ZDjzWx.js +1 -0
  277. codex/static_root/assets/forwardRefs-D1ZDjzWx.js.br +0 -0
  278. codex/static_root/assets/forwardRefs-D1ZDjzWx.js.gz +0 -0
  279. codex/static_root/assets/group-tab-DkAIGL8z.527cad03c21d.js +1 -0
  280. codex/static_root/assets/group-tab-DkAIGL8z.527cad03c21d.js.br +0 -0
  281. codex/static_root/assets/group-tab-DkAIGL8z.527cad03c21d.js.gz +0 -0
  282. codex/static_root/assets/group-tab-DkAIGL8z.js +1 -0
  283. codex/static_root/assets/group-tab-DkAIGL8z.js.br +0 -0
  284. codex/static_root/assets/group-tab-DkAIGL8z.js.gz +0 -0
  285. codex/static_root/assets/http-error-CODU7jcH.8c13689ae574.css +1 -0
  286. codex/static_root/assets/http-error-CODU7jcH.8c13689ae574.css.br +0 -0
  287. codex/static_root/assets/http-error-CODU7jcH.8c13689ae574.css.gz +0 -0
  288. codex/static_root/assets/http-error-CODU7jcH.css +1 -0
  289. codex/static_root/assets/http-error-CODU7jcH.css.br +0 -0
  290. codex/static_root/assets/http-error-CODU7jcH.css.gz +0 -0
  291. codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js +1 -0
  292. codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js.br +0 -0
  293. codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js.gz +0 -0
  294. codex/static_root/assets/http-error-CjSb8orc.js +1 -0
  295. codex/static_root/assets/http-error-CjSb8orc.js.br +0 -0
  296. codex/static_root/assets/http-error-CjSb8orc.js.gz +0 -0
  297. codex/static_root/assets/index-CoFXW6I0.27f397e1425e.js +1 -0
  298. codex/static_root/assets/index-CoFXW6I0.27f397e1425e.js.br +0 -0
  299. codex/static_root/assets/index-CoFXW6I0.27f397e1425e.js.gz +0 -0
  300. codex/static_root/assets/index-CoFXW6I0.js +1 -0
  301. codex/static_root/assets/index-CoFXW6I0.js.br +0 -0
  302. codex/static_root/assets/index-CoFXW6I0.js.gz +0 -0
  303. codex/static_root/assets/{library-tab-Cat0MAK5.5911f022188e.css → library-tab-CgsXOX_r.75baedb7e976.css} +1 -1
  304. codex/static_root/assets/library-tab-CgsXOX_r.75baedb7e976.css.br +0 -0
  305. codex/static_root/assets/library-tab-CgsXOX_r.75baedb7e976.css.gz +0 -0
  306. codex/static_root/assets/{library-tab-Cat0MAK5.css → library-tab-CgsXOX_r.css} +1 -1
  307. codex/static_root/assets/library-tab-CgsXOX_r.css.br +0 -0
  308. codex/static_root/assets/library-tab-CgsXOX_r.css.gz +0 -0
  309. codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js +1 -0
  310. codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js.br +0 -0
  311. codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js.gz +0 -0
  312. codex/static_root/assets/library-tab-hkMMBz1x.js +1 -0
  313. codex/static_root/assets/library-tab-hkMMBz1x.js.br +0 -0
  314. codex/static_root/assets/library-tab-hkMMBz1x.js.gz +0 -0
  315. codex/static_root/assets/main-DCaPxp2h.076707ddd123.js +35 -0
  316. codex/static_root/assets/main-DCaPxp2h.076707ddd123.js.br +0 -0
  317. codex/static_root/assets/main-DCaPxp2h.076707ddd123.js.gz +0 -0
  318. codex/static_root/assets/main-DCaPxp2h.js +35 -0
  319. codex/static_root/assets/main-DCaPxp2h.js.br +0 -0
  320. codex/static_root/assets/main-DCaPxp2h.js.gz +0 -0
  321. codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js +1 -0
  322. codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js.br +0 -0
  323. codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js.gz +0 -0
  324. codex/static_root/assets/pager-full-pdf-CwmA9y3l.js +1 -0
  325. codex/static_root/assets/pager-full-pdf-CwmA9y3l.js.br +0 -0
  326. codex/static_root/assets/pager-full-pdf-CwmA9y3l.js.gz +0 -0
  327. codex/static_root/assets/pagination-toolbar-D5VQREy5.css +1 -0
  328. codex/static_root/assets/pagination-toolbar-D5VQREy5.css.br +0 -0
  329. codex/static_root/assets/pagination-toolbar-D5VQREy5.css.gz +0 -0
  330. codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css +1 -0
  331. codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css.br +0 -0
  332. codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css.gz +0 -0
  333. codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js +1 -0
  334. codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js.br +0 -0
  335. codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js.gz +0 -0
  336. codex/static_root/assets/pagination-toolbar-DoqxSygU.js +1 -0
  337. codex/static_root/assets/pagination-toolbar-DoqxSygU.js.br +0 -0
  338. codex/static_root/assets/pagination-toolbar-DoqxSygU.js.gz +0 -0
  339. codex/static_root/assets/pdf-doc-BwxvAx1z.96cbc39c321d.js +348 -0
  340. codex/static_root/assets/pdf-doc-BwxvAx1z.96cbc39c321d.js.br +0 -0
  341. codex/static_root/assets/pdf-doc-BwxvAx1z.96cbc39c321d.js.gz +0 -0
  342. codex/static_root/assets/pdf-doc-BwxvAx1z.js +348 -0
  343. codex/static_root/assets/pdf-doc-BwxvAx1z.js.br +0 -0
  344. codex/static_root/assets/pdf-doc-BwxvAx1z.js.gz +0 -0
  345. codex/static_root/assets/{reader-Dd2KmdCN.115d4bfe9280.css → reader-D_3ruSqa.2ed32f08e906.css} +1 -1
  346. codex/static_root/assets/reader-D_3ruSqa.2ed32f08e906.css.br +0 -0
  347. codex/static_root/assets/reader-D_3ruSqa.2ed32f08e906.css.gz +0 -0
  348. codex/static_root/assets/{reader-Dd2KmdCN.css → reader-D_3ruSqa.css} +1 -1
  349. codex/static_root/assets/reader-D_3ruSqa.css.br +0 -0
  350. codex/static_root/assets/reader-D_3ruSqa.css.gz +0 -0
  351. codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js +2 -0
  352. codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js.br +0 -0
  353. codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js.gz +0 -0
  354. codex/static_root/assets/reader-hHIonVbA.js +2 -0
  355. codex/static_root/assets/reader-hHIonVbA.js.br +0 -0
  356. codex/static_root/assets/reader-hHIonVbA.js.gz +0 -0
  357. codex/static_root/assets/relation-chips-D7-5kPem.4443b085aca2.js +1 -0
  358. codex/static_root/assets/relation-chips-D7-5kPem.4443b085aca2.js.br +0 -0
  359. codex/static_root/assets/relation-chips-D7-5kPem.4443b085aca2.js.gz +0 -0
  360. codex/static_root/assets/relation-chips-D7-5kPem.js +1 -0
  361. codex/static_root/assets/relation-chips-D7-5kPem.js.br +0 -0
  362. codex/static_root/assets/relation-chips-D7-5kPem.js.gz +0 -0
  363. codex/static_root/assets/settings-drawer-CdFmOhnd.f7dcd12b3ebc.js +2 -0
  364. codex/static_root/assets/settings-drawer-CdFmOhnd.f7dcd12b3ebc.js.br +0 -0
  365. codex/static_root/assets/settings-drawer-CdFmOhnd.f7dcd12b3ebc.js.gz +0 -0
  366. codex/static_root/assets/settings-drawer-CdFmOhnd.js +2 -0
  367. codex/static_root/assets/settings-drawer-CdFmOhnd.js.br +0 -0
  368. codex/static_root/assets/settings-drawer-CdFmOhnd.js.gz +0 -0
  369. codex/static_root/assets/settings-drawer-DMSsWF8c.75a6ea969e71.css +1 -0
  370. codex/static_root/assets/settings-drawer-DMSsWF8c.75a6ea969e71.css.br +0 -0
  371. codex/static_root/assets/settings-drawer-DMSsWF8c.75a6ea969e71.css.gz +0 -0
  372. codex/static_root/assets/settings-drawer-DMSsWF8c.css +1 -0
  373. codex/static_root/assets/settings-drawer-DMSsWF8c.css.br +0 -0
  374. codex/static_root/assets/settings-drawer-DMSsWF8c.css.gz +0 -0
  375. codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js +1 -0
  376. codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js.br +0 -0
  377. codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js.gz +0 -0
  378. codex/static_root/assets/stats-tab-BzaipD0m.js +1 -0
  379. codex/static_root/assets/stats-tab-BzaipD0m.js.br +0 -0
  380. codex/static_root/assets/stats-tab-BzaipD0m.js.gz +0 -0
  381. codex/static_root/assets/task-tab-DCnS1sM9.44d8435b4989.js +1 -0
  382. codex/static_root/assets/task-tab-DCnS1sM9.44d8435b4989.js.br +0 -0
  383. codex/static_root/assets/task-tab-DCnS1sM9.44d8435b4989.js.gz +0 -0
  384. codex/static_root/assets/task-tab-DCnS1sM9.js +1 -0
  385. codex/static_root/assets/task-tab-DCnS1sM9.js.br +0 -0
  386. codex/static_root/assets/task-tab-DCnS1sM9.js.gz +0 -0
  387. codex/static_root/assets/unauthorized-CsSak07X.c5536d9dae75.css +1 -0
  388. codex/static_root/assets/unauthorized-CsSak07X.c5536d9dae75.css.br +0 -0
  389. codex/static_root/assets/unauthorized-CsSak07X.c5536d9dae75.css.gz +0 -0
  390. codex/static_root/assets/unauthorized-CsSak07X.css +1 -0
  391. codex/static_root/assets/unauthorized-CsSak07X.css.br +0 -0
  392. codex/static_root/assets/unauthorized-CsSak07X.css.gz +0 -0
  393. codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js +1 -0
  394. codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js.br +0 -0
  395. codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js.gz +0 -0
  396. codex/static_root/assets/unauthorized-DJSr03Dw.js +1 -0
  397. codex/static_root/assets/unauthorized-DJSr03Dw.js.br +0 -0
  398. codex/static_root/assets/unauthorized-DJSr03Dw.js.gz +0 -0
  399. codex/static_root/assets/user-tab-DAK_Deoh.1832877d449a.js +1 -0
  400. codex/static_root/assets/user-tab-DAK_Deoh.1832877d449a.js.br +0 -0
  401. codex/static_root/assets/user-tab-DAK_Deoh.1832877d449a.js.gz +0 -0
  402. codex/static_root/assets/user-tab-DAK_Deoh.js +1 -0
  403. codex/static_root/assets/user-tab-DAK_Deoh.js.br +0 -0
  404. codex/static_root/assets/user-tab-DAK_Deoh.js.gz +0 -0
  405. codex/static_root/manifest.cbc39bca88fc.json +735 -0
  406. codex/static_root/manifest.cbc39bca88fc.json.br +0 -0
  407. codex/static_root/manifest.cbc39bca88fc.json.gz +0 -0
  408. codex/static_root/manifest.json +388 -365
  409. codex/static_root/manifest.json.br +0 -0
  410. codex/static_root/manifest.json.gz +0 -0
  411. codex/static_root/staticfiles.json +1 -1
  412. codex/status_controller.py +9 -12
  413. codex/templates/index.html +1 -1
  414. codex/threads.py +3 -3
  415. codex/urls/api/admin.py +4 -3
  416. codex/urls/api/browser.py +1 -1
  417. codex/urls/opds/v2.py +6 -0
  418. codex/urls/root.py +4 -3
  419. codex/views/admin/api_key.py +1 -4
  420. codex/views/admin/flag.py +5 -1
  421. codex/views/admin/library.py +4 -4
  422. codex/views/admin/stats.py +10 -10
  423. codex/views/admin/tasks.py +9 -9
  424. codex/views/auth.py +3 -8
  425. codex/views/bookmark.py +53 -41
  426. codex/views/browser/annotate/bookmark.py +6 -4
  427. codex/views/browser/annotate/card.py +3 -18
  428. codex/views/browser/annotate/order.py +51 -25
  429. codex/views/browser/bookmark.py +53 -0
  430. codex/views/browser/breadcrumbs.py +6 -5
  431. codex/views/browser/browser.py +2 -2
  432. codex/views/browser/choices.py +6 -5
  433. codex/views/browser/cover.py +6 -3
  434. codex/views/browser/download.py +4 -1
  435. codex/views/browser/filters/bookmark.py +5 -33
  436. codex/views/browser/filters/field.py +1 -1
  437. codex/views/browser/filters/filter.py +6 -8
  438. codex/views/browser/filters/group.py +5 -4
  439. codex/views/browser/filters/search/field/expression.py +1 -2
  440. codex/views/browser/filters/search/field/optimize.py +1 -1
  441. codex/views/browser/filters/search/field/parse.py +2 -2
  442. codex/views/browser/filters/search/parse.py +4 -19
  443. codex/views/browser/group_mtime.py +3 -3
  444. codex/views/browser/metadata/annotate.py +1 -1
  445. codex/views/browser/metadata/copy_intersections.py +1 -1
  446. codex/views/browser/metadata/metadata.py +2 -2
  447. codex/views/browser/mtime.py +1 -1
  448. codex/views/browser/order_by.py +9 -6
  449. codex/views/browser/params.py +1 -1
  450. codex/views/browser/settings.py +1 -1
  451. codex/views/browser/validate.py +8 -5
  452. codex/views/const.py +0 -3
  453. codex/views/frontend.py +20 -5
  454. codex/views/mixins.py +19 -30
  455. codex/views/opds/authentication_v1.py +1 -1
  456. codex/views/opds/const.py +6 -4
  457. codex/views/opds/util.py +5 -5
  458. codex/views/opds/v1/entry/entry.py +4 -2
  459. codex/views/opds/v1/entry/links.py +5 -7
  460. codex/views/opds/v1/facets.py +8 -4
  461. codex/views/opds/v1/feed.py +5 -5
  462. codex/views/opds/v1/links.py +11 -6
  463. codex/views/opds/v2/const.py +5 -2
  464. codex/views/opds/v2/feed.py +6 -5
  465. codex/views/opds/v2/href.py +60 -0
  466. codex/views/opds/v2/links.py +13 -47
  467. codex/views/opds/v2/progression.py +136 -0
  468. codex/views/opds/v2/publications.py +31 -21
  469. codex/views/opds/v2/top_links.py +2 -1
  470. codex/views/public.py +12 -5
  471. codex/views/reader/books.py +22 -10
  472. codex/views/reader/page.py +8 -8
  473. codex/views/reader/params.py +2 -2
  474. codex/views/reader/reader.py +6 -6
  475. codex/views/reader/settings.py +1 -1
  476. codex/views/session.py +8 -2
  477. codex/views/settings.py +2 -2
  478. codex/views/timezone.py +2 -2
  479. codex/views/util.py +10 -9
  480. codex/views/version.py +1 -1
  481. {codex-1.7.2.dist-info → codex-1.7.3.dist-info}/METADATA +21 -26
  482. codex-1.7.3.dist-info/RECORD +1031 -0
  483. {codex-1.7.2.dist-info → codex-1.7.3.dist-info}/WHEEL +1 -1
  484. codex/serializers/opds/v2.py +0 -178
  485. codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js +0 -1
  486. codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js.br +0 -0
  487. codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js.gz +0 -0
  488. codex/static_root/assets/VCheckbox-DLMzIII1.js +0 -1
  489. codex/static_root/assets/VCheckbox-DLMzIII1.js.br +0 -0
  490. codex/static_root/assets/VCheckbox-DLMzIII1.js.gz +0 -0
  491. codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js +0 -1
  492. codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js.br +0 -0
  493. codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js.gz +0 -0
  494. codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js +0 -1
  495. codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js.br +0 -0
  496. codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js.gz +0 -0
  497. codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js +0 -1
  498. codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js.br +0 -0
  499. codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js.gz +0 -0
  500. codex/static_root/assets/VCombobox-CBY8K5CP.js +0 -1
  501. codex/static_root/assets/VCombobox-CBY8K5CP.js.br +0 -0
  502. codex/static_root/assets/VCombobox-CBY8K5CP.js.gz +0 -0
  503. codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css +0 -1
  504. codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css.br +0 -0
  505. codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css.gz +0 -0
  506. codex/static_root/assets/VDialog-DXQz0Ylp.css +0 -1
  507. codex/static_root/assets/VDialog-DXQz0Ylp.css.br +0 -0
  508. codex/static_root/assets/VDialog-DXQz0Ylp.css.gz +0 -0
  509. codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js +0 -1
  510. codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js.br +0 -0
  511. codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js.gz +0 -0
  512. codex/static_root/assets/VDialog-Db4tJYqR.js +0 -1
  513. codex/static_root/assets/VDialog-Db4tJYqR.js.br +0 -0
  514. codex/static_root/assets/VDialog-Db4tJYqR.js.gz +0 -0
  515. codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js +0 -1
  516. codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js.br +0 -0
  517. codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js.gz +0 -0
  518. codex/static_root/assets/VExpansionPanels-DN4yGbOt.js +0 -1
  519. codex/static_root/assets/VExpansionPanels-DN4yGbOt.js.br +0 -0
  520. codex/static_root/assets/VExpansionPanels-DN4yGbOt.js.gz +0 -0
  521. codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js +0 -1
  522. codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js.br +0 -0
  523. codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js.gz +0 -0
  524. codex/static_root/assets/VRadioGroup-D2-PWEfs.js +0 -1
  525. codex/static_root/assets/VRadioGroup-D2-PWEfs.js.br +0 -0
  526. codex/static_root/assets/VRadioGroup-D2-PWEfs.js.gz +0 -0
  527. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css +0 -1
  528. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.br +0 -0
  529. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.gz +0 -0
  530. codex/static_root/assets/VSelect-DLu8bpcs.css +0 -1
  531. codex/static_root/assets/VSelect-DLu8bpcs.css.br +0 -0
  532. codex/static_root/assets/VSelect-DLu8bpcs.css.gz +0 -0
  533. codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js +0 -1
  534. codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js.br +0 -0
  535. codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js.gz +0 -0
  536. codex/static_root/assets/VSelect-DqXJ23Pc.js +0 -1
  537. codex/static_root/assets/VSelect-DqXJ23Pc.js.br +0 -0
  538. codex/static_root/assets/VSelect-DqXJ23Pc.js.gz +0 -0
  539. codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css +0 -1
  540. codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css.br +0 -0
  541. codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css.gz +0 -0
  542. codex/static_root/assets/VSelectionControl-CiViEYoC.css +0 -1
  543. codex/static_root/assets/VSelectionControl-CiViEYoC.css.br +0 -0
  544. codex/static_root/assets/VSelectionControl-CiViEYoC.css.gz +0 -0
  545. codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js +0 -1
  546. codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js.br +0 -0
  547. codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js.gz +0 -0
  548. codex/static_root/assets/VSelectionControl-CxhDNufT.js +0 -1
  549. codex/static_root/assets/VSelectionControl-CxhDNufT.js.br +0 -0
  550. codex/static_root/assets/VSelectionControl-CxhDNufT.js.gz +0 -0
  551. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css +0 -1
  552. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.br +0 -0
  553. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.gz +0 -0
  554. codex/static_root/assets/VSlideGroup-BtXPhMOT.css +0 -1
  555. codex/static_root/assets/VSlideGroup-BtXPhMOT.css.br +0 -0
  556. codex/static_root/assets/VSlideGroup-BtXPhMOT.css.gz +0 -0
  557. codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js +0 -1
  558. codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js.br +0 -0
  559. codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js.gz +0 -0
  560. codex/static_root/assets/VSlideGroup-DRbthp6q.js +0 -1
  561. codex/static_root/assets/VSlideGroup-DRbthp6q.js.br +0 -0
  562. codex/static_root/assets/VSlideGroup-DRbthp6q.js.gz +0 -0
  563. codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js +0 -1
  564. codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js.br +0 -0
  565. codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js.gz +0 -0
  566. codex/static_root/assets/VTable-Cbq-yJos.js +0 -1
  567. codex/static_root/assets/VTable-Cbq-yJos.js.br +0 -0
  568. codex/static_root/assets/VTable-Cbq-yJos.js.gz +0 -0
  569. codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css +0 -1
  570. codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.br +0 -0
  571. codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.gz +0 -0
  572. codex/static_root/assets/VTextField-Crc3gdNh.css +0 -1
  573. codex/static_root/assets/VTextField-Crc3gdNh.css.br +0 -0
  574. codex/static_root/assets/VTextField-Crc3gdNh.css.gz +0 -0
  575. codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js +0 -1
  576. codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js.br +0 -0
  577. codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js.gz +0 -0
  578. codex/static_root/assets/VTextField-X5yAw35c.js +0 -1
  579. codex/static_root/assets/VTextField-X5yAw35c.js.br +0 -0
  580. codex/static_root/assets/VTextField-X5yAw35c.js.gz +0 -0
  581. codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js +0 -1
  582. codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js.br +0 -0
  583. codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js.gz +0 -0
  584. codex/static_root/assets/VWindowItem-CRqhVh-9.js +0 -1
  585. codex/static_root/assets/VWindowItem-CRqhVh-9.js.br +0 -0
  586. codex/static_root/assets/VWindowItem-CRqhVh-9.js.gz +0 -0
  587. codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js +0 -1
  588. codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js.br +0 -0
  589. codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js.gz +0 -0
  590. codex/static_root/assets/admin-BFvQwinN.js +0 -1
  591. codex/static_root/assets/admin-BFvQwinN.js.br +0 -0
  592. codex/static_root/assets/admin-BFvQwinN.js.gz +0 -0
  593. codex/static_root/assets/admin-DJ7pIXDQ.css +0 -1
  594. codex/static_root/assets/admin-DJ7pIXDQ.css.br +0 -0
  595. codex/static_root/assets/admin-DJ7pIXDQ.css.gz +0 -0
  596. codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css +0 -1
  597. codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.br +0 -0
  598. codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.gz +0 -0
  599. codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js +0 -1
  600. codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js.br +0 -0
  601. codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js.gz +0 -0
  602. codex/static_root/assets/admin-menu-Jfmp_Yd8.js +0 -1
  603. codex/static_root/assets/admin-menu-Jfmp_Yd8.js.br +0 -0
  604. codex/static_root/assets/admin-menu-Jfmp_Yd8.js.gz +0 -0
  605. codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js +0 -1
  606. codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js.br +0 -0
  607. codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js.gz +0 -0
  608. codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js +0 -1
  609. codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js.br +0 -0
  610. codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js.gz +0 -0
  611. codex/static_root/assets/browser-CctlSJji.css +0 -1
  612. codex/static_root/assets/browser-CctlSJji.css.br +0 -0
  613. codex/static_root/assets/browser-CctlSJji.css.gz +0 -0
  614. codex/static_root/assets/browser-CctlSJji.d42d796476d2.css +0 -1
  615. codex/static_root/assets/browser-CctlSJji.d42d796476d2.css.br +0 -0
  616. codex/static_root/assets/browser-CctlSJji.d42d796476d2.css.gz +0 -0
  617. codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js +0 -1
  618. codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js.br +0 -0
  619. codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js.gz +0 -0
  620. codex/static_root/assets/browser-DJnEeVHz.js +0 -1
  621. codex/static_root/assets/browser-DJnEeVHz.js.br +0 -0
  622. codex/static_root/assets/browser-DJnEeVHz.js.gz +0 -0
  623. codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js +0 -1
  624. codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js.br +0 -0
  625. codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js.gz +0 -0
  626. codex/static_root/assets/change-password-dialog-DJtOQw7K.js +0 -1
  627. codex/static_root/assets/change-password-dialog-DJtOQw7K.js.br +0 -0
  628. codex/static_root/assets/change-password-dialog-DJtOQw7K.js.gz +0 -0
  629. codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js +0 -1
  630. codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js.br +0 -0
  631. codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js.gz +0 -0
  632. codex/static_root/assets/confirm-dialog-CME4gKSZ.js +0 -1
  633. codex/static_root/assets/confirm-dialog-CME4gKSZ.js.br +0 -0
  634. codex/static_root/assets/confirm-dialog-CME4gKSZ.js.gz +0 -0
  635. codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js +0 -1
  636. codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js.br +0 -2
  637. codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js.gz +0 -0
  638. codex/static_root/assets/datetime-column-D_F30OLW.js +0 -1
  639. codex/static_root/assets/datetime-column-D_F30OLW.js.br +0 -2
  640. codex/static_root/assets/datetime-column-D_F30OLW.js.gz +0 -0
  641. codex/static_root/assets/filter-ud5mPZpn.0f0a537959aa.js.br +0 -0
  642. codex/static_root/assets/filter-ud5mPZpn.0f0a537959aa.js.gz +0 -0
  643. codex/static_root/assets/filter-ud5mPZpn.js.br +0 -0
  644. codex/static_root/assets/filter-ud5mPZpn.js.gz +0 -0
  645. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css +0 -1
  646. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.br +0 -0
  647. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.gz +0 -0
  648. codex/static_root/assets/flag-tab-CqWovuBu.css +0 -1
  649. codex/static_root/assets/flag-tab-CqWovuBu.css.br +0 -0
  650. codex/static_root/assets/flag-tab-CqWovuBu.css.gz +0 -0
  651. codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js +0 -1
  652. codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js.br +0 -0
  653. codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js.gz +0 -0
  654. codex/static_root/assets/flag-tab-k2g6u_vi.js +0 -1
  655. codex/static_root/assets/flag-tab-k2g6u_vi.js.br +0 -0
  656. codex/static_root/assets/flag-tab-k2g6u_vi.js.gz +0 -0
  657. codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js +0 -1
  658. codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js.br +0 -0
  659. codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js.gz +0 -0
  660. codex/static_root/assets/group-tab-C6Ykf03Z.js +0 -1
  661. codex/static_root/assets/group-tab-C6Ykf03Z.js.br +0 -0
  662. codex/static_root/assets/group-tab-C6Ykf03Z.js.gz +0 -0
  663. codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css +0 -1
  664. codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css.br +0 -0
  665. codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css.gz +0 -0
  666. codex/static_root/assets/http-error-Ctcws1xe.css +0 -1
  667. codex/static_root/assets/http-error-Ctcws1xe.css.br +0 -0
  668. codex/static_root/assets/http-error-Ctcws1xe.css.gz +0 -0
  669. codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js +0 -1
  670. codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js.br +0 -0
  671. codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js.gz +0 -0
  672. codex/static_root/assets/http-error-DQBHK8v5.js +0 -1
  673. codex/static_root/assets/http-error-DQBHK8v5.js.br +0 -0
  674. codex/static_root/assets/http-error-DQBHK8v5.js.gz +0 -0
  675. codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js +0 -1
  676. codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js.br +0 -0
  677. codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js.gz +0 -0
  678. codex/static_root/assets/index-ClGiHwWc.js +0 -1
  679. codex/static_root/assets/index-ClGiHwWc.js.br +0 -0
  680. codex/static_root/assets/index-ClGiHwWc.js.gz +0 -0
  681. codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js +0 -1
  682. codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js.br +0 -0
  683. codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js.gz +0 -0
  684. codex/static_root/assets/library-tab-BpinbqAu.js +0 -1
  685. codex/static_root/assets/library-tab-BpinbqAu.js.br +0 -0
  686. codex/static_root/assets/library-tab-BpinbqAu.js.gz +0 -0
  687. codex/static_root/assets/library-tab-Cat0MAK5.5911f022188e.css.br +0 -0
  688. codex/static_root/assets/library-tab-Cat0MAK5.5911f022188e.css.gz +0 -0
  689. codex/static_root/assets/library-tab-Cat0MAK5.css.br +0 -0
  690. codex/static_root/assets/library-tab-Cat0MAK5.css.gz +0 -0
  691. codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js +0 -35
  692. codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js.br +0 -0
  693. codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js.gz +0 -0
  694. codex/static_root/assets/main-BVKrDunc.js +0 -35
  695. codex/static_root/assets/main-BVKrDunc.js.br +0 -0
  696. codex/static_root/assets/main-BVKrDunc.js.gz +0 -0
  697. codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js +0 -1
  698. codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js.br +0 -0
  699. codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js.gz +0 -0
  700. codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js +0 -1
  701. codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js.br +0 -0
  702. codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js.gz +0 -0
  703. codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css +0 -1
  704. codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css.br +0 -0
  705. codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css.gz +0 -0
  706. codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css +0 -1
  707. codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css.br +0 -0
  708. codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css.gz +0 -0
  709. codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js +0 -1
  710. codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js.br +0 -0
  711. codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js.gz +0 -0
  712. codex/static_root/assets/pagination-toolbar-Diad0EdD.js +0 -1
  713. codex/static_root/assets/pagination-toolbar-Diad0EdD.js.br +0 -0
  714. codex/static_root/assets/pagination-toolbar-Diad0EdD.js.gz +0 -0
  715. codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js +0 -305
  716. codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js.br +0 -0
  717. codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js.gz +0 -0
  718. codex/static_root/assets/pdf-doc-b-GyNR6z.js +0 -305
  719. codex/static_root/assets/pdf-doc-b-GyNR6z.js.br +0 -0
  720. codex/static_root/assets/pdf-doc-b-GyNR6z.js.gz +0 -0
  721. codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js +0 -2
  722. codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js.br +0 -0
  723. codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js.gz +0 -0
  724. codex/static_root/assets/reader-2up6WEuE.js +0 -2
  725. codex/static_root/assets/reader-2up6WEuE.js.br +0 -0
  726. codex/static_root/assets/reader-2up6WEuE.js.gz +0 -0
  727. codex/static_root/assets/reader-Dd2KmdCN.115d4bfe9280.css.br +0 -0
  728. codex/static_root/assets/reader-Dd2KmdCN.115d4bfe9280.css.gz +0 -0
  729. codex/static_root/assets/reader-Dd2KmdCN.css.br +0 -0
  730. codex/static_root/assets/reader-Dd2KmdCN.css.gz +0 -0
  731. codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js +0 -1
  732. codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js.br +0 -0
  733. codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js.gz +0 -0
  734. codex/static_root/assets/relation-chips-piYv1IcD.js +0 -1
  735. codex/static_root/assets/relation-chips-piYv1IcD.js.br +0 -0
  736. codex/static_root/assets/relation-chips-piYv1IcD.js.gz +0 -0
  737. codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css +0 -1
  738. codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css.br +0 -0
  739. codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css.gz +0 -0
  740. codex/static_root/assets/settings-drawer-DKncO_vX.css +0 -1
  741. codex/static_root/assets/settings-drawer-DKncO_vX.css.br +0 -0
  742. codex/static_root/assets/settings-drawer-DKncO_vX.css.gz +0 -0
  743. codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js +0 -2
  744. codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js.br +0 -0
  745. codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js.gz +0 -0
  746. codex/static_root/assets/settings-drawer-yVoY-WCS.js +0 -2
  747. codex/static_root/assets/settings-drawer-yVoY-WCS.js.br +0 -0
  748. codex/static_root/assets/settings-drawer-yVoY-WCS.js.gz +0 -0
  749. codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js +0 -1
  750. codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js.br +0 -0
  751. codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js.gz +0 -0
  752. codex/static_root/assets/stats-tab-bqSPLvTp.js +0 -1
  753. codex/static_root/assets/stats-tab-bqSPLvTp.js.br +0 -0
  754. codex/static_root/assets/stats-tab-bqSPLvTp.js.gz +0 -0
  755. codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js +0 -1
  756. codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js.br +0 -0
  757. codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js.gz +0 -0
  758. codex/static_root/assets/task-tab-DWPKaGPT.js +0 -1
  759. codex/static_root/assets/task-tab-DWPKaGPT.js.br +0 -0
  760. codex/static_root/assets/task-tab-DWPKaGPT.js.gz +0 -0
  761. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css +0 -1
  762. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.br +0 -4
  763. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.gz +0 -0
  764. codex/static_root/assets/transition-5LRFTPo5.css +0 -1
  765. codex/static_root/assets/transition-5LRFTPo5.css.br +0 -4
  766. codex/static_root/assets/transition-5LRFTPo5.css.gz +0 -0
  767. codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js +0 -1
  768. codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js.br +0 -0
  769. codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js.gz +0 -0
  770. codex/static_root/assets/transition-DWVQ2EZ3.js +0 -1
  771. codex/static_root/assets/transition-DWVQ2EZ3.js.br +0 -0
  772. codex/static_root/assets/transition-DWVQ2EZ3.js.gz +0 -0
  773. codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js +0 -1
  774. codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js.br +0 -0
  775. codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js.gz +0 -0
  776. codex/static_root/assets/unauthorized-CEGD20tR.js +0 -1
  777. codex/static_root/assets/unauthorized-CEGD20tR.js.br +0 -0
  778. codex/static_root/assets/unauthorized-CEGD20tR.js.gz +0 -0
  779. codex/static_root/assets/unauthorized-DyojW2ic.css +0 -1
  780. codex/static_root/assets/unauthorized-DyojW2ic.css.br +0 -0
  781. codex/static_root/assets/unauthorized-DyojW2ic.css.gz +0 -0
  782. codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css +0 -1
  783. codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css.br +0 -0
  784. codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css.gz +0 -0
  785. codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js +0 -1
  786. codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js.br +0 -0
  787. codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js.gz +0 -0
  788. codex/static_root/assets/user-tab-EsokzMCB.js +0 -1
  789. codex/static_root/assets/user-tab-EsokzMCB.js.br +0 -0
  790. codex/static_root/assets/user-tab-EsokzMCB.js.gz +0 -0
  791. codex/static_root/manifest.4a38de3db1c5.json +0 -712
  792. codex/static_root/manifest.4a38de3db1c5.json.br +0 -0
  793. codex/static_root/manifest.4a38de3db1c5.json.gz +0 -0
  794. codex-1.7.2.dist-info/RECORD +0 -1015
  795. /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css → VCheckbox-CvH8ekHL.016ed8d222c4.css} +0 -0
  796. /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css.br → VCheckbox-CvH8ekHL.016ed8d222c4.css.br} +0 -0
  797. /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css.gz → VCheckbox-CvH8ekHL.016ed8d222c4.css.gz} +0 -0
  798. /codex/static_root/assets/{VCheckbox-CMKdyl0R.css → VCheckbox-CvH8ekHL.css} +0 -0
  799. /codex/static_root/assets/{VCheckbox-CMKdyl0R.css.br → VCheckbox-CvH8ekHL.css.br} +0 -0
  800. /codex/static_root/assets/{VCheckbox-CMKdyl0R.css.gz → VCheckbox-CvH8ekHL.css.gz} +0 -0
  801. /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css → VCombobox-BQHELb_o.9f25a34994e2.css} +0 -0
  802. /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css.br → VCombobox-BQHELb_o.9f25a34994e2.css.br} +0 -0
  803. /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css.gz → VCombobox-BQHELb_o.9f25a34994e2.css.gz} +0 -0
  804. /codex/static_root/assets/{VCombobox-bwEYrXCg.css → VCombobox-BQHELb_o.css} +0 -0
  805. /codex/static_root/assets/{VCombobox-bwEYrXCg.css.br → VCombobox-BQHELb_o.css.br} +0 -0
  806. /codex/static_root/assets/{VCombobox-bwEYrXCg.css.gz → VCombobox-BQHELb_o.css.gz} +0 -0
  807. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css → VExpansionPanels-RsCANmDP.5b17872981df.css} +0 -0
  808. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css.br → VExpansionPanels-RsCANmDP.5b17872981df.css.br} +0 -0
  809. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css.gz → VExpansionPanels-RsCANmDP.5b17872981df.css.gz} +0 -0
  810. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css → VExpansionPanels-RsCANmDP.css} +0 -0
  811. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css.br → VExpansionPanels-RsCANmDP.css.br} +0 -0
  812. /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css.gz → VExpansionPanels-RsCANmDP.css.gz} +0 -0
  813. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css → VRadioGroup-Cp9mZ7cb.8e3741381961.css} +0 -0
  814. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css.br → VRadioGroup-Cp9mZ7cb.8e3741381961.css.br} +0 -0
  815. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css.gz → VRadioGroup-Cp9mZ7cb.8e3741381961.css.gz} +0 -0
  816. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css → VRadioGroup-Cp9mZ7cb.css} +0 -0
  817. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css.br → VRadioGroup-Cp9mZ7cb.css.br} +0 -0
  818. /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css.gz → VRadioGroup-Cp9mZ7cb.css.gz} +0 -0
  819. /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css → VTable-BnxSZ_W5.c36f0a6a30cf.css} +0 -0
  820. /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css.br → VTable-BnxSZ_W5.c36f0a6a30cf.css.br} +0 -0
  821. /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css.gz → VTable-BnxSZ_W5.c36f0a6a30cf.css.gz} +0 -0
  822. /codex/static_root/assets/{VTable-Y5Sc3hJd.css → VTable-BnxSZ_W5.css} +0 -0
  823. /codex/static_root/assets/{VTable-Y5Sc3hJd.css.br → VTable-BnxSZ_W5.css.br} +0 -0
  824. /codex/static_root/assets/{VTable-Y5Sc3hJd.css.gz → VTable-BnxSZ_W5.css.gz} +0 -0
  825. /codex/static_root/assets/{VWindowItem-ByIod57Y.css → VWindowItem-CWBhiE_Y.css} +0 -0
  826. /codex/static_root/assets/{VWindowItem-ByIod57Y.css.br → VWindowItem-CWBhiE_Y.css.br} +0 -0
  827. /codex/static_root/assets/{VWindowItem-ByIod57Y.css.gz → VWindowItem-CWBhiE_Y.css.gz} +0 -0
  828. /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css → VWindowItem-CWBhiE_Y.f7fb19752bf3.css} +0 -0
  829. /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css.br → VWindowItem-CWBhiE_Y.f7fb19752bf3.css.br} +0 -0
  830. /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css.gz → VWindowItem-CWBhiE_Y.f7fb19752bf3.css.gz} +0 -0
  831. /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css → admin-menu-B3iXsOyy.c13b7df2ff57.css} +0 -0
  832. /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css.br → admin-menu-B3iXsOyy.c13b7df2ff57.css.br} +0 -0
  833. /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css.gz → admin-menu-B3iXsOyy.c13b7df2ff57.css.gz} +0 -0
  834. /codex/static_root/assets/{admin-menu-B9bzD6hV.css → admin-menu-B3iXsOyy.css} +0 -0
  835. /codex/static_root/assets/{admin-menu-B9bzD6hV.css.br → admin-menu-B3iXsOyy.css.br} +0 -0
  836. /codex/static_root/assets/{admin-menu-B9bzD6hV.css.gz → admin-menu-B3iXsOyy.css.gz} +0 -0
  837. /codex/static_root/assets/{admin-settings-button-progress-DUUQfVsZ.2548c49a853e.css → admin-settings-button-progress-BGB22oTD.2548c49a853e.css} +0 -0
  838. /codex/static_root/assets/{admin-settings-button-progress-DUUQfVsZ.css → admin-settings-button-progress-BGB22oTD.css} +0 -0
  839. /codex/static_root/assets/{change-password-dialog-C_EOKOn9.a30e68c6e303.css → change-password-dialog-D0ymWcl_.a30e68c6e303.css} +0 -0
  840. /codex/static_root/assets/{change-password-dialog-C_EOKOn9.a30e68c6e303.css.br → change-password-dialog-D0ymWcl_.a30e68c6e303.css.br} +0 -0
  841. /codex/static_root/assets/{change-password-dialog-C_EOKOn9.a30e68c6e303.css.gz → change-password-dialog-D0ymWcl_.a30e68c6e303.css.gz} +0 -0
  842. /codex/static_root/assets/{change-password-dialog-C_EOKOn9.css → change-password-dialog-D0ymWcl_.css} +0 -0
  843. /codex/static_root/assets/{change-password-dialog-C_EOKOn9.css.br → change-password-dialog-D0ymWcl_.css.br} +0 -0
  844. /codex/static_root/assets/{change-password-dialog-C_EOKOn9.css.gz → change-password-dialog-D0ymWcl_.css.gz} +0 -0
  845. /codex/static_root/assets/{confirm-dialog-54rblwf7.9b5915b112c0.css → confirm-dialog-B1ABbGMU.9b5915b112c0.css} +0 -0
  846. /codex/static_root/assets/{confirm-dialog-54rblwf7.9b5915b112c0.css.br → confirm-dialog-B1ABbGMU.9b5915b112c0.css.br} +0 -0
  847. /codex/static_root/assets/{confirm-dialog-54rblwf7.css → confirm-dialog-B1ABbGMU.css} +0 -0
  848. /codex/static_root/assets/{confirm-dialog-54rblwf7.css.br → confirm-dialog-B1ABbGMU.css.br} +0 -0
  849. /codex/static_root/assets/{datetime-column-DeCthByU.1f3bf499e063.css → datetime-column-BavtvLnf.1f3bf499e063.css} +0 -0
  850. /codex/static_root/assets/{datetime-column-DeCthByU.css → datetime-column-BavtvLnf.css} +0 -0
  851. /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css → group-tab-_vKWzoyd.948e907b1e6b.css} +0 -0
  852. /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css.br → group-tab-_vKWzoyd.948e907b1e6b.css.br} +0 -0
  853. /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css.gz → group-tab-_vKWzoyd.948e907b1e6b.css.gz} +0 -0
  854. /codex/static_root/assets/{group-tab-DkIN1Heu.css → group-tab-_vKWzoyd.css} +0 -0
  855. /codex/static_root/assets/{group-tab-DkIN1Heu.css.br → group-tab-_vKWzoyd.css.br} +0 -0
  856. /codex/static_root/assets/{group-tab-DkIN1Heu.css.gz → group-tab-_vKWzoyd.css.gz} +0 -0
  857. /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css → index-BHXJTQ4V.523d7b3d350f.css} +0 -0
  858. /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css.br → index-BHXJTQ4V.523d7b3d350f.css.br} +0 -0
  859. /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css.gz → index-BHXJTQ4V.523d7b3d350f.css.gz} +0 -0
  860. /codex/static_root/assets/{index-CL_6g4tJ.css → index-BHXJTQ4V.css} +0 -0
  861. /codex/static_root/assets/{index-CL_6g4tJ.css.br → index-BHXJTQ4V.css.br} +0 -0
  862. /codex/static_root/assets/{index-CL_6g4tJ.css.gz → index-BHXJTQ4V.css.gz} +0 -0
  863. /codex/static_root/assets/{main-BZ73p_WW.css → main-K8cER0IH.css} +0 -0
  864. /codex/static_root/assets/{main-BZ73p_WW.css.br → main-K8cER0IH.css.br} +0 -0
  865. /codex/static_root/assets/{main-BZ73p_WW.css.gz → main-K8cER0IH.css.gz} +0 -0
  866. /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css → main-K8cER0IH.d529e8b3f52a.css} +0 -0
  867. /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css.br → main-K8cER0IH.d529e8b3f52a.css.br} +0 -0
  868. /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css.gz → main-K8cER0IH.d529e8b3f52a.css.gz} +0 -0
  869. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css → pdf-doc-B4cGW_Hl.b94aac7e3313.css} +0 -0
  870. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css.br → pdf-doc-B4cGW_Hl.b94aac7e3313.css.br} +0 -0
  871. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css.gz → pdf-doc-B4cGW_Hl.b94aac7e3313.css.gz} +0 -0
  872. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css → pdf-doc-B4cGW_Hl.css} +0 -0
  873. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css.br → pdf-doc-B4cGW_Hl.css.br} +0 -0
  874. /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css.gz → pdf-doc-B4cGW_Hl.css.gz} +0 -0
  875. /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css → relation-chips-DpbzrZxT.01269a188e01.css} +0 -0
  876. /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css.br → relation-chips-DpbzrZxT.01269a188e01.css.br} +0 -0
  877. /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css.gz → relation-chips-DpbzrZxT.01269a188e01.css.gz} +0 -0
  878. /codex/static_root/assets/{relation-chips-ByfWwuQc.css → relation-chips-DpbzrZxT.css} +0 -0
  879. /codex/static_root/assets/{relation-chips-ByfWwuQc.css.br → relation-chips-DpbzrZxT.css.br} +0 -0
  880. /codex/static_root/assets/{relation-chips-ByfWwuQc.css.gz → relation-chips-DpbzrZxT.css.gz} +0 -0
  881. /codex/static_root/assets/{stats-tab-BlXGStge.9fdb0106124d.css → stats-tab-WvF2acoZ.9fdb0106124d.css} +0 -0
  882. /codex/static_root/assets/{stats-tab-BlXGStge.9fdb0106124d.css.br → stats-tab-WvF2acoZ.9fdb0106124d.css.br} +0 -0
  883. /codex/static_root/assets/{stats-tab-BlXGStge.9fdb0106124d.css.gz → stats-tab-WvF2acoZ.9fdb0106124d.css.gz} +0 -0
  884. /codex/static_root/assets/{stats-tab-BlXGStge.css → stats-tab-WvF2acoZ.css} +0 -0
  885. /codex/static_root/assets/{stats-tab-BlXGStge.css.br → stats-tab-WvF2acoZ.css.br} +0 -0
  886. /codex/static_root/assets/{stats-tab-BlXGStge.css.gz → stats-tab-WvF2acoZ.css.gz} +0 -0
  887. /codex/static_root/assets/{task-tab-EGlhcKTH.478e74041f80.css → task-tab-DfdUY9Rc.478e74041f80.css} +0 -0
  888. /codex/static_root/assets/{task-tab-EGlhcKTH.478e74041f80.css.br → task-tab-DfdUY9Rc.478e74041f80.css.br} +0 -0
  889. /codex/static_root/assets/{task-tab-EGlhcKTH.478e74041f80.css.gz → task-tab-DfdUY9Rc.478e74041f80.css.gz} +0 -0
  890. /codex/static_root/assets/{task-tab-EGlhcKTH.css → task-tab-DfdUY9Rc.css} +0 -0
  891. /codex/static_root/assets/{task-tab-EGlhcKTH.css.br → task-tab-DfdUY9Rc.css.br} +0 -0
  892. /codex/static_root/assets/{task-tab-EGlhcKTH.css.gz → task-tab-DfdUY9Rc.css.gz} +0 -0
  893. {codex-1.7.2.dist-info → codex-1.7.3.dist-info}/LICENSE +0 -0
  894. {codex-1.7.2.dist-info → codex-1.7.3.dist-info}/entry_points.txt +0 -0
@@ -19,7 +19,10 @@ class BrowserOrderByView(BrowserGroupMtimeView):
19
19
  if not self._order_key:
20
20
  order_key: str = self.params["order_by"]
21
21
  if (order_key == "search_score" and not self.fts_mode) or (
22
- order_key == "filename" and not self.admin_flags["folder_view"]
22
+ order_key == "filename"
23
+ and not self.admin_flags["folder_view"]
24
+ or order_key == "child_count"
25
+ and self.TARGET == "cover"
23
26
  ):
24
27
  order_key = "sort_name"
25
28
  self._order_key = order_key
@@ -29,6 +32,8 @@ class BrowserOrderByView(BrowserGroupMtimeView):
29
32
  """Order by for comics (and covers)."""
30
33
  if not order_key:
31
34
  order_key = self.order_key
35
+ if order_key == "child_count":
36
+ order_key = "sort_name"
32
37
  if order_key == "sort_name":
33
38
  if not comic_sort_names:
34
39
  comic_sort_names = self._comic_sort_names
@@ -50,7 +55,7 @@ class BrowserOrderByView(BrowserGroupMtimeView):
50
55
  order_fields_head += ["bookmark_updated_at"]
51
56
  return order_fields_head
52
57
 
53
- def add_order_by(self, qs, order_key="", do_reverse=True, comic_sort_names=None):
58
+ def add_order_by(self, qs, order_key="", comic_sort_names=None):
54
59
  """Create the order_by list."""
55
60
  order_fields_head = ()
56
61
  if qs.model is Comic:
@@ -60,11 +65,9 @@ class BrowserOrderByView(BrowserGroupMtimeView):
60
65
 
61
66
  order_fields = (*order_fields_head, "pk")
62
67
 
63
- prefix = "-" if do_reverse and self.params.get("order_reverse") else ""
64
- order_by = []
68
+ prefix = "-" if self.params.get("order_reverse") else ""
65
69
  if prefix:
66
- for field in order_fields:
67
- order_by.append(prefix + field)
70
+ order_by = [prefix + field for field in order_fields]
68
71
  else:
69
72
  order_by = order_fields
70
73
 
@@ -58,7 +58,7 @@ class BrowserParamsView(SessionView):
58
58
  validated_data = serializer.validated_data
59
59
 
60
60
  if validated_data:
61
- params.update(validated_data) # type: ignore
61
+ params.update(validated_data)
62
62
  self._params = MappingProxyType(params)
63
63
  self.validate_settings()
64
64
  return self._params
@@ -9,7 +9,7 @@ class BrowserSettingsView(SettingsView):
9
9
  """Get Browser Settings."""
10
10
 
11
11
  # Put Browser Settings is normally done through BrowserView.get()
12
- serializer_class = BrowserSettingsSerializer # type: ignore
12
+ serializer_class = BrowserSettingsSerializer
13
13
 
14
14
  SESSION_KEY = SettingsView.BROWSER_SESSION_KEY
15
15
 
@@ -3,6 +3,7 @@
3
3
  from collections.abc import Mapping
4
4
  from copy import deepcopy
5
5
  from types import MappingProxyType
6
+ from typing import Any
6
7
 
7
8
  from rest_framework.exceptions import NotFound
8
9
 
@@ -73,17 +74,18 @@ class BrowserValidateView(SearchFilterView):
73
74
  self, reason, route_mask=None, settings_mask: Mapping | None = None
74
75
  ):
75
76
  """Redirect the client to a valid group url."""
76
- route = mapping_to_dict(self.DEFAULT_ROUTE)
77
+ route: dict[str, Any] = mapping_to_dict(self.DEFAULT_ROUTE) # type:ignore[reportAssignmentType]
77
78
  if route_mask:
78
- route["params"].update(route_mask) # type: ignore
79
- settings: dict = deepcopy(mapping_to_dict(self.params)) # type: ignore
79
+ route["params"].update(route_mask)
80
+ settings: dict[str, Any] = deepcopy(mapping_to_dict(self.params)) # type: ignore[reportAssignmentType]
80
81
  if settings_mask:
81
82
  settings.update(settings_mask)
82
83
  detail = {"route": route, "settings": settings, "reason": reason}
83
84
  raise SeeOtherRedirectError(detail=detail)
84
85
 
85
86
  def _get_valid_browse_top_groups(self):
86
- """Get valid top groups for the current settings.
87
+ """
88
+ Get valid top groups for the current settings.
87
89
 
88
90
  Valid top groups are determined by the Browser Settings.
89
91
  """
@@ -118,7 +120,8 @@ class BrowserValidateView(SearchFilterView):
118
120
  self.raise_redirect(reason, route, settings_mask)
119
121
 
120
122
  def _get_valid_browse_nav_groups(self, valid_top_groups):
121
- """Get valid nav groups for the current settings.
123
+ """
124
+ Get valid nav groups for the current settings.
122
125
 
123
126
  Valid nav groups are the top group and below that are also
124
127
  enabled in browser settings.
codex/views/const.py CHANGED
@@ -76,9 +76,6 @@ METADATA_GROUP_RELATION = MappingProxyType(
76
76
  {
77
77
  **GROUP_NAME_MAP,
78
78
  COMIC_GROUP: "comic",
79
- # Possible to list all groups in a non group view, but could get crazy.
80
- # FOLDER_GROUP: "comic__folder",
81
- # STORY_ARC_GROUP: "comic__story_arc_number__story_arc"
82
79
  }
83
80
  )
84
81
  CUSTOM_COVER_GROUP_RELATION = MappingProxyType(
codex/views/frontend.py CHANGED
@@ -6,6 +6,7 @@ from rest_framework.permissions import AllowAny
6
6
  from rest_framework.renderers import TemplateHTMLRenderer
7
7
  from rest_framework.response import Response
8
8
 
9
+ from codex.models.admin import AdminFlag
9
10
  from codex.serializers.route import RouteSerializer
10
11
  from codex.views.session import SessionView
11
12
 
@@ -16,13 +17,27 @@ class IndexView(SessionView):
16
17
  SESSION_KEY = SessionView.BROWSER_SESSION_KEY
17
18
 
18
19
  permission_classes = (AllowAny,)
19
- renderer_classes: ClassVar[list] = [TemplateHTMLRenderer] # type: ignore
20
+ renderer_classes: ClassVar[list] = [TemplateHTMLRenderer] # type: ignore[reportIncompatibleVariableOverride]
20
21
  template_name = "index.html"
21
22
 
22
- def get(self, *_args, **_kwargs):
23
- """Get the app index page."""
23
+ def _get_last_route(self):
24
+ """Get the last route from the session."""
24
25
  last_route = self.get_last_route(name=False)
25
26
  serializer = RouteSerializer(last_route)
26
- last_route = serializer.data
27
- extra_context = {"last_route": last_route}
27
+ return serializer.data
28
+
29
+ def _get_title(self):
30
+ """Get the title from the banner text."""
31
+ bt_flag = AdminFlag.objects.get(key="BT")
32
+ title = "Codex"
33
+ if bt_flag.value:
34
+ title = bt_flag.value + " - " + title
35
+ return title
36
+
37
+ def get(self, *_args, **_kwargs):
38
+ """Get the app index page."""
39
+ extra_context = {
40
+ "last_route": self._get_last_route(),
41
+ "title": self._get_title(),
42
+ }
28
43
  return Response(extra_context)
codex/views/mixins.py CHANGED
@@ -2,40 +2,46 @@
2
2
 
3
3
  from django.db.models.expressions import F
4
4
 
5
+ from codex.logger.logging import get_logger
5
6
  from codex.models.comic import Comic, Imprint, Volume
7
+ from codex.views.browser.filters.filter import BrowserFilterView
6
8
  from codex.views.const import GROUP_NAME_MAP
7
9
 
10
+ LOG = get_logger(__name__)
8
11
  _SHOW_GROUPS = tuple(GROUP_NAME_MAP.keys())
12
+ _GROUP_NAME_TARGETS = frozenset({"browser", "opds1", "opds2", "reader"})
13
+ _VARIABLE_SHOW = "pi"
9
14
 
10
15
 
11
- class SharedAnnotationsMixin:
16
+ class SharedAnnotationsMixin(BrowserFilterView):
12
17
  """Cross view annotation methods."""
13
18
 
14
19
  @staticmethod
15
- def _get_order_groups(model_group, pks):
20
+ def _get_order_groups(parent_group, pks, show):
16
21
  """Annotate sort_name."""
17
- if not pks or len(pks) > 1:
18
- order_groups = _SHOW_GROUPS
19
- elif model_group == "c":
22
+ if parent_group == "c":
20
23
  order_groups = ()
21
24
  else:
22
25
  for index, nav_group in enumerate(_SHOW_GROUPS):
23
- if nav_group == model_group:
24
- order_groups = _SHOW_GROUPS[index + 1 :]
26
+ if nav_group in _VARIABLE_SHOW and not show.get(nav_group):
27
+ continue
28
+ if nav_group == parent_group:
29
+ watermark = index
30
+ if pks and len(pks) == 1:
31
+ watermark += 1
32
+ order_groups = _SHOW_GROUPS[watermark:]
25
33
  break
26
34
  else:
27
35
  order_groups = _SHOW_GROUPS
28
36
  return order_groups
29
37
 
30
38
  @classmethod
31
- def get_sort_name_annotations(cls, model, model_group, pks, show):
39
+ def get_sort_name_annotations(cls, model, parent_group, pks, show):
32
40
  """Annotate sort names for browser subclasses and reader."""
33
41
  sort_name_annotations = {}
34
42
  if model is Comic:
35
- order_groups = cls._get_order_groups(model_group, pks)
43
+ order_groups = cls._get_order_groups(parent_group, pks, show)
36
44
  for order_group in order_groups:
37
- if show and not show.get(order_group):
38
- continue
39
45
  group_name = GROUP_NAME_MAP[order_group]
40
46
  ann_name = f"{group_name}_sort_name"
41
47
  name_field = "name" if group_name == "volume" else "sort_name"
@@ -49,8 +55,8 @@ class SharedAnnotationsMixin:
49
55
  def annotate_group_names(cls, qs):
50
56
  """Annotate name fields by hoisting them up."""
51
57
  # Optimized to only lookup what is used on the frontend
52
- target = cls.TARGET # type: ignore
53
- if target not in frozenset({"browser", "opds1", "opds2", "reader"}):
58
+ target = cls.TARGET
59
+ if target not in _GROUP_NAME_TARGETS:
54
60
  return qs
55
61
  group_names = {}
56
62
  if qs.model is Comic:
@@ -69,20 +75,3 @@ class SharedAnnotationsMixin:
69
75
  elif qs.model is Imprint:
70
76
  group_names["publisher_name"] = F("publisher__name")
71
77
  return qs.annotate(**group_names)
72
-
73
-
74
- class BookmarkSearchMixin:
75
- """Create Bookmark Search kwargs."""
76
-
77
- @staticmethod
78
- def get_bookmark_search_kwargs(auth_filter, comic_filter=None):
79
- """Get the search kwargs for a user's authentication state."""
80
- # search kwargs are relative to the bookmark object.
81
- search_kwargs = {}
82
- search_kwargs.update(auth_filter)
83
-
84
- if comic_filter:
85
- for key, value in comic_filter.items():
86
- search_kwargs[f"comic__{key}"] = value
87
-
88
- return search_kwargs
@@ -40,7 +40,7 @@ _DOC = MappingProxyType(
40
40
  "labels": {"login": "Username", "password": "Password"},
41
41
  },
42
42
  {
43
- # XXX Out of spec type
43
+ # Out of spec type
44
44
  "type": "cookie",
45
45
  "links": [
46
46
  {
codex/views/opds/const.py CHANGED
@@ -28,6 +28,7 @@ class Rel:
28
28
  SORT_NEW = "http://opds-spec.org/sort/new"
29
29
  POPULAR = "http://opds-spec.org/sort/popular"
30
30
  FEATURED = "http://opds-spec.org/featured"
31
+ PROGRESSION = "http://www.cantook.com/api/progression"
31
32
  SELF = "self"
32
33
  START = "start"
33
34
  UP = "up"
@@ -47,16 +48,17 @@ class MimeType:
47
48
 
48
49
  ATOM = "application/atom+xml"
49
50
  _PROFILE_CATALOG = "profile=opds-catalog"
50
- NAV = ";".join((ATOM, _PROFILE_CATALOG, "kind=navigation"))
51
- ACQUISITION = ";".join((ATOM, _PROFILE_CATALOG, "kind=acquisition"))
52
- ENTRY_CATALOG = ";".join((ATOM, "type=entry", _PROFILE_CATALOG))
51
+ NAV = f"{ATOM};{_PROFILE_CATALOG};kind=navigation"
52
+ ACQUISITION = f"{ATOM};{_PROFILE_CATALOG};kind=acquisition"
53
+ ENTRY_CATALOG = f"{ATOM};type=entry;{_PROFILE_CATALOG}"
53
54
  AUTHENTICATION = "application/opds-authentication+json"
54
55
  OPENSEARCH = "application/opensearchdescription+xml"
55
56
  STREAM = "image/jpeg"
56
57
  OPDS_JSON = "application/opds+json"
57
58
  OPDS_PUB = "application/opds-publication+json"
59
+ PROGRESSION = "application/vnd.readium.progression+json"
58
60
  BOOK = "http://schema.org/Book"
59
- # COMIC = "https://schema.org/ComicStory"
61
+ # COMIC = "https://schema.org/ComicStory" unused
60
62
  JPEG = "image/jpeg"
61
63
  WEBP = "image/webp"
62
64
  HTML = "text/html"
codex/views/opds/util.py CHANGED
@@ -31,7 +31,7 @@ def update_href_query_params(href, old_query_params, new_query_params=None):
31
31
  return href
32
32
 
33
33
 
34
- def get_contributor_people(comic_pks, roles, exclude=False):
34
+ def get_contributor_people(comic_pks, roles, exclude):
35
35
  """Get contributors that are not authors."""
36
36
  people = ContributorPerson.objects.filter(
37
37
  contributor__comic__in=comic_pks,
@@ -43,7 +43,7 @@ def get_contributor_people(comic_pks, roles, exclude=False):
43
43
  return people.distinct().only("name")
44
44
 
45
45
 
46
- def get_contributors(comic_pks, roles, exclude=False):
46
+ def get_contributors(comic_pks, roles, exclude):
47
47
  """Get credits that are not part of other roles."""
48
48
  contributors = Contributor.objects.filter(comic__in=comic_pks)
49
49
  if exclude:
@@ -59,8 +59,8 @@ def get_m2m_objects(pks) -> dict:
59
59
  for model in OPDS_M2M_MODELS:
60
60
  table = model.__name__.lower()
61
61
  rel = GroupACLMixin.get_rel_prefix(model)
62
- comic_filter = {rel + "__in": pks}
63
- qs = model.objects.filter(**comic_filter).order_by("name").only("name")
62
+ comic_filter = {rel + "in": pks}
63
+ qs = model.objects.filter(**comic_filter).only("name").order_by("name")
64
64
  cats[table] = qs
65
65
 
66
66
  return cats
@@ -78,7 +78,7 @@ def full_redirect_view(url_name):
78
78
  path = request.get_full_path()
79
79
  if path:
80
80
  parts = path.split("?")
81
- if len(parts) >= 2: # noqa PLR2004
81
+ if len(parts) >= 2: # noqa: PLR2004
82
82
  parts[0] = url
83
83
  url = "?".join(parts)
84
84
 
@@ -47,8 +47,10 @@ class OPDS1Entry(OPDS1EntryLinksMixin):
47
47
  elif group == "c":
48
48
  title = Comic.get_title(
49
49
  self.obj,
50
- zero_pad=self.zero_pad,
50
+ volume=True,
51
+ name=True,
51
52
  filename_fallback=self.title_filename_fallback,
53
+ zero_pad=self.zero_pad,
52
54
  )
53
55
  parts.append(title)
54
56
 
@@ -133,7 +135,7 @@ class OPDS1Entry(OPDS1EntryLinksMixin):
133
135
  """Get Author names."""
134
136
  if not self.metadata:
135
137
  return []
136
- people = get_contributor_people(self.obj.ids, AUTHOR_ROLES)
138
+ people = get_contributor_people(self.obj.ids, AUTHOR_ROLES, exclude=False)
137
139
  return self._add_url_to_obj(people, "contributors")
138
140
 
139
141
  @property
@@ -20,7 +20,7 @@ class OPDS1EntryLinksMixin:
20
20
  """OPDS v1 Entry Links Methods."""
21
21
 
22
22
  def __init__(
23
- self, obj, query_params, data: OPDS1EntryData, title_filename_fallback=False
23
+ self, obj, query_params, data: OPDS1EntryData, title_filename_fallback: bool
24
24
  ):
25
25
  """Initialize params."""
26
26
  self.obj = obj
@@ -35,7 +35,6 @@ class OPDS1EntryLinksMixin:
35
35
  def _cover_link(self, rel):
36
36
  if self.fake:
37
37
  return None
38
- # cover_pk = getattr(self.obj, "cover_pk", None)
39
38
  try:
40
39
  kwargs = {"group": self.obj.group, "pks": self.obj.ids}
41
40
  ts = floor(datetime.timestamp(self.obj.updated_at))
@@ -46,12 +45,11 @@ class OPDS1EntryLinksMixin:
46
45
  }
47
46
  href = reverse("opds:bin:cover", kwargs=kwargs)
48
47
  href = update_href_query_params(href, query_params)
49
- mime_type = "image/webp"
50
- return OPDS1Link(rel, href, mime_type)
48
+ return OPDS1Link(rel, href, MimeType.WEBP)
51
49
  except Exception:
52
50
  LOG.exception("create thumb")
53
51
 
54
- def _nav_href(self, metadata=False):
52
+ def _nav_href(self, metadata: bool):
55
53
  try:
56
54
  pks = sorted(self.obj.ids)
57
55
  kwargs = {"group": self.obj.group, "pks": pks, "page": 1}
@@ -73,7 +71,7 @@ class OPDS1EntryLinksMixin:
73
71
  LOG.exception(msg)
74
72
  raise
75
73
 
76
- def _nav_link(self, metadata=False):
74
+ def _nav_link(self, metadata: bool):
77
75
  href = self._nav_href(metadata)
78
76
 
79
77
  group = self.obj.group
@@ -155,7 +153,7 @@ class OPDS1EntryLinksMixin:
155
153
 
156
154
  if self.obj.group == "c" and not self.fake:
157
155
  result += self._links_comic()
158
- elif nav := self._nav_link():
156
+ elif nav := self._nav_link(metadata=False):
159
157
  result += [nav]
160
158
 
161
159
  except Exception:
@@ -169,11 +169,14 @@ class OPDS1FacetsView(BrowserView):
169
169
  )
170
170
  qps = {**self.request.GET}
171
171
  qps.update(query_params)
172
- zero_pad: int = self.obj["zero_pad"] # type: ignore
172
+ zero_pad: int = self.obj["zero_pad"]
173
173
  data = OPDS1EntryData(
174
- self.opds_acquisition_groups, zero_pad, False, self.mime_type_map
174
+ self.opds_acquisition_groups,
175
+ zero_pad,
176
+ metadata=False,
177
+ mime_type_map=self.mime_type_map,
175
178
  )
176
- return OPDS1Entry(entry_obj, qps, data)
179
+ return OPDS1Entry(entry_obj, qps, data, title_filename_fallback=False)
177
180
 
178
181
  def _is_facet_active(self, facet_group, facet):
179
182
  compare = [facet.value]
@@ -231,7 +234,8 @@ class OPDS1FacetsView(BrowserView):
231
234
  facets += [facet_obj]
232
235
  return facets
233
236
 
234
- def facets(self, entries=False, root=True):
237
+ def facets(self, entries: bool, root: bool):
238
+ # entries false, root true
235
239
  """Return facets."""
236
240
  facets = []
237
241
  group = self.kwargs.get("group")
@@ -75,7 +75,7 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
75
75
  """Create the feed title."""
76
76
  result = ""
77
77
  try:
78
- browser_title: Mapping[str, Any] = self.obj.get("title") # type: ignore
78
+ browser_title: Mapping[str, Any] = self.obj.get("title", {})
79
79
  if browser_title:
80
80
  parent_name = browser_title.get("parent_name", "All")
81
81
  pks = self.kwargs["pks"]
@@ -97,7 +97,7 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
97
97
  try:
98
98
  mtime = self.obj.get("mtime")
99
99
  if mtime:
100
- datestr = mtime.isoformat() # type: ignore
100
+ datestr = mtime.isoformat()
101
101
  except Exception:
102
102
  LOG.exception("Getting OPDS v1 updated")
103
103
  return datestr
@@ -124,13 +124,13 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
124
124
  """Get entries by key section."""
125
125
  entries = []
126
126
  if objs := self.obj.get(key):
127
- zero_pad: int = self.obj["zero_pad"] # type: ignore
127
+ zero_pad: int = self.obj["zero_pad"]
128
128
  data = OPDS1EntryData(
129
129
  self.opds_acquisition_groups, zero_pad, metadata, self.mime_type_map
130
130
  )
131
131
  fallback = bool(self.admin_flags.get("folder_view"))
132
132
  import_pks = set()
133
- for obj in objs: # type: ignore
133
+ for obj in objs:
134
134
  entry = OPDS1Entry(
135
135
  obj,
136
136
  self.request.GET,
@@ -157,7 +157,7 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
157
157
  entries += self.add_top_links(RootTopLinks.ALL)
158
158
  entries += self.facets(entries=True, root=at_root)
159
159
 
160
- entries += self._get_entries_section("groups", False)
160
+ entries += self._get_entries_section("groups", metadata=False)
161
161
  metadata = self.request.GET.get("opdsMetadata", "").lower() not in FALSY
162
162
  entries += self._get_entries_section("books", metadata)
163
163
  except Exception:
@@ -105,7 +105,7 @@ class RootTopLinks:
105
105
  class OPDS1LinksView(OPDS1FacetsView):
106
106
  """OPDS 1 Links methods."""
107
107
 
108
- # overwritten in get_object()
108
+ # overwritten in get_object method
109
109
  DEFAULT_ROUTE = MappingProxyType(
110
110
  {
111
111
  **OPDS1FacetsView.DEFAULT_ROUTE,
@@ -143,7 +143,7 @@ class OPDS1LinksView(OPDS1FacetsView):
143
143
  def _root_links(self):
144
144
  """Navigation Root Links."""
145
145
  links = []
146
- if up_route := self.get_last_route():
146
+ if up_route := self.get_last_route(name=True):
147
147
  links += [self._link(up_route, Rel.UP)]
148
148
  page = self.kwargs.get("page", 1)
149
149
  if page > 1:
@@ -179,7 +179,7 @@ class OPDS1LinksView(OPDS1FacetsView):
179
179
  for top_link in TopLinks.ALL + RootTopLinks.ALL:
180
180
  if not self.is_top_link_displayed(top_link):
181
181
  links += [self._top_link(top_link)]
182
- if facets := self.facets():
182
+ if facets := self.facets(entries=False, root=True):
183
183
  links += facets
184
184
  except Exception:
185
185
  LOG.exception("Getting OPDS v1 links")
@@ -194,11 +194,16 @@ class OPDS1LinksView(OPDS1FacetsView):
194
194
  name=name,
195
195
  summary=top_link.desc,
196
196
  )
197
- zero_pad: int = self.obj["zero_pad"] # type: ignore
197
+ zero_pad: int = self.obj["zero_pad"]
198
198
  data = OPDS1EntryData(
199
- self.opds_acquisition_groups, zero_pad, False, self.mime_type_map
199
+ self.opds_acquisition_groups,
200
+ zero_pad,
201
+ metadata=False,
202
+ mime_type_map=self.mime_type_map,
203
+ )
204
+ return OPDS1Entry(
205
+ entry_obj, top_link.query_params, data, title_filename_fallback=False
200
206
  )
201
- return OPDS1Entry(entry_obj, top_link.query_params, data)
202
207
 
203
208
  def add_top_links(self, top_links):
204
209
  """Add a list of top links as entries if they should be enabled."""
@@ -31,7 +31,10 @@ FACETS = (
31
31
  "Order Direction",
32
32
  "orderReverse",
33
33
  "⇕",
34
- (Facet(False, "Ascending"), Facet(True, "Descending")),
34
+ (
35
+ Facet(query_param_value=False, title="Ascending"),
36
+ Facet(query_param_value=True, title="Descending"),
37
+ ),
35
38
  ),
36
39
  FacetGroup(
37
40
  "Top Group",
@@ -114,5 +117,5 @@ class LinksSectionData:
114
117
 
115
118
 
116
119
  TOP_NAV_GROUP_SECTION_DATA = LinksSectionData(group_kwarg=True)
117
- GROUPS_SECTION_DATA = LinksSectionData("Groups", Rel.SUB, True)
120
+ GROUPS_SECTION_DATA = LinksSectionData("Groups", Rel.SUB, group_kwarg=True)
118
121
  FACETS_SECTION_DATA = LinksSectionData(rel=Rel.FACET, links_key="links")
@@ -8,7 +8,7 @@ from rest_framework.response import Response
8
8
  from codex.logger.logging import get_logger
9
9
  from codex.models import AdminFlag
10
10
  from codex.serializers.browser.settings import OPDSSettingsSerializer
11
- from codex.serializers.opds.v2 import OPDS2FeedSerializer
11
+ from codex.serializers.opds.v2.feed import OPDS2FeedSerializer
12
12
  from codex.views.const import MAX_OBJ_PER_PAGE
13
13
  from codex.views.opds.auth import OPDSAuthMixin
14
14
  from codex.views.opds.const import BLANK_TITLE
@@ -20,7 +20,8 @@ from codex.views.opds.v2.const import (
20
20
  TOP_NAV_GROUP_SECTION_DATA,
21
21
  NavigationGroup,
22
22
  )
23
- from codex.views.opds.v2.links import HrefData, LinkData
23
+ from codex.views.opds.v2.href import HrefData
24
+ from codex.views.opds.v2.links import LinkData
24
25
  from codex.views.opds.v2.publications import OPDS2PublicationView
25
26
 
26
27
  LOG = get_logger(__name__)
@@ -55,9 +56,9 @@ class OPDS2FeedView(OPDSAuthMixin, OPDS2PublicationView):
55
56
 
56
57
  # def _detect_user_agent(self):
57
58
  # """Hacks for individual clients."""
58
- # user_agent = self.request.headers.get("User-Agent")
59
+ # user_agent = self.request.headers.get("User-Agent") # noqa: ERA001
59
60
  # if not user_agent:
60
- # return
61
+ # return # noqa: ERA001
61
62
 
62
63
  @staticmethod
63
64
  def _is_allowed(link_spec):
@@ -184,7 +185,7 @@ class OPDS2FeedView(OPDSAuthMixin, OPDS2PublicationView):
184
185
  title = self._title(title)
185
186
  number_of_items = total_count
186
187
  current_page = self.kwargs.get("page")
187
- up_route = self.get_last_route()
188
+ up_route = self.get_last_route(name=True)
188
189
  links = self.get_links(up_route)
189
190
  facets = self._get_facets()
190
191
 
@@ -0,0 +1,60 @@
1
+ """Href methods for OPDS v2.0 Feed."""
2
+
3
+ from abc import ABC
4
+ from dataclasses import dataclass
5
+
6
+ from django.urls import reverse
7
+ from rest_framework.views import APIView
8
+
9
+ from codex.views.opds.util import update_href_query_params
10
+ from codex.views.util import pop_name
11
+
12
+
13
+ @dataclass
14
+ class HrefData:
15
+ """Data for creating hrefs."""
16
+
17
+ kwargs: dict | None = None
18
+ query_params: dict | None = None
19
+ absolute_query_params: bool = False
20
+ url_name: str | None = None
21
+ min_page: int | None = None
22
+ max_page: int | None = None
23
+
24
+
25
+ class OPDS2HrefMixin(APIView, ABC):
26
+ """Create links method."""
27
+
28
+ @property
29
+ def num_pages(self) -> int:
30
+ """Dummy."""
31
+ return 1
32
+
33
+ def _href_page_validate(self, kwargs, data):
34
+ """Validate the page bounds."""
35
+ min_page = 1 if data.min_page is None else data.min_page
36
+ max_page = self.num_pages if data.max_page is None else data.max_page
37
+ page = int(kwargs["page"])
38
+ return page >= min_page and page <= max_page
39
+
40
+ def _href_update_query_params(self, href, data):
41
+ """Update the query params."""
42
+ if data.absolute_query_params and data.query_params:
43
+ href = update_href_query_params(href, data.query_params)
44
+ elif hasattr(self, "request"):
45
+ # if request link and not init static links
46
+ href = update_href_query_params(
47
+ href, self.request.GET, new_query_params=data.query_params
48
+ )
49
+ return href
50
+
51
+ def href(self, data):
52
+ """Create an href."""
53
+ url_name = data.url_name if data.url_name else "opds:v2:feed"
54
+ kwargs = data.kwargs if data.kwargs is not None else self.kwargs
55
+ if "page" in kwargs and not self._href_page_validate(kwargs, data):
56
+ return None
57
+
58
+ kwargs = pop_name(kwargs)
59
+ href = reverse(url_name, kwargs=kwargs)
60
+ return self._href_update_query_params(href, data)