codex 1.6.0a5__py3-none-any.whl → 1.6.0a7__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 (564) hide show
  1. codex/exceptions.py +1 -0
  2. codex/librarian/covers/purge.py +1 -2
  3. codex/librarian/importer/aggregate_metadata.py +2 -10
  4. codex/librarian/importer/cache.py +47 -0
  5. codex/librarian/importer/const.py +8 -0
  6. codex/librarian/importer/deleted.py +45 -7
  7. codex/librarian/importer/importerd.py +11 -1
  8. codex/librarian/importer/update_comics.py +0 -2
  9. codex/librarian/janitor/janitor.py +1 -1
  10. codex/librarian/librariand.py +1 -1
  11. codex/migrations/0029_choices_adminflag_and_timestamp.py +44 -0
  12. codex/models/admin.py +0 -1
  13. codex/permissions.py +1 -1
  14. codex/serializers/admin.py +1 -2
  15. codex/serializers/browser/filters.py +8 -101
  16. codex/serializers/browser/mixins.py +20 -3
  17. codex/serializers/browser/page.py +2 -3
  18. codex/serializers/browser/settings.py +2 -0
  19. codex/serializers/fields.py +123 -0
  20. codex/serializers/mtime.py +25 -0
  21. codex/serializers/opds/v2.py +7 -11
  22. codex/serializers/opds/v2_unused.py +5 -3
  23. codex/serializers/reader.py +5 -2
  24. codex/serializers/route.py +7 -3
  25. codex/static_root/assets/VCheckbox-BOUtyxuo.c690f0cdbe48.js +1 -0
  26. codex/static_root/assets/VCheckbox-BOUtyxuo.c690f0cdbe48.js.br +0 -0
  27. codex/static_root/assets/VCheckbox-BOUtyxuo.c690f0cdbe48.js.gz +0 -0
  28. codex/static_root/assets/VCheckbox-BOUtyxuo.js +1 -0
  29. codex/static_root/assets/VCheckbox-BOUtyxuo.js.br +0 -0
  30. codex/static_root/assets/VCheckbox-BOUtyxuo.js.gz +0 -0
  31. codex/static_root/assets/VCheckboxBtn-B1-m5pEh.e2b8cbdb92c9.js +1 -0
  32. codex/static_root/assets/VCheckboxBtn-B1-m5pEh.e2b8cbdb92c9.js.br +0 -0
  33. codex/static_root/assets/VCheckboxBtn-B1-m5pEh.e2b8cbdb92c9.js.gz +0 -0
  34. codex/static_root/assets/VCheckboxBtn-B1-m5pEh.js +1 -0
  35. codex/static_root/assets/VCheckboxBtn-B1-m5pEh.js.br +0 -0
  36. codex/static_root/assets/VCheckboxBtn-B1-m5pEh.js.gz +0 -0
  37. codex/static_root/assets/VCombobox-DjkDXe33.22617ea193b1.js +1 -0
  38. codex/static_root/assets/VCombobox-DjkDXe33.22617ea193b1.js.br +0 -0
  39. codex/static_root/assets/VCombobox-DjkDXe33.22617ea193b1.js.gz +0 -0
  40. codex/static_root/assets/VCombobox-DjkDXe33.js +1 -0
  41. codex/static_root/assets/VCombobox-DjkDXe33.js.br +0 -0
  42. codex/static_root/assets/VCombobox-DjkDXe33.js.gz +0 -0
  43. codex/static_root/assets/VDialog-X0zn9AGX.0d89c749b9a6.js +1 -0
  44. codex/static_root/assets/VDialog-X0zn9AGX.0d89c749b9a6.js.br +0 -0
  45. codex/static_root/assets/VDialog-X0zn9AGX.0d89c749b9a6.js.gz +0 -0
  46. codex/static_root/assets/VDialog-X0zn9AGX.js +1 -0
  47. codex/static_root/assets/VDialog-X0zn9AGX.js.br +0 -0
  48. codex/static_root/assets/VDialog-X0zn9AGX.js.gz +0 -0
  49. codex/static_root/assets/VExpansionPanels-CRevojaF.43d65c777c58.js +1 -0
  50. codex/static_root/assets/VExpansionPanels-CRevojaF.43d65c777c58.js.br +0 -0
  51. codex/static_root/assets/VExpansionPanels-CRevojaF.43d65c777c58.js.gz +0 -0
  52. codex/static_root/assets/VExpansionPanels-CRevojaF.js +1 -0
  53. codex/static_root/assets/VExpansionPanels-CRevojaF.js.br +0 -0
  54. codex/static_root/assets/VExpansionPanels-CRevojaF.js.gz +0 -0
  55. codex/static_root/assets/VRadioGroup-8nrrxjDv.2b4dfb984a8c.js +1 -0
  56. codex/static_root/assets/VRadioGroup-8nrrxjDv.2b4dfb984a8c.js.br +0 -0
  57. codex/static_root/assets/VRadioGroup-8nrrxjDv.2b4dfb984a8c.js.gz +0 -0
  58. codex/static_root/assets/VRadioGroup-8nrrxjDv.js +1 -0
  59. codex/static_root/assets/VRadioGroup-8nrrxjDv.js.br +0 -0
  60. codex/static_root/assets/VRadioGroup-8nrrxjDv.js.gz +0 -0
  61. codex/static_root/assets/VSelect-DgfIKRnC.fa7a73a9c415.js +1 -0
  62. codex/static_root/assets/VSelect-DgfIKRnC.fa7a73a9c415.js.br +0 -0
  63. codex/static_root/assets/VSelect-DgfIKRnC.fa7a73a9c415.js.gz +0 -0
  64. codex/static_root/assets/VSelect-DgfIKRnC.js +1 -0
  65. codex/static_root/assets/VSelect-DgfIKRnC.js.br +0 -0
  66. codex/static_root/assets/VSelect-DgfIKRnC.js.gz +0 -0
  67. codex/static_root/assets/VSelectionControl-CGu0oz0K.3030b7a270d6.js +1 -0
  68. codex/static_root/assets/VSelectionControl-CGu0oz0K.3030b7a270d6.js.br +0 -0
  69. codex/static_root/assets/VSelectionControl-CGu0oz0K.3030b7a270d6.js.gz +0 -0
  70. codex/static_root/assets/VSelectionControl-CGu0oz0K.js +1 -0
  71. codex/static_root/assets/VSelectionControl-CGu0oz0K.js.br +0 -0
  72. codex/static_root/assets/VSelectionControl-CGu0oz0K.js.gz +0 -0
  73. codex/static_root/assets/VSlideGroup-D_oNvCOd.71a7101cdddd.js +1 -0
  74. codex/static_root/assets/VSlideGroup-D_oNvCOd.71a7101cdddd.js.br +0 -0
  75. codex/static_root/assets/VSlideGroup-D_oNvCOd.71a7101cdddd.js.gz +0 -0
  76. codex/static_root/assets/VSlideGroup-D_oNvCOd.js +1 -0
  77. codex/static_root/assets/VSlideGroup-D_oNvCOd.js.br +0 -0
  78. codex/static_root/assets/VSlideGroup-D_oNvCOd.js.gz +0 -0
  79. codex/static_root/assets/{VTable-FKMTcdkF.6c1eed84d25e.js → VTable-C7pKI7gU.087912f706f5.js} +1 -1
  80. codex/static_root/assets/VTable-C7pKI7gU.087912f706f5.js.br +0 -0
  81. codex/static_root/assets/VTable-C7pKI7gU.087912f706f5.js.gz +0 -0
  82. codex/static_root/assets/{VTable-FKMTcdkF.js → VTable-C7pKI7gU.js} +1 -1
  83. codex/static_root/assets/VTable-C7pKI7gU.js.br +0 -0
  84. codex/static_root/assets/VTable-C7pKI7gU.js.gz +0 -0
  85. codex/static_root/assets/{VTextField-Dftcik85.js → VTextField-Bs8oq9mk.7999fef12a03.js} +1 -1
  86. codex/static_root/assets/VTextField-Bs8oq9mk.7999fef12a03.js.br +0 -0
  87. codex/static_root/assets/VTextField-Bs8oq9mk.7999fef12a03.js.gz +0 -0
  88. codex/static_root/assets/{VTextField-Dftcik85.cb2f1dda87e1.js → VTextField-Bs8oq9mk.js} +1 -1
  89. codex/static_root/assets/VTextField-Bs8oq9mk.js.br +0 -0
  90. codex/static_root/assets/VTextField-Bs8oq9mk.js.gz +0 -0
  91. codex/static_root/assets/{VWindowItem-CYCwnt3s.28025dc36c6a.js → VWindowItem-iyZ1XOkP.409f7d292253.js} +1 -1
  92. codex/static_root/assets/VWindowItem-iyZ1XOkP.409f7d292253.js.br +0 -0
  93. codex/static_root/assets/VWindowItem-iyZ1XOkP.409f7d292253.js.gz +0 -0
  94. codex/static_root/assets/{VWindowItem-CYCwnt3s.js → VWindowItem-iyZ1XOkP.js} +1 -1
  95. codex/static_root/assets/VWindowItem-iyZ1XOkP.js.br +0 -0
  96. codex/static_root/assets/VWindowItem-iyZ1XOkP.js.gz +0 -0
  97. codex/static_root/assets/admin-B0pCBjma.2407da79bd20.js +1 -0
  98. codex/static_root/assets/admin-B0pCBjma.2407da79bd20.js.br +0 -0
  99. codex/static_root/assets/admin-B0pCBjma.2407da79bd20.js.gz +0 -0
  100. codex/static_root/assets/admin-B0pCBjma.js +1 -0
  101. codex/static_root/assets/admin-B0pCBjma.js.br +0 -0
  102. codex/static_root/assets/admin-B0pCBjma.js.gz +0 -0
  103. codex/static_root/assets/admin-drawer-panel-BxoNUHQr.5e2e1a4a255d.js +30 -0
  104. codex/static_root/assets/admin-drawer-panel-BxoNUHQr.5e2e1a4a255d.js.br +0 -0
  105. codex/static_root/assets/admin-drawer-panel-BxoNUHQr.5e2e1a4a255d.js.gz +0 -0
  106. codex/static_root/assets/admin-drawer-panel-BxoNUHQr.js +30 -0
  107. codex/static_root/assets/admin-drawer-panel-BxoNUHQr.js.br +0 -0
  108. codex/static_root/assets/admin-drawer-panel-BxoNUHQr.js.gz +0 -0
  109. codex/static_root/assets/{admin-drawer-panel-BHdNPwzF.bd2c1d6148bb.css → admin-drawer-panel-o87BwD38.ce39427c8201.css} +1 -1
  110. codex/static_root/assets/admin-drawer-panel-o87BwD38.ce39427c8201.css.br +0 -0
  111. codex/static_root/assets/{admin-drawer-panel-BHdNPwzF.bd2c1d6148bb.css.gz → admin-drawer-panel-o87BwD38.ce39427c8201.css.gz} +0 -0
  112. codex/static_root/assets/{admin-drawer-panel-BHdNPwzF.css → admin-drawer-panel-o87BwD38.css} +1 -1
  113. codex/static_root/assets/admin-drawer-panel-o87BwD38.css.br +0 -0
  114. codex/static_root/assets/{admin-drawer-panel-BHdNPwzF.css.gz → admin-drawer-panel-o87BwD38.css.gz} +0 -0
  115. codex/static_root/assets/browser-DbyAjCNh.577a228a966b.js +1 -0
  116. codex/static_root/assets/browser-DbyAjCNh.577a228a966b.js.br +0 -0
  117. codex/static_root/assets/browser-DbyAjCNh.577a228a966b.js.gz +0 -0
  118. codex/static_root/assets/browser-DbyAjCNh.js +1 -0
  119. codex/static_root/assets/browser-DbyAjCNh.js.br +0 -0
  120. codex/static_root/assets/browser-DbyAjCNh.js.gz +0 -0
  121. codex/static_root/assets/browser-VnzNj1t3.cff861ad2ca3.css +1 -0
  122. codex/static_root/assets/browser-VnzNj1t3.cff861ad2ca3.css.br +0 -0
  123. codex/static_root/assets/browser-VnzNj1t3.cff861ad2ca3.css.gz +0 -0
  124. codex/static_root/assets/browser-VnzNj1t3.css +1 -0
  125. codex/static_root/assets/browser-VnzNj1t3.css.br +0 -0
  126. codex/static_root/assets/browser-VnzNj1t3.css.gz +0 -0
  127. codex/static_root/assets/{change-password-dialog-BIBG6Bk8.3583021c124a.js → change-password-dialog-DZ9dP8_F.930f4cae3cb0.js} +1 -1
  128. codex/static_root/assets/change-password-dialog-DZ9dP8_F.930f4cae3cb0.js.br +0 -0
  129. codex/static_root/assets/change-password-dialog-DZ9dP8_F.930f4cae3cb0.js.gz +0 -0
  130. codex/static_root/assets/{change-password-dialog-BIBG6Bk8.js → change-password-dialog-DZ9dP8_F.js} +1 -1
  131. codex/static_root/assets/change-password-dialog-DZ9dP8_F.js.br +0 -0
  132. codex/static_root/assets/change-password-dialog-DZ9dP8_F.js.gz +0 -0
  133. codex/static_root/assets/{confirm-dialog-DARLmXRf.53fc6938fb8c.js → confirm-dialog-RP7JNStF.a752a7c1e697.js} +1 -1
  134. codex/static_root/assets/confirm-dialog-RP7JNStF.a752a7c1e697.js.br +0 -0
  135. codex/static_root/assets/confirm-dialog-RP7JNStF.a752a7c1e697.js.gz +0 -0
  136. codex/static_root/assets/{confirm-dialog-DARLmXRf.js → confirm-dialog-RP7JNStF.js} +1 -1
  137. codex/static_root/assets/confirm-dialog-RP7JNStF.js.br +0 -0
  138. codex/static_root/assets/confirm-dialog-RP7JNStF.js.gz +0 -0
  139. codex/static_root/assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js +1 -0
  140. codex/static_root/assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js.br +0 -0
  141. codex/static_root/assets/copy-to-clipboard-DoUvDJVx.js +1 -0
  142. codex/static_root/assets/copy-to-clipboard-DoUvDJVx.js.br +0 -0
  143. codex/static_root/assets/{datetime-column-LpLgWpkf.16ce3324970f.js → datetime-column-Cu3WYyPj.54b4c3817b74.js} +1 -1
  144. codex/static_root/assets/datetime-column-Cu3WYyPj.54b4c3817b74.js.br +0 -0
  145. codex/static_root/assets/datetime-column-Cu3WYyPj.54b4c3817b74.js.gz +0 -0
  146. codex/static_root/assets/{datetime-column-LpLgWpkf.js → datetime-column-Cu3WYyPj.js} +1 -1
  147. codex/static_root/assets/datetime-column-Cu3WYyPj.js.br +0 -0
  148. codex/static_root/assets/datetime-column-Cu3WYyPj.js.gz +0 -0
  149. codex/static_root/assets/filter-DAdGUt-1.3261cbcd50b5.js +1 -0
  150. codex/static_root/assets/filter-DAdGUt-1.3261cbcd50b5.js.br +0 -0
  151. codex/static_root/assets/filter-DAdGUt-1.3261cbcd50b5.js.gz +0 -0
  152. codex/static_root/assets/filter-DAdGUt-1.js +1 -0
  153. codex/static_root/assets/filter-DAdGUt-1.js.br +0 -0
  154. codex/static_root/assets/filter-DAdGUt-1.js.gz +0 -0
  155. codex/static_root/assets/flag-tab-BP7Zs7iQ.cb16ef6363d4.js +1 -0
  156. codex/static_root/assets/flag-tab-BP7Zs7iQ.cb16ef6363d4.js.br +0 -0
  157. codex/static_root/assets/flag-tab-BP7Zs7iQ.cb16ef6363d4.js.gz +0 -0
  158. codex/static_root/assets/flag-tab-BP7Zs7iQ.js +1 -0
  159. codex/static_root/assets/flag-tab-BP7Zs7iQ.js.br +0 -0
  160. codex/static_root/assets/flag-tab-BP7Zs7iQ.js.gz +0 -0
  161. codex/static_root/assets/{group-tab-MK1lcjUU.98406d5babdc.js → group-tab-DEwh4jfB.a95097b5e320.js} +1 -1
  162. codex/static_root/assets/group-tab-DEwh4jfB.a95097b5e320.js.br +0 -0
  163. codex/static_root/assets/group-tab-DEwh4jfB.a95097b5e320.js.gz +0 -0
  164. codex/static_root/assets/{group-tab-MK1lcjUU.js → group-tab-DEwh4jfB.js} +1 -1
  165. codex/static_root/assets/group-tab-DEwh4jfB.js.br +0 -0
  166. codex/static_root/assets/group-tab-DEwh4jfB.js.gz +0 -0
  167. codex/static_root/assets/http-error-xs3mIL8U.e143c472a96c.js +1 -0
  168. codex/static_root/assets/http-error-xs3mIL8U.e143c472a96c.js.br +0 -0
  169. codex/static_root/assets/http-error-xs3mIL8U.e143c472a96c.js.gz +0 -0
  170. codex/static_root/assets/http-error-xs3mIL8U.js +1 -0
  171. codex/static_root/assets/http-error-xs3mIL8U.js.br +0 -0
  172. codex/static_root/assets/http-error-xs3mIL8U.js.gz +0 -0
  173. codex/static_root/assets/{library-tab-DYeEBYlT.a2a2ef088d1c.js → library-tab-DrXvD9B2.f765f9d3bae4.js} +1 -1
  174. codex/static_root/assets/library-tab-DrXvD9B2.f765f9d3bae4.js.br +0 -0
  175. codex/static_root/assets/library-tab-DrXvD9B2.f765f9d3bae4.js.gz +0 -0
  176. codex/static_root/assets/{library-tab-DYeEBYlT.js → library-tab-DrXvD9B2.js} +1 -1
  177. codex/static_root/assets/library-tab-DrXvD9B2.js.br +0 -0
  178. codex/static_root/assets/library-tab-DrXvD9B2.js.gz +0 -0
  179. codex/static_root/assets/main-Dy9Uqpmh.2f99b1914b3e.js +32 -0
  180. codex/static_root/assets/main-Dy9Uqpmh.2f99b1914b3e.js.br +0 -0
  181. codex/static_root/assets/main-Dy9Uqpmh.2f99b1914b3e.js.gz +0 -0
  182. codex/static_root/assets/main-Dy9Uqpmh.js +32 -0
  183. codex/static_root/assets/main-Dy9Uqpmh.js.br +0 -0
  184. codex/static_root/assets/main-Dy9Uqpmh.js.gz +0 -0
  185. codex/static_root/assets/{main-sK7HC5h4.css → main-Ztp855PW.css} +1 -1
  186. codex/static_root/assets/main-Ztp855PW.css.br +0 -0
  187. codex/static_root/assets/{main-sK7HC5h4.css.gz → main-Ztp855PW.css.gz} +0 -0
  188. codex/static_root/assets/{main-sK7HC5h4.6f04ddfc5f1a.css → main-Ztp855PW.d46d718fac45.css} +1 -1
  189. codex/static_root/assets/main-Ztp855PW.d46d718fac45.css.br +0 -0
  190. codex/static_root/assets/{main-sK7HC5h4.6f04ddfc5f1a.css.gz → main-Ztp855PW.d46d718fac45.css.gz} +0 -0
  191. codex/static_root/assets/pagination-toolbar-DbS_HOT1.81222ab51ef4.js +1 -0
  192. codex/static_root/assets/pagination-toolbar-DbS_HOT1.81222ab51ef4.js.br +0 -0
  193. codex/static_root/assets/pagination-toolbar-DbS_HOT1.81222ab51ef4.js.gz +0 -0
  194. codex/static_root/assets/pagination-toolbar-DbS_HOT1.js +1 -0
  195. codex/static_root/assets/pagination-toolbar-DbS_HOT1.js.br +0 -0
  196. codex/static_root/assets/pagination-toolbar-DbS_HOT1.js.gz +0 -0
  197. codex/static_root/assets/{pagination-toolbar-ClZui9Zf.697d7ae11c21.css → pagination-toolbar-r6nbtWxg.4088ab042c0c.css} +1 -1
  198. codex/static_root/assets/pagination-toolbar-r6nbtWxg.4088ab042c0c.css.br +0 -0
  199. codex/static_root/assets/pagination-toolbar-r6nbtWxg.4088ab042c0c.css.gz +0 -0
  200. codex/static_root/assets/{pagination-toolbar-ClZui9Zf.css → pagination-toolbar-r6nbtWxg.css} +1 -1
  201. codex/static_root/assets/pagination-toolbar-r6nbtWxg.css.br +0 -0
  202. codex/static_root/assets/pagination-toolbar-r6nbtWxg.css.gz +0 -0
  203. codex/static_root/assets/pdf-doc-obrBwxa6.ec9bd13a5786.js +305 -0
  204. codex/static_root/assets/pdf-doc-obrBwxa6.ec9bd13a5786.js.br +0 -0
  205. codex/static_root/assets/pdf-doc-obrBwxa6.ec9bd13a5786.js.gz +0 -0
  206. codex/static_root/assets/pdf-doc-obrBwxa6.js +305 -0
  207. codex/static_root/assets/pdf-doc-obrBwxa6.js.br +0 -0
  208. codex/static_root/assets/pdf-doc-obrBwxa6.js.gz +0 -0
  209. codex/static_root/assets/reader-BXKUaUeC.953d30b969ef.js +2 -0
  210. codex/static_root/assets/reader-BXKUaUeC.953d30b969ef.js.br +0 -0
  211. codex/static_root/assets/reader-BXKUaUeC.953d30b969ef.js.gz +0 -0
  212. codex/static_root/assets/reader-BXKUaUeC.js +2 -0
  213. codex/static_root/assets/reader-BXKUaUeC.js.br +0 -0
  214. codex/static_root/assets/reader-BXKUaUeC.js.gz +0 -0
  215. codex/static_root/assets/{reader-CF3xt6JG.19fad7f62450.css → reader-OXJ1KVaW.a463b19d0508.css} +1 -1
  216. codex/static_root/assets/reader-OXJ1KVaW.a463b19d0508.css.br +0 -0
  217. codex/static_root/assets/reader-OXJ1KVaW.a463b19d0508.css.gz +0 -0
  218. codex/static_root/assets/{reader-CF3xt6JG.css → reader-OXJ1KVaW.css} +1 -1
  219. codex/static_root/assets/reader-OXJ1KVaW.css.br +0 -0
  220. codex/static_root/assets/reader-OXJ1KVaW.css.gz +0 -0
  221. codex/static_root/assets/relation-chips-CZJcLjc8.1d7426dab654.js +1 -0
  222. codex/static_root/assets/relation-chips-CZJcLjc8.1d7426dab654.js.br +0 -0
  223. codex/static_root/assets/relation-chips-CZJcLjc8.1d7426dab654.js.gz +0 -0
  224. codex/static_root/assets/relation-chips-CZJcLjc8.js +1 -0
  225. codex/static_root/assets/relation-chips-CZJcLjc8.js.br +0 -0
  226. codex/static_root/assets/relation-chips-CZJcLjc8.js.gz +0 -0
  227. codex/static_root/assets/settings-drawer-7iTnAdjf.337eecf2fdbb.js +2 -0
  228. codex/static_root/assets/settings-drawer-7iTnAdjf.337eecf2fdbb.js.br +0 -0
  229. codex/static_root/assets/settings-drawer-7iTnAdjf.337eecf2fdbb.js.gz +0 -0
  230. codex/static_root/assets/settings-drawer-7iTnAdjf.js +2 -0
  231. codex/static_root/assets/settings-drawer-7iTnAdjf.js.br +0 -0
  232. codex/static_root/assets/settings-drawer-7iTnAdjf.js.gz +0 -0
  233. codex/static_root/assets/{settings-drawer-BJOfMtqA.6471a50fc05b.css → settings-drawer-nZ9HvKSZ.01744e131806.css} +1 -1
  234. codex/static_root/assets/settings-drawer-nZ9HvKSZ.01744e131806.css.br +0 -0
  235. codex/static_root/assets/settings-drawer-nZ9HvKSZ.01744e131806.css.gz +0 -0
  236. codex/static_root/assets/{settings-drawer-BJOfMtqA.css → settings-drawer-nZ9HvKSZ.css} +1 -1
  237. codex/static_root/assets/settings-drawer-nZ9HvKSZ.css.br +0 -0
  238. codex/static_root/assets/settings-drawer-nZ9HvKSZ.css.gz +0 -0
  239. codex/static_root/assets/stats-tab-CQsK1n8O.544bf50ffb22.js +1 -0
  240. codex/static_root/assets/stats-tab-CQsK1n8O.544bf50ffb22.js.br +0 -0
  241. codex/static_root/assets/stats-tab-CQsK1n8O.544bf50ffb22.js.gz +0 -0
  242. codex/static_root/assets/stats-tab-CQsK1n8O.js +1 -0
  243. codex/static_root/assets/stats-tab-CQsK1n8O.js.br +0 -0
  244. codex/static_root/assets/stats-tab-CQsK1n8O.js.gz +0 -0
  245. codex/static_root/assets/task-tab-C60TLP6e.63aa929a4ed6.js +1 -0
  246. codex/static_root/assets/task-tab-C60TLP6e.63aa929a4ed6.js.br +0 -0
  247. codex/static_root/assets/task-tab-C60TLP6e.63aa929a4ed6.js.gz +0 -0
  248. codex/static_root/assets/task-tab-C60TLP6e.js +1 -0
  249. codex/static_root/assets/task-tab-C60TLP6e.js.br +0 -0
  250. codex/static_root/assets/task-tab-C60TLP6e.js.gz +0 -0
  251. codex/static_root/assets/to-case-CR9beRR0.21bb805fdab4.js +1 -0
  252. codex/static_root/assets/to-case-CR9beRR0.js +1 -0
  253. codex/static_root/assets/unauthorized-Bs7NSqea.c55650fac055.js +1 -0
  254. codex/static_root/assets/unauthorized-Bs7NSqea.c55650fac055.js.br +0 -0
  255. codex/static_root/assets/unauthorized-Bs7NSqea.c55650fac055.js.gz +0 -0
  256. codex/static_root/assets/unauthorized-Bs7NSqea.js +1 -0
  257. codex/static_root/assets/unauthorized-Bs7NSqea.js.br +0 -0
  258. codex/static_root/assets/unauthorized-Bs7NSqea.js.gz +0 -0
  259. codex/static_root/assets/user-tab-ChuH7Atm.7e80cf1fb78e.js +1 -0
  260. codex/static_root/assets/user-tab-ChuH7Atm.7e80cf1fb78e.js.br +0 -0
  261. codex/static_root/assets/user-tab-ChuH7Atm.7e80cf1fb78e.js.gz +0 -0
  262. codex/static_root/assets/user-tab-ChuH7Atm.js +1 -0
  263. codex/static_root/assets/user-tab-ChuH7Atm.js.br +0 -0
  264. codex/static_root/assets/user-tab-ChuH7Atm.js.gz +0 -0
  265. codex/static_root/js/choices.079a01e0be1a.json +1 -0
  266. codex/static_root/js/choices.079a01e0be1a.json.br +0 -0
  267. codex/static_root/js/choices.079a01e0be1a.json.gz +0 -0
  268. codex/static_root/js/choices.json +1 -1
  269. codex/static_root/js/choices.json.br +0 -0
  270. codex/static_root/js/choices.json.gz +0 -0
  271. codex/static_root/manifest.dad79c8475ae.json +629 -0
  272. codex/static_root/manifest.dad79c8475ae.json.br +0 -0
  273. codex/static_root/manifest.dad79c8475ae.json.gz +0 -0
  274. codex/static_root/manifest.json +265 -278
  275. codex/static_root/manifest.json.br +0 -0
  276. codex/static_root/manifest.json.gz +0 -0
  277. codex/static_root/staticfiles.json +1 -1
  278. codex/urls/api/auth.py +2 -1
  279. codex/urls/api/browser.py +2 -2
  280. codex/urls/api/reader.py +2 -2
  281. codex/urls/api/v3.py +2 -0
  282. codex/util.py +10 -0
  283. codex/views/admin/api_key.py +2 -6
  284. codex/views/admin/auth.py +30 -0
  285. codex/views/admin/flag.py +2 -7
  286. codex/views/admin/group.py +2 -6
  287. codex/views/admin/library.py +7 -20
  288. codex/views/admin/stats.py +7 -66
  289. codex/views/admin/tasks.py +12 -11
  290. codex/views/admin/user.py +3 -9
  291. codex/views/auth.py +31 -52
  292. codex/views/bookmark.py +7 -11
  293. codex/views/browser/{browser_annotations.py → annotations.py} +119 -78
  294. codex/views/browser/base.py +24 -72
  295. codex/views/browser/breadcrumbs.py +200 -0
  296. codex/views/browser/browser.py +64 -344
  297. codex/views/browser/choices.py +25 -33
  298. codex/views/browser/filters/annotations.py +2 -2
  299. codex/views/browser/filters/bookmark.py +9 -13
  300. codex/views/browser/filters/field.py +9 -6
  301. codex/views/browser/filters/group.py +8 -5
  302. codex/views/browser/filters/search.py +11 -8
  303. codex/views/browser/metadata.py +3 -7
  304. codex/views/browser/{browser_order_by.py → order_by.py} +2 -6
  305. codex/views/browser/paginate.py +106 -0
  306. codex/views/browser/{session.py → settings.py} +4 -3
  307. codex/views/browser/title.py +48 -0
  308. codex/views/browser/validate.py +158 -0
  309. codex/views/const.py +97 -0
  310. codex/views/cover.py +4 -6
  311. codex/views/download.py +5 -8
  312. codex/views/frontend.py +4 -2
  313. codex/views/mtime.py +70 -0
  314. codex/views/opds/auth.py +17 -0
  315. codex/views/opds/authentication_v1.py +46 -45
  316. codex/views/opds/binary.py +4 -9
  317. codex/views/opds/const.py +13 -0
  318. codex/views/opds/urls.py +5 -4
  319. codex/views/opds/util.py +2 -8
  320. codex/views/opds/v1/facets.py +6 -7
  321. codex/views/opds/v1/feed.py +10 -17
  322. codex/views/opds/v1/links.py +6 -5
  323. codex/views/opds/v1/opensearch_v1.py +2 -6
  324. codex/views/opds/v2/feed.py +12 -15
  325. codex/views/opds/v2/links.py +3 -2
  326. codex/views/opds/v2/publications.py +21 -20
  327. codex/views/opds/v2/top_links.py +2 -2
  328. codex/views/public.py +38 -0
  329. codex/views/reader/arcs.py +101 -0
  330. codex/views/reader/books.py +199 -0
  331. codex/views/reader/page.py +3 -7
  332. codex/views/reader/reader.py +53 -298
  333. codex/views/reader/{session.py → settings.py} +4 -2
  334. codex/views/session.py +74 -102
  335. codex/views/settings.py +34 -0
  336. codex/views/template.py +3 -3
  337. codex/views/util.py +31 -0
  338. codex/views/utils.py +26 -0
  339. codex/views/version.py +2 -2
  340. {codex-1.6.0a5.dist-info → codex-1.6.0a7.dist-info}/METADATA +12 -8
  341. {codex-1.6.0a5.dist-info → codex-1.6.0a7.dist-info}/RECORD +344 -330
  342. codex/static_root/assets/VCheckbox-BF_99tgB.7fe59e56d9d4.js +0 -1
  343. codex/static_root/assets/VCheckbox-BF_99tgB.7fe59e56d9d4.js.br +0 -0
  344. codex/static_root/assets/VCheckbox-BF_99tgB.7fe59e56d9d4.js.gz +0 -0
  345. codex/static_root/assets/VCheckbox-BF_99tgB.js +0 -1
  346. codex/static_root/assets/VCheckbox-BF_99tgB.js.br +0 -0
  347. codex/static_root/assets/VCheckbox-BF_99tgB.js.gz +0 -0
  348. codex/static_root/assets/VCheckboxBtn-Coc7g8m7.31e1e6aa44c9.js +0 -1
  349. codex/static_root/assets/VCheckboxBtn-Coc7g8m7.31e1e6aa44c9.js.br +0 -0
  350. codex/static_root/assets/VCheckboxBtn-Coc7g8m7.31e1e6aa44c9.js.gz +0 -0
  351. codex/static_root/assets/VCheckboxBtn-Coc7g8m7.js +0 -1
  352. codex/static_root/assets/VCheckboxBtn-Coc7g8m7.js.br +0 -0
  353. codex/static_root/assets/VCheckboxBtn-Coc7g8m7.js.gz +0 -0
  354. codex/static_root/assets/VCombobox-CTRWnOuM.0f00903c2ebc.js +0 -1
  355. codex/static_root/assets/VCombobox-CTRWnOuM.0f00903c2ebc.js.br +0 -0
  356. codex/static_root/assets/VCombobox-CTRWnOuM.0f00903c2ebc.js.gz +0 -0
  357. codex/static_root/assets/VCombobox-CTRWnOuM.js +0 -1
  358. codex/static_root/assets/VCombobox-CTRWnOuM.js.br +0 -0
  359. codex/static_root/assets/VCombobox-CTRWnOuM.js.gz +0 -0
  360. codex/static_root/assets/VDialog-pzwzInEh.51acf566a069.js +0 -1
  361. codex/static_root/assets/VDialog-pzwzInEh.51acf566a069.js.br +0 -0
  362. codex/static_root/assets/VDialog-pzwzInEh.51acf566a069.js.gz +0 -0
  363. codex/static_root/assets/VDialog-pzwzInEh.js +0 -1
  364. codex/static_root/assets/VDialog-pzwzInEh.js.br +0 -0
  365. codex/static_root/assets/VDialog-pzwzInEh.js.gz +0 -0
  366. codex/static_root/assets/VExpansionPanels-CKSq1GpG.0ecf702c5b67.js +0 -1
  367. codex/static_root/assets/VExpansionPanels-CKSq1GpG.0ecf702c5b67.js.br +0 -0
  368. codex/static_root/assets/VExpansionPanels-CKSq1GpG.0ecf702c5b67.js.gz +0 -0
  369. codex/static_root/assets/VExpansionPanels-CKSq1GpG.js +0 -1
  370. codex/static_root/assets/VExpansionPanels-CKSq1GpG.js.br +0 -0
  371. codex/static_root/assets/VExpansionPanels-CKSq1GpG.js.gz +0 -0
  372. codex/static_root/assets/VRadioGroup-CW5GobGU.b72925bca3de.js +0 -1
  373. codex/static_root/assets/VRadioGroup-CW5GobGU.b72925bca3de.js.br +0 -0
  374. codex/static_root/assets/VRadioGroup-CW5GobGU.b72925bca3de.js.gz +0 -0
  375. codex/static_root/assets/VRadioGroup-CW5GobGU.js +0 -1
  376. codex/static_root/assets/VRadioGroup-CW5GobGU.js.br +0 -0
  377. codex/static_root/assets/VRadioGroup-CW5GobGU.js.gz +0 -0
  378. codex/static_root/assets/VSelect-ChOlLRyH.00b11751b25e.js +0 -1
  379. codex/static_root/assets/VSelect-ChOlLRyH.00b11751b25e.js.br +0 -0
  380. codex/static_root/assets/VSelect-ChOlLRyH.00b11751b25e.js.gz +0 -0
  381. codex/static_root/assets/VSelect-ChOlLRyH.js +0 -1
  382. codex/static_root/assets/VSelect-ChOlLRyH.js.br +0 -0
  383. codex/static_root/assets/VSelect-ChOlLRyH.js.gz +0 -0
  384. codex/static_root/assets/VSelectionControl-DKOhc2zB.061dca094303.js +0 -1
  385. codex/static_root/assets/VSelectionControl-DKOhc2zB.061dca094303.js.br +0 -0
  386. codex/static_root/assets/VSelectionControl-DKOhc2zB.061dca094303.js.gz +0 -0
  387. codex/static_root/assets/VSelectionControl-DKOhc2zB.js +0 -1
  388. codex/static_root/assets/VSelectionControl-DKOhc2zB.js.br +0 -0
  389. codex/static_root/assets/VSelectionControl-DKOhc2zB.js.gz +0 -0
  390. codex/static_root/assets/VSlideGroup-zFz5_byd.e0e246b7acbb.js +0 -1
  391. codex/static_root/assets/VSlideGroup-zFz5_byd.e0e246b7acbb.js.br +0 -0
  392. codex/static_root/assets/VSlideGroup-zFz5_byd.e0e246b7acbb.js.gz +0 -0
  393. codex/static_root/assets/VSlideGroup-zFz5_byd.js +0 -1
  394. codex/static_root/assets/VSlideGroup-zFz5_byd.js.br +0 -0
  395. codex/static_root/assets/VSlideGroup-zFz5_byd.js.gz +0 -0
  396. codex/static_root/assets/VTable-FKMTcdkF.6c1eed84d25e.js.br +0 -0
  397. codex/static_root/assets/VTable-FKMTcdkF.6c1eed84d25e.js.gz +0 -0
  398. codex/static_root/assets/VTable-FKMTcdkF.js.br +0 -0
  399. codex/static_root/assets/VTable-FKMTcdkF.js.gz +0 -0
  400. codex/static_root/assets/VTextField-Dftcik85.cb2f1dda87e1.js.br +0 -0
  401. codex/static_root/assets/VTextField-Dftcik85.cb2f1dda87e1.js.gz +0 -0
  402. codex/static_root/assets/VTextField-Dftcik85.js.br +0 -0
  403. codex/static_root/assets/VTextField-Dftcik85.js.gz +0 -0
  404. codex/static_root/assets/VWindowItem-CYCwnt3s.28025dc36c6a.js.br +0 -0
  405. codex/static_root/assets/VWindowItem-CYCwnt3s.28025dc36c6a.js.gz +0 -0
  406. codex/static_root/assets/VWindowItem-CYCwnt3s.js.br +0 -0
  407. codex/static_root/assets/VWindowItem-CYCwnt3s.js.gz +0 -0
  408. codex/static_root/assets/admin-DH_DrB0F.dc45fb726e07.js +0 -1
  409. codex/static_root/assets/admin-DH_DrB0F.dc45fb726e07.js.br +0 -0
  410. codex/static_root/assets/admin-DH_DrB0F.dc45fb726e07.js.gz +0 -0
  411. codex/static_root/assets/admin-DH_DrB0F.js +0 -1
  412. codex/static_root/assets/admin-DH_DrB0F.js.br +0 -0
  413. codex/static_root/assets/admin-DH_DrB0F.js.gz +0 -0
  414. codex/static_root/assets/admin-drawer-panel-B2rmpAVA.a9e72fbfdadc.js +0 -30
  415. codex/static_root/assets/admin-drawer-panel-B2rmpAVA.a9e72fbfdadc.js.br +0 -0
  416. codex/static_root/assets/admin-drawer-panel-B2rmpAVA.a9e72fbfdadc.js.gz +0 -0
  417. codex/static_root/assets/admin-drawer-panel-B2rmpAVA.js +0 -30
  418. codex/static_root/assets/admin-drawer-panel-B2rmpAVA.js.br +0 -0
  419. codex/static_root/assets/admin-drawer-panel-B2rmpAVA.js.gz +0 -0
  420. codex/static_root/assets/admin-drawer-panel-BHdNPwzF.bd2c1d6148bb.css.br +0 -0
  421. codex/static_root/assets/admin-drawer-panel-BHdNPwzF.css.br +0 -0
  422. codex/static_root/assets/browser-CpppBvim.a1b5d4fe97b1.css +0 -1
  423. codex/static_root/assets/browser-CpppBvim.a1b5d4fe97b1.css.br +0 -0
  424. codex/static_root/assets/browser-CpppBvim.a1b5d4fe97b1.css.gz +0 -0
  425. codex/static_root/assets/browser-CpppBvim.css +0 -1
  426. codex/static_root/assets/browser-CpppBvim.css.br +0 -0
  427. codex/static_root/assets/browser-CpppBvim.css.gz +0 -0
  428. codex/static_root/assets/browser-lKU7rqLd.cdb86e625ed9.js +0 -1
  429. codex/static_root/assets/browser-lKU7rqLd.cdb86e625ed9.js.br +0 -0
  430. codex/static_root/assets/browser-lKU7rqLd.cdb86e625ed9.js.gz +0 -0
  431. codex/static_root/assets/browser-lKU7rqLd.js +0 -1
  432. codex/static_root/assets/browser-lKU7rqLd.js.br +0 -0
  433. codex/static_root/assets/browser-lKU7rqLd.js.gz +0 -0
  434. codex/static_root/assets/change-password-dialog-BIBG6Bk8.3583021c124a.js.br +0 -0
  435. codex/static_root/assets/change-password-dialog-BIBG6Bk8.3583021c124a.js.gz +0 -0
  436. codex/static_root/assets/change-password-dialog-BIBG6Bk8.js.br +0 -0
  437. codex/static_root/assets/change-password-dialog-BIBG6Bk8.js.gz +0 -0
  438. codex/static_root/assets/confirm-dialog-DARLmXRf.53fc6938fb8c.js.br +0 -0
  439. codex/static_root/assets/confirm-dialog-DARLmXRf.53fc6938fb8c.js.gz +0 -0
  440. codex/static_root/assets/confirm-dialog-DARLmXRf.js.br +0 -0
  441. codex/static_root/assets/confirm-dialog-DARLmXRf.js.gz +0 -0
  442. codex/static_root/assets/datetime-column-LpLgWpkf.16ce3324970f.js.br +0 -0
  443. codex/static_root/assets/datetime-column-LpLgWpkf.16ce3324970f.js.gz +0 -0
  444. codex/static_root/assets/datetime-column-LpLgWpkf.js.br +0 -0
  445. codex/static_root/assets/datetime-column-LpLgWpkf.js.gz +0 -0
  446. codex/static_root/assets/filter-jRB1Ob6r.6a559a53e805.js +0 -1
  447. codex/static_root/assets/filter-jRB1Ob6r.6a559a53e805.js.br +0 -0
  448. codex/static_root/assets/filter-jRB1Ob6r.6a559a53e805.js.gz +0 -0
  449. codex/static_root/assets/filter-jRB1Ob6r.js +0 -1
  450. codex/static_root/assets/filter-jRB1Ob6r.js.br +0 -0
  451. codex/static_root/assets/filter-jRB1Ob6r.js.gz +0 -0
  452. codex/static_root/assets/flag-tab-mYS2wg5e.17829c46cae9.js +0 -1
  453. codex/static_root/assets/flag-tab-mYS2wg5e.17829c46cae9.js.br +0 -0
  454. codex/static_root/assets/flag-tab-mYS2wg5e.17829c46cae9.js.gz +0 -0
  455. codex/static_root/assets/flag-tab-mYS2wg5e.js +0 -1
  456. codex/static_root/assets/flag-tab-mYS2wg5e.js.br +0 -0
  457. codex/static_root/assets/flag-tab-mYS2wg5e.js.gz +0 -0
  458. codex/static_root/assets/group-tab-MK1lcjUU.98406d5babdc.js.br +0 -0
  459. codex/static_root/assets/group-tab-MK1lcjUU.98406d5babdc.js.gz +0 -0
  460. codex/static_root/assets/group-tab-MK1lcjUU.js.br +0 -0
  461. codex/static_root/assets/group-tab-MK1lcjUU.js.gz +0 -0
  462. codex/static_root/assets/http-error-HFeYnF0n.a3c578a0265e.js +0 -1
  463. codex/static_root/assets/http-error-HFeYnF0n.a3c578a0265e.js.br +0 -0
  464. codex/static_root/assets/http-error-HFeYnF0n.a3c578a0265e.js.gz +0 -0
  465. codex/static_root/assets/http-error-HFeYnF0n.js +0 -1
  466. codex/static_root/assets/http-error-HFeYnF0n.js.br +0 -0
  467. codex/static_root/assets/http-error-HFeYnF0n.js.gz +0 -0
  468. codex/static_root/assets/index-DUjeNg4x.36d50c91b2c1.js +0 -1
  469. codex/static_root/assets/index-DUjeNg4x.36d50c91b2c1.js.br +0 -0
  470. codex/static_root/assets/index-DUjeNg4x.36d50c91b2c1.js.gz +0 -0
  471. codex/static_root/assets/index-DUjeNg4x.js +0 -1
  472. codex/static_root/assets/index-DUjeNg4x.js.br +0 -0
  473. codex/static_root/assets/index-DUjeNg4x.js.gz +0 -0
  474. codex/static_root/assets/library-tab-DYeEBYlT.a2a2ef088d1c.js.br +0 -0
  475. codex/static_root/assets/library-tab-DYeEBYlT.a2a2ef088d1c.js.gz +0 -0
  476. codex/static_root/assets/library-tab-DYeEBYlT.js.br +0 -0
  477. codex/static_root/assets/library-tab-DYeEBYlT.js.gz +0 -0
  478. codex/static_root/assets/main-gSW7TFDY.329223b148d4.js +0 -32
  479. codex/static_root/assets/main-gSW7TFDY.329223b148d4.js.br +0 -0
  480. codex/static_root/assets/main-gSW7TFDY.329223b148d4.js.gz +0 -0
  481. codex/static_root/assets/main-gSW7TFDY.js +0 -32
  482. codex/static_root/assets/main-gSW7TFDY.js.br +0 -0
  483. codex/static_root/assets/main-gSW7TFDY.js.gz +0 -0
  484. codex/static_root/assets/main-sK7HC5h4.6f04ddfc5f1a.css.br +0 -0
  485. codex/static_root/assets/main-sK7HC5h4.css.br +0 -0
  486. codex/static_root/assets/pagination-toolbar-ClZui9Zf.697d7ae11c21.css.br +0 -0
  487. codex/static_root/assets/pagination-toolbar-ClZui9Zf.697d7ae11c21.css.gz +0 -0
  488. codex/static_root/assets/pagination-toolbar-ClZui9Zf.css.br +0 -0
  489. codex/static_root/assets/pagination-toolbar-ClZui9Zf.css.gz +0 -0
  490. codex/static_root/assets/pagination-toolbar-Dlm70Bhs.8f23f8bd9a05.js +0 -1
  491. codex/static_root/assets/pagination-toolbar-Dlm70Bhs.8f23f8bd9a05.js.br +0 -0
  492. codex/static_root/assets/pagination-toolbar-Dlm70Bhs.8f23f8bd9a05.js.gz +0 -0
  493. codex/static_root/assets/pagination-toolbar-Dlm70Bhs.js +0 -1
  494. codex/static_root/assets/pagination-toolbar-Dlm70Bhs.js.br +0 -0
  495. codex/static_root/assets/pagination-toolbar-Dlm70Bhs.js.gz +0 -0
  496. codex/static_root/assets/pdf-doc-BTdS9hUz.7c966524280a.js +0 -35
  497. codex/static_root/assets/pdf-doc-BTdS9hUz.7c966524280a.js.br +0 -0
  498. codex/static_root/assets/pdf-doc-BTdS9hUz.7c966524280a.js.gz +0 -0
  499. codex/static_root/assets/pdf-doc-BTdS9hUz.js +0 -35
  500. codex/static_root/assets/pdf-doc-BTdS9hUz.js.br +0 -0
  501. codex/static_root/assets/pdf-doc-BTdS9hUz.js.gz +0 -0
  502. codex/static_root/assets/reader-BtSTIETq.f940f66c0e58.js +0 -2
  503. codex/static_root/assets/reader-BtSTIETq.f940f66c0e58.js.br +0 -0
  504. codex/static_root/assets/reader-BtSTIETq.f940f66c0e58.js.gz +0 -0
  505. codex/static_root/assets/reader-BtSTIETq.js +0 -2
  506. codex/static_root/assets/reader-BtSTIETq.js.br +0 -0
  507. codex/static_root/assets/reader-BtSTIETq.js.gz +0 -0
  508. codex/static_root/assets/reader-CF3xt6JG.19fad7f62450.css.br +0 -0
  509. codex/static_root/assets/reader-CF3xt6JG.19fad7f62450.css.gz +0 -0
  510. codex/static_root/assets/reader-CF3xt6JG.css.br +0 -0
  511. codex/static_root/assets/reader-CF3xt6JG.css.gz +0 -0
  512. codex/static_root/assets/relation-chips-C4Ob7ySi.95855a010f4a.js +0 -1
  513. codex/static_root/assets/relation-chips-C4Ob7ySi.95855a010f4a.js.br +0 -0
  514. codex/static_root/assets/relation-chips-C4Ob7ySi.95855a010f4a.js.gz +0 -0
  515. codex/static_root/assets/relation-chips-C4Ob7ySi.js +0 -1
  516. codex/static_root/assets/relation-chips-C4Ob7ySi.js.br +0 -0
  517. codex/static_root/assets/relation-chips-C4Ob7ySi.js.gz +0 -0
  518. codex/static_root/assets/settings-drawer-BJOfMtqA.6471a50fc05b.css.br +0 -0
  519. codex/static_root/assets/settings-drawer-BJOfMtqA.6471a50fc05b.css.gz +0 -0
  520. codex/static_root/assets/settings-drawer-BJOfMtqA.css.br +0 -0
  521. codex/static_root/assets/settings-drawer-BJOfMtqA.css.gz +0 -0
  522. codex/static_root/assets/settings-drawer-xSctoxZn.4ce8afcb879a.js +0 -2
  523. codex/static_root/assets/settings-drawer-xSctoxZn.4ce8afcb879a.js.br +0 -0
  524. codex/static_root/assets/settings-drawer-xSctoxZn.4ce8afcb879a.js.gz +0 -0
  525. codex/static_root/assets/settings-drawer-xSctoxZn.js +0 -2
  526. codex/static_root/assets/settings-drawer-xSctoxZn.js.br +0 -0
  527. codex/static_root/assets/settings-drawer-xSctoxZn.js.gz +0 -0
  528. codex/static_root/assets/stats-tab-C_uC_U7o.e6b014b6e8c6.js +0 -1
  529. codex/static_root/assets/stats-tab-C_uC_U7o.e6b014b6e8c6.js.br +0 -0
  530. codex/static_root/assets/stats-tab-C_uC_U7o.e6b014b6e8c6.js.gz +0 -0
  531. codex/static_root/assets/stats-tab-C_uC_U7o.js +0 -1
  532. codex/static_root/assets/stats-tab-C_uC_U7o.js.br +0 -0
  533. codex/static_root/assets/stats-tab-C_uC_U7o.js.gz +0 -0
  534. codex/static_root/assets/task-tab-VIpy1Ula.c07877250c88.js +0 -1
  535. codex/static_root/assets/task-tab-VIpy1Ula.c07877250c88.js.br +0 -0
  536. codex/static_root/assets/task-tab-VIpy1Ula.c07877250c88.js.gz +0 -0
  537. codex/static_root/assets/task-tab-VIpy1Ula.js +0 -1
  538. codex/static_root/assets/task-tab-VIpy1Ula.js.br +0 -0
  539. codex/static_root/assets/task-tab-VIpy1Ula.js.gz +0 -0
  540. codex/static_root/assets/to-case-kUm8NPpW.5b3369f511b8.js +0 -1
  541. codex/static_root/assets/to-case-kUm8NPpW.js +0 -1
  542. codex/static_root/assets/unauthorized-kEuFL5br.475729603aeb.js +0 -1
  543. codex/static_root/assets/unauthorized-kEuFL5br.475729603aeb.js.br +0 -0
  544. codex/static_root/assets/unauthorized-kEuFL5br.475729603aeb.js.gz +0 -0
  545. codex/static_root/assets/unauthorized-kEuFL5br.js +0 -1
  546. codex/static_root/assets/unauthorized-kEuFL5br.js.br +0 -0
  547. codex/static_root/assets/unauthorized-kEuFL5br.js.gz +0 -0
  548. codex/static_root/assets/user-tab-CZNFTTEI.f3940a75daae.js +0 -1
  549. codex/static_root/assets/user-tab-CZNFTTEI.f3940a75daae.js.br +0 -0
  550. codex/static_root/assets/user-tab-CZNFTTEI.f3940a75daae.js.gz +0 -0
  551. codex/static_root/assets/user-tab-CZNFTTEI.js +0 -1
  552. codex/static_root/assets/user-tab-CZNFTTEI.js.br +0 -0
  553. codex/static_root/assets/user-tab-CZNFTTEI.js.gz +0 -0
  554. codex/static_root/js/choices.23fedac2b9ba.json +0 -1
  555. codex/static_root/js/choices.23fedac2b9ba.json.br +0 -0
  556. codex/static_root/js/choices.23fedac2b9ba.json.gz +0 -0
  557. codex/static_root/manifest.6ef112683dae.json +0 -642
  558. codex/static_root/manifest.6ef112683dae.json.br +0 -0
  559. codex/static_root/manifest.6ef112683dae.json.gz +0 -0
  560. codex/views/browser/browser_breadcrumbs.py +0 -175
  561. codex/views/browser/const.py +0 -3
  562. {codex-1.6.0a5.dist-info → codex-1.6.0a7.dist-info}/LICENSE +0 -0
  563. {codex-1.6.0a5.dist-info → codex-1.6.0a7.dist-info}/WHEEL +0 -0
  564. {codex-1.6.0a5.dist-info → codex-1.6.0a7.dist-info}/entry_points.txt +0 -0
@@ -9,26 +9,27 @@ from codex.librarian.covers.create import CoverCreateMixin
9
9
  from codex.models import Comic
10
10
  from codex.views.opds.const import AUTHOR_ROLES, MimeType, Rel
11
11
  from codex.views.opds.util import get_contributors, get_m2m_objects
12
- from codex.views.opds.v2.links import HrefData, LinkData, LinksMixin
13
-
14
-
15
- class PublicationMixin(LinksMixin):
12
+ from codex.views.opds.v2.top_links import HrefData, LinkData, OPDS2TopLinksView
13
+
14
+ _MD_CONTRIBUTOR_MAP = MappingProxyType(
15
+ {
16
+ "author": AUTHOR_ROLES,
17
+ # "translator": {},
18
+ "editor": {"Editor"},
19
+ "artist": {"CoverArtist"},
20
+ # "illustrator": {},
21
+ "letterer": {"Letterer"},
22
+ "penciller": {"Penciller"},
23
+ "colorist": {"Colorist"},
24
+ "inker": {"Inker"},
25
+ }
26
+ )
27
+ _CONTRIBUTOR_ROLES = frozenset({x for s in _MD_CONTRIBUTOR_MAP.values() for x in s})
28
+
29
+
30
+ class OPDS2PublicationView(OPDS2TopLinksView):
16
31
  """Publication Methods for OPDS 2.0 feed."""
17
32
 
18
- _MD_CONTRIBUTOR_MAP = MappingProxyType(
19
- {
20
- "author": AUTHOR_ROLES,
21
- # "translator": {},
22
- "editor": {"Editor"},
23
- "artist": {"CoverArtist"},
24
- # "illustrator": {},
25
- "letterer": {"Letterer"},
26
- "penciller": {"Penciller"},
27
- "colorist": {"Colorist"},
28
- "inker": {"Inker"},
29
- }
30
- )
31
- _CONTRIBUTOR_ROLES = frozenset({x for s in _MD_CONTRIBUTOR_MAP.values() for x in s})
32
33
  is_opds_metadata = False
33
34
 
34
35
  def _get_big_image_link(self, obj, cover_pk):
@@ -106,9 +107,9 @@ class PublicationMixin(LinksMixin):
106
107
 
107
108
  def _publication_extended_metadata(self, md, obj):
108
109
  """Publication m2m metadata only on the metadata alternate link."""
109
- for key, roles in self._MD_CONTRIBUTOR_MAP.items():
110
+ for key, roles in _MD_CONTRIBUTOR_MAP.items():
110
111
  self._add_contributors(md, obj.ids, key, roles)
111
- if contributors := get_contributors(obj.ids, self._CONTRIBUTOR_ROLES, True):
112
+ if contributors := get_contributors(obj.ids, _CONTRIBUTOR_ROLES, True):
112
113
  md["contributor"] = contributors
113
114
 
114
115
  if m2m_objs := get_m2m_objects(obj.ids):
@@ -1,10 +1,10 @@
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, LinksMixin
4
+ from codex.views.opds.v2.links import HrefData, LinkData, OPDS2LinksView
5
5
 
6
6
 
7
- class TopLinksMixin(LinksMixin):
7
+ class OPDS2TopLinksView(OPDS2LinksView):
8
8
  """OPDS 2.0 top links section methods."""
9
9
 
10
10
  def _link_auth(self):
codex/views/public.py ADDED
@@ -0,0 +1,38 @@
1
+ """Public non-authenticated views."""
2
+
3
+ from rest_framework.generics import GenericAPIView
4
+ from rest_framework.mixins import RetrieveModelMixin
5
+ from rest_framework.parsers import JSONParser
6
+
7
+ from codex.logger.logging import get_logger
8
+ from codex.models import AdminFlag
9
+ from codex.serializers.auth import AuthAdminFlagsSerializer
10
+ from codex.serializers.choices import CHOICES
11
+
12
+ LOG = get_logger(__name__)
13
+ _ADMIN_FLAG_KEYS = frozenset(
14
+ {
15
+ AdminFlag.FlagChoices.NON_USERS.value,
16
+ AdminFlag.FlagChoices.REGISTRATION.value,
17
+ }
18
+ )
19
+
20
+
21
+ class AdminFlagsView(GenericAPIView, RetrieveModelMixin):
22
+ """Get admin flags relevant to auth."""
23
+
24
+ parser_classes = (JSONParser,)
25
+ serializer_class = AuthAdminFlagsSerializer
26
+ queryset = AdminFlag.objects.filter(key__in=_ADMIN_FLAG_KEYS).only("key", "on")
27
+
28
+ def get_object(self):
29
+ """Get admin flags."""
30
+ flags = {}
31
+ for obj in self.get_queryset(): # type: ignore
32
+ name = CHOICES["admin"]["adminFlags"][obj.key].lower().replace(" ", "_")
33
+ flags[name] = obj.on
34
+ return flags
35
+
36
+ def get(self, request, *args, **kwargs):
37
+ """Get admin flags relevant to auth."""
38
+ return self.retrieve(request, *args, **kwargs)
@@ -0,0 +1,101 @@
1
+ """Reader get Arcs methods."""
2
+
3
+ from types import MappingProxyType
4
+
5
+ from codex.models import AdminFlag
6
+ from codex.util import max_none
7
+ from codex.views.const import FOLDER_GROUP
8
+ from codex.views.reader.books import ReaderBooksView
9
+
10
+
11
+ class ReaderArcsView(ReaderBooksView):
12
+ """Reader get Arcs methods."""
13
+
14
+ def __init__(self, *args, **kwargs):
15
+ """Initialize instance vars."""
16
+ super().__init__(*args, **kwargs)
17
+ self.params: MappingProxyType = MappingProxyType({})
18
+
19
+ def _get_folder_arc(self, book):
20
+ """Create the folder arc."""
21
+ efv_flag = (
22
+ AdminFlag.objects.only("on")
23
+ .get(key=AdminFlag.FlagChoices.FOLDER_VIEW.value)
24
+ .on
25
+ )
26
+
27
+ if efv_flag:
28
+ folder = book.parent_folder
29
+ folder_arc = {
30
+ "group": FOLDER_GROUP,
31
+ "pks": (folder.pk,),
32
+ "name": folder.name,
33
+ "mtime": folder.updated_at,
34
+ }
35
+ else:
36
+ folder_arc = None
37
+ return folder_arc
38
+
39
+ def _get_series_arc(self, book):
40
+ """Create the series arc."""
41
+ series = book.series
42
+ if series:
43
+ arc_pks = self.get_series_pks_from_breadcrumbs()
44
+ if book.series.pk not in arc_pks:
45
+ arc_pks = (book.series.pk,)
46
+ arc = (
47
+ {
48
+ "group": "s",
49
+ "pks": arc_pks,
50
+ "name": series.name,
51
+ "mtime": series.updated_at,
52
+ }
53
+ if series
54
+ else None
55
+ )
56
+ else:
57
+ arc = None
58
+ return arc
59
+
60
+ def _get_story_arcs(self, book):
61
+ """Create story arcs."""
62
+ sas = []
63
+ for san in book.story_arc_numbers.all():
64
+ sa = san.story_arc
65
+ arc = {
66
+ "group": "a",
67
+ "pks": (sa.pk,),
68
+ "name": sa.name,
69
+ "mtime": sa.updated_at,
70
+ }
71
+ sas.append(arc)
72
+ return sorted(sas, key=lambda x: x["name"])
73
+
74
+ def get_arcs(self, book):
75
+ """Get all series/folder/story arcs."""
76
+ # create top arcs
77
+ folder_arc = self._get_folder_arc(book)
78
+ series_arc = self._get_series_arc(book)
79
+
80
+ # order top arcs
81
+ top_group = self.params.get("top_group")
82
+ if top_group == FOLDER_GROUP and folder_arc:
83
+ arc = folder_arc
84
+ other_arc = series_arc
85
+ else:
86
+ arc = series_arc
87
+ other_arc = folder_arc
88
+
89
+ arcs = []
90
+ arcs.append(arc)
91
+ if other_arc:
92
+ arcs.append(other_arc)
93
+
94
+ # story arcs
95
+ sas = self._get_story_arcs(book)
96
+ arcs += sas
97
+
98
+ max_mtime = None
99
+ for arc in arcs:
100
+ max_mtime = max_none(max_mtime, arc["mtime"])
101
+ return arcs, max_mtime
@@ -0,0 +1,199 @@
1
+ """Get Books methods."""
2
+
3
+ from copy import deepcopy
4
+ from typing import TYPE_CHECKING
5
+
6
+ from django.db.models import F, IntegerField, Value
7
+
8
+ from codex.models import Bookmark, Comic
9
+ from codex.views.bookmark import BookmarkBaseView
10
+ from codex.views.const import FOLDER_GROUP
11
+ from codex.views.mixins import SharedAnnotationsMixin
12
+ from codex.views.session import SessionView
13
+
14
+ if TYPE_CHECKING:
15
+ from collections.abc import Mapping
16
+
17
+ _MIN_CRUMB_WALKBACK_LEN = 3
18
+ _SETTINGS_ATTRS = ("fit_to", "two_pages", "reading_direction")
19
+ _COMIC_FIELDS = (
20
+ "file_type",
21
+ "issue_number",
22
+ "issue_suffix",
23
+ "page_count",
24
+ "series",
25
+ "volume",
26
+ "reading_direction",
27
+ "updated_at",
28
+ )
29
+
30
+
31
+ class ReaderBooksView(BookmarkBaseView, SessionView, SharedAnnotationsMixin):
32
+ """Get Books methods."""
33
+
34
+ def get_series_pks_from_breadcrumbs(self):
35
+ """Get Multi-Group pks from the breadcrumbs."""
36
+ if self.series_pks:
37
+ return self.series_pks
38
+ breadcrumbs = self.get_from_session(
39
+ "breadcrumbs", session_key=self.BROWSER_SESSION_KEY
40
+ )
41
+ if breadcrumbs:
42
+ crumb = breadcrumbs[-1]
43
+ crumb_group = crumb.get("group")
44
+ if crumb_group == "v" and len(breadcrumbs) >= _MIN_CRUMB_WALKBACK_LEN:
45
+ crumb = breadcrumbs[-2]
46
+ crumb_group = crumb.get("group")
47
+ if crumb_group == "s":
48
+ self.series_pks = crumb.get("pks", ())
49
+
50
+ return self.series_pks
51
+
52
+ def _get_reader_arc_pks(
53
+ self, arc, arc_pk_select_related, prefetch_related, arc_pk_rel
54
+ ):
55
+ """Get the nav filter."""
56
+ arc_pks = arc.get("pks", ())
57
+ if not arc_pks:
58
+ comic_pk = self.kwargs["pk"]
59
+ try:
60
+ arc_pk_qs = Comic.objects.filter(pk=comic_pk)
61
+ arc_pk_qs = arc_pk_qs.select_related(*arc_pk_select_related)
62
+ arc_pk_qs = arc_pk_qs.prefetch_related(*prefetch_related)
63
+ arc_pk = arc_pk_qs.values_list(arc_pk_rel, flat=True)[0]
64
+ except IndexError:
65
+ arc_pk = 0
66
+
67
+ if arc_pk_rel == "series__pk":
68
+ multi_arc_pks = self.get_series_pks_from_breadcrumbs()
69
+ if not arc_pk or arc_pk in multi_arc_pks:
70
+ arc_pks = multi_arc_pks
71
+ if not arc_pks:
72
+ arc_pks = (arc_pk,)
73
+
74
+ return arc_pks
75
+
76
+ def _get_comics_list(self):
77
+ """Get the reader naviation group filter."""
78
+ select_related = ("series", "volume")
79
+ prefetch_related = ()
80
+
81
+ arc: Mapping = self.params.get("arc", {}) # type: ignore
82
+
83
+ arc_group = arc.get("group", "s")
84
+ if arc_group == "a":
85
+ # for story arcs
86
+ rel = "story_arc_numbers__story_arc"
87
+ fields = _COMIC_FIELDS
88
+ arc_pk_rel = "story_arc_numbers__story_arc__pk"
89
+ prefetch_related = (*prefetch_related, "story_arc_numbers__story_arc")
90
+ arc_index = F("story_arc_numbers__number")
91
+ ordering = ("arc_index", "date")
92
+ arc_pk_select_related = ()
93
+ elif arc_group == FOLDER_GROUP:
94
+ # folder mode
95
+ rel = "parent_folder"
96
+ fields = (*_COMIC_FIELDS, "parent_folder")
97
+ arc_pk_rel = "parent_folder__pk"
98
+ select_related = (*select_related, "parent_folder")
99
+ arc_index = Value(None, IntegerField())
100
+ ordering = ("path", "pk")
101
+ arc_pk_select_related = ("parent_folder",)
102
+ else:
103
+ # browser mode.
104
+ rel = "series"
105
+ fields = _COMIC_FIELDS
106
+ arc_pk_rel = "series__pk"
107
+ arc_index = Value(None, IntegerField())
108
+ ordering = ()
109
+ arc_pk_select_related = ("series",)
110
+
111
+ arc_pks = self._get_reader_arc_pks(
112
+ arc,
113
+ arc_pk_select_related,
114
+ prefetch_related,
115
+ arc_pk_rel,
116
+ )
117
+ nav_filter = {f"{rel}__in": arc_pks}
118
+ group_acl_filter = self.get_group_acl_filter(Comic)
119
+
120
+ qs = (
121
+ Comic.objects.filter(group_acl_filter)
122
+ .filter(**nav_filter)
123
+ .select_related(*select_related)
124
+ .prefetch_related(*prefetch_related)
125
+ .only(*fields)
126
+ .annotate(
127
+ issue_count=F("volume__issue_count"),
128
+ )
129
+ .annotate(
130
+ arc_pk=F(arc_pk_rel),
131
+ arc_index=arc_index,
132
+ )
133
+ .annotate(mtime=F("updated_at"))
134
+ )
135
+ qs = self.annotate_group_names(qs, Comic)
136
+ if arc_group == "s":
137
+ show = deepcopy(
138
+ self.get_from_session("show", session_key=self.BROWSER_SESSION_KEY)
139
+ )
140
+ show.pop("p", None)
141
+ show.pop("i", None)
142
+ qs, comic_sort_names = self.alias_sort_names(
143
+ qs, Comic, pks=arc_pks, model_group="i", show=show
144
+ )
145
+ ordering = (
146
+ *comic_sort_names,
147
+ "issue_number",
148
+ "issue_suffix",
149
+ "sort_name",
150
+ )
151
+ return qs.order_by(*ordering), arc_group
152
+
153
+ def _append_with_settings(self, book, bookmark_filter):
154
+ """Append bookmark to book list."""
155
+ book.settings = (
156
+ Bookmark.objects.filter(**bookmark_filter, comic=book)
157
+ .only(*_SETTINGS_ATTRS)
158
+ .first()
159
+ )
160
+ return book
161
+
162
+ def get_book_collection(self):
163
+ """Get the -1, +1 window around the current issue.
164
+
165
+ Uses iteration in python. There are some complicated ways of
166
+ doing this with __gt[0] & __lt[0] in the db, but I think they
167
+ might be even more expensive.
168
+
169
+ Yields 1 to 3 books
170
+ """
171
+ comics, arc_group = self._get_comics_list()
172
+ bookmark_filter = self.get_bookmark_filter()
173
+ books = {}
174
+ prev_book = None
175
+ pk = self.kwargs.get("pk")
176
+ for index, book in enumerate(comics):
177
+ if books:
178
+ # after match set next comic and break
179
+ books["next"] = self._append_with_settings(book, bookmark_filter)
180
+ break
181
+ if book.pk == pk:
182
+ # first match. set previous and current comic
183
+ if prev_book:
184
+ books["prev"] = self._append_with_settings(
185
+ prev_book, bookmark_filter
186
+ )
187
+ # create extra current book attrs:
188
+ if book.arc_index is None: # type: ignore
189
+ book.arc_index = index + 1 # type: ignore
190
+ book.filename = book.get_filename() # type: ignore
191
+ book.arc_group = arc_group
192
+ book.arc_count = comics.count()
193
+ books["current"] = self._append_with_settings(book, bookmark_filter)
194
+ else:
195
+ # Haven't matched yet, so set the previous comic
196
+ prev_book = book
197
+ return books
198
+
199
+ #####
@@ -1,7 +1,5 @@
1
1
  """Views for reading comic books."""
2
2
 
3
- from typing import ClassVar
4
-
5
3
  from comicbox.box import Comicbox
6
4
  from django.http import HttpResponse
7
5
  from drf_spectacular.types import OpenApiTypes
@@ -11,12 +9,11 @@ from rest_framework.negotiation import BaseContentNegotiation
11
9
 
12
10
  from codex.logger.logging import get_logger
13
11
  from codex.models import Comic
14
- from codex.views.auth import IsAuthenticatedOrEnabledNonUsers
15
12
  from codex.views.bookmark import BookmarkBaseView
16
13
  from codex.views.const import FALSY
17
14
 
18
15
  LOG = get_logger(__name__)
19
- PDF_MIME_TYPE = "application/pdf"
16
+ _PDF_MIME_TYPE = "application/pdf"
20
17
 
21
18
 
22
19
  class IgnoreClientContentNegotiation(BaseContentNegotiation):
@@ -43,7 +40,6 @@ class ReaderPageView(BookmarkBaseView):
43
40
  X_MOZ_PRE_HEADERS = frozenset({"prefetch", "preload", "prerender", "subresource"})
44
41
  content_type = "image/jpeg"
45
42
  content_negotiation_class = IgnoreClientContentNegotiation # type: ignore
46
- permission_classes: ClassVar[list] = [IsAuthenticatedOrEnabledNonUsers] # type:ignore
47
43
 
48
44
  def _update_bookmark(self):
49
45
  """Update the bookmark if the bookmark param was passed."""
@@ -67,7 +63,7 @@ class ReaderPageView(BookmarkBaseView):
67
63
  page = self.kwargs.get("page")
68
64
  to_pixmap = self.request.GET.get("pixmap", "").lower() not in FALSY
69
65
  if comic.file_type == Comic.FileType.PDF.value and not to_pixmap:
70
- content_type = PDF_MIME_TYPE
66
+ content_type = _PDF_MIME_TYPE
71
67
  else:
72
68
  content_type = self.content_type
73
69
  with Comicbox(comic.path) as cb:
@@ -81,7 +77,7 @@ class ReaderPageView(BookmarkBaseView):
81
77
  ],
82
78
  responses={
83
79
  (200, content_type): OpenApiTypes.BINARY,
84
- (200, PDF_MIME_TYPE): OpenApiTypes.BINARY,
80
+ (200, _PDF_MIME_TYPE): OpenApiTypes.BINARY,
85
81
  },
86
82
  )
87
83
  def get(self, *_args, **_kwargs):