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
@@ -1,30 +1,17 @@
1
1
  """Links methods for OPDS v2.0 Feed."""
2
2
 
3
+ from collections.abc import Mapping
3
4
  from copy import deepcopy
4
5
  from dataclasses import dataclass
5
6
  from datetime import datetime
6
7
  from urllib.parse import parse_qsl, urlparse
7
8
 
8
9
  from django.db.models import QuerySet
9
- from django.urls import reverse
10
10
 
11
11
  from codex.settings.settings import FALSY
12
12
  from codex.views.browser.browser import BrowserView
13
13
  from codex.views.opds.const import MimeType, Rel
14
- from codex.views.opds.util import update_href_query_params
15
- from codex.views.util import pop_name
16
-
17
-
18
- @dataclass
19
- class HrefData:
20
- """Data for creating hrefs."""
21
-
22
- kwargs: dict | None = None
23
- query_params: dict | None = None
24
- absolute_query_params: bool = False
25
- url_name: str | None = None
26
- min_page: int | None = None
27
- max_page: int | None = None
14
+ from codex.views.opds.v2.href import HrefData, OPDS2HrefMixin
28
15
 
29
16
 
30
17
  @dataclass
@@ -40,9 +27,10 @@ class LinkData:
40
27
  width: int | None = None
41
28
  href: str | None = None
42
29
  num_items: int | None = None
30
+ authenticate: Mapping | None = None
43
31
 
44
32
 
45
- class OPDS2LinksView(BrowserView):
33
+ class OPDS2LinksView(OPDS2HrefMixin, BrowserView):
46
34
  """Links methods for OPDS 2.0 Feed."""
47
35
 
48
36
  def __init__(self, *args, **kwargs):
@@ -70,41 +58,12 @@ class OPDS2LinksView(BrowserView):
70
58
  self._num_pages = self.group_and_books[2]
71
59
  return self._num_pages
72
60
 
73
- def _href_page_validate(self, kwargs, data):
74
- """Validate the page bounds."""
75
- min_page = 1 if data.min_page is None else data.min_page
76
- max_page = self.num_pages if data.max_page is None else data.max_page
77
- page = int(kwargs["page"])
78
- return page >= min_page and page <= max_page
79
-
80
- def _href_update_query_params(self, href, data):
81
- """Update the query params."""
82
- if data.absolute_query_params and data.query_params:
83
- href = update_href_query_params(href, data.query_params)
84
- elif hasattr(self, "request"):
85
- # if request link and not init static links
86
- href = update_href_query_params(
87
- href, self.request.GET, new_query_params=data.query_params
88
- )
89
- return href
90
-
91
- def _href(self, data):
92
- """Create an href."""
93
- url_name = data.url_name if data.url_name else "opds:v2:feed"
94
- kwargs = data.kwargs if data.kwargs is not None else self.kwargs
95
- if "page" in kwargs and not self._href_page_validate(kwargs, data):
96
- return None
97
-
98
- kwargs = pop_name(kwargs)
99
- href = reverse(url_name, kwargs=kwargs)
100
- return self._href_update_query_params(href, data)
101
-
102
61
  def link(self, data):
103
62
  """Create a link element."""
104
63
  if data.href:
105
64
  href = data.href
106
65
  else:
107
- href = self._href(data.href_data)
66
+ href = self.href(data.href_data)
108
67
  if not href:
109
68
  return None
110
69
  mime_type = data.mime_type if data.mime_type else MimeType.OPDS_JSON
@@ -118,8 +77,15 @@ class OPDS2LinksView(BrowserView):
118
77
  link["height"] = data.height
119
78
  if data.width:
120
79
  link["width"] = data.width
80
+
81
+ # Properties
82
+ if data.num_items or data.authenticate:
83
+ link["properties"] = {}
121
84
  if data.num_items:
122
- link["properties"] = {"number_of_items": data.num_items}
85
+ link["properties"]["number_of_items"] = data.num_items
86
+ if data.authenticate:
87
+ link["properties"]["authenticate"] = data.authenticate
88
+
123
89
  return link
124
90
 
125
91
  @staticmethod
@@ -0,0 +1,136 @@
1
+ """OPDS 2 Progression view."""
2
+ # https://github.com/opds-community/drafts/discussions/67#discussioncomment-6414507
3
+
4
+ from types import MappingProxyType
5
+
6
+ from django.db.models.expressions import F, Value
7
+ from django.db.models.fields import FloatField
8
+ from django.db.models.functions.comparison import Cast, Coalesce, Greatest, Least
9
+ from django.db.models.query_utils import FilteredRelation
10
+ from rest_framework.exceptions import ValidationError
11
+ from rest_framework.response import Response
12
+
13
+ from codex.logger.logging import get_logger
14
+ from codex.serializers.opds.v2.progression import OPDS2ProgressionSerializer
15
+ from codex.util import max_none
16
+ from codex.views.auth import AuthFilterGenericAPIView
17
+ from codex.views.bookmark import BookmarkFilterMixin, BookmarkPageView
18
+ from codex.views.const import GROUP_MODEL_MAP
19
+ from codex.views.opds.v2.href import HrefData, OPDS2HrefMixin
20
+
21
+ _EMPTY_DEVICE = MappingProxyType(
22
+ {
23
+ "id": "",
24
+ "name": "",
25
+ }
26
+ )
27
+ LOG = get_logger(__name__)
28
+
29
+
30
+ # This is an independent api requiring a separate get.
31
+ class OPDS2ProgressionView(
32
+ BookmarkFilterMixin, OPDS2HrefMixin, BookmarkPageView, AuthFilterGenericAPIView
33
+ ):
34
+ """OPDS 2 Progression view."""
35
+
36
+ serializer_class = OPDS2ProgressionSerializer
37
+
38
+ @property
39
+ def modified(self):
40
+ """Get modified from bookmark."""
41
+ return self._obj.bookmark_updated_at # type: ignore[reportAttributeAccessIssue]
42
+
43
+ @property
44
+ def device(self):
45
+ """Dummy device."""
46
+ # Codex doesn't record this.
47
+ return _EMPTY_DEVICE
48
+
49
+ @property
50
+ def title(self):
51
+ """The locator title is the page number."""
52
+ return f"Page {self._obj.page}" # type: ignore[reportAttributeAccessIssue]
53
+
54
+ @property
55
+ def _progression_href(self):
56
+ """Build a Progression HRef."""
57
+ acq_kwargs = {
58
+ "pk": self._obj.pk,
59
+ "page": self._obj.page, # type: ignore[reportAttributeAccessIssue]
60
+ }
61
+ max_page = max_none(self._obj.page_count - 1, 0) # type: ignore[reportAttributeAccessIssue]
62
+ data = HrefData(
63
+ acq_kwargs,
64
+ url_name="opds:bin:page",
65
+ min_page=0,
66
+ max_page=max_page,
67
+ )
68
+ return self.href(data)
69
+
70
+ @property
71
+ def _locations(self):
72
+ """Build the Locations object."""
73
+ return {
74
+ "position": self._obj.page, # type: ignore[reportAttributeAccessIssue]
75
+ "progression": self._obj.progress, # type: ignore[reportAttributeAccessIssue]
76
+ "total_progression": self._obj.progress, # type: ignore[reportAttributeAccessIssue]
77
+ }
78
+
79
+ @property
80
+ def locator(self):
81
+ """Build the Locator object."""
82
+ return {
83
+ "title": self.title, # See publication.py:103
84
+ "href": self._progression_href,
85
+ "type": "image/jpeg",
86
+ "locations": self._locations,
87
+ }
88
+
89
+ def get_object(self):
90
+ """Build the progression data object."""
91
+ group = self.kwargs.get("group")
92
+ pk = self.kwargs.get("pk")
93
+
94
+ if not pk:
95
+ reason = f"Bad primary key for {group}:{pk}"
96
+ return ValidationError(reason, code="422")
97
+
98
+ model = GROUP_MODEL_MAP.get(group)
99
+ if not model:
100
+ reason = f"No model found for group {group}"
101
+ raise ValidationError(reason, code="422")
102
+
103
+ acl_filter = self.get_group_acl_filter(model, self.request.user)
104
+ qs = model.objects.filter(acl_filter).distinct()
105
+
106
+ bm_rel = self.get_bm_rel(model)
107
+ bm_filter = self.get_my_bookmark_filter(bm_rel)
108
+ progress = Least(
109
+ F("page") / Greatest(Cast(F("page_count"), FloatField()), 1.0), Value(1.0)
110
+ )
111
+
112
+ qs = qs.annotate(
113
+ my_bookmark=FilteredRelation("bookmark", condition=bm_filter),
114
+ bookmark_updated_at=F("my_bookmark__updated_at"),
115
+ page=Coalesce(F("my_bookmark__page"), 0),
116
+ progress=progress,
117
+ )
118
+ self._obj = qs.only("page_count").distinct().get(pk=pk)
119
+
120
+ return {
121
+ "modified": self.modified,
122
+ "device": self.device,
123
+ "locator": self.locator,
124
+ }
125
+
126
+ def get(self, *args, **kwargs):
127
+ """Get Response."""
128
+ try:
129
+ obj = self.get_object()
130
+ serializer = self.get_serializer(obj)
131
+ return Response(serializer.data)
132
+ except Exception:
133
+ LOG.exception("progression")
134
+ raise
135
+
136
+ # PUT handled by BookmarkPageView parent
@@ -10,15 +10,17 @@ from codex.models import Comic
10
10
  from codex.settings.settings import FALSY
11
11
  from codex.views.opds.const import AUTHOR_ROLES, MimeType, Rel
12
12
  from codex.views.opds.util import get_contributors, get_m2m_objects
13
- from codex.views.opds.v2.top_links import HrefData, LinkData, OPDS2TopLinksView
13
+ from codex.views.opds.v2.href import HrefData
14
+ from codex.views.opds.v2.links import LinkData
15
+ from codex.views.opds.v2.top_links import OPDS2TopLinksView
14
16
 
15
17
  _MD_CONTRIBUTOR_MAP = MappingProxyType(
16
18
  {
17
19
  "author": AUTHOR_ROLES,
18
- # "translator": {},
20
+ # "translator": {}, unused
19
21
  "editor": {"Editor"},
20
22
  "artist": {"CoverArtist"},
21
- # "illustrator": {},
23
+ # "illustrator": {}, unused, could use penciller
22
24
  "letterer": {"Letterer"},
23
25
  "penciller": {"Penciller"},
24
26
  "colorist": {"Colorist"},
@@ -40,7 +42,9 @@ class OPDS2PublicationView(OPDS2TopLinksView):
40
42
  "dynamicCovers": False,
41
43
  "ts": ts,
42
44
  }
43
- href_data = HrefData(kwargs, query_params, True, "opds:bin:cover")
45
+ href_data = HrefData(
46
+ kwargs, query_params, absolute_query_params=True, url_name="opds:bin:cover"
47
+ )
44
48
  link_data = LinkData(
45
49
  Rel.THUMBNAIL,
46
50
  href_data,
@@ -63,15 +67,13 @@ class OPDS2PublicationView(OPDS2TopLinksView):
63
67
  @staticmethod
64
68
  def _add_contributors(md, pks, key, roles):
65
69
  """Add contributors to metadata."""
66
- if contributors := get_contributors(pks, roles):
70
+ if contributors := get_contributors(pks, roles, exclude=False):
67
71
  md[key] = contributors
68
72
 
69
73
  def _publication_optional_metadata(self, md, obj):
70
74
  """Add optional Publication Metadtata."""
71
75
  if subtitle := obj.name:
72
76
  md["subtitle"] = subtitle
73
- # if identifier := obj.get("guid")
74
- # md["identifier"] = identifier
75
77
  if desc := obj.summary:
76
78
  md["description"] = desc
77
79
  if lang := obj.language:
@@ -87,25 +89,21 @@ class OPDS2PublicationView(OPDS2TopLinksView):
87
89
  """Publication m2m metadata only on the metadata alternate link."""
88
90
  for key, roles in _MD_CONTRIBUTOR_MAP.items():
89
91
  self._add_contributors(md, obj.ids, key, roles)
90
- if contributors := get_contributors(obj.ids, _CONTRIBUTOR_ROLES, True):
92
+ if contributors := get_contributors(obj.ids, _CONTRIBUTOR_ROLES, exclude=True):
91
93
  md["contributor"] = contributors
92
94
 
93
95
  if m2m_objs := get_m2m_objects(obj.ids):
94
- # XXX Subjects can also have links
96
+ # Subjects can also have links
95
97
  # https://readium.org/webpub-manifest/schema/subject-object.schema.json
96
- subjects = []
97
- for subjs in m2m_objs.values():
98
- for subj in subjs:
99
- subjects.append(subj.name)
100
- md["subject"] = subjects
98
+ md["subject"] = [subj.name for subjs in m2m_objs.values() for subj in subjs]
101
99
 
102
100
  def _publication_metadata(self, obj, zero_pad):
103
101
  title = Comic.get_title(
104
102
  obj,
105
103
  volume=False,
106
104
  name=False,
107
- zero_pad=zero_pad,
108
105
  filename_fallback=self.title_filename_fallback,
106
+ zero_pad=zero_pad,
109
107
  )
110
108
  md = {
111
109
  "type": MimeType.BOOK,
@@ -127,10 +125,6 @@ class OPDS2PublicationView(OPDS2TopLinksView):
127
125
  download_mime_type = MimeType.FILE_TYPE_MAP.get(obj.file_type, MimeType.OCTET)
128
126
  self_kwargs = {"pk": obj.pk, "page": 1}
129
127
 
130
- # This would be for comic streaming which is not supported by OPDS 2 yet?
131
- # self_href_data = HrefData(self_kwargs, absolute_query_params=True)
132
- # self_link_data = LinkData(Rel.SELF, self_href_data, mime_type=MimeType.OPDS_PUB)
133
-
134
128
  alt_kwargs = self_kwargs
135
129
  alt_href_data = HrefData(
136
130
  alt_kwargs,
@@ -154,11 +148,27 @@ class OPDS2PublicationView(OPDS2TopLinksView):
154
148
  acq_href_data,
155
149
  mime_type=download_mime_type,
156
150
  )
151
+ prog_kwargs = {"group": "c", "pk": obj.pk}
152
+ prog_href_data = HrefData(prog_kwargs, url_name="opds:v2:position")
153
+
154
+ auth_href_data = HrefData({}, url_name="opds:authentication:v1")
155
+ auth_link_data = LinkData(
156
+ Rel.AUTHENTICATION,
157
+ auth_href_data,
158
+ mime_type=MimeType.AUTHENTICATION,
159
+ )
160
+ auth_link = self.link(auth_link_data)
161
+
162
+ prog_link_data = LinkData(
163
+ Rel.PROGRESSION,
164
+ prog_href_data,
165
+ mime_type=MimeType.PROGRESSION,
166
+ authenticate=auth_link,
167
+ )
157
168
  links = [
158
- # Comic streaming link (unsupported)
159
- # self.link(self_link_data),
160
169
  self.link(alt_link_data),
161
170
  self.link(acq_link_data),
171
+ self.link(prog_link_data),
162
172
  ]
163
173
  pub["links"] = links
164
174
 
@@ -1,7 +1,8 @@
1
1
  """OPDS v2.0 top links section methods."""
2
2
 
3
3
  from codex.views.opds.const import MimeType, Rel
4
- from codex.views.opds.v2.links import HrefData, LinkData, OPDS2LinksView
4
+ from codex.views.opds.v2.href import HrefData
5
+ from codex.views.opds.v2.links import LinkData, OPDS2LinksView
5
6
 
6
7
 
7
8
  class OPDS2TopLinksView(OPDS2LinksView):
codex/views/public.py CHANGED
@@ -13,6 +13,7 @@ _ADMIN_FLAG_KEYS = frozenset(
13
13
  {
14
14
  AdminFlag.FlagChoices.NON_USERS.value,
15
15
  AdminFlag.FlagChoices.REGISTRATION.value,
16
+ AdminFlag.FlagChoices.BANNER_TEXT.value,
16
17
  }
17
18
  )
18
19
 
@@ -21,16 +22,22 @@ class AdminFlagsView(GenericAPIView, RetrieveModelMixin):
21
22
  """Get admin flags relevant to auth."""
22
23
 
23
24
  serializer_class = AuthAdminFlagsSerializer
24
- queryset = AdminFlag.objects.filter(key__in=_ADMIN_FLAG_KEYS).only("key", "on")
25
+ queryset = AdminFlag.objects.filter(key__in=_ADMIN_FLAG_KEYS).only(
26
+ "key", "on", "value"
27
+ )
25
28
 
26
29
  def get_object(self):
27
30
  """Get admin flags."""
28
31
  flags = {}
29
- for obj in self.get_queryset(): # type: ignore
32
+ for obj in self.get_queryset():
30
33
  name = ADMIN_FLAG_CHOICES[obj.key].lower().replace(" ", "_")
31
- flags[name] = obj.on
34
+ if obj.key == AdminFlag.FlagChoices.BANNER_TEXT.value:
35
+ val = obj.value
36
+ else:
37
+ val = obj.on
38
+ flags[name] = val
32
39
  return flags
33
40
 
34
- def get(self, request, *args, **kwargs):
41
+ def get(self, *args, **kwargs):
35
42
  """Get admin flags relevant to auth."""
36
- return self.retrieve(request, *args, **kwargs)
43
+ return self.retrieve(*args, **kwargs)
@@ -6,7 +6,7 @@ from django.db.models import F
6
6
  from django.db.models.query import Q
7
7
 
8
8
  from codex.models import Bookmark, Comic
9
- from codex.views.bookmark import BookmarkBaseView
9
+ from codex.views.bookmark import BookmarkAuthMixin
10
10
  from codex.views.browser.filters.field import ComicFieldFilterView
11
11
  from codex.views.const import (
12
12
  FOLDER_GROUP,
@@ -15,7 +15,7 @@ from codex.views.const import (
15
15
  NONE_INTEGERFIELD,
16
16
  STORY_ARC_GROUP,
17
17
  )
18
- from codex.views.mixins import BookmarkSearchMixin, SharedAnnotationsMixin
18
+ from codex.views.mixins import SharedAnnotationsMixin
19
19
  from codex.views.reader.params import ReaderParamsView
20
20
 
21
21
  if TYPE_CHECKING:
@@ -34,9 +34,7 @@ _COMIC_FIELDS = (
34
34
  )
35
35
 
36
36
 
37
- class ReaderBooksView(
38
- BookmarkBaseView, ReaderParamsView, SharedAnnotationsMixin, BookmarkSearchMixin
39
- ):
37
+ class ReaderBooksView(SharedAnnotationsMixin, BookmarkAuthMixin, ReaderParamsView):
40
38
  """Get Books methods."""
41
39
 
42
40
  def _get_reader_arc_pks(
@@ -81,10 +79,10 @@ class ReaderBooksView(
81
79
  """Get ordering for query."""
82
80
  sort_name_annotations = {}
83
81
  if arc_group in ("v", "s"):
82
+ parent_group = "i" if arc_group == "s" else "s"
84
83
  show = self.params["show"]
85
- model_group = "i" if arc_group == "s" else "s"
86
84
  sort_name_annotations = self.get_sort_name_annotations(
87
- model, model_group, arc_pks, show
85
+ model, parent_group, arc_pks, show
88
86
  )
89
87
  if sort_name_annotations and model is Comic:
90
88
  ordering += (*sort_name_annotations.keys(),)
@@ -97,7 +95,7 @@ class ReaderBooksView(
97
95
 
98
96
  def _get_comics_list(self):
99
97
  """Get the reader naviation group filter."""
100
- arc: Mapping = self.params.get("arc", {}) # type: ignore
98
+ arc: Mapping = self.params.get("arc", {})
101
99
 
102
100
  arc_group = arc.get("group", "")
103
101
  if not GROUP_MODEL_MAP.get(arc_group):
@@ -149,6 +147,19 @@ class ReaderBooksView(
149
147
  qs = qs.order_by(*ordering)
150
148
  return qs, arc_group
151
149
 
150
+ @staticmethod
151
+ def _get_bookmark_filter(auth_filter, comic_filter=None):
152
+ """Get the search kwargs for a user's authentication state."""
153
+ # search kwargs are relative to the bookmark object.
154
+ search_kwargs = {}
155
+ search_kwargs.update(auth_filter)
156
+
157
+ if comic_filter:
158
+ for key, value in comic_filter.items():
159
+ search_kwargs[f"comic__{key}"] = value
160
+
161
+ return search_kwargs
162
+
152
163
  def _append_with_settings(self, book, bookmark_filter):
153
164
  """Append bookmark to book list."""
154
165
  book.settings = (
@@ -159,7 +170,8 @@ class ReaderBooksView(
159
170
  return book
160
171
 
161
172
  def get_book_collection(self):
162
- """Get the -1, +1 window around the current issue.
173
+ """
174
+ Get the -1, +1 window around the current issue.
163
175
 
164
176
  Uses iteration in python. There are some complicated ways of
165
177
  doing this with __gt[0] & __lt[0] in the db, but I think they
@@ -169,7 +181,7 @@ class ReaderBooksView(
169
181
  """
170
182
  comics, arc_group = self._get_comics_list()
171
183
  auth_filter = self.get_bookmark_auth_filter()
172
- bookmark_filter = self.get_bookmark_search_kwargs(auth_filter)
184
+ bookmark_filter = self._get_bookmark_filter(auth_filter)
173
185
  books = {}
174
186
  prev_book = None
175
187
  pk = self.kwargs.get("pk")
@@ -14,7 +14,8 @@ from codex.librarian.mp_queue import LIBRARIAN_QUEUE
14
14
  from codex.logger.logging import get_logger
15
15
  from codex.models.comic import Comic, FileType
16
16
  from codex.settings.settings import FALSY
17
- from codex.views.bookmark import BookmarkBaseView
17
+ from codex.views.auth import AuthFilterAPIView
18
+ from codex.views.bookmark import BookmarkAuthMixin
18
19
  from codex.views.util import chunker
19
20
 
20
21
  LOG = get_logger(__name__)
@@ -31,23 +32,23 @@ class IgnoreClientContentNegotiation(BaseContentNegotiation):
31
32
  """Select the first parser in the `.parser_classes` list."""
32
33
  return next(iter(parsers))
33
34
 
34
- def select_renderer( # type: ignore
35
+ def select_renderer(
35
36
  self,
36
37
  request, # noqa: ARG002
37
38
  renderers,
38
- _format_suffix="",
39
+ format_suffix="", # noqa: ARG002, F841, RUF100
39
40
  ):
40
41
  """Select the first renderer in the `.renderer_classes` list."""
41
42
  renderer = next(iter(renderers))
42
43
  return (renderer, renderer.media_type)
43
44
 
44
45
 
45
- class ReaderPageView(BookmarkBaseView):
46
+ class ReaderPageView(BookmarkAuthMixin, AuthFilterAPIView):
46
47
  """Display a comic page from the archive itself."""
47
48
 
48
49
  X_MOZ_PRE_HEADERS = frozenset({"prefetch", "preload", "prerender", "subresource"})
49
50
  content_type = "image/jpeg"
50
- content_negotiation_class = IgnoreClientContentNegotiation # type: ignore
51
+ content_negotiation_class = IgnoreClientContentNegotiation # type: ignore[reportAssignmentType]
51
52
 
52
53
  def _update_bookmark(self):
53
54
  """Update the bookmark if the bookmark param was passed."""
@@ -59,12 +60,11 @@ class ReaderPageView(BookmarkBaseView):
59
60
  return
60
61
 
61
62
  auth_filter = self.get_bookmark_auth_filter()
62
- pk = self.kwargs.get("pk")
63
- comic_filter = {"pk": pk}
63
+ comic_pks = (self.kwargs.get("pk"),)
64
64
  page = self.kwargs.get("page")
65
65
  updates = {"page": page}
66
66
 
67
- task = BookmarkUpdateTask(auth_filter, comic_filter, updates)
67
+ task = BookmarkUpdateTask(auth_filter, comic_pks, updates)
68
68
  LIBRARIAN_QUEUE.put(task)
69
69
 
70
70
  def _get_page_image(self):
@@ -121,9 +121,9 @@ class ReaderParamsView(SessionView):
121
121
  serializer = self.input_serializer_class(data=data)
122
122
  serializer.is_valid(raise_exception=True)
123
123
 
124
- params: dict = mapping_to_dict(_DEFAULT_PARAMS) # type: ignore
124
+ params: dict[str, Any] = mapping_to_dict(_DEFAULT_PARAMS) # type: ignore[reportAssignmentType]
125
125
  if serializer.validated_data:
126
- params.update(serializer.validated_data) # type: ignore
126
+ params.update(serializer.validated_data)
127
127
  self._ensure_arc_contains_comic(params)
128
128
  self._ensure_arc(params)
129
129
 
@@ -58,7 +58,7 @@ class ReaderView(ReaderArcsView):
58
58
  task = LazyImportComicsTask(frozenset(import_pks))
59
59
  LIBRARIAN_QUEUE.put(task)
60
60
 
61
- def get_object(self): # type: ignore
61
+ def get_object(self):
62
62
  """Get the previous and next comics in a group or story arc."""
63
63
  # Books
64
64
  books = self.get_book_collection()
@@ -82,13 +82,13 @@ class ReaderView(ReaderArcsView):
82
82
 
83
83
  arc = self.params.get("arc", {})
84
84
  if not arc.get("group"):
85
- arc["group"] = current.arc_group # type: ignore
85
+ arc["group"] = current.arc_group
86
86
  if not arc.get("pks"):
87
- arc["pks"] = (current.arc_pk,) # type: ignore
88
- arc["index"] = current.arc_index # type:ignore
89
- arc["count"] = current.arc_count # type: ignore
87
+ arc["pks"] = (current.arc_pk,)
88
+ arc["index"] = current.arc_index
89
+ arc["count"] = current.arc_count
90
90
 
91
- close_route = self.get_last_route()
91
+ close_route = self.get_last_route(name=True)
92
92
 
93
93
  return {
94
94
  "books": books,
@@ -7,6 +7,6 @@ from codex.views.settings import SettingsView
7
7
  class ReaderSettingsView(SettingsView):
8
8
  """Get Reader Settings."""
9
9
 
10
- serializer_class = ReaderSettingsSerializer # type: ignore
10
+ serializer_class = ReaderSettingsSerializer
11
11
 
12
12
  SESSION_KEY = "reader"
codex/views/session.py CHANGED
@@ -3,6 +3,7 @@
3
3
  from abc import ABC
4
4
  from copy import deepcopy
5
5
  from types import MappingProxyType
6
+ from typing import TYPE_CHECKING
6
7
 
7
8
  from codex.choices import BROWSER_DEFAULTS, READER_DEFAULTS
8
9
  from codex.logger.logging import get_logger
@@ -10,6 +11,9 @@ from codex.util import mapping_to_dict
10
11
  from codex.views.auth import AuthFilterGenericAPIView
11
12
  from codex.views.util import pop_name
12
13
 
14
+ if TYPE_CHECKING:
15
+ from collections.abc import Mapping
16
+
13
17
  LOG = get_logger(__name__)
14
18
 
15
19
  CONTRIBUTOR_PERSON_UI_FIELD = "contributors"
@@ -78,13 +82,15 @@ class SessionView(AuthFilterGenericAPIView, ABC):
78
82
  default = self.SESSION_DEFAULTS[session_key][key]
79
83
  return session.get(key, default)
80
84
 
81
- def get_last_route(self, name=True):
85
+ def get_last_route(self, name: bool):
82
86
  """Get the last route from the breadcrumbs."""
83
87
  breadcrumbs = self.get_from_session(
84
88
  "breadcrumbs", session_key=self.BROWSER_SESSION_KEY
85
89
  )
86
90
  if not breadcrumbs:
87
- default_breadcrumbs: tuple[dict] = BROWSER_DEFAULTS["breadcrumbs"] # type: ignore
91
+ default_breadcrumbs: tuple[
92
+ Mapping[str, str | tuple[int, ...] | int], ...
93
+ ] = BROWSER_DEFAULTS["breadcrumbs"] # type: ignore[reportAssignmentType]
88
94
  breadcrumbs = default_breadcrumbs
89
95
  last_route = breadcrumbs[-1]
90
96
  if not name:
codex/views/settings.py CHANGED
@@ -29,7 +29,7 @@ class SettingsView(SessionView, ABC):
29
29
  serializer = self.input_serializer_class(data=data)
30
30
  serializer.is_valid(raise_exception=True)
31
31
  validated_data = serializer.validated_data
32
- only = validated_data.get("only") if validated_data else None # type: ignore
32
+ only = validated_data.get("only") if validated_data else None
33
33
  params = self.load_params_from_session(only=only)
34
34
  params = self.validate_settings_get(validated_data, params)
35
35
  serializer = self.get_serializer(params)
@@ -38,7 +38,7 @@ class SettingsView(SessionView, ABC):
38
38
  @extend_schema(responses=None)
39
39
  def patch(self, *args, **kwargs):
40
40
  """Update session settings."""
41
- data = self.request.data # type: ignore
41
+ data = self.request.data
42
42
  serializer = self.get_serializer(data=data)
43
43
  serializer.is_valid(raise_exception=True)
44
44
  params = self.load_params_from_session()
codex/views/timezone.py CHANGED
@@ -28,11 +28,11 @@ class TimezoneView(AuthGenericAPIView):
28
28
  @extend_schema(request=input_serializer_class)
29
29
  def put(self, *args, **kwargs):
30
30
  """Get the user info for the current user."""
31
- data = self.request.data # type: ignore
31
+ data = self.request.data
32
32
  serializer = self.input_serializer_class(data=data)
33
33
  serializer.is_valid(raise_exception=True)
34
34
  try:
35
- timezone = serializer.validated_data.get("timezone") # type: ignore
35
+ timezone = serializer.validated_data.get("timezone")
36
36
  self._save_timezone(timezone)
37
37
  except Exception as exc:
38
38
  reason = f"update user timezone {exc}"