codex 1.7.0a0__py3-none-any.whl → 1.7.0a2__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.
- codex/choices.py +424 -0
- codex/choices_to_json.py +122 -0
- codex/db.py +31 -15
- codex/exceptions.py +2 -3
- codex/librarian/bookmark/__init__.py +1 -0
- codex/librarian/bookmark/bookmarkd.py +38 -0
- codex/librarian/bookmark/tasks.py +19 -0
- codex/librarian/bookmark/update.py +154 -0
- codex/librarian/covers/coverd.py +3 -4
- codex/librarian/covers/create.py +8 -7
- codex/librarian/covers/path.py +1 -2
- codex/librarian/covers/purge.py +2 -2
- codex/librarian/janitor/integrity.py +1 -0
- codex/librarian/librariand.py +5 -0
- codex/librarian/watchdog/emitter.py +21 -19
- codex/librarian/watchdog/event_batcherd.py +0 -1
- codex/migrations/0030_nocase_collation_day_month_indexes_status_types.py +4 -0
- codex/models/admin.py +0 -5
- codex/models/functions.py +6 -5
- codex/models/query.py +6 -0
- codex/run.py +11 -9
- codex/serializers/admin/tasks.py +2 -2
- codex/serializers/browser/mixins.py +18 -14
- codex/serializers/browser/settings.py +4 -4
- codex/serializers/fields.py +9 -5
- codex/startup.py +6 -4
- codex/static_root/assets/VCheckbox-CCOzQpCw.a65ad95bd21a.js +1 -0
- codex/static_root/assets/VCheckbox-CCOzQpCw.a65ad95bd21a.js.br +0 -0
- codex/static_root/assets/VCheckbox-CCOzQpCw.a65ad95bd21a.js.gz +0 -0
- codex/static_root/assets/VCheckbox-CCOzQpCw.js +1 -0
- codex/static_root/assets/VCheckbox-CCOzQpCw.js.br +0 -0
- codex/static_root/assets/VCheckbox-CCOzQpCw.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-DnBH3a96.876fda35b85a.js +1 -0
- codex/static_root/assets/VCheckboxBtn-DnBH3a96.876fda35b85a.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DnBH3a96.876fda35b85a.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-DnBH3a96.js +1 -0
- codex/static_root/assets/VCheckboxBtn-DnBH3a96.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DnBH3a96.js.gz +0 -0
- codex/static_root/assets/VCombobox-DwwoR4yO.e7a4db7ab7f0.js +1 -0
- codex/static_root/assets/VCombobox-DwwoR4yO.e7a4db7ab7f0.js.br +0 -0
- codex/static_root/assets/VCombobox-DwwoR4yO.e7a4db7ab7f0.js.gz +0 -0
- codex/static_root/assets/VCombobox-DwwoR4yO.js +1 -0
- codex/static_root/assets/VCombobox-DwwoR4yO.js.br +0 -0
- codex/static_root/assets/VCombobox-DwwoR4yO.js.gz +0 -0
- codex/static_root/assets/VDialog-CSvrKKb2.css +1 -0
- codex/static_root/assets/VDialog-CSvrKKb2.css.br +0 -0
- codex/static_root/assets/VDialog-CSvrKKb2.css.gz +0 -0
- codex/static_root/assets/VDialog-CSvrKKb2.fd4d50904b17.css +1 -0
- codex/static_root/assets/VDialog-CSvrKKb2.fd4d50904b17.css.br +0 -0
- codex/static_root/assets/VDialog-CSvrKKb2.fd4d50904b17.css.gz +0 -0
- codex/static_root/assets/VDialog-DbN2FfmF.b2843f79d90f.js +1 -0
- codex/static_root/assets/VDialog-DbN2FfmF.b2843f79d90f.js.br +0 -0
- codex/static_root/assets/VDialog-DbN2FfmF.b2843f79d90f.js.gz +0 -0
- codex/static_root/assets/VDialog-DbN2FfmF.js +1 -0
- codex/static_root/assets/VDialog-DbN2FfmF.js.br +0 -0
- codex/static_root/assets/VDialog-DbN2FfmF.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-CBPnoy7O.212f4cad7d78.js +1 -0
- codex/static_root/assets/VExpansionPanels-CBPnoy7O.212f4cad7d78.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-CBPnoy7O.212f4cad7d78.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-CBPnoy7O.js +1 -0
- codex/static_root/assets/VExpansionPanels-CBPnoy7O.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-CBPnoy7O.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-C7Zu_Eup.b42735892aec.js +1 -0
- codex/static_root/assets/VRadioGroup-C7Zu_Eup.b42735892aec.js.br +0 -0
- codex/static_root/assets/VRadioGroup-C7Zu_Eup.b42735892aec.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-C7Zu_Eup.js +1 -0
- codex/static_root/assets/VRadioGroup-C7Zu_Eup.js.br +0 -0
- codex/static_root/assets/VRadioGroup-C7Zu_Eup.js.gz +0 -0
- codex/static_root/assets/VSelect-BTy7SKk0.dee138de5dd0.js +1 -0
- codex/static_root/assets/VSelect-BTy7SKk0.dee138de5dd0.js.br +0 -0
- codex/static_root/assets/VSelect-BTy7SKk0.dee138de5dd0.js.gz +0 -0
- codex/static_root/assets/VSelect-BTy7SKk0.js +1 -0
- codex/static_root/assets/VSelect-BTy7SKk0.js.br +0 -0
- codex/static_root/assets/VSelect-BTy7SKk0.js.gz +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css +1 -0
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.br +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.gz +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.css +1 -0
- codex/static_root/assets/VSelect-DLu8bpcs.css.br +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.css.gz +0 -0
- codex/static_root/assets/VSelectionControl-B42mmzLA.bf64d259ddef.js +1 -0
- codex/static_root/assets/VSelectionControl-B42mmzLA.bf64d259ddef.js.br +0 -0
- codex/static_root/assets/VSelectionControl-B42mmzLA.bf64d259ddef.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-B42mmzLA.js +1 -0
- codex/static_root/assets/VSelectionControl-B42mmzLA.js.br +0 -0
- codex/static_root/assets/VSelectionControl-B42mmzLA.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css +1 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.br +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.gz +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css +1 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css.br +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css.gz +0 -0
- codex/static_root/assets/VSlideGroup-BtfHoWCn.33e2bd94e34a.js +1 -0
- codex/static_root/assets/VSlideGroup-BtfHoWCn.33e2bd94e34a.js.br +0 -0
- codex/static_root/assets/VSlideGroup-BtfHoWCn.33e2bd94e34a.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-BtfHoWCn.js +1 -0
- codex/static_root/assets/VSlideGroup-BtfHoWCn.js.br +0 -0
- codex/static_root/assets/VSlideGroup-BtfHoWCn.js.gz +0 -0
- codex/static_root/assets/VTable-R3X0iPjV.ee07d9c2ca5f.js +1 -0
- codex/static_root/assets/VTable-R3X0iPjV.ee07d9c2ca5f.js.br +0 -0
- codex/static_root/assets/VTable-R3X0iPjV.ee07d9c2ca5f.js.gz +0 -0
- codex/static_root/assets/VTable-R3X0iPjV.js +1 -0
- codex/static_root/assets/VTable-R3X0iPjV.js.br +0 -0
- codex/static_root/assets/VTable-R3X0iPjV.js.gz +0 -0
- codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css +1 -0
- codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css.br +0 -0
- codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css.gz +0 -0
- codex/static_root/assets/VTextField-BnCEPZIq.css +1 -0
- codex/static_root/assets/VTextField-BnCEPZIq.css.br +0 -0
- codex/static_root/assets/VTextField-BnCEPZIq.css.gz +0 -0
- codex/static_root/assets/VTextField-D9pqgz_R.47beb9e7e547.js +1 -0
- codex/static_root/assets/VTextField-D9pqgz_R.47beb9e7e547.js.br +0 -0
- codex/static_root/assets/VTextField-D9pqgz_R.47beb9e7e547.js.gz +0 -0
- codex/static_root/assets/VTextField-D9pqgz_R.js +1 -0
- codex/static_root/assets/VTextField-D9pqgz_R.js.br +0 -0
- codex/static_root/assets/VTextField-D9pqgz_R.js.gz +0 -0
- codex/static_root/assets/VWindowItem-DHTDdYfK.f6bf6b893442.js +1 -0
- codex/static_root/assets/VWindowItem-DHTDdYfK.f6bf6b893442.js.br +0 -0
- codex/static_root/assets/VWindowItem-DHTDdYfK.f6bf6b893442.js.gz +0 -0
- codex/static_root/assets/VWindowItem-DHTDdYfK.js +1 -0
- codex/static_root/assets/VWindowItem-DHTDdYfK.js.br +0 -0
- codex/static_root/assets/VWindowItem-DHTDdYfK.js.gz +0 -0
- codex/static_root/assets/admin-CIWyRJnH.dde0ee029f08.js +1 -0
- codex/static_root/assets/admin-CIWyRJnH.dde0ee029f08.js.br +0 -0
- codex/static_root/assets/admin-CIWyRJnH.dde0ee029f08.js.gz +0 -0
- codex/static_root/assets/admin-CIWyRJnH.js +1 -0
- codex/static_root/assets/admin-CIWyRJnH.js.br +0 -0
- codex/static_root/assets/admin-CIWyRJnH.js.gz +0 -0
- codex/static_root/assets/{admin-CWEjaFr5.7d4523387384.css → admin-DJ7pIXDQ.css} +1 -1
- codex/static_root/assets/admin-DJ7pIXDQ.css.br +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.css.gz +0 -0
- codex/static_root/assets/{admin-CWEjaFr5.css → admin-DJ7pIXDQ.e2a77af73ef2.css} +1 -1
- codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.br +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.gz +0 -0
- codex/static_root/assets/admin-menu-B9bzD6hV.c13b7df2ff57.css +1 -0
- codex/static_root/assets/admin-menu-B9bzD6hV.c13b7df2ff57.css.br +0 -0
- codex/static_root/assets/admin-menu-B9bzD6hV.c13b7df2ff57.css.gz +0 -0
- codex/static_root/assets/admin-menu-B9bzD6hV.css +1 -0
- codex/static_root/assets/admin-menu-B9bzD6hV.css.br +0 -0
- codex/static_root/assets/admin-menu-B9bzD6hV.css.gz +0 -0
- codex/static_root/assets/admin-menu-BHOUwxhf.1ed26b58fb9f.js +1 -0
- codex/static_root/assets/admin-menu-BHOUwxhf.1ed26b58fb9f.js.br +0 -0
- codex/static_root/assets/admin-menu-BHOUwxhf.1ed26b58fb9f.js.gz +0 -0
- codex/static_root/assets/admin-menu-BHOUwxhf.js +1 -0
- codex/static_root/assets/admin-menu-BHOUwxhf.js.br +0 -0
- codex/static_root/assets/admin-menu-BHOUwxhf.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-DHIl0C8k.85a213c96423.js +1 -0
- codex/static_root/assets/admin-settings-button-progress-DHIl0C8k.85a213c96423.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-DHIl0C8k.85a213c96423.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-DHIl0C8k.js +1 -0
- codex/static_root/assets/admin-settings-button-progress-DHIl0C8k.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-DHIl0C8k.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-DUUQfVsZ.2548c49a853e.css +1 -0
- codex/static_root/assets/admin-settings-button-progress-DUUQfVsZ.css +1 -0
- codex/static_root/assets/browser-6T4uwUjJ.7dd4a7f74df6.js +1 -0
- codex/static_root/assets/browser-6T4uwUjJ.7dd4a7f74df6.js.br +0 -0
- codex/static_root/assets/browser-6T4uwUjJ.7dd4a7f74df6.js.gz +0 -0
- codex/static_root/assets/browser-6T4uwUjJ.js +1 -0
- codex/static_root/assets/browser-6T4uwUjJ.js.br +0 -0
- codex/static_root/assets/browser-6T4uwUjJ.js.gz +0 -0
- codex/static_root/assets/browser-Br5CorL4.6e2a416309d5.css +1 -0
- codex/static_root/assets/browser-Br5CorL4.6e2a416309d5.css.br +0 -0
- codex/static_root/assets/browser-Br5CorL4.6e2a416309d5.css.gz +0 -0
- codex/static_root/assets/browser-Br5CorL4.css +1 -0
- codex/static_root/assets/browser-Br5CorL4.css.br +0 -0
- codex/static_root/assets/browser-Br5CorL4.css.gz +0 -0
- codex/static_root/assets/change-password-dialog-BfiQBpUn.48db4c906920.js +1 -0
- codex/static_root/assets/change-password-dialog-BfiQBpUn.48db4c906920.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BfiQBpUn.48db4c906920.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-BfiQBpUn.js +1 -0
- codex/static_root/assets/change-password-dialog-BfiQBpUn.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BfiQBpUn.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css +1 -0
- codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css.br +0 -0
- codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css.gz +0 -0
- codex/static_root/assets/change-password-dialog-DrIXdKUC.css +1 -0
- codex/static_root/assets/change-password-dialog-DrIXdKUC.css.br +0 -0
- codex/static_root/assets/change-password-dialog-DrIXdKUC.css.gz +0 -0
- codex/static_root/assets/confirm-dialog-B7w6z2rf.472011c06253.css +1 -0
- codex/static_root/assets/confirm-dialog-B7w6z2rf.css +1 -0
- codex/static_root/assets/confirm-dialog-Iyuhxfyi.cf28325e58b7.js +1 -0
- codex/static_root/assets/confirm-dialog-Iyuhxfyi.cf28325e58b7.js.br +0 -0
- codex/static_root/assets/confirm-dialog-Iyuhxfyi.cf28325e58b7.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-Iyuhxfyi.js +1 -0
- codex/static_root/assets/confirm-dialog-Iyuhxfyi.js.br +0 -0
- codex/static_root/assets/confirm-dialog-Iyuhxfyi.js.gz +0 -0
- codex/static_root/assets/datetime-column-Dnxh9sRh.b6a92a6bcce9.js +1 -0
- codex/static_root/assets/datetime-column-Dnxh9sRh.b6a92a6bcce9.js.br +0 -0
- codex/static_root/assets/datetime-column-Dnxh9sRh.b6a92a6bcce9.js.gz +0 -0
- codex/static_root/assets/datetime-column-Dnxh9sRh.js +1 -0
- codex/static_root/assets/datetime-column-Dnxh9sRh.js.br +0 -0
- codex/static_root/assets/datetime-column-Dnxh9sRh.js.gz +0 -0
- codex/static_root/assets/filter-CmOjoKbH.ea79c4727d92.js +1 -0
- codex/static_root/assets/filter-CmOjoKbH.ea79c4727d92.js.br +0 -0
- codex/static_root/assets/filter-CmOjoKbH.ea79c4727d92.js.gz +0 -0
- codex/static_root/assets/filter-CmOjoKbH.js +1 -0
- codex/static_root/assets/filter-CmOjoKbH.js.br +0 -0
- codex/static_root/assets/filter-CmOjoKbH.js.gz +0 -0
- codex/static_root/assets/flag-tab-1PeNvDA9.2fc60db57915.js +1 -0
- codex/static_root/assets/flag-tab-1PeNvDA9.2fc60db57915.js.br +0 -0
- codex/static_root/assets/flag-tab-1PeNvDA9.2fc60db57915.js.gz +0 -0
- codex/static_root/assets/flag-tab-1PeNvDA9.js +1 -0
- codex/static_root/assets/flag-tab-1PeNvDA9.js.br +0 -0
- codex/static_root/assets/flag-tab-1PeNvDA9.js.gz +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css +1 -0
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.br +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.gz +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.css +1 -0
- codex/static_root/assets/flag-tab-CqWovuBu.css.br +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.css.gz +0 -0
- codex/static_root/assets/group-tab-DkIN1Heu.948e907b1e6b.css +1 -0
- codex/static_root/assets/group-tab-DkIN1Heu.948e907b1e6b.css.br +0 -0
- codex/static_root/assets/group-tab-DkIN1Heu.948e907b1e6b.css.gz +0 -0
- codex/static_root/assets/group-tab-DkIN1Heu.css +1 -0
- codex/static_root/assets/group-tab-DkIN1Heu.css.br +0 -0
- codex/static_root/assets/group-tab-DkIN1Heu.css.gz +0 -0
- codex/static_root/assets/group-tab-Zl_C7M7Z.dbeed7f2d08f.js +1 -0
- codex/static_root/assets/group-tab-Zl_C7M7Z.dbeed7f2d08f.js.br +0 -0
- codex/static_root/assets/group-tab-Zl_C7M7Z.dbeed7f2d08f.js.gz +0 -0
- codex/static_root/assets/group-tab-Zl_C7M7Z.js +1 -0
- codex/static_root/assets/group-tab-Zl_C7M7Z.js.br +0 -0
- codex/static_root/assets/group-tab-Zl_C7M7Z.js.gz +0 -0
- codex/static_root/assets/http-error-YNrrsTPg.73e9978dc0ce.js +1 -0
- codex/static_root/assets/http-error-YNrrsTPg.73e9978dc0ce.js.br +0 -0
- codex/static_root/assets/http-error-YNrrsTPg.73e9978dc0ce.js.gz +0 -0
- codex/static_root/assets/http-error-YNrrsTPg.js +1 -0
- codex/static_root/assets/http-error-YNrrsTPg.js.br +0 -0
- codex/static_root/assets/http-error-YNrrsTPg.js.gz +0 -0
- codex/static_root/assets/index-CL_6g4tJ.523d7b3d350f.css +1 -0
- codex/static_root/assets/index-CL_6g4tJ.523d7b3d350f.css.br +0 -0
- codex/static_root/assets/index-CL_6g4tJ.523d7b3d350f.css.gz +0 -0
- codex/static_root/assets/index-CL_6g4tJ.css +1 -0
- codex/static_root/assets/index-CL_6g4tJ.css.br +0 -0
- codex/static_root/assets/index-CL_6g4tJ.css.gz +0 -0
- codex/static_root/assets/index-j5K-C_JC.65c2dc5af141.js +1 -0
- codex/static_root/assets/index-j5K-C_JC.65c2dc5af141.js.br +0 -0
- codex/static_root/assets/index-j5K-C_JC.65c2dc5af141.js.gz +0 -0
- codex/static_root/assets/index-j5K-C_JC.js +1 -0
- codex/static_root/assets/index-j5K-C_JC.js.br +0 -0
- codex/static_root/assets/index-j5K-C_JC.js.gz +0 -0
- codex/static_root/assets/library-tab-CxKs8G-K.c6bfd6d53b17.js +1 -0
- codex/static_root/assets/library-tab-CxKs8G-K.c6bfd6d53b17.js.br +0 -0
- codex/static_root/assets/library-tab-CxKs8G-K.c6bfd6d53b17.js.gz +0 -0
- codex/static_root/assets/library-tab-CxKs8G-K.js +1 -0
- codex/static_root/assets/library-tab-CxKs8G-K.js.br +0 -0
- codex/static_root/assets/library-tab-CxKs8G-K.js.gz +0 -0
- codex/static_root/assets/{library-tab-Bh7ErAk7.7c44200ee727.css → library-tab-Wew8YOLv.0c1780a6b68e.css} +1 -1
- codex/static_root/assets/library-tab-Wew8YOLv.0c1780a6b68e.css.br +0 -0
- codex/static_root/assets/library-tab-Wew8YOLv.0c1780a6b68e.css.gz +0 -0
- codex/static_root/assets/{library-tab-Bh7ErAk7.css → library-tab-Wew8YOLv.css} +1 -1
- codex/static_root/assets/library-tab-Wew8YOLv.css.br +0 -0
- codex/static_root/assets/library-tab-Wew8YOLv.css.gz +0 -0
- codex/static_root/assets/main-H14uUxuN.cc1511f0f146.js +35 -0
- codex/static_root/assets/main-H14uUxuN.cc1511f0f146.js.br +0 -0
- codex/static_root/assets/main-H14uUxuN.cc1511f0f146.js.gz +0 -0
- codex/static_root/assets/main-H14uUxuN.js +35 -0
- codex/static_root/assets/main-H14uUxuN.js.br +0 -0
- codex/static_root/assets/main-H14uUxuN.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-DcRg28qt.ca9cdb9619ff.js +1 -0
- codex/static_root/assets/pager-full-pdf-DcRg28qt.ca9cdb9619ff.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-DcRg28qt.ca9cdb9619ff.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-DcRg28qt.js +1 -0
- codex/static_root/assets/pager-full-pdf-DcRg28qt.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-DcRg28qt.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-BgoV4zqc.ab5fa1be17a3.js +1 -0
- codex/static_root/assets/pagination-toolbar-BgoV4zqc.ab5fa1be17a3.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-BgoV4zqc.ab5fa1be17a3.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-BgoV4zqc.js +1 -0
- codex/static_root/assets/pagination-toolbar-BgoV4zqc.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-BgoV4zqc.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-BcRNpoaW.882f6e967869.js → pdf-doc-BbuJd_VS.225d8590d020.js} +3 -3
- codex/static_root/assets/pdf-doc-BbuJd_VS.225d8590d020.js.br +0 -0
- codex/static_root/assets/pdf-doc-BbuJd_VS.225d8590d020.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-BcRNpoaW.js → pdf-doc-BbuJd_VS.js} +3 -3
- codex/static_root/assets/pdf-doc-BbuJd_VS.js.br +0 -0
- codex/static_root/assets/pdf-doc-BbuJd_VS.js.gz +0 -0
- codex/static_root/assets/reader-DORea4Al.d8e756bb0027.js +2 -0
- codex/static_root/assets/reader-DORea4Al.d8e756bb0027.js.br +0 -0
- codex/static_root/assets/reader-DORea4Al.d8e756bb0027.js.gz +0 -0
- codex/static_root/assets/reader-DORea4Al.js +2 -0
- codex/static_root/assets/reader-DORea4Al.js.br +0 -0
- codex/static_root/assets/reader-DORea4Al.js.gz +0 -0
- codex/static_root/assets/{reader-DveZZr9x.7b21b9f8f628.css → reader-OpKdTZ_B.css} +1 -1
- codex/static_root/assets/reader-OpKdTZ_B.css.br +0 -0
- codex/static_root/assets/reader-OpKdTZ_B.css.gz +0 -0
- codex/static_root/assets/{reader-DveZZr9x.css → reader-OpKdTZ_B.ebd1512b7014.css} +1 -1
- codex/static_root/assets/reader-OpKdTZ_B.ebd1512b7014.css.br +0 -0
- codex/static_root/assets/reader-OpKdTZ_B.ebd1512b7014.css.gz +0 -0
- codex/static_root/assets/relation-chips-kqofGdNg.0c7a53962f2b.js +1 -0
- codex/static_root/assets/relation-chips-kqofGdNg.0c7a53962f2b.js.br +0 -0
- codex/static_root/assets/relation-chips-kqofGdNg.0c7a53962f2b.js.gz +0 -0
- codex/static_root/assets/relation-chips-kqofGdNg.js +1 -0
- codex/static_root/assets/relation-chips-kqofGdNg.js.br +0 -0
- codex/static_root/assets/relation-chips-kqofGdNg.js.gz +0 -0
- codex/static_root/assets/settings-drawer-C-hgtHJt.0eaf7e00ee9b.js +2 -0
- codex/static_root/assets/settings-drawer-C-hgtHJt.0eaf7e00ee9b.js.br +0 -0
- codex/static_root/assets/settings-drawer-C-hgtHJt.0eaf7e00ee9b.js.gz +0 -0
- codex/static_root/assets/settings-drawer-C-hgtHJt.js +2 -0
- codex/static_root/assets/settings-drawer-C-hgtHJt.js.br +0 -0
- codex/static_root/assets/settings-drawer-C-hgtHJt.js.gz +0 -0
- codex/static_root/assets/{stats-tab-DpfGsVX3.1cb66f2649a9.css → stats-tab-BAYTqQNg.5f715428c394.css} +1 -1
- codex/static_root/assets/stats-tab-BAYTqQNg.5f715428c394.css.br +0 -0
- codex/static_root/assets/stats-tab-BAYTqQNg.5f715428c394.css.gz +0 -0
- codex/static_root/assets/{stats-tab-DpfGsVX3.css → stats-tab-BAYTqQNg.css} +1 -1
- codex/static_root/assets/stats-tab-BAYTqQNg.css.br +0 -0
- codex/static_root/assets/stats-tab-BAYTqQNg.css.gz +0 -0
- codex/static_root/assets/stats-tab-C7iJCFa5.f1039eba03c2.js +1 -0
- codex/static_root/assets/stats-tab-C7iJCFa5.f1039eba03c2.js.br +0 -0
- codex/static_root/assets/stats-tab-C7iJCFa5.f1039eba03c2.js.gz +0 -0
- codex/static_root/assets/stats-tab-C7iJCFa5.js +1 -0
- codex/static_root/assets/stats-tab-C7iJCFa5.js.br +0 -0
- codex/static_root/assets/stats-tab-C7iJCFa5.js.gz +0 -0
- codex/static_root/assets/task-tab--cXi48kg.5dfd6890a1c2.css +1 -0
- codex/static_root/assets/{task-tab-1XiWn9xP.06cb8e1b794d.css.br → task-tab--cXi48kg.5dfd6890a1c2.css.br} +1 -1
- codex/static_root/assets/task-tab--cXi48kg.5dfd6890a1c2.css.gz +0 -0
- codex/static_root/assets/task-tab--cXi48kg.css +1 -0
- codex/static_root/assets/{task-tab-1XiWn9xP.css.br → task-tab--cXi48kg.css.br} +1 -1
- codex/static_root/assets/task-tab--cXi48kg.css.gz +0 -0
- codex/static_root/assets/task-tab-Drfz5uaT.0b387dcd4f5a.js +1 -0
- codex/static_root/assets/task-tab-Drfz5uaT.0b387dcd4f5a.js.br +0 -0
- codex/static_root/assets/task-tab-Drfz5uaT.0b387dcd4f5a.js.gz +0 -0
- codex/static_root/assets/task-tab-Drfz5uaT.js +1 -0
- codex/static_root/assets/task-tab-Drfz5uaT.js.br +0 -0
- codex/static_root/assets/task-tab-Drfz5uaT.js.gz +0 -0
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css +1 -0
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.br +4 -0
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.gz +0 -0
- codex/static_root/assets/transition-5LRFTPo5.css +1 -0
- codex/static_root/assets/transition-5LRFTPo5.css.br +4 -0
- codex/static_root/assets/transition-5LRFTPo5.css.gz +0 -0
- codex/static_root/assets/transition-CQVFPpmZ.ba35e475243a.js +1 -0
- codex/static_root/assets/transition-CQVFPpmZ.ba35e475243a.js.br +0 -0
- codex/static_root/assets/transition-CQVFPpmZ.ba35e475243a.js.gz +0 -0
- codex/static_root/assets/transition-CQVFPpmZ.js +1 -0
- codex/static_root/assets/transition-CQVFPpmZ.js.br +0 -0
- codex/static_root/assets/transition-CQVFPpmZ.js.gz +0 -0
- codex/static_root/assets/unauthorized-Cfxq6rru.968d6e6e57bd.js +1 -0
- codex/static_root/assets/unauthorized-Cfxq6rru.968d6e6e57bd.js.br +0 -0
- codex/static_root/assets/unauthorized-Cfxq6rru.968d6e6e57bd.js.gz +0 -0
- codex/static_root/assets/unauthorized-Cfxq6rru.js +1 -0
- codex/static_root/assets/unauthorized-Cfxq6rru.js.br +0 -0
- codex/static_root/assets/unauthorized-Cfxq6rru.js.gz +0 -0
- codex/static_root/assets/user-tab-icKcK_Qd.c29142ed5212.js +1 -0
- codex/static_root/assets/user-tab-icKcK_Qd.c29142ed5212.js.br +0 -0
- codex/static_root/assets/user-tab-icKcK_Qd.c29142ed5212.js.gz +0 -0
- codex/static_root/assets/user-tab-icKcK_Qd.js +1 -0
- codex/static_root/assets/user-tab-icKcK_Qd.js.br +0 -0
- codex/static_root/assets/user-tab-icKcK_Qd.js.gz +0 -0
- codex/static_root/manifest.3eee2b4822b7.json +712 -0
- codex/static_root/manifest.3eee2b4822b7.json.br +0 -0
- codex/static_root/manifest.3eee2b4822b7.json.gz +0 -0
- codex/static_root/manifest.json +377 -300
- codex/static_root/manifest.json.br +0 -0
- codex/static_root/manifest.json.gz +0 -0
- codex/static_root/staticfiles.json +1 -1
- codex/status_controller.py +5 -6
- codex/threads.py +1 -1
- codex/urls/api/auth.py +1 -1
- codex/urls/api/browser.py +1 -1
- codex/views/admin/library.py +18 -13
- codex/views/admin/stats.py +23 -16
- codex/views/auth.py +42 -77
- codex/views/bookmark.py +16 -153
- codex/views/browser/annotate/__init__.py +1 -0
- codex/views/browser/annotate/bookmark.py +112 -0
- codex/views/browser/annotate/card.py +61 -0
- codex/views/browser/annotate/order.py +247 -0
- codex/views/browser/breadcrumbs.py +90 -11
- codex/views/browser/browser.py +44 -110
- codex/views/browser/choices.py +15 -18
- codex/views/browser/cover.py +10 -20
- codex/views/browser/filters/bookmark.py +18 -19
- codex/views/browser/filters/field.py +8 -3
- codex/views/browser/filters/filter.py +69 -0
- codex/views/browser/filters/group.py +9 -6
- codex/views/browser/filters/search/fts.py +5 -19
- codex/views/browser/filters/search/parse.py +54 -24
- codex/views/browser/group_mtime.py +83 -0
- codex/views/browser/metadata/__init__.py +1 -0
- codex/views/browser/metadata/annotate.py +109 -0
- codex/views/browser/metadata/copy_intersections.py +90 -0
- codex/views/browser/metadata/metadata.py +83 -0
- codex/views/browser/metadata/query_intersections.py +112 -0
- codex/views/browser/mtime.py +2 -10
- codex/views/browser/order_by.py +22 -22
- codex/views/browser/page_in_bounds.py +2 -2
- codex/views/browser/paginate.py +9 -15
- codex/views/browser/params.py +64 -0
- codex/views/browser/title.py +1 -6
- codex/views/browser/validate.py +68 -33
- codex/views/download.py +1 -1
- codex/views/mixins.py +27 -15
- codex/views/opds/const.py +2 -3
- codex/views/opds/urls.py +2 -2
- codex/views/opds/util.py +2 -3
- codex/views/opds/v1/entry/links.py +3 -1
- codex/views/opds/v1/facets.py +65 -12
- codex/views/opds/v1/feed.py +5 -64
- codex/views/opds/v1/links.py +5 -4
- codex/views/opds/v2/feed.py +1 -28
- codex/views/opds/v2/links.py +26 -1
- codex/views/opds/v2/publications.py +5 -6
- codex/views/opds/v2/top_links.py +3 -6
- codex/views/public.py +2 -2
- codex/views/reader/arcs.py +0 -3
- codex/views/reader/books.py +57 -41
- codex/views/reader/page.py +10 -4
- codex/views/reader/{init.py → params.py} +37 -31
- codex/views/reader/reader.py +1 -2
- codex/views/session.py +43 -54
- codex/views/timezone.py +54 -0
- codex/views/version.py +1 -1
- {codex-1.7.0a0.dist-info → codex-1.7.0a2.dist-info}/METADATA +1 -1
- {codex-1.7.0a0.dist-info → codex-1.7.0a2.dist-info}/RECORD +417 -383
- codex/serializers/choices.py +0 -196
- codex/static_root/assets/VCheckbox-CWiqcZ7a.3feebd47daab.js +0 -1
- codex/static_root/assets/VCheckbox-CWiqcZ7a.3feebd47daab.js.br +0 -0
- codex/static_root/assets/VCheckbox-CWiqcZ7a.3feebd47daab.js.gz +0 -0
- codex/static_root/assets/VCheckbox-CWiqcZ7a.js +0 -1
- codex/static_root/assets/VCheckbox-CWiqcZ7a.js.br +0 -0
- codex/static_root/assets/VCheckbox-CWiqcZ7a.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-Dk3iB62X.bc66d5351baa.js +0 -1
- codex/static_root/assets/VCheckboxBtn-Dk3iB62X.bc66d5351baa.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-Dk3iB62X.bc66d5351baa.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-Dk3iB62X.js +0 -1
- codex/static_root/assets/VCheckboxBtn-Dk3iB62X.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-Dk3iB62X.js.gz +0 -0
- codex/static_root/assets/VCombobox-D1_KU27A.b1d30587a973.js +0 -1
- codex/static_root/assets/VCombobox-D1_KU27A.b1d30587a973.js.br +0 -0
- codex/static_root/assets/VCombobox-D1_KU27A.b1d30587a973.js.gz +0 -0
- codex/static_root/assets/VCombobox-D1_KU27A.js +0 -1
- codex/static_root/assets/VCombobox-D1_KU27A.js.br +0 -0
- codex/static_root/assets/VCombobox-D1_KU27A.js.gz +0 -0
- codex/static_root/assets/VDialog-38np3TSA.5a0cb7a9e56d.css +0 -1
- codex/static_root/assets/VDialog-38np3TSA.5a0cb7a9e56d.css.br +0 -0
- codex/static_root/assets/VDialog-38np3TSA.5a0cb7a9e56d.css.gz +0 -0
- codex/static_root/assets/VDialog-38np3TSA.css +0 -1
- codex/static_root/assets/VDialog-38np3TSA.css.br +0 -0
- codex/static_root/assets/VDialog-38np3TSA.css.gz +0 -0
- codex/static_root/assets/VDialog-GbxvFMMN.594fb3a39ced.js +0 -1
- codex/static_root/assets/VDialog-GbxvFMMN.594fb3a39ced.js.br +0 -0
- codex/static_root/assets/VDialog-GbxvFMMN.594fb3a39ced.js.gz +0 -0
- codex/static_root/assets/VDialog-GbxvFMMN.js +0 -1
- codex/static_root/assets/VDialog-GbxvFMMN.js.br +0 -0
- codex/static_root/assets/VDialog-GbxvFMMN.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-Cywv_bEj.a762e63858e5.js +0 -1
- codex/static_root/assets/VExpansionPanels-Cywv_bEj.a762e63858e5.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-Cywv_bEj.a762e63858e5.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-Cywv_bEj.js +0 -1
- codex/static_root/assets/VExpansionPanels-Cywv_bEj.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-Cywv_bEj.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-C0etmxpZ.0eb3009a6300.js +0 -1
- codex/static_root/assets/VRadioGroup-C0etmxpZ.0eb3009a6300.js.br +0 -0
- codex/static_root/assets/VRadioGroup-C0etmxpZ.0eb3009a6300.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-C0etmxpZ.js +0 -1
- codex/static_root/assets/VRadioGroup-C0etmxpZ.js.br +0 -0
- codex/static_root/assets/VRadioGroup-C0etmxpZ.js.gz +0 -0
- codex/static_root/assets/VSelect-Ca2bIOso.6613989e4c45.css +0 -1
- codex/static_root/assets/VSelect-Ca2bIOso.6613989e4c45.css.br +0 -0
- codex/static_root/assets/VSelect-Ca2bIOso.6613989e4c45.css.gz +0 -0
- codex/static_root/assets/VSelect-Ca2bIOso.css +0 -1
- codex/static_root/assets/VSelect-Ca2bIOso.css.br +0 -0
- codex/static_root/assets/VSelect-Ca2bIOso.css.gz +0 -0
- codex/static_root/assets/VSelect-txrnRiNJ.a5625760018c.js +0 -1
- codex/static_root/assets/VSelect-txrnRiNJ.a5625760018c.js.br +0 -0
- codex/static_root/assets/VSelect-txrnRiNJ.a5625760018c.js.gz +0 -0
- codex/static_root/assets/VSelect-txrnRiNJ.js +0 -1
- codex/static_root/assets/VSelect-txrnRiNJ.js.br +0 -0
- codex/static_root/assets/VSelect-txrnRiNJ.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-CY6RmcvW.7e8824224f6c.js +0 -1
- codex/static_root/assets/VSelectionControl-CY6RmcvW.7e8824224f6c.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CY6RmcvW.7e8824224f6c.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-CY6RmcvW.js +0 -1
- codex/static_root/assets/VSelectionControl-CY6RmcvW.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CY6RmcvW.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css +0 -1
- codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css.br +0 -0
- codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css.gz +0 -0
- codex/static_root/assets/VSlideGroup-Dk_1upHt.css +0 -1
- codex/static_root/assets/VSlideGroup-Dk_1upHt.css.br +0 -0
- codex/static_root/assets/VSlideGroup-Dk_1upHt.css.gz +0 -0
- codex/static_root/assets/VSlideGroup-DtEQMwY1.6c72325635ed.js +0 -1
- codex/static_root/assets/VSlideGroup-DtEQMwY1.6c72325635ed.js.br +0 -0
- codex/static_root/assets/VSlideGroup-DtEQMwY1.6c72325635ed.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-DtEQMwY1.js +0 -1
- codex/static_root/assets/VSlideGroup-DtEQMwY1.js.br +0 -0
- codex/static_root/assets/VSlideGroup-DtEQMwY1.js.gz +0 -0
- codex/static_root/assets/VTable-2af995xo.6c5bf36631b2.js +0 -1
- codex/static_root/assets/VTable-2af995xo.6c5bf36631b2.js.br +0 -0
- codex/static_root/assets/VTable-2af995xo.6c5bf36631b2.js.gz +0 -0
- codex/static_root/assets/VTable-2af995xo.js +0 -1
- codex/static_root/assets/VTable-2af995xo.js.br +0 -0
- codex/static_root/assets/VTable-2af995xo.js.gz +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css +0 -1
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.br +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.gz +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.css +0 -1
- codex/static_root/assets/VTextField-Crc3gdNh.css.br +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.css.gz +0 -0
- codex/static_root/assets/VTextField-G6CMj7yO.657a130dd302.js +0 -1
- codex/static_root/assets/VTextField-G6CMj7yO.657a130dd302.js.br +0 -0
- codex/static_root/assets/VTextField-G6CMj7yO.657a130dd302.js.gz +0 -0
- codex/static_root/assets/VTextField-G6CMj7yO.js +0 -1
- codex/static_root/assets/VTextField-G6CMj7yO.js.br +0 -0
- codex/static_root/assets/VTextField-G6CMj7yO.js.gz +0 -0
- codex/static_root/assets/VWindowItem-CzoGd6Ul.721e5da11ad4.js +0 -1
- codex/static_root/assets/VWindowItem-CzoGd6Ul.721e5da11ad4.js.br +0 -0
- codex/static_root/assets/VWindowItem-CzoGd6Ul.721e5da11ad4.js.gz +0 -0
- codex/static_root/assets/VWindowItem-CzoGd6Ul.js +0 -1
- codex/static_root/assets/VWindowItem-CzoGd6Ul.js.br +0 -0
- codex/static_root/assets/VWindowItem-CzoGd6Ul.js.gz +0 -0
- codex/static_root/assets/admin-CWEjaFr5.7d4523387384.css.br +0 -0
- codex/static_root/assets/admin-CWEjaFr5.7d4523387384.css.gz +0 -0
- codex/static_root/assets/admin-CWEjaFr5.css.br +0 -0
- codex/static_root/assets/admin-CWEjaFr5.css.gz +0 -0
- codex/static_root/assets/admin-CsPAIQeG.5175467148a3.js +0 -1
- codex/static_root/assets/admin-CsPAIQeG.5175467148a3.js.br +0 -0
- codex/static_root/assets/admin-CsPAIQeG.5175467148a3.js.gz +0 -0
- codex/static_root/assets/admin-CsPAIQeG.js +0 -1
- codex/static_root/assets/admin-CsPAIQeG.js.br +0 -0
- codex/static_root/assets/admin-CsPAIQeG.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-BAT7GA64.73a064628c19.js +0 -30
- codex/static_root/assets/admin-drawer-panel-BAT7GA64.73a064628c19.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-BAT7GA64.73a064628c19.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-BAT7GA64.js +0 -30
- codex/static_root/assets/admin-drawer-panel-BAT7GA64.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-BAT7GA64.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.3cb33056e994.css +0 -1
- codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.3cb33056e994.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.3cb33056e994.css.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.css +0 -1
- codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.css.gz +0 -0
- codex/static_root/assets/browser-C18l93yc.923860009ef4.js +0 -1
- codex/static_root/assets/browser-C18l93yc.923860009ef4.js.br +0 -0
- codex/static_root/assets/browser-C18l93yc.923860009ef4.js.gz +0 -0
- codex/static_root/assets/browser-C18l93yc.js +0 -1
- codex/static_root/assets/browser-C18l93yc.js.br +0 -0
- codex/static_root/assets/browser-C18l93yc.js.gz +0 -0
- codex/static_root/assets/browser-DaAqlBYO.708ecf0904bb.css +0 -1
- codex/static_root/assets/browser-DaAqlBYO.708ecf0904bb.css.br +0 -0
- codex/static_root/assets/browser-DaAqlBYO.708ecf0904bb.css.gz +0 -0
- codex/static_root/assets/browser-DaAqlBYO.css +0 -1
- codex/static_root/assets/browser-DaAqlBYO.css.br +0 -0
- codex/static_root/assets/browser-DaAqlBYO.css.gz +0 -0
- codex/static_root/assets/change-password-dialog-BazJdNs9.0a4e02656a35.js +0 -1
- codex/static_root/assets/change-password-dialog-BazJdNs9.0a4e02656a35.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BazJdNs9.0a4e02656a35.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-BazJdNs9.js +0 -1
- codex/static_root/assets/change-password-dialog-BazJdNs9.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BazJdNs9.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-Mlmvz8_4.111421f51e79.css +0 -1
- codex/static_root/assets/change-password-dialog-Mlmvz8_4.111421f51e79.css.br +0 -0
- codex/static_root/assets/change-password-dialog-Mlmvz8_4.111421f51e79.css.gz +0 -0
- codex/static_root/assets/change-password-dialog-Mlmvz8_4.css +0 -1
- codex/static_root/assets/change-password-dialog-Mlmvz8_4.css.br +0 -0
- codex/static_root/assets/change-password-dialog-Mlmvz8_4.css.gz +0 -0
- codex/static_root/assets/confirm-dialog-BmhedLCx.7c2103d319d4.css +0 -1
- codex/static_root/assets/confirm-dialog-BmhedLCx.css +0 -1
- codex/static_root/assets/confirm-dialog-CbW3hlOp.9dd39b443c31.js +0 -1
- codex/static_root/assets/confirm-dialog-CbW3hlOp.9dd39b443c31.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CbW3hlOp.9dd39b443c31.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CbW3hlOp.js +0 -1
- codex/static_root/assets/confirm-dialog-CbW3hlOp.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CbW3hlOp.js.gz +0 -0
- codex/static_root/assets/datetime-column-uSqKZU37.b157b0743db5.js +0 -1
- codex/static_root/assets/datetime-column-uSqKZU37.b157b0743db5.js.br +0 -0
- codex/static_root/assets/datetime-column-uSqKZU37.b157b0743db5.js.gz +0 -0
- codex/static_root/assets/datetime-column-uSqKZU37.js +0 -1
- codex/static_root/assets/datetime-column-uSqKZU37.js.br +0 -0
- codex/static_root/assets/datetime-column-uSqKZU37.js.gz +0 -0
- codex/static_root/assets/filter-CBl5KEsB.845a81573c2e.js +0 -1
- codex/static_root/assets/filter-CBl5KEsB.845a81573c2e.js.br +0 -0
- codex/static_root/assets/filter-CBl5KEsB.845a81573c2e.js.gz +0 -0
- codex/static_root/assets/filter-CBl5KEsB.js +0 -1
- codex/static_root/assets/filter-CBl5KEsB.js.br +0 -0
- codex/static_root/assets/filter-CBl5KEsB.js.gz +0 -0
- codex/static_root/assets/flag-tab-CT8pqM4r.ecb6eee2e7a0.js +0 -1
- codex/static_root/assets/flag-tab-CT8pqM4r.ecb6eee2e7a0.js.br +0 -0
- codex/static_root/assets/flag-tab-CT8pqM4r.ecb6eee2e7a0.js.gz +0 -0
- codex/static_root/assets/flag-tab-CT8pqM4r.js +0 -1
- codex/static_root/assets/flag-tab-CT8pqM4r.js.br +0 -0
- codex/static_root/assets/flag-tab-CT8pqM4r.js.gz +0 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.css +0 -1
- codex/static_root/assets/flag-tab-DBqpLKi7.css.br +0 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.css.gz +0 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css +0 -1
- codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css.br +0 -0
- codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css.gz +0 -0
- codex/static_root/assets/group-tab-BOW9kigw.7e5007596367.js +0 -1
- codex/static_root/assets/group-tab-BOW9kigw.7e5007596367.js.br +0 -0
- codex/static_root/assets/group-tab-BOW9kigw.7e5007596367.js.gz +0 -0
- codex/static_root/assets/group-tab-BOW9kigw.js +0 -1
- codex/static_root/assets/group-tab-BOW9kigw.js.br +0 -0
- codex/static_root/assets/group-tab-BOW9kigw.js.gz +0 -0
- codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css +0 -1
- codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css.br +0 -0
- codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css.gz +0 -0
- codex/static_root/assets/group-tab-CBKuS3Iv.css +0 -1
- codex/static_root/assets/group-tab-CBKuS3Iv.css.br +0 -0
- codex/static_root/assets/group-tab-CBKuS3Iv.css.gz +0 -0
- codex/static_root/assets/http-error-C6yuLApo.45cf99eb7a70.js +0 -1
- codex/static_root/assets/http-error-C6yuLApo.45cf99eb7a70.js.br +0 -4
- codex/static_root/assets/http-error-C6yuLApo.45cf99eb7a70.js.gz +0 -0
- codex/static_root/assets/http-error-C6yuLApo.js +0 -1
- codex/static_root/assets/http-error-C6yuLApo.js.br +0 -4
- codex/static_root/assets/http-error-C6yuLApo.js.gz +0 -0
- codex/static_root/assets/library-tab-Bh7ErAk7.7c44200ee727.css.br +0 -2
- codex/static_root/assets/library-tab-Bh7ErAk7.7c44200ee727.css.gz +0 -0
- codex/static_root/assets/library-tab-Bh7ErAk7.css.br +0 -2
- codex/static_root/assets/library-tab-Bh7ErAk7.css.gz +0 -0
- codex/static_root/assets/library-tab-D3WOtpE0.9af34e6e7235.js +0 -1
- codex/static_root/assets/library-tab-D3WOtpE0.9af34e6e7235.js.br +0 -0
- codex/static_root/assets/library-tab-D3WOtpE0.9af34e6e7235.js.gz +0 -0
- codex/static_root/assets/library-tab-D3WOtpE0.js +0 -1
- codex/static_root/assets/library-tab-D3WOtpE0.js.br +0 -0
- codex/static_root/assets/library-tab-D3WOtpE0.js.gz +0 -0
- codex/static_root/assets/main-CmjU2oTp.6a471f6900e5.js +0 -6
- codex/static_root/assets/main-CmjU2oTp.6a471f6900e5.js.br +0 -0
- codex/static_root/assets/main-CmjU2oTp.6a471f6900e5.js.gz +0 -0
- codex/static_root/assets/main-CmjU2oTp.js +0 -6
- codex/static_root/assets/main-CmjU2oTp.js.br +0 -0
- codex/static_root/assets/main-CmjU2oTp.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-BH54_5f6.6e92d0555cd7.js +0 -1
- codex/static_root/assets/pager-full-pdf-BH54_5f6.6e92d0555cd7.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-BH54_5f6.6e92d0555cd7.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-BH54_5f6.js +0 -1
- codex/static_root/assets/pager-full-pdf-BH54_5f6.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-BH54_5f6.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-JH3Kbffr.451171f7ac33.js +0 -1
- codex/static_root/assets/pagination-toolbar-JH3Kbffr.451171f7ac33.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-JH3Kbffr.451171f7ac33.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-JH3Kbffr.js +0 -1
- codex/static_root/assets/pagination-toolbar-JH3Kbffr.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-JH3Kbffr.js.gz +0 -0
- codex/static_root/assets/pdf-doc-BcRNpoaW.882f6e967869.js.br +0 -0
- codex/static_root/assets/pdf-doc-BcRNpoaW.882f6e967869.js.gz +0 -0
- codex/static_root/assets/pdf-doc-BcRNpoaW.js.br +0 -0
- codex/static_root/assets/pdf-doc-BcRNpoaW.js.gz +0 -0
- codex/static_root/assets/reader-DIPRg2VB.900370e097aa.js +0 -2
- codex/static_root/assets/reader-DIPRg2VB.900370e097aa.js.br +0 -0
- codex/static_root/assets/reader-DIPRg2VB.900370e097aa.js.gz +0 -0
- codex/static_root/assets/reader-DIPRg2VB.js +0 -2
- codex/static_root/assets/reader-DIPRg2VB.js.br +0 -0
- codex/static_root/assets/reader-DIPRg2VB.js.gz +0 -0
- codex/static_root/assets/reader-DveZZr9x.7b21b9f8f628.css.br +0 -0
- codex/static_root/assets/reader-DveZZr9x.7b21b9f8f628.css.gz +0 -0
- codex/static_root/assets/reader-DveZZr9x.css.br +0 -0
- codex/static_root/assets/reader-DveZZr9x.css.gz +0 -0
- codex/static_root/assets/relation-chips-3tTlR5QH.71f18bc92adc.js +0 -1
- codex/static_root/assets/relation-chips-3tTlR5QH.71f18bc92adc.js.br +0 -0
- codex/static_root/assets/relation-chips-3tTlR5QH.71f18bc92adc.js.gz +0 -0
- codex/static_root/assets/relation-chips-3tTlR5QH.js +0 -1
- codex/static_root/assets/relation-chips-3tTlR5QH.js.br +0 -0
- codex/static_root/assets/relation-chips-3tTlR5QH.js.gz +0 -0
- codex/static_root/assets/settings-drawer-BdyFhA_r.151f4c3061ed.js +0 -2
- codex/static_root/assets/settings-drawer-BdyFhA_r.151f4c3061ed.js.br +0 -0
- codex/static_root/assets/settings-drawer-BdyFhA_r.151f4c3061ed.js.gz +0 -0
- codex/static_root/assets/settings-drawer-BdyFhA_r.js +0 -2
- codex/static_root/assets/settings-drawer-BdyFhA_r.js.br +0 -0
- codex/static_root/assets/settings-drawer-BdyFhA_r.js.gz +0 -0
- codex/static_root/assets/stats-tab-DeKjwvmh.7557c71b4cfa.js +0 -1
- codex/static_root/assets/stats-tab-DeKjwvmh.7557c71b4cfa.js.br +0 -0
- codex/static_root/assets/stats-tab-DeKjwvmh.7557c71b4cfa.js.gz +0 -0
- codex/static_root/assets/stats-tab-DeKjwvmh.js +0 -1
- codex/static_root/assets/stats-tab-DeKjwvmh.js.br +0 -0
- codex/static_root/assets/stats-tab-DeKjwvmh.js.gz +0 -0
- codex/static_root/assets/stats-tab-DpfGsVX3.1cb66f2649a9.css.br +0 -0
- codex/static_root/assets/stats-tab-DpfGsVX3.1cb66f2649a9.css.gz +0 -0
- codex/static_root/assets/stats-tab-DpfGsVX3.css.br +0 -0
- codex/static_root/assets/stats-tab-DpfGsVX3.css.gz +0 -0
- codex/static_root/assets/task-tab-1XiWn9xP.06cb8e1b794d.css +0 -1
- codex/static_root/assets/task-tab-1XiWn9xP.06cb8e1b794d.css.gz +0 -0
- codex/static_root/assets/task-tab-1XiWn9xP.css +0 -1
- codex/static_root/assets/task-tab-1XiWn9xP.css.gz +0 -0
- codex/static_root/assets/task-tab-C8D0qRP_.d4ab174c69a3.js +0 -1
- codex/static_root/assets/task-tab-C8D0qRP_.d4ab174c69a3.js.br +0 -0
- codex/static_root/assets/task-tab-C8D0qRP_.d4ab174c69a3.js.gz +0 -0
- codex/static_root/assets/task-tab-C8D0qRP_.js +0 -1
- codex/static_root/assets/task-tab-C8D0qRP_.js.br +0 -0
- codex/static_root/assets/task-tab-C8D0qRP_.js.gz +0 -0
- codex/static_root/assets/unauthorized-BHgBRF4z.8e5c1b9e52b0.js +0 -1
- codex/static_root/assets/unauthorized-BHgBRF4z.8e5c1b9e52b0.js.br +0 -0
- codex/static_root/assets/unauthorized-BHgBRF4z.8e5c1b9e52b0.js.gz +0 -0
- codex/static_root/assets/unauthorized-BHgBRF4z.js +0 -1
- codex/static_root/assets/unauthorized-BHgBRF4z.js.br +0 -0
- codex/static_root/assets/unauthorized-BHgBRF4z.js.gz +0 -0
- codex/static_root/assets/user-tab-BU31Z92y.35613c713faf.js +0 -1
- codex/static_root/assets/user-tab-BU31Z92y.35613c713faf.js.br +0 -0
- codex/static_root/assets/user-tab-BU31Z92y.35613c713faf.js.gz +0 -0
- codex/static_root/assets/user-tab-BU31Z92y.js +0 -1
- codex/static_root/assets/user-tab-BU31Z92y.js.br +0 -0
- codex/static_root/assets/user-tab-BU31Z92y.js.gz +0 -0
- codex/static_root/js/choices-admin.8aa64c911203.json +0 -1
- codex/static_root/js/choices-admin.8aa64c911203.json.br +0 -0
- codex/static_root/js/choices-admin.8aa64c911203.json.gz +0 -0
- codex/static_root/js/choices-admin.json +0 -1
- codex/static_root/js/choices-admin.json.br +0 -0
- codex/static_root/js/choices-admin.json.gz +0 -0
- codex/static_root/js/choices.2f6b0359e1ef.json +0 -1
- codex/static_root/js/choices.2f6b0359e1ef.json.br +0 -0
- codex/static_root/js/choices.2f6b0359e1ef.json.gz +0 -0
- codex/static_root/js/choices.json +0 -1
- codex/static_root/js/choices.json.br +0 -0
- codex/static_root/js/choices.json.gz +0 -0
- codex/static_root/manifest.45cb46e19686.json +0 -635
- codex/static_root/manifest.45cb46e19686.json.br +0 -0
- codex/static_root/manifest.45cb46e19686.json.gz +0 -0
- codex/views/browser/annotations.py +0 -339
- codex/views/browser/base.py +0 -139
- codex/views/browser/filters/annotations.py +0 -125
- codex/views/browser/metadata.py +0 -332
- {codex-1.7.0a0.dist-info → codex-1.7.0a2.dist-info}/LICENSE +0 -0
- {codex-1.7.0a0.dist-info → codex-1.7.0a2.dist-info}/WHEEL +0 -0
- {codex-1.7.0a0.dist-info → codex-1.7.0a2.dist-info}/entry_points.txt +0 -0
codex/views/opds/v1/facets.py
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from types import MappingProxyType
|
|
5
|
+
from typing import Any
|
|
5
6
|
|
|
6
7
|
from django.urls import reverse
|
|
7
8
|
|
|
8
9
|
from codex.models import AdminFlag
|
|
9
10
|
from codex.views.browser.browser import BrowserView
|
|
10
|
-
from codex.views.opds.const import MimeType, Rel
|
|
11
|
-
from codex.views.opds.util import update_href_query_params
|
|
11
|
+
from codex.views.opds.const import MimeType, Rel, UserAgentNames
|
|
12
|
+
from codex.views.opds.util import get_user_agent_name, update_href_query_params
|
|
12
13
|
from codex.views.opds.v1.data import OPDS1Link
|
|
13
14
|
from codex.views.opds.v1.entry.data import OPDS1EntryData, OPDS1EntryObject
|
|
14
15
|
from codex.views.opds.v1.entry.entry import OPDS1Entry
|
|
@@ -81,13 +82,61 @@ DEFAULT_FACETS = {
|
|
|
81
82
|
class OPDS1FacetsView(BrowserView):
|
|
82
83
|
"""OPDS 1 Facets methods."""
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
def __init__(self, *args, **kwargs):
|
|
86
|
+
"""Initialize properties."""
|
|
87
|
+
super().__init__(*args, **kwargs)
|
|
88
|
+
self._user_agent_name: str | None = None
|
|
89
|
+
self._mime_type_map: MappingProxyType[str, str] | None = None
|
|
90
|
+
self._use_facets: bool | None = None
|
|
91
|
+
self._obj: MappingProxyType[str, Any] | None = None
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def user_agent_name(self) -> str:
|
|
95
|
+
"""Memoize user agent name."""
|
|
96
|
+
if self._user_agent_name is None:
|
|
97
|
+
self._user_agent_name = get_user_agent_name(self.request)
|
|
98
|
+
return self._user_agent_name
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def mime_type_map(self) -> MappingProxyType[str, str]:
|
|
102
|
+
"""Memoize mime type map."""
|
|
103
|
+
if self._mime_type_map is None:
|
|
104
|
+
self._mime_type_map = (
|
|
105
|
+
MimeType.SIMPLE_FILE_TYPE_MAP
|
|
106
|
+
if self.user_agent_name in UserAgentNames.SIMPLE_DOWNLOAD_MIME_TYPES
|
|
107
|
+
else MimeType.FILE_TYPE_MAP
|
|
108
|
+
)
|
|
109
|
+
return self._mime_type_map
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def use_facets(self) -> bool:
|
|
113
|
+
"""Memoize use_facets."""
|
|
114
|
+
if self._use_facets is None:
|
|
115
|
+
self._use_facets = self.user_agent_name in UserAgentNames.FACET_SUPPORT
|
|
116
|
+
return self._use_facets
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def obj(self) -> MappingProxyType[str, Any]:
|
|
120
|
+
"""Get the browser page and serialize it for this subclass."""
|
|
121
|
+
if self._obj is None:
|
|
122
|
+
group_qs, book_qs, num_pages, total_count, zero_pad, mtime = (
|
|
123
|
+
self._get_group_and_books()
|
|
124
|
+
)
|
|
125
|
+
book_qs = book_qs.select_related("series", "volume", "language")
|
|
126
|
+
|
|
127
|
+
title = self.get_browser_page_title()
|
|
128
|
+
self._obj = MappingProxyType(
|
|
129
|
+
{
|
|
130
|
+
"title": title,
|
|
131
|
+
"groups": group_qs,
|
|
132
|
+
"books": book_qs,
|
|
133
|
+
"zero_pad": zero_pad,
|
|
134
|
+
"num_pages": num_pages,
|
|
135
|
+
"total_count": total_count,
|
|
136
|
+
"mtime": mtime,
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
return self._obj
|
|
91
140
|
|
|
92
141
|
def _facet(self, kwargs, facet_group, facet_title, new_query_params):
|
|
93
142
|
kwargs = pop_name(kwargs)
|
|
@@ -120,9 +169,9 @@ class OPDS1FacetsView(BrowserView):
|
|
|
120
169
|
)
|
|
121
170
|
qps = {**self.request.GET}
|
|
122
171
|
qps.update(query_params)
|
|
123
|
-
zero_pad = self.obj["zero_pad"]
|
|
172
|
+
zero_pad: int = self.obj["zero_pad"] # type: ignore
|
|
124
173
|
data = OPDS1EntryData(
|
|
125
|
-
self.
|
|
174
|
+
self.opds_acquisition_groups, zero_pad, False, self.mime_type_map
|
|
126
175
|
)
|
|
127
176
|
return OPDS1Entry(entry_obj, qps, data)
|
|
128
177
|
|
|
@@ -185,7 +234,11 @@ class OPDS1FacetsView(BrowserView):
|
|
|
185
234
|
def facets(self, entries=False, root=True):
|
|
186
235
|
"""Return facets."""
|
|
187
236
|
facets = []
|
|
188
|
-
|
|
237
|
+
group = self.kwargs.get("group")
|
|
238
|
+
add_order_facets = (
|
|
239
|
+
group != "c" and self.user_agent_name not in UserAgentNames.CLIENT_REORDERS
|
|
240
|
+
)
|
|
241
|
+
if not add_order_facets:
|
|
189
242
|
facets += self._facet_group(FacetGroups.ORDER_BY, entries)
|
|
190
243
|
facets += self._facet_group(FacetGroups.ORDER_REVERSE, entries)
|
|
191
244
|
if root:
|
codex/views/opds/v1/feed.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""OPDS v1 feed."""
|
|
2
2
|
|
|
3
|
-
from types import MappingProxyType
|
|
4
3
|
from typing import TYPE_CHECKING, Any
|
|
5
4
|
|
|
6
5
|
from drf_spectacular.utils import extend_schema
|
|
@@ -17,8 +16,7 @@ from codex.serializers.opds.v1 import (
|
|
|
17
16
|
from codex.settings.settings import FALSY
|
|
18
17
|
from codex.views.const import MAX_OBJ_PER_PAGE
|
|
19
18
|
from codex.views.opds.auth import OPDSTemplateView
|
|
20
|
-
from codex.views.opds.const import BLANK_TITLE
|
|
21
|
-
from codex.views.opds.util import get_user_agent_name
|
|
19
|
+
from codex.views.opds.const import BLANK_TITLE
|
|
22
20
|
from codex.views.opds.v1.entry.data import OPDS1EntryData
|
|
23
21
|
from codex.views.opds.v1.entry.entry import OPDS1Entry
|
|
24
22
|
from codex.views.opds.v1.links import (
|
|
@@ -55,14 +53,14 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
|
|
|
55
53
|
def opds_ns(self):
|
|
56
54
|
"""Dynamic opds namespace."""
|
|
57
55
|
try:
|
|
58
|
-
return OpdsNs.ACQUISITION if self.
|
|
56
|
+
return OpdsNs.ACQUISITION if self.is_opds_acquisition else OpdsNs.CATALOG
|
|
59
57
|
except Exception:
|
|
60
58
|
LOG.exception("Getting OPDS v1 namespace")
|
|
61
59
|
|
|
62
60
|
@property
|
|
63
61
|
def is_acquisition(self):
|
|
64
62
|
"""Is acquisition."""
|
|
65
|
-
return self.
|
|
63
|
+
return self.is_opds_acquisition
|
|
66
64
|
|
|
67
65
|
@property
|
|
68
66
|
def id_tag(self):
|
|
@@ -128,7 +126,7 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
|
|
|
128
126
|
if objs := self.obj.get(key):
|
|
129
127
|
zero_pad: int = self.obj["zero_pad"] # type: ignore
|
|
130
128
|
data = OPDS1EntryData(
|
|
131
|
-
self.
|
|
129
|
+
self.opds_acquisition_groups, zero_pad, metadata, self.mime_type_map
|
|
132
130
|
)
|
|
133
131
|
fallback = bool(self.admin_flags.get("folder_view"))
|
|
134
132
|
import_pks = set()
|
|
@@ -166,65 +164,8 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
|
|
|
166
164
|
LOG.exception("Getting OPDS v1 entries")
|
|
167
165
|
return entries
|
|
168
166
|
|
|
169
|
-
def get_object(self): # type: ignore
|
|
170
|
-
"""Get the browser page and serialize it for this subclass."""
|
|
171
|
-
group_qs, book_qs, num_pages, total_count, zero_pad, mtime = (
|
|
172
|
-
super()._get_group_and_books()
|
|
173
|
-
)
|
|
174
|
-
book_qs = book_qs.select_related("series", "volume", "language")
|
|
175
|
-
|
|
176
|
-
title = self.get_browser_page_title()
|
|
177
|
-
self.obj = MappingProxyType(
|
|
178
|
-
{
|
|
179
|
-
"title": title,
|
|
180
|
-
"groups": group_qs,
|
|
181
|
-
"books": book_qs,
|
|
182
|
-
"zero_pad": zero_pad,
|
|
183
|
-
"num_pages": num_pages,
|
|
184
|
-
"total_count": total_count,
|
|
185
|
-
"mtime": mtime,
|
|
186
|
-
}
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
self.is_aq_feed = self.model_group in ("c", "f")
|
|
190
|
-
|
|
191
|
-
# Do not return a Mapping despite the type. Return self for the serializer.
|
|
192
|
-
return self
|
|
193
|
-
|
|
194
|
-
def _set_user_agent_variables(self):
|
|
195
|
-
"""Set User Agent variables."""
|
|
196
|
-
user_agent_name = get_user_agent_name(self.request)
|
|
197
|
-
|
|
198
|
-
self.user_facets = user_agent_name in UserAgentNames.FACET_SUPPORT
|
|
199
|
-
self.skip_order_facets = user_agent_name in UserAgentNames.CLIENT_REORDERS
|
|
200
|
-
if user_agent_name in UserAgentNames.SIMPLE_DOWNLOAD_MIME_TYPES:
|
|
201
|
-
self.mime_type_map = MimeType.SIMPLE_FILE_TYPE_MAP
|
|
202
|
-
|
|
203
|
-
def set_opds_request_type(self):
|
|
204
|
-
"""Set the opds request type variables."""
|
|
205
|
-
group = self.kwargs.get("group")
|
|
206
|
-
if group == "a":
|
|
207
|
-
self.acquisition_groups = frozenset({"a", "c"})
|
|
208
|
-
pks = self.kwargs["pks"]
|
|
209
|
-
self.is_opds_1_acquisition = group in self.acquisition_groups and pks
|
|
210
|
-
else:
|
|
211
|
-
self.acquisition_groups = frozenset({*self.valid_nav_groups[-2:]} | {"c"})
|
|
212
|
-
self.is_opds_1_acquisition = group in self.acquisition_groups
|
|
213
|
-
self.is_opds_metadata = (
|
|
214
|
-
self.request.GET.get("opdsMetadata", "").lower() not in FALSY
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
def init_request(self):
|
|
218
|
-
"""Initialize request."""
|
|
219
|
-
super().init_request()
|
|
220
|
-
self.set_opds_request_type()
|
|
221
|
-
self._set_user_agent_variables()
|
|
222
|
-
self.skip_order_facets |= self.kwargs.get("group") == "c"
|
|
223
|
-
|
|
224
167
|
@extend_schema(parameters=[input_serializer_class])
|
|
225
168
|
def get(self, *_args, **_kwargs):
|
|
226
169
|
"""Get the feed."""
|
|
227
|
-
self.
|
|
228
|
-
obj = self.get_object()
|
|
229
|
-
serializer = self.get_serializer(obj)
|
|
170
|
+
serializer = self.get_serializer(self)
|
|
230
171
|
return Response(serializer.data, content_type=self.content_type)
|
codex/views/opds/v1/links.py
CHANGED
|
@@ -112,7 +112,6 @@ class OPDS1LinksView(OPDS1FacetsView):
|
|
|
112
112
|
"name": "opds:v1:feed",
|
|
113
113
|
}
|
|
114
114
|
)
|
|
115
|
-
is_aq_feed = False
|
|
116
115
|
|
|
117
116
|
def is_top_link_displayed(self, top_link):
|
|
118
117
|
"""Determine if this top link should be displayed."""
|
|
@@ -160,7 +159,9 @@ class OPDS1LinksView(OPDS1FacetsView):
|
|
|
160
159
|
"""Create all the links."""
|
|
161
160
|
links = []
|
|
162
161
|
try:
|
|
163
|
-
mime_type =
|
|
162
|
+
mime_type = (
|
|
163
|
+
MimeType.ACQUISITION if self.is_opds_acquisition else MimeType.NAV
|
|
164
|
+
)
|
|
164
165
|
links += [
|
|
165
166
|
OPDS1Link("self", self.request.get_full_path(), mime_type),
|
|
166
167
|
OPDS1Link(
|
|
@@ -193,9 +194,9 @@ class OPDS1LinksView(OPDS1FacetsView):
|
|
|
193
194
|
name=name,
|
|
194
195
|
summary=top_link.desc,
|
|
195
196
|
)
|
|
196
|
-
zero_pad = self.obj["zero_pad"]
|
|
197
|
+
zero_pad: int = self.obj["zero_pad"] # type: ignore
|
|
197
198
|
data = OPDS1EntryData(
|
|
198
|
-
self.
|
|
199
|
+
self.opds_acquisition_groups, zero_pad, False, self.mime_type_map
|
|
199
200
|
)
|
|
200
201
|
return OPDS1Entry(entry_obj, top_link.query_params, data)
|
|
201
202
|
|
codex/views/opds/v2/feed.py
CHANGED
|
@@ -9,7 +9,6 @@ from codex.logger.logging import get_logger
|
|
|
9
9
|
from codex.models import AdminFlag
|
|
10
10
|
from codex.serializers.browser.settings import OPDSSettingsSerializer
|
|
11
11
|
from codex.serializers.opds.v2 import OPDS2FeedSerializer
|
|
12
|
-
from codex.settings.settings import FALSY
|
|
13
12
|
from codex.views.const import MAX_OBJ_PER_PAGE
|
|
14
13
|
from codex.views.opds.auth import OPDSAuthMixin
|
|
15
14
|
from codex.views.opds.const import BLANK_TITLE
|
|
@@ -177,16 +176,10 @@ class OPDS2FeedView(OPDSAuthMixin, OPDS2PublicationView):
|
|
|
177
176
|
|
|
178
177
|
def get_object(self):
|
|
179
178
|
"""Get the browser page and serialize it for this subclass."""
|
|
180
|
-
group_qs, book_qs,
|
|
181
|
-
self._get_group_and_books()
|
|
182
|
-
)
|
|
179
|
+
group_qs, book_qs, _, total_count, zero_pad, mtime = self.group_and_books
|
|
183
180
|
title = self.get_browser_page_title()
|
|
184
181
|
# convert browser_page into opds page
|
|
185
182
|
|
|
186
|
-
# instance vars
|
|
187
|
-
self.is_aq_feed = self.model_group in ("c", "f")
|
|
188
|
-
self.num_pages = num_pages
|
|
189
|
-
|
|
190
183
|
# opds page
|
|
191
184
|
title = self._title(title)
|
|
192
185
|
number_of_items = total_count
|
|
@@ -215,31 +208,11 @@ class OPDS2FeedView(OPDSAuthMixin, OPDS2PublicationView):
|
|
|
215
208
|
}
|
|
216
209
|
)
|
|
217
210
|
|
|
218
|
-
def set_opds_request_type(self):
|
|
219
|
-
"""Set opds request type variables."""
|
|
220
|
-
group = self.kwargs.get("group")
|
|
221
|
-
if group in {"f", "a"}:
|
|
222
|
-
pks = self.kwargs["pks"]
|
|
223
|
-
self.is_opds_2_acquisition = bool(pks)
|
|
224
|
-
else:
|
|
225
|
-
acquisition_groups = frozenset(self.valid_nav_groups[-2:])
|
|
226
|
-
self.is_opds_2_acquisition = group in acquisition_groups
|
|
227
|
-
self.is_opds_metadata = (
|
|
228
|
-
self.request.GET.get("opdsMetadata", "").lower() not in FALSY
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
def init_request(self):
|
|
232
|
-
"""Initialize request."""
|
|
233
|
-
super().init_request()
|
|
234
|
-
self.set_opds_request_type()
|
|
235
|
-
# self._detect_user_agent()
|
|
236
|
-
|
|
237
211
|
@extend_schema(
|
|
238
212
|
parameters=[input_serializer_class],
|
|
239
213
|
)
|
|
240
214
|
def get(self, *_args, **_kwargs):
|
|
241
215
|
"""Get the feed."""
|
|
242
|
-
self.init_request()
|
|
243
216
|
obj = self.get_object()
|
|
244
217
|
serializer = self.get_serializer(obj)
|
|
245
218
|
return Response(serializer.data)
|
codex/views/opds/v2/links.py
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from copy import deepcopy
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
+
from datetime import datetime
|
|
5
6
|
from urllib.parse import parse_qsl, urlparse
|
|
6
7
|
|
|
8
|
+
from django.db.models import QuerySet
|
|
7
9
|
from django.urls import reverse
|
|
8
10
|
|
|
9
11
|
from codex.settings.settings import FALSY
|
|
@@ -43,7 +45,30 @@ class LinkData:
|
|
|
43
45
|
class OPDS2LinksView(BrowserView):
|
|
44
46
|
"""Links methods for OPDS 2.0 Feed."""
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
def __init__(self, *args, **kwargs):
|
|
49
|
+
"""Initialize properties."""
|
|
50
|
+
super().__init__(*args, **kwargs)
|
|
51
|
+
self._num_pages: int | None = None
|
|
52
|
+
self._group_and_books: (
|
|
53
|
+
tuple[QuerySet, QuerySet, int, int, int | None, datetime | None] | None
|
|
54
|
+
) = None
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def group_and_books(
|
|
58
|
+
self,
|
|
59
|
+
) -> tuple[QuerySet, QuerySet, int, int, int | None, datetime | None]:
|
|
60
|
+
"""Memoize Group And Books for num_pages."""
|
|
61
|
+
# group_qs, book_qs, num_pages, total_count, zero_pad, mtime
|
|
62
|
+
if self._group_and_books is None:
|
|
63
|
+
self._group_and_books = self._get_group_and_books()
|
|
64
|
+
return self._group_and_books
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def num_pages(self) -> int:
|
|
68
|
+
"""Memoize num_pages."""
|
|
69
|
+
if self._num_pages is None:
|
|
70
|
+
self._num_pages = self.group_and_books[2]
|
|
71
|
+
return self._num_pages
|
|
47
72
|
|
|
48
73
|
def _href_page_validate(self, kwargs, data):
|
|
49
74
|
"""Validate the page bounds."""
|
|
@@ -5,8 +5,9 @@ from math import floor
|
|
|
5
5
|
from types import MappingProxyType
|
|
6
6
|
from urllib.parse import quote_plus
|
|
7
7
|
|
|
8
|
-
from codex.librarian.covers.create import
|
|
8
|
+
from codex.librarian.covers.create import THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH
|
|
9
9
|
from codex.models import Comic
|
|
10
|
+
from codex.settings.settings import FALSY
|
|
10
11
|
from codex.views.opds.const import AUTHOR_ROLES, MimeType, Rel
|
|
11
12
|
from codex.views.opds.util import get_contributors, get_m2m_objects
|
|
12
13
|
from codex.views.opds.v2.top_links import HrefData, LinkData, OPDS2TopLinksView
|
|
@@ -30,8 +31,6 @@ _CONTRIBUTOR_ROLES = frozenset({x for s in _MD_CONTRIBUTOR_MAP.values() for x in
|
|
|
30
31
|
class OPDS2PublicationView(OPDS2TopLinksView):
|
|
31
32
|
"""Publication Methods for OPDS 2.0 feed."""
|
|
32
33
|
|
|
33
|
-
is_opds_metadata = False
|
|
34
|
-
|
|
35
34
|
def _images(self, obj):
|
|
36
35
|
# Images
|
|
37
36
|
kwargs = {"group": obj.group, "pks": obj.ids}
|
|
@@ -46,8 +45,8 @@ class OPDS2PublicationView(OPDS2TopLinksView):
|
|
|
46
45
|
Rel.THUMBNAIL,
|
|
47
46
|
href_data,
|
|
48
47
|
mime_type=MimeType.WEBP,
|
|
49
|
-
height=
|
|
50
|
-
width=
|
|
48
|
+
height=THUMBNAIL_HEIGHT,
|
|
49
|
+
width=THUMBNAIL_WIDTH,
|
|
51
50
|
)
|
|
52
51
|
|
|
53
52
|
cover_link = self.link(link_data)
|
|
@@ -115,7 +114,7 @@ class OPDS2PublicationView(OPDS2TopLinksView):
|
|
|
115
114
|
"title": title,
|
|
116
115
|
}
|
|
117
116
|
self._publication_optional_metadata(md, obj)
|
|
118
|
-
if self.
|
|
117
|
+
if self.request.GET.get("opdsMetadata", "").lower() not in FALSY:
|
|
119
118
|
self._publication_extended_metadata(md, obj)
|
|
120
119
|
return md
|
|
121
120
|
|
codex/views/opds/v2/top_links.py
CHANGED
|
@@ -26,10 +26,7 @@ class OPDS2TopLinksView(OPDS2LinksView):
|
|
|
26
26
|
link_data = LinkData(Rel.SEARCH, href_data, template="{?query}")
|
|
27
27
|
return self.link(link_data)
|
|
28
28
|
|
|
29
|
-
def
|
|
30
|
-
"""Initialize static links."""
|
|
31
|
-
super().__init__(*args, **kwargs)
|
|
32
|
-
|
|
29
|
+
def _get_static_links(self):
|
|
33
30
|
start_href_data = HrefData(
|
|
34
31
|
{}, url_name="opds:v2:start", absolute_query_params=True
|
|
35
32
|
)
|
|
@@ -46,7 +43,7 @@ class OPDS2TopLinksView(OPDS2LinksView):
|
|
|
46
43
|
mime_type=MimeType.HTML,
|
|
47
44
|
)
|
|
48
45
|
|
|
49
|
-
|
|
46
|
+
return (
|
|
50
47
|
self._link_auth(),
|
|
51
48
|
self._link_search(),
|
|
52
49
|
self.link(start_link_data),
|
|
@@ -73,7 +70,7 @@ class OPDS2TopLinksView(OPDS2LinksView):
|
|
|
73
70
|
up_link_data = LinkData(Rel.UP, up_href_data)
|
|
74
71
|
links_data = [
|
|
75
72
|
self.link_self(),
|
|
76
|
-
*self.
|
|
73
|
+
*self._get_static_links(),
|
|
77
74
|
self._link_page("first", 1),
|
|
78
75
|
self._link_page("previous", page - 1),
|
|
79
76
|
self._link_page("next", page + 1),
|
codex/views/public.py
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
from rest_framework.generics import GenericAPIView
|
|
4
4
|
from rest_framework.mixins import RetrieveModelMixin
|
|
5
5
|
|
|
6
|
+
from codex.choices import ADMIN_FLAG_CHOICES
|
|
6
7
|
from codex.logger.logging import get_logger
|
|
7
8
|
from codex.models import AdminFlag
|
|
8
9
|
from codex.serializers.auth import AuthAdminFlagsSerializer
|
|
9
|
-
from codex.serializers.choices import CHOICES
|
|
10
10
|
|
|
11
11
|
LOG = get_logger(__name__)
|
|
12
12
|
_ADMIN_FLAG_KEYS = frozenset(
|
|
@@ -27,7 +27,7 @@ class AdminFlagsView(GenericAPIView, RetrieveModelMixin):
|
|
|
27
27
|
"""Get admin flags."""
|
|
28
28
|
flags = {}
|
|
29
29
|
for obj in self.get_queryset(): # type: ignore
|
|
30
|
-
name =
|
|
30
|
+
name = ADMIN_FLAG_CHOICES[obj.key].lower().replace(" ", "_")
|
|
31
31
|
flags[name] = obj.on
|
|
32
32
|
return flags
|
|
33
33
|
|
codex/views/reader/arcs.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""Reader get Arcs methods."""
|
|
2
2
|
|
|
3
|
-
from types import MappingProxyType
|
|
4
|
-
|
|
5
3
|
from codex.models import AdminFlag
|
|
6
4
|
from codex.util import max_none
|
|
7
5
|
from codex.views.const import (
|
|
@@ -17,7 +15,6 @@ class ReaderArcsView(ReaderBooksView):
|
|
|
17
15
|
def __init__(self, *args, **kwargs):
|
|
18
16
|
"""Initialize instance vars."""
|
|
19
17
|
super().__init__(*args, **kwargs)
|
|
20
|
-
self.params: MappingProxyType = MappingProxyType({})
|
|
21
18
|
|
|
22
19
|
def _get_group_arc(self, book, attr, browser_arc_group, arcs, max_mtime):
|
|
23
20
|
"""Append the volume arc."""
|
codex/views/reader/books.py
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from django.db.models import F
|
|
6
|
+
from django.db.models.query import Q
|
|
6
7
|
|
|
7
8
|
from codex.models import Bookmark, Comic
|
|
8
|
-
from codex.views.bookmark import
|
|
9
|
+
from codex.views.bookmark import BookmarkBaseView
|
|
9
10
|
from codex.views.browser.filters.field import ComicFieldFilterView
|
|
10
11
|
from codex.views.const import (
|
|
11
12
|
FOLDER_GROUP,
|
|
@@ -14,8 +15,8 @@ from codex.views.const import (
|
|
|
14
15
|
NONE_INTEGERFIELD,
|
|
15
16
|
STORY_ARC_GROUP,
|
|
16
17
|
)
|
|
17
|
-
from codex.views.mixins import SharedAnnotationsMixin
|
|
18
|
-
from codex.views.reader.
|
|
18
|
+
from codex.views.mixins import BookmarkSearchMixin, SharedAnnotationsMixin
|
|
19
|
+
from codex.views.reader.params import ReaderParamsView
|
|
19
20
|
|
|
20
21
|
if TYPE_CHECKING:
|
|
21
22
|
from collections.abc import Mapping
|
|
@@ -33,7 +34,9 @@ _COMIC_FIELDS = (
|
|
|
33
34
|
)
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
class ReaderBooksView(
|
|
37
|
+
class ReaderBooksView(
|
|
38
|
+
BookmarkBaseView, ReaderParamsView, SharedAnnotationsMixin, BookmarkSearchMixin
|
|
39
|
+
):
|
|
37
40
|
"""Get Books methods."""
|
|
38
41
|
|
|
39
42
|
def _get_reader_arc_pks(
|
|
@@ -62,6 +65,36 @@ class ReaderBooksView(BookmarkFilterBaseView, ReaderInitView, SharedAnnotationsM
|
|
|
62
65
|
|
|
63
66
|
return arc_pks
|
|
64
67
|
|
|
68
|
+
def _get_comics_filter(self, rel, arc, arc_pks):
|
|
69
|
+
"""Build the filter."""
|
|
70
|
+
group_acl_filter = self.get_group_acl_filter(Comic, self.request.user)
|
|
71
|
+
nav_filter = {f"{rel}__in": arc_pks}
|
|
72
|
+
query_filter = group_acl_filter & Q(**nav_filter)
|
|
73
|
+
if browser_filters := arc.get("filters"):
|
|
74
|
+
# no search at this time.
|
|
75
|
+
query_filter &= ComicFieldFilterView.get_all_comic_field_filters(
|
|
76
|
+
"", browser_filters
|
|
77
|
+
)
|
|
78
|
+
return query_filter
|
|
79
|
+
|
|
80
|
+
def _get_comics_annotation_and_ordering(self, model, arc_group, arc_pks, ordering):
|
|
81
|
+
"""Get ordering for query."""
|
|
82
|
+
sort_name_annotations = {}
|
|
83
|
+
if arc_group in ("v", "s"):
|
|
84
|
+
show = self.params["show"]
|
|
85
|
+
model_group = "i" if arc_group == "s" else "s"
|
|
86
|
+
sort_name_annotations = self.get_sort_name_annotations(
|
|
87
|
+
model, model_group, arc_pks, show
|
|
88
|
+
)
|
|
89
|
+
if sort_name_annotations and model is Comic:
|
|
90
|
+
ordering += (*sort_name_annotations.keys(),)
|
|
91
|
+
ordering += (
|
|
92
|
+
"issue_number",
|
|
93
|
+
"issue_suffix",
|
|
94
|
+
"sort_name",
|
|
95
|
+
)
|
|
96
|
+
return sort_name_annotations, tuple(ordering)
|
|
97
|
+
|
|
65
98
|
def _get_comics_list(self):
|
|
66
99
|
"""Get the reader naviation group filter."""
|
|
67
100
|
arc: Mapping = self.params.get("arc", {}) # type: ignore
|
|
@@ -74,63 +107,45 @@ class ReaderBooksView(BookmarkFilterBaseView, ReaderInitView, SharedAnnotationsM
|
|
|
74
107
|
fields = _COMIC_FIELDS
|
|
75
108
|
arc_pk_rel = rel + "__pk"
|
|
76
109
|
arc_index = NONE_INTEGERFIELD
|
|
77
|
-
ordering = ()
|
|
78
110
|
arc_pk_select_related = (rel,)
|
|
79
111
|
select_related = ()
|
|
80
112
|
prefetch_related = ()
|
|
113
|
+
ordering = ()
|
|
81
114
|
|
|
82
115
|
if arc_group == STORY_ARC_GROUP:
|
|
83
|
-
prefetch_related = (*prefetch_related, rel)
|
|
84
116
|
arc_index = F("story_arc_numbers__number")
|
|
85
|
-
ordering = ("arc_index", "date", "pk")
|
|
86
117
|
arc_pk_select_related = ()
|
|
118
|
+
prefetch_related = (*prefetch_related, rel)
|
|
119
|
+
ordering = ("arc_index", "date", "pk")
|
|
87
120
|
elif arc_group == FOLDER_GROUP:
|
|
88
|
-
select_related = (rel,)
|
|
89
121
|
fields = (*_COMIC_FIELDS, rel)
|
|
122
|
+
select_related = (rel,)
|
|
90
123
|
ordering = ("path", "pk")
|
|
91
124
|
|
|
92
125
|
arc_pks = self._get_reader_arc_pks(
|
|
93
126
|
arc, arc_pk_select_related, prefetch_related, arc_pk_rel, arc_group
|
|
94
127
|
)
|
|
95
|
-
group_acl_filter = self.get_group_acl_filter(Comic)
|
|
96
|
-
nav_filter = {f"{rel}__in": arc_pks}
|
|
97
128
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
# no search at this time.
|
|
101
|
-
field_filters = ComicFieldFilterView.get_all_comic_field_filters(
|
|
102
|
-
"", browser_filters
|
|
103
|
-
)
|
|
104
|
-
qs = qs.filter(field_filters)
|
|
129
|
+
query_filter = self._get_comics_filter(rel, arc, arc_pks)
|
|
130
|
+
qs = Comic.objects.filter(query_filter)
|
|
105
131
|
|
|
106
132
|
if select_related:
|
|
107
133
|
qs = qs.select_related(*select_related)
|
|
108
134
|
if prefetch_related:
|
|
109
135
|
qs = qs.prefetch_related(*prefetch_related)
|
|
110
|
-
qs = (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
arc_index=arc_index,
|
|
118
|
-
)
|
|
119
|
-
.annotate(mtime=F("updated_at"))
|
|
136
|
+
qs = qs.only(*fields)
|
|
137
|
+
qs = self.annotate_group_names(qs)
|
|
138
|
+
qs = qs.annotate(
|
|
139
|
+
issue_count=F("volume__issue_count"),
|
|
140
|
+
arc_pk=F(arc_pk_rel),
|
|
141
|
+
arc_index=arc_index,
|
|
142
|
+
mtime=F("updated_at"),
|
|
120
143
|
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
qs
|
|
126
|
-
qs, Comic, pks=arc_pks, model_group=model_group, show=show
|
|
127
|
-
)
|
|
128
|
-
ordering = (
|
|
129
|
-
*comic_sort_names,
|
|
130
|
-
"issue_number",
|
|
131
|
-
"issue_suffix",
|
|
132
|
-
"sort_name",
|
|
133
|
-
)
|
|
144
|
+
sort_names_alias, ordering = self._get_comics_annotation_and_ordering(
|
|
145
|
+
qs.model, arc_group, arc_pks, ordering
|
|
146
|
+
)
|
|
147
|
+
if sort_names_alias:
|
|
148
|
+
qs = qs.alias(**sort_names_alias)
|
|
134
149
|
qs = qs.order_by(*ordering)
|
|
135
150
|
return qs, arc_group
|
|
136
151
|
|
|
@@ -153,7 +168,8 @@ class ReaderBooksView(BookmarkFilterBaseView, ReaderInitView, SharedAnnotationsM
|
|
|
153
168
|
Yields 1 to 3 books
|
|
154
169
|
"""
|
|
155
170
|
comics, arc_group = self._get_comics_list()
|
|
156
|
-
|
|
171
|
+
auth_filter = self.get_bookmark_auth_filter()
|
|
172
|
+
bookmark_filter = self.get_bookmark_search_kwargs(auth_filter)
|
|
157
173
|
books = {}
|
|
158
174
|
prev_book = None
|
|
159
175
|
pk = self.kwargs.get("pk")
|
codex/views/reader/page.py
CHANGED
|
@@ -9,6 +9,8 @@ from drf_spectacular.utils import OpenApiParameter, extend_schema
|
|
|
9
9
|
from rest_framework.exceptions import NotFound
|
|
10
10
|
from rest_framework.negotiation import BaseContentNegotiation
|
|
11
11
|
|
|
12
|
+
from codex.librarian.bookmark.tasks import BookmarkUpdateTask
|
|
13
|
+
from codex.librarian.mp_queue import LIBRARIAN_QUEUE
|
|
12
14
|
from codex.logger.logging import get_logger
|
|
13
15
|
from codex.models.comic import Comic, FileType
|
|
14
16
|
from codex.settings.settings import FALSY
|
|
@@ -55,15 +57,19 @@ class ReaderPageView(BookmarkBaseView):
|
|
|
55
57
|
)
|
|
56
58
|
if not do_bookmark:
|
|
57
59
|
return
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
|
|
61
|
+
auth_filter = self.get_bookmark_auth_filter()
|
|
60
62
|
pk = self.kwargs.get("pk")
|
|
61
63
|
comic_filter = {"pk": pk}
|
|
62
|
-
self.
|
|
64
|
+
page = self.kwargs.get("page")
|
|
65
|
+
updates = {"page": page}
|
|
66
|
+
|
|
67
|
+
task = BookmarkUpdateTask(auth_filter, comic_filter, updates)
|
|
68
|
+
LIBRARIAN_QUEUE.put(task)
|
|
63
69
|
|
|
64
70
|
def _get_page_image(self):
|
|
65
71
|
"""Get the image data and content type."""
|
|
66
|
-
group_acl_filter = self.get_group_acl_filter(Comic)
|
|
72
|
+
group_acl_filter = self.get_group_acl_filter(Comic, self.request.user)
|
|
67
73
|
pk = self.kwargs.get("pk")
|
|
68
74
|
comic = Comic.objects.filter(group_acl_filter).only("path").get(pk=pk)
|
|
69
75
|
page = self.kwargs.get("page")
|