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/choices.py
ADDED
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
"""Frontend Choices, Defaults and Messages."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from types import MappingProxyType
|
|
5
|
+
|
|
6
|
+
BROWSER_BOOKMARK_FILTER_CHOICES = MappingProxyType(
|
|
7
|
+
{
|
|
8
|
+
"": "All",
|
|
9
|
+
"IN_PROGRESS": "In Progress",
|
|
10
|
+
"READ": "Read",
|
|
11
|
+
"UNREAD": "Unread",
|
|
12
|
+
},
|
|
13
|
+
)
|
|
14
|
+
BROWSER_ORDER_BY_CHOICES = MappingProxyType(
|
|
15
|
+
{
|
|
16
|
+
"age_rating": "Age Rating",
|
|
17
|
+
"bookmark_updated_at": "Last Read",
|
|
18
|
+
"community_rating": "Community Rating",
|
|
19
|
+
"created_at": "Added Time",
|
|
20
|
+
"critical_rating": "Critical Rating",
|
|
21
|
+
"date": "Publish Date",
|
|
22
|
+
"filename": "Filename",
|
|
23
|
+
"page_count": "Page Count",
|
|
24
|
+
"search_score": "Search Score",
|
|
25
|
+
"size": "File Size",
|
|
26
|
+
"sort_name": "Name",
|
|
27
|
+
"story_arc_number": "Story Arc Number",
|
|
28
|
+
"updated_at": "Updated Time",
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
_GROUP_NAMES = {
|
|
32
|
+
"p": "Publishers",
|
|
33
|
+
"i": "Imprints",
|
|
34
|
+
"s": "Series",
|
|
35
|
+
"v": "Volumes",
|
|
36
|
+
}
|
|
37
|
+
BROWSER_TOP_GROUP_CHOICES = MappingProxyType(
|
|
38
|
+
{
|
|
39
|
+
**_GROUP_NAMES,
|
|
40
|
+
"c": "Issues",
|
|
41
|
+
"f": "Folders",
|
|
42
|
+
"a": "Story Arcs",
|
|
43
|
+
},
|
|
44
|
+
)
|
|
45
|
+
VUETIFY_NULL_CODE = -1
|
|
46
|
+
BROWSER_CHOICES = MappingProxyType(
|
|
47
|
+
{
|
|
48
|
+
"bookmark_filter": BROWSER_BOOKMARK_FILTER_CHOICES,
|
|
49
|
+
"order_by": BROWSER_ORDER_BY_CHOICES,
|
|
50
|
+
"top_group": BROWSER_TOP_GROUP_CHOICES,
|
|
51
|
+
"vuetify_null_code": VUETIFY_NULL_CODE,
|
|
52
|
+
"settings_group": {**_GROUP_NAMES},
|
|
53
|
+
"identifier_types": {
|
|
54
|
+
"comicvine": "Comic Vine",
|
|
55
|
+
"comixology": "Comixology",
|
|
56
|
+
"asin": "Amazon",
|
|
57
|
+
"gtin": "GTIN",
|
|
58
|
+
"isbn": "ISBN",
|
|
59
|
+
"upc": "UPC",
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
READER_CHOICES = MappingProxyType(
|
|
65
|
+
{
|
|
66
|
+
"fit_to": MappingProxyType(
|
|
67
|
+
{
|
|
68
|
+
"H": "Fit to Height",
|
|
69
|
+
"O": "Original Size",
|
|
70
|
+
"S": "Fit to Screen",
|
|
71
|
+
"W": "Fit to Width",
|
|
72
|
+
}
|
|
73
|
+
),
|
|
74
|
+
"reading_direction": MappingProxyType(
|
|
75
|
+
{
|
|
76
|
+
"btt": "Bottom to Top",
|
|
77
|
+
"ltr": "Left to Right",
|
|
78
|
+
"rtl": "Right to Left",
|
|
79
|
+
"ttb": "Top to Bottom",
|
|
80
|
+
}
|
|
81
|
+
),
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
DEFAULT_BROWSER_ROUTE = MappingProxyType({"group": "r", "pks": (0,), "page": 1})
|
|
85
|
+
_DEFAULT_BROWSER_BREADCRUMBS = (DEFAULT_BROWSER_ROUTE,)
|
|
86
|
+
_DEFAULT_SHOW = MappingProxyType({"i": False, "p": True, "s": True, "v": False})
|
|
87
|
+
BROWSER_DEFAULTS = MappingProxyType(
|
|
88
|
+
{
|
|
89
|
+
"bookmark_filter": "",
|
|
90
|
+
"breadcrumbs": _DEFAULT_BROWSER_BREADCRUMBS,
|
|
91
|
+
"custom_covers": True,
|
|
92
|
+
"dynamic_covers": True,
|
|
93
|
+
"order_by": "sort_name",
|
|
94
|
+
"order_reverse": False,
|
|
95
|
+
"q": "",
|
|
96
|
+
# "search_results_limit": 100,
|
|
97
|
+
"show": _DEFAULT_SHOW,
|
|
98
|
+
"top_group": "p",
|
|
99
|
+
"twenty_four_hour_time": False,
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
READER_DEFAULTS = MappingProxyType(
|
|
103
|
+
{
|
|
104
|
+
"finish_on_last_page": True,
|
|
105
|
+
"fit_to": "S",
|
|
106
|
+
"reading_direction": "ltr",
|
|
107
|
+
"read_rtl_in_reverse": False,
|
|
108
|
+
"two_pages": False,
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
ADMIN_FLAG_CHOICES = MappingProxyType(
|
|
113
|
+
{
|
|
114
|
+
"AU": "Auto Update",
|
|
115
|
+
"FV": "Folder View",
|
|
116
|
+
"IM": "Import Metadata on Library Scan",
|
|
117
|
+
"NU": "Non Users",
|
|
118
|
+
"RG": "Registration",
|
|
119
|
+
"ST": "Send Stats",
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
ADMIN_STATUS_TITLES = MappingProxyType(
|
|
124
|
+
{
|
|
125
|
+
"CCC": "Create Covers",
|
|
126
|
+
"CCD": "Remove Covers",
|
|
127
|
+
"CFO": "Find Orphan Covers",
|
|
128
|
+
"IAF": "Adopt Orphan Folders",
|
|
129
|
+
"ICC": "Create Custom Covers",
|
|
130
|
+
"ICD": "Delete Custom Covers",
|
|
131
|
+
"ICL": "Link Custom Covers",
|
|
132
|
+
"ICM": "Custom Covers Moved",
|
|
133
|
+
"ICQ": "Discover Missing Custom Covers",
|
|
134
|
+
"ICU": "Modify Custom Covers",
|
|
135
|
+
"IDD": "Remove Folders",
|
|
136
|
+
"IDM": "Move Folders",
|
|
137
|
+
"IDU": "Modify Folders",
|
|
138
|
+
"IFC": "Create Books",
|
|
139
|
+
"IFD": "Remove Books",
|
|
140
|
+
"IFI": "Record Failed Imports",
|
|
141
|
+
"IFM": "Move Books",
|
|
142
|
+
"IFU": "Modify Books",
|
|
143
|
+
"IGU": "Update First Covers",
|
|
144
|
+
"IMC": "Link Books to Tags",
|
|
145
|
+
"IMQ": "Prepare Tags for Linking",
|
|
146
|
+
"ITC": "Create Missing Tags",
|
|
147
|
+
"ITQ": "Discover Missing Tags",
|
|
148
|
+
"ITR": "Read Book Tags",
|
|
149
|
+
"JCB": "Cleanup Orphan Bookmarks",
|
|
150
|
+
"JCD": "Cleanup Custom Covers",
|
|
151
|
+
"JCR": "Restart Codex",
|
|
152
|
+
"JCS": "Stop Codex",
|
|
153
|
+
"JCU": "Update Codex Software",
|
|
154
|
+
"JDB": "Backup Database",
|
|
155
|
+
"JDO": "Optimize Database",
|
|
156
|
+
"JFC": "Search Index Integrity Check",
|
|
157
|
+
"JFR": "Search Index Repair",
|
|
158
|
+
"JIC": "Database Integrity Check",
|
|
159
|
+
"JIF": "Database Foreign Key Check",
|
|
160
|
+
"JLV": "Check Codex Latest Version",
|
|
161
|
+
"JSD": "Cleanup Expired Sessions",
|
|
162
|
+
"JTD": "Cleanup Stale Tags",
|
|
163
|
+
"SIC": "Search Index Create",
|
|
164
|
+
"SID": "Search Index Remove Stale Records",
|
|
165
|
+
"SIO": "Search Index Optimize",
|
|
166
|
+
"SIU": "Search Index Update",
|
|
167
|
+
"SIX": "Search Index Clear",
|
|
168
|
+
"WPO": "Poll Library",
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Easier to store in vuetify format
|
|
173
|
+
ADMIN_TASK_GROUPS = MappingProxyType(
|
|
174
|
+
{
|
|
175
|
+
"tasks": (
|
|
176
|
+
{
|
|
177
|
+
"title": "Libraries",
|
|
178
|
+
"tasks": [
|
|
179
|
+
{
|
|
180
|
+
"value": "poll",
|
|
181
|
+
"title": "Poll All Libraries",
|
|
182
|
+
"desc": "Update Libraries if changes detected",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"value": "poll_force",
|
|
186
|
+
"title": "Force Update All Libraries",
|
|
187
|
+
"desc": "Forcibly update all comics in all libraries",
|
|
188
|
+
"confirm": "This can take a long time",
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"value": "force_update_all_failed_imports",
|
|
192
|
+
"title": "Update All Failed Imports",
|
|
193
|
+
"desc": "Forcibly update all failed imports in all libraries",
|
|
194
|
+
"confirm": "This can take a long time",
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"value": "watchdog_sync",
|
|
198
|
+
"title": "Sync Watchdog with DB",
|
|
199
|
+
"desc": "Ensure the Watchdog file watcher is enabled per database preferences for each library",
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"title": "Covers",
|
|
205
|
+
"tasks": [
|
|
206
|
+
{
|
|
207
|
+
"value": "purge_comic_covers",
|
|
208
|
+
"title": "Remove Comic Covers",
|
|
209
|
+
"desc": "from every library",
|
|
210
|
+
"confirm": "Are you sure?",
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"value": "create_all_comic_covers",
|
|
214
|
+
"title": "Create All Comic Covers",
|
|
215
|
+
"desc": "Pre-generate covers for every comic in every library and all custom covers",
|
|
216
|
+
"confirm": "Are you sure?",
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"value": "force_update_groups",
|
|
220
|
+
"title": "Update Group Timestamps",
|
|
221
|
+
"desc": "Force the update of group timestamps. Will bust the browser cache for browser views and covers.",
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"title": "Search Index",
|
|
227
|
+
"tasks": [
|
|
228
|
+
{
|
|
229
|
+
"value": "search_index_update",
|
|
230
|
+
"title": "Update Search Index",
|
|
231
|
+
"desc": "with recently changed comics",
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"value": "search_index_optimize",
|
|
235
|
+
"title": "Optimize Search Index",
|
|
236
|
+
"desc": "Merge Search Index for optimal lookup time. Runs nightly.",
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"value": "search_index_rebuild",
|
|
240
|
+
"title": "Rebuild Search Index",
|
|
241
|
+
"desc": "Delete and rebuild the search index from scratch",
|
|
242
|
+
"confirm": "This can take a long time",
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"value": "search_index_remove_stale",
|
|
246
|
+
"title": "Remove Stale Index Entries",
|
|
247
|
+
"desc": "Remove search index entries that are no longer in the library.",
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"value": "search_index_abort",
|
|
251
|
+
"title": "Abort Search Indexing",
|
|
252
|
+
"desc": "Aborts search index update and remove tasks.",
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"value": "search_index_clear",
|
|
256
|
+
"title": "Clear Search Index",
|
|
257
|
+
"desc": "of all entries",
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"value": "db_fts_integrity_check",
|
|
261
|
+
"title": "Integrity Check Search Index",
|
|
262
|
+
"desc": "Repairs Search Index on failure. Runs nightly",
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"value": "db_fts_rebuild",
|
|
266
|
+
"title": "Repair Search Index",
|
|
267
|
+
"desc": "Probably faster than Rebuild if integrity check fails.",
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"title": "Database",
|
|
273
|
+
"tasks": [
|
|
274
|
+
{
|
|
275
|
+
"value": "db_vacuum",
|
|
276
|
+
"title": "Optimize & Compact Database",
|
|
277
|
+
"desc": "Run the sqlite3 OPTIMIZE and VACUUM pragmas. Runs nightly",
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"value": "db_backup",
|
|
281
|
+
"title": "Backup Database",
|
|
282
|
+
"desc": "Runs nightly",
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"value": "db_foreign_key_check",
|
|
286
|
+
"title": "Remove Illegal Foreign Keys",
|
|
287
|
+
"desc": "Check for and remove illegal foreign keys. Mark affected comics for update. Runs nightly.",
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"value": "db_integrity_check_quick",
|
|
291
|
+
"title": "Check Database Integrity Quickly",
|
|
292
|
+
"desc": "Check logs for results. Runs nightly.",
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"value": "db_integrity_check_long",
|
|
296
|
+
"title": "Check Database Integrity Thoroughly",
|
|
297
|
+
"desc": "Check logs for results.",
|
|
298
|
+
"confirm": "Can take a while on large databases, Are you sure?",
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"title": "Codex Software",
|
|
304
|
+
"tasks": [
|
|
305
|
+
{
|
|
306
|
+
"value": "codex_latest_version",
|
|
307
|
+
"title": "Check for Codex Latest Version",
|
|
308
|
+
"desc": "Check PyPi for the latest version of Codex",
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"value": "codex_update",
|
|
312
|
+
"title": "Update Codex",
|
|
313
|
+
"desc": "If Codex updates to a new version, it will restart",
|
|
314
|
+
"confirm": "Are you sure?",
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"value": "codex_restart",
|
|
318
|
+
"title": "Restart Codex Server",
|
|
319
|
+
"desc": "Immediately",
|
|
320
|
+
"confirm": "Are you sure?",
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"value": "codex_shutdown",
|
|
324
|
+
"title": "Shutdown Codex Server",
|
|
325
|
+
"desc": "Immediately",
|
|
326
|
+
"confirm": "Are you sure?",
|
|
327
|
+
},
|
|
328
|
+
],
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"title": "Notify",
|
|
332
|
+
"tasks": [
|
|
333
|
+
{
|
|
334
|
+
"value": "notify_library_changed",
|
|
335
|
+
"title": "Notify Library Changed ",
|
|
336
|
+
"desc": "Signal all clients that the libraries have changed and the browser should fetch new data.",
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"value": "notify_librarian_status",
|
|
340
|
+
"title": "Notify Librarian Status",
|
|
341
|
+
"desc": "Signal Admin clients to fetch librarian status.",
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"title": "Cleanup",
|
|
347
|
+
"tasks": [
|
|
348
|
+
{
|
|
349
|
+
"value": "cleanup_fks",
|
|
350
|
+
"title": "Remove Orphan Tags",
|
|
351
|
+
"desc": "After deleting comics, unused linked objects remain in case new comics use them. Runs nightly.",
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"value": "cleanup_db_custom_covers",
|
|
355
|
+
"title": "Remove Orphan Database Custom Covers",
|
|
356
|
+
"desc": "Remove Custom Covers from the db that no longer represent custom cover images on disk. Runs nightly.",
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"value": "cleanup_sessions",
|
|
360
|
+
"title": "Cleanup Sessions",
|
|
361
|
+
"desc": "Remove corrupt and expired sessions. Runs nightly.",
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"value": "cleanup_covers",
|
|
365
|
+
"title": "Remove Orphan Cover Thumbnails",
|
|
366
|
+
"desc": "no longer have source comics or custom images. Runs nightly.",
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
"value": "cleanup_bookmarks",
|
|
370
|
+
"title": "Remove Orphan Bookmarks",
|
|
371
|
+
"desc": "Owned by no session or user. Runs nightly.",
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"value": "adopt_folders",
|
|
375
|
+
"title": "Adopt Orphan Folders",
|
|
376
|
+
"desc": "Move orphaned folders from the top of the folder tree to under their correct parent. Runs nightly and at startup.",
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
"value": "librarian_clear_status",
|
|
380
|
+
"title": "Clear Librarian Statuses",
|
|
381
|
+
"desc": "Mark all Librarian tasks finished.",
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
"value": "janitor_nightly",
|
|
385
|
+
"title": "Run Nightly Maintenance",
|
|
386
|
+
"desc": "Runs several tasks above that also run nightly.",
|
|
387
|
+
"confirm": "Launches several tasks that run nightly anyway.",
|
|
388
|
+
},
|
|
389
|
+
],
|
|
390
|
+
},
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def _group_task_values(groups):
|
|
397
|
+
"""Extract values into sorted tuple."""
|
|
398
|
+
values = []
|
|
399
|
+
for group in groups["tasks"]:
|
|
400
|
+
for item in group["tasks"]:
|
|
401
|
+
values.append(item["value"])
|
|
402
|
+
return tuple(sorted(values))
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
ADMIN_TASKS = _group_task_values(ADMIN_TASK_GROUPS)
|
|
406
|
+
WEBSOCKET_MESSAGES = MappingProxyType(
|
|
407
|
+
{
|
|
408
|
+
"messages": {
|
|
409
|
+
"FAILED_IMPORTS": "FAILED_IMPORTS",
|
|
410
|
+
"LIBRARY_CHANGED": "LIBRARY_CHANGED",
|
|
411
|
+
"LIBRARIAN_STATUS": "LIBRARIAN_STATUS",
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
)
|
|
415
|
+
DUMMY_NULL_NAME = "_none_"
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def mapping_to_dict(data):
|
|
419
|
+
"""Convert nested Mapping objects to dicts."""
|
|
420
|
+
if isinstance(data, Mapping):
|
|
421
|
+
return {key: mapping_to_dict(value) for key, value in data.items()}
|
|
422
|
+
if isinstance(data, list | tuple | frozenset | set):
|
|
423
|
+
return [mapping_to_dict(item) for item in data]
|
|
424
|
+
return data
|
codex/choices_to_json.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Dump choices to JSON."""
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from types import MappingProxyType
|
|
8
|
+
|
|
9
|
+
from caseconverter import camelcase
|
|
10
|
+
|
|
11
|
+
from codex.choices import (
|
|
12
|
+
ADMIN_FLAG_CHOICES,
|
|
13
|
+
ADMIN_STATUS_TITLES,
|
|
14
|
+
ADMIN_TASK_GROUPS,
|
|
15
|
+
BROWSER_CHOICES,
|
|
16
|
+
BROWSER_DEFAULTS,
|
|
17
|
+
READER_CHOICES,
|
|
18
|
+
READER_DEFAULTS,
|
|
19
|
+
WEBSOCKET_MESSAGES,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
_DEFAULTS = MappingProxyType(
|
|
23
|
+
{"browser-choices.json": BROWSER_DEFAULTS, "reader-choices.json": READER_DEFAULTS}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
_DUMPS = MappingProxyType(
|
|
27
|
+
{
|
|
28
|
+
"admin-flag-choices.json": ADMIN_FLAG_CHOICES,
|
|
29
|
+
"admin-status-titles.json": ADMIN_STATUS_TITLES,
|
|
30
|
+
"browser-choices.json": BROWSER_CHOICES,
|
|
31
|
+
"reader-choices.json": READER_CHOICES,
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
_MAP_DUMPS = MappingProxyType(
|
|
36
|
+
{
|
|
37
|
+
"admin-tasks.json": ADMIN_TASK_GROUPS,
|
|
38
|
+
"browser-defaults.json": BROWSER_DEFAULTS,
|
|
39
|
+
"browser-map.json": BROWSER_CHOICES,
|
|
40
|
+
"reader-map.json": READER_CHOICES,
|
|
41
|
+
"websocket-messages.json": WEBSOCKET_MESSAGES,
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _to_vuetify_choices(defaults, key, obj_map):
|
|
47
|
+
"""Transform a dict into a list of vuetify choices."""
|
|
48
|
+
default = defaults.get(key)
|
|
49
|
+
vuetify_list = []
|
|
50
|
+
for value, title in obj_map.items():
|
|
51
|
+
vuetify_dict = {
|
|
52
|
+
"value": value,
|
|
53
|
+
"title": title,
|
|
54
|
+
}
|
|
55
|
+
if default == value:
|
|
56
|
+
vuetify_dict["default"] = True
|
|
57
|
+
vuetify_list.append(vuetify_dict)
|
|
58
|
+
return vuetify_list
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _json_key(key):
|
|
62
|
+
"""Transform key to json version."""
|
|
63
|
+
return key if key.upper() == key else camelcase(key)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _make_json_serializable(data):
|
|
67
|
+
"""Convert nested Mapping objects to dicts."""
|
|
68
|
+
if isinstance(data, Mapping):
|
|
69
|
+
json_dict = {}
|
|
70
|
+
for key, value in data.items():
|
|
71
|
+
if key == "pks":
|
|
72
|
+
# Special route serializer
|
|
73
|
+
# XXX possibly should use actual route serializer for route not just pks
|
|
74
|
+
json_dict[key] = ",".join(str(pk) for pk in sorted(value))
|
|
75
|
+
else:
|
|
76
|
+
json_dict[_json_key(key)] = _make_json_serializable(value)
|
|
77
|
+
return json_dict
|
|
78
|
+
if isinstance(data, list | tuple | frozenset | set):
|
|
79
|
+
return [_make_json_serializable(item) for item in data]
|
|
80
|
+
return data
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _to_vuetify_dict(fn, data):
|
|
84
|
+
"""Convert mappings to vuetify dict list."""
|
|
85
|
+
vuetify_data = {}
|
|
86
|
+
defaults = _DEFAULTS.get(fn) or {}
|
|
87
|
+
for key, obj in data.items():
|
|
88
|
+
if isinstance(obj, Mapping):
|
|
89
|
+
vuetify_value = _to_vuetify_choices(defaults, key, obj)
|
|
90
|
+
else:
|
|
91
|
+
vuetify_value = _make_json_serializable(obj)
|
|
92
|
+
vuetify_data[_json_key(key)] = vuetify_value
|
|
93
|
+
return vuetify_data
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _dump(parent_path, fn, data, vuetify=True):
|
|
97
|
+
"""Dump data to json file."""
|
|
98
|
+
vuetify_data = (
|
|
99
|
+
_to_vuetify_dict(fn, data) if vuetify else _make_json_serializable(data)
|
|
100
|
+
)
|
|
101
|
+
path = parent_path / Path(fn)
|
|
102
|
+
with path.open("w") as json_file:
|
|
103
|
+
json.dump(vuetify_data, json_file, indent=2)
|
|
104
|
+
json_file.write("\n")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def main():
|
|
108
|
+
"""Dump all files."""
|
|
109
|
+
import sys
|
|
110
|
+
|
|
111
|
+
parent_path = sys.argv[1] if len(sys.argv) > 1 else "."
|
|
112
|
+
parent_path = Path(parent_path)
|
|
113
|
+
parent_path.mkdir(exist_ok=True)
|
|
114
|
+
for fn, data in _DUMPS.items():
|
|
115
|
+
_dump(parent_path, fn, data)
|
|
116
|
+
|
|
117
|
+
for fn, data in _MAP_DUMPS.items():
|
|
118
|
+
_dump(parent_path, fn, data, False)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
main()
|
codex/db.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Low level database utilities."""
|
|
2
2
|
|
|
3
|
-
import re
|
|
4
3
|
import sqlite3
|
|
4
|
+
import subprocess
|
|
5
5
|
|
|
6
6
|
from django.core.management import call_command
|
|
7
7
|
from django.db import DEFAULT_DB_ALIAS, connection, connections
|
|
@@ -29,9 +29,9 @@ from codex.settings.settings import (
|
|
|
29
29
|
)
|
|
30
30
|
from codex.version import VERSION
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
_REPAIR_FLAG_PATH = CONFIG_PATH / "rebuild_db"
|
|
33
|
+
_REBUILT_DB_PATH = DB_PATH.parent / (DB_PATH.name + ".rebuilt")
|
|
34
|
+
_REPAIR_ARGS = ("sqlite3", DB_PATH, ".recover")
|
|
35
35
|
|
|
36
36
|
LOG = get_logger(__name__)
|
|
37
37
|
|
|
@@ -82,24 +82,38 @@ def _repair_db():
|
|
|
82
82
|
def _rebuild_db():
|
|
83
83
|
"""Dump and rebuild the database."""
|
|
84
84
|
# Drastic
|
|
85
|
-
if not
|
|
86
|
-
return
|
|
85
|
+
if not _REPAIR_FLAG_PATH.exists():
|
|
86
|
+
return False
|
|
87
87
|
|
|
88
88
|
LOG.warning("REBUILDING DATABASE!!")
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
_REBUILT_DB_PATH.unlink(missing_ok=True)
|
|
90
|
+
recover_proc = subprocess.Popen(_REPAIR_ARGS, stdout=subprocess.PIPE) # noqa: S603
|
|
91
|
+
with sqlite3.connect(_REBUILT_DB_PATH) as new_db_conn:
|
|
91
92
|
new_db_cur = new_db_conn.cursor()
|
|
92
|
-
|
|
93
|
-
for line in
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
if recover_proc.stdout:
|
|
94
|
+
for line in recover_proc.stdout:
|
|
95
|
+
row = line.decode().strip()
|
|
96
|
+
replaced_row = (
|
|
97
|
+
"PRAGMA writable_schema = reset;"
|
|
98
|
+
if row == "PRAGMA writable_schema = off;"
|
|
99
|
+
else row
|
|
100
|
+
)
|
|
101
|
+
new_db_cur.execute(replaced_row)
|
|
102
|
+
new_db_cur.close()
|
|
103
|
+
if recover_proc.stdout:
|
|
104
|
+
recover_proc.stdout.close()
|
|
105
|
+
recover_proc.wait(timeout=15)
|
|
97
106
|
|
|
98
107
|
backup_path = _get_backup_db_path("before-rebuild")
|
|
99
108
|
DB_PATH.rename(backup_path)
|
|
100
109
|
LOG.info("Backed up old db to %s", backup_path)
|
|
101
|
-
|
|
110
|
+
_REBUILT_DB_PATH.replace(DB_PATH)
|
|
111
|
+
_REPAIR_FLAG_PATH.unlink(missing_ok=True)
|
|
102
112
|
LOG.info("Rebuilt database.")
|
|
113
|
+
LOG.info("You may start codex normally now.")
|
|
114
|
+
for handler in LOG.handlers:
|
|
115
|
+
handler.flush()
|
|
116
|
+
return True
|
|
103
117
|
|
|
104
118
|
|
|
105
119
|
def ensure_db_schema():
|
|
@@ -107,7 +121,8 @@ def ensure_db_schema():
|
|
|
107
121
|
LOG.info("Ensuring database is correct and up to date...")
|
|
108
122
|
table_names = connection.introspection.table_names()
|
|
109
123
|
if db_exists := "django_migrations" in table_names:
|
|
110
|
-
_rebuild_db()
|
|
124
|
+
if _rebuild_db():
|
|
125
|
+
return False
|
|
111
126
|
_repair_db()
|
|
112
127
|
|
|
113
128
|
if not db_exists or _has_unapplied_migrations():
|
|
@@ -117,3 +132,4 @@ def ensure_db_schema():
|
|
|
117
132
|
else:
|
|
118
133
|
LOG.info("Database up to date.")
|
|
119
134
|
LOG.info("Database ready.")
|
|
135
|
+
return True
|
codex/exceptions.py
CHANGED
|
@@ -11,8 +11,8 @@ from django.utils.http import urlencode
|
|
|
11
11
|
from rest_framework.exceptions import APIException
|
|
12
12
|
from rest_framework.status import HTTP_303_SEE_OTHER
|
|
13
13
|
|
|
14
|
+
from codex.choices import DEFAULT_BROWSER_ROUTE
|
|
14
15
|
from codex.logger.logging import get_logger
|
|
15
|
-
from codex.serializers.choices import DEFAULTS
|
|
16
16
|
from codex.serializers.fields import BreadcrumbsField
|
|
17
17
|
from codex.serializers.route import RouteSerializer
|
|
18
18
|
from codex.views.util import pop_name
|
|
@@ -24,7 +24,6 @@ if TYPE_CHECKING:
|
|
|
24
24
|
LOG = get_logger(__name__)
|
|
25
25
|
_OPDS_REDIRECT_SETTINGS_KEYS = ("order_by", "top_group")
|
|
26
26
|
_REDIRECT_SETTINGS_KEYS = ("breadcrumbs", *_OPDS_REDIRECT_SETTINGS_KEYS)
|
|
27
|
-
_DEFAULT_ROUTE = DEFAULTS["breadcrumbs"][0]
|
|
28
27
|
|
|
29
28
|
|
|
30
29
|
class SeeOtherRedirectError(APIException):
|
|
@@ -41,7 +40,7 @@ class SeeOtherRedirectError(APIException):
|
|
|
41
40
|
|
|
42
41
|
# Get route params
|
|
43
42
|
route = detail.get("route", {})
|
|
44
|
-
params = route.get("params",
|
|
43
|
+
params = route.get("params", DEFAULT_BROWSER_ROUTE)
|
|
45
44
|
params = pop_name(params)
|
|
46
45
|
route = deepcopy(route)
|
|
47
46
|
route["params"] = params
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Bookmark Thread."""
|