codex 1.7.3a2__py3-none-any.whl → 1.7.4__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/asgi.py +2 -1
- codex/choices.py +12 -12
- codex/choices_to_json.py +8 -8
- codex/db.py +2 -2
- codex/exceptions.py +6 -7
- codex/librarian/bookmark/bookmarkd.py +8 -4
- codex/librarian/bookmark/update.py +82 -48
- codex/librarian/covers/create.py +10 -8
- codex/librarian/covers/path.py +6 -5
- codex/librarian/covers/purge.py +2 -2
- codex/librarian/importer/aggregate.py +2 -2
- codex/librarian/importer/cache.py +1 -4
- codex/librarian/importer/create_comics.py +2 -2
- codex/librarian/importer/create_covers.py +1 -1
- codex/librarian/importer/create_fks.py +4 -3
- codex/librarian/importer/deleted.py +3 -3
- codex/librarian/importer/extract.py +56 -37
- codex/librarian/importer/failed_imports.py +1 -1
- codex/librarian/importer/importer.py +3 -1
- codex/librarian/importer/importerd.py +3 -3
- codex/librarian/importer/link_comics.py +2 -1
- codex/librarian/importer/moved.py +2 -7
- codex/librarian/importer/query_fks.py +1 -4
- codex/librarian/importer/tasks.py +1 -1
- codex/librarian/janitor/integrity.py +27 -20
- codex/librarian/janitor/janitor.py +1 -1
- codex/librarian/janitor/latest_version.py +1 -1
- codex/librarian/janitor/update.py +2 -2
- codex/librarian/janitor/vacuum.py +1 -1
- codex/librarian/librariand.py +3 -2
- codex/librarian/notifier/notifierd.py +2 -1
- codex/librarian/search/optimize.py +1 -1
- codex/librarian/search/remove.py +1 -1
- codex/librarian/search/update.py +4 -4
- codex/librarian/telemeter/stats.py +7 -6
- codex/librarian/telemeter/telemeter.py +0 -1
- codex/librarian/watchdog/db_snapshot.py +3 -3
- codex/librarian/watchdog/dir_snapshot_diff.py +3 -4
- codex/librarian/watchdog/emitter.py +4 -4
- codex/librarian/watchdog/event_batcherd.py +2 -1
- codex/librarian/watchdog/events.py +1 -2
- codex/librarian/watchdog/observers.py +15 -10
- codex/logger/logging.py +1 -1
- codex/memory.py +3 -2
- codex/migrations/0001_init.py +1 -2
- codex/migrations/0014_pdf_issue_suffix_remove_cover_image_sort_name.py +1 -2
- codex/migrations/0018_rename_userbookmark_bookmark.py +1 -2
- codex/migrations/0028_telemeter.py +1 -5
- codex/models/base.py +3 -1
- codex/models/bookmark.py +4 -7
- codex/models/comic.py +2 -2
- codex/models/functions.py +12 -5
- codex/models/groups.py +1 -1
- codex/models/library.py +1 -1
- codex/models/paths.py +4 -4
- codex/models/query.py +8 -4
- codex/models/util.py +1 -1
- codex/permissions.py +1 -1
- codex/run.py +1 -1
- codex/serializers/admin/libraries.py +1 -3
- codex/serializers/admin/stats.py +4 -4
- codex/serializers/auth.py +4 -2
- codex/serializers/browser/choices.py +87 -9
- codex/serializers/browser/filters.py +9 -37
- codex/serializers/browser/metadata.py +2 -1
- codex/serializers/browser/mixins.py +7 -3
- codex/serializers/browser/mtime.py +3 -5
- codex/serializers/browser/page.py +5 -4
- codex/serializers/browser/settings.py +7 -5
- codex/serializers/fields/__init__.py +37 -0
- codex/serializers/fields/auth.py +45 -0
- codex/serializers/fields/browser.py +85 -0
- codex/serializers/fields/group.py +13 -0
- codex/serializers/fields/reader.py +22 -0
- codex/serializers/fields/sanitized.py +13 -0
- codex/serializers/fields/session.py +15 -0
- codex/serializers/fields/stats.py +36 -0
- codex/serializers/fields/vuetify.py +62 -0
- codex/serializers/models/base.py +1 -1
- codex/serializers/models/comic.py +2 -2
- codex/serializers/models/groups.py +0 -2
- codex/serializers/models/named.py +1 -1
- codex/serializers/models/pycountry.py +1 -1
- codex/serializers/opds/authentication.py +4 -2
- codex/serializers/opds/urls.py +2 -1
- codex/serializers/opds/v1.py +4 -3
- codex/serializers/opds/v2/feed.py +2 -1
- codex/serializers/opds/v2/links.py +23 -21
- codex/serializers/opds/v2/metadata.py +4 -8
- codex/serializers/opds/v2/progression.py +5 -3
- codex/serializers/opds/v2/publication.py +16 -18
- codex/serializers/opds/v2/unused.py +15 -8
- codex/serializers/reader.py +16 -14
- codex/serializers/redirect.py +2 -1
- codex/serializers/route.py +6 -4
- codex/serializers/settings.py +5 -3
- codex/serializers/versions.py +2 -1
- codex/settings/settings.py +4 -3
- codex/signals/django_signals.py +1 -1
- codex/static_root/assets/{VCheckbox-FaT6MGfu.f6732060f734.js → VCheckbox-CtTi6T7d.87331fa7e77f.js} +1 -1
- codex/static_root/assets/VCheckbox-CtTi6T7d.87331fa7e77f.js.br +0 -0
- codex/static_root/assets/VCheckbox-CtTi6T7d.87331fa7e77f.js.gz +0 -0
- codex/static_root/assets/{VCheckbox-FaT6MGfu.js → VCheckbox-CtTi6T7d.js} +1 -1
- codex/static_root/assets/VCheckbox-CtTi6T7d.js.br +0 -0
- codex/static_root/assets/VCheckbox-CtTi6T7d.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-CZ_P-qUM.847452d574cf.js → VCheckboxBtn-DQafuWTH.dada5e0634ef.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-DQafuWTH.dada5e0634ef.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DQafuWTH.dada5e0634ef.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-CZ_P-qUM.js → VCheckboxBtn-DQafuWTH.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-DQafuWTH.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DQafuWTH.js.gz +0 -0
- codex/static_root/assets/{VCombobox-C8QLNlSl.6f431e19a453.js → VCombobox-C6TX3Dhp.e619423a6463.js} +1 -1
- codex/static_root/assets/VCombobox-C6TX3Dhp.e619423a6463.js.br +0 -0
- codex/static_root/assets/VCombobox-C6TX3Dhp.e619423a6463.js.gz +0 -0
- codex/static_root/assets/{VCombobox-C8QLNlSl.js → VCombobox-C6TX3Dhp.js} +1 -1
- codex/static_root/assets/VCombobox-C6TX3Dhp.js.br +0 -0
- codex/static_root/assets/VCombobox-C6TX3Dhp.js.gz +0 -0
- codex/static_root/assets/{VDialog-RVLeW7je.c0c7eef71eec.js → VDialog-CknWq2kd.b2d301ec6ac5.js} +1 -1
- codex/static_root/assets/VDialog-CknWq2kd.b2d301ec6ac5.js.br +0 -0
- codex/static_root/assets/VDialog-CknWq2kd.b2d301ec6ac5.js.gz +0 -0
- codex/static_root/assets/{VDialog-RVLeW7je.js → VDialog-CknWq2kd.js} +1 -1
- codex/static_root/assets/VDialog-CknWq2kd.js.br +0 -0
- codex/static_root/assets/VDialog-CknWq2kd.js.gz +0 -0
- codex/static_root/assets/{VDivider-D1Ot4vR2.9dbee744fb3c.js → VDivider-F4DUgr74.62bc92cab97d.js} +1 -1
- codex/static_root/assets/VDivider-F4DUgr74.62bc92cab97d.js.br +0 -0
- codex/static_root/assets/VDivider-F4DUgr74.62bc92cab97d.js.gz +0 -0
- codex/static_root/assets/{VDivider-D1Ot4vR2.js → VDivider-F4DUgr74.js} +1 -1
- codex/static_root/assets/VDivider-F4DUgr74.js.br +0 -0
- codex/static_root/assets/VDivider-F4DUgr74.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-DQilGHZk.43f06d0a45e0.js → VExpansionPanels-CprYUTGT.39b8a50cde43.js} +1 -1
- codex/static_root/assets/VExpansionPanels-CprYUTGT.39b8a50cde43.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-CprYUTGT.39b8a50cde43.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-DQilGHZk.js → VExpansionPanels-CprYUTGT.js} +1 -1
- codex/static_root/assets/VExpansionPanels-CprYUTGT.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-CprYUTGT.js.gz +0 -0
- codex/static_root/assets/{VForm-DNmY-qFJ.81f3a5ff7ec3.js → VForm-DnWAUsrl.4ab0786d658e.js} +1 -1
- codex/static_root/assets/VForm-DnWAUsrl.4ab0786d658e.js.br +0 -0
- codex/static_root/assets/VForm-DnWAUsrl.4ab0786d658e.js.gz +0 -0
- codex/static_root/assets/{VForm-DNmY-qFJ.js → VForm-DnWAUsrl.js} +1 -1
- codex/static_root/assets/VForm-DnWAUsrl.js.br +0 -0
- codex/static_root/assets/VForm-DnWAUsrl.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DoayJpcS.fe5e0e74ffee.js → VRadioGroup-D71Rszum.befc87b0c476.js} +1 -1
- codex/static_root/assets/VRadioGroup-D71Rszum.befc87b0c476.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D71Rszum.befc87b0c476.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DoayJpcS.js → VRadioGroup-D71Rszum.js} +1 -1
- codex/static_root/assets/VRadioGroup-D71Rszum.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D71Rszum.js.gz +0 -0
- codex/static_root/assets/{VSelect-BSLmHX_P.9ab865ec0fad.js → VSelect-CbPDrHNj.4809fbbf00f0.js} +1 -1
- codex/static_root/assets/VSelect-CbPDrHNj.4809fbbf00f0.js.br +0 -0
- codex/static_root/assets/VSelect-CbPDrHNj.4809fbbf00f0.js.gz +0 -0
- codex/static_root/assets/{VSelect-BSLmHX_P.js → VSelect-CbPDrHNj.js} +1 -1
- codex/static_root/assets/VSelect-CbPDrHNj.js.br +0 -0
- codex/static_root/assets/VSelect-CbPDrHNj.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-TaKCeZgb.ad6c96efe57c.js → VSelectionControl-It389cbo.ac75aee480a0.js} +1 -1
- codex/static_root/assets/VSelectionControl-It389cbo.ac75aee480a0.js.br +0 -0
- codex/static_root/assets/VSelectionControl-It389cbo.ac75aee480a0.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-TaKCeZgb.js → VSelectionControl-It389cbo.js} +1 -1
- codex/static_root/assets/VSelectionControl-It389cbo.js.br +0 -0
- codex/static_root/assets/VSelectionControl-It389cbo.js.gz +0 -0
- codex/static_root/assets/{VTable-BfcOiEpa.77ef3973bb54.js → VTable-D9e3lKk6.7cd0760008c7.js} +1 -1
- codex/static_root/assets/VTable-D9e3lKk6.7cd0760008c7.js.br +0 -0
- codex/static_root/assets/VTable-D9e3lKk6.7cd0760008c7.js.gz +0 -0
- codex/static_root/assets/{VTable-BfcOiEpa.js → VTable-D9e3lKk6.js} +1 -1
- codex/static_root/assets/VTable-D9e3lKk6.js.br +0 -0
- codex/static_root/assets/VTable-D9e3lKk6.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-D8lWcbQY.e4c75ad78718.js → VWindowItem-B4VZ37cq.e45c5018cc73.js} +1 -1
- codex/static_root/assets/VWindowItem-B4VZ37cq.e45c5018cc73.js.br +0 -0
- codex/static_root/assets/VWindowItem-B4VZ37cq.e45c5018cc73.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-D8lWcbQY.js → VWindowItem-B4VZ37cq.js} +1 -1
- codex/static_root/assets/VWindowItem-B4VZ37cq.js.br +0 -0
- codex/static_root/assets/VWindowItem-B4VZ37cq.js.gz +0 -0
- codex/static_root/assets/{admin-CBLHOrM9.8c3c2268bc96.js → admin-Bkd8zuSF.2a29386f3488.js} +1 -1
- codex/static_root/assets/admin-Bkd8zuSF.2a29386f3488.js.br +0 -0
- codex/static_root/assets/admin-Bkd8zuSF.2a29386f3488.js.gz +0 -0
- codex/static_root/assets/{admin-CBLHOrM9.js → admin-Bkd8zuSF.js} +1 -1
- codex/static_root/assets/admin-Bkd8zuSF.js.br +0 -0
- codex/static_root/assets/admin-Bkd8zuSF.js.gz +0 -0
- codex/static_root/assets/{admin-80eqCqtz.d6deb9edb8cb.js → admin-CFTKGwmx.18915c5df4d3.js} +1 -1
- codex/static_root/assets/admin-CFTKGwmx.18915c5df4d3.js.br +0 -0
- codex/static_root/assets/admin-CFTKGwmx.18915c5df4d3.js.gz +0 -0
- codex/static_root/assets/{admin-80eqCqtz.js → admin-CFTKGwmx.js} +1 -1
- codex/static_root/assets/admin-CFTKGwmx.js.br +0 -0
- codex/static_root/assets/admin-CFTKGwmx.js.gz +0 -0
- codex/static_root/assets/{admin-menu-_aAGknKO.0c08c9bd2e7d.js → admin-menu-CxZqtPES.7b3a06ce4b92.js} +1 -1
- codex/static_root/assets/admin-menu-CxZqtPES.7b3a06ce4b92.js.br +0 -0
- codex/static_root/assets/admin-menu-CxZqtPES.7b3a06ce4b92.js.gz +0 -0
- codex/static_root/assets/{admin-menu-_aAGknKO.js → admin-menu-CxZqtPES.js} +1 -1
- codex/static_root/assets/admin-menu-CxZqtPES.js.br +0 -0
- codex/static_root/assets/admin-menu-CxZqtPES.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-BqRFyhjf.2bb1194b21e2.js → admin-settings-button-progress-D2TfW_5T.8a9d411ee79d.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-D2TfW_5T.8a9d411ee79d.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-D2TfW_5T.8a9d411ee79d.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-BqRFyhjf.js → admin-settings-button-progress-D2TfW_5T.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-D2TfW_5T.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-D2TfW_5T.js.gz +0 -0
- codex/static_root/assets/browser-Br2DgAdi.433cca495d61.js +1 -0
- codex/static_root/assets/browser-Br2DgAdi.433cca495d61.js.br +0 -0
- codex/static_root/assets/browser-Br2DgAdi.433cca495d61.js.gz +0 -0
- codex/static_root/assets/browser-Br2DgAdi.js +1 -0
- codex/static_root/assets/browser-Br2DgAdi.js.br +0 -0
- codex/static_root/assets/browser-Br2DgAdi.js.gz +0 -0
- codex/static_root/assets/{browser-chTZ1CM4.521193ab0710.css → browser-DNzQvgkY.aea8b7d7ca40.css} +1 -1
- codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css.br +0 -0
- codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css.gz +0 -0
- codex/static_root/assets/{browser-chTZ1CM4.css → browser-DNzQvgkY.css} +1 -1
- codex/static_root/assets/browser-DNzQvgkY.css.br +0 -0
- codex/static_root/assets/browser-DNzQvgkY.css.gz +0 -0
- codex/static_root/assets/{change-password-dialog-1ZVP_Q2w.ae0d9e5bd42b.js → change-password-dialog-CSylx5Qb.319466c891c9.js} +1 -1
- codex/static_root/assets/change-password-dialog-CSylx5Qb.319466c891c9.js.br +0 -0
- codex/static_root/assets/change-password-dialog-CSylx5Qb.319466c891c9.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-1ZVP_Q2w.js → change-password-dialog-CSylx5Qb.js} +1 -1
- codex/static_root/assets/change-password-dialog-CSylx5Qb.js.br +0 -0
- codex/static_root/assets/change-password-dialog-CSylx5Qb.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-DqCey9Iq.e315d7f8f752.js → confirm-dialog-Bx2R2vgR.d42b6449c495.js} +1 -1
- codex/static_root/assets/confirm-dialog-Bx2R2vgR.d42b6449c495.js.br +0 -0
- codex/static_root/assets/confirm-dialog-Bx2R2vgR.d42b6449c495.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-DqCey9Iq.js → confirm-dialog-Bx2R2vgR.js} +1 -1
- codex/static_root/assets/confirm-dialog-Bx2R2vgR.js.br +0 -0
- codex/static_root/assets/confirm-dialog-Bx2R2vgR.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CBA8bYeO.17a31f189d66.js → datetime-column-sOrWMDcU.9ad225af18db.js} +1 -1
- codex/static_root/assets/datetime-column-sOrWMDcU.9ad225af18db.js.br +2 -0
- codex/static_root/assets/datetime-column-sOrWMDcU.9ad225af18db.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CBA8bYeO.js → datetime-column-sOrWMDcU.js} +1 -1
- codex/static_root/assets/datetime-column-sOrWMDcU.js.br +2 -0
- codex/static_root/assets/datetime-column-sOrWMDcU.js.gz +0 -0
- codex/static_root/assets/{filter-mnO3lLPo.659442401b16.js → filter-SgjvoAvL.094069d6978d.js} +1 -1
- codex/static_root/assets/filter-SgjvoAvL.094069d6978d.js.br +0 -0
- codex/static_root/assets/filter-SgjvoAvL.094069d6978d.js.gz +0 -0
- codex/static_root/assets/{filter-mnO3lLPo.js → filter-SgjvoAvL.js} +1 -1
- codex/static_root/assets/filter-SgjvoAvL.js.br +0 -0
- codex/static_root/assets/filter-SgjvoAvL.js.gz +0 -0
- codex/static_root/assets/{flag-tab-Bc677pNb.1b8a2f7c0dc3.js → flag-tab-B_0tGWPg.e46d1782b327.js} +1 -1
- codex/static_root/assets/flag-tab-B_0tGWPg.e46d1782b327.js.br +0 -0
- codex/static_root/assets/flag-tab-B_0tGWPg.e46d1782b327.js.gz +0 -0
- codex/static_root/assets/{flag-tab-Bc677pNb.js → flag-tab-B_0tGWPg.js} +1 -1
- codex/static_root/assets/flag-tab-B_0tGWPg.js.br +0 -0
- codex/static_root/assets/flag-tab-B_0tGWPg.js.gz +0 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css +1 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css.br +0 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css.gz +0 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.css +1 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.css.br +0 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.css.gz +0 -0
- codex/static_root/assets/{forwardRefs-DPRKg5wq.6f09e9d22fa6.js → forwardRefs-DqbPK1-k.bb9d6863ac16.js} +1 -1
- codex/static_root/assets/forwardRefs-DqbPK1-k.bb9d6863ac16.js.br +0 -0
- codex/static_root/assets/forwardRefs-DqbPK1-k.bb9d6863ac16.js.gz +0 -0
- codex/static_root/assets/{forwardRefs-DPRKg5wq.js → forwardRefs-DqbPK1-k.js} +1 -1
- codex/static_root/assets/forwardRefs-DqbPK1-k.js.br +0 -0
- codex/static_root/assets/forwardRefs-DqbPK1-k.js.gz +0 -0
- codex/static_root/assets/{group-tab-BVlBrMwo.1127b51be6e7.js → group-tab-DXxQUa6C.f1f12f39b167.js} +1 -1
- codex/static_root/assets/group-tab-DXxQUa6C.f1f12f39b167.js.br +0 -0
- codex/static_root/assets/group-tab-DXxQUa6C.f1f12f39b167.js.gz +0 -0
- codex/static_root/assets/{group-tab-BVlBrMwo.js → group-tab-DXxQUa6C.js} +1 -1
- codex/static_root/assets/group-tab-DXxQUa6C.js.br +0 -0
- codex/static_root/assets/group-tab-DXxQUa6C.js.gz +0 -0
- codex/static_root/assets/{http-error-C9-_aEBF.d29b164e80de.js → http-error-BVMwwrFo.a7be6a26c9eb.js} +1 -1
- codex/static_root/assets/http-error-BVMwwrFo.a7be6a26c9eb.js.br +0 -0
- codex/static_root/assets/http-error-BVMwwrFo.a7be6a26c9eb.js.gz +0 -0
- codex/static_root/assets/{http-error-C9-_aEBF.js → http-error-BVMwwrFo.js} +1 -1
- codex/static_root/assets/http-error-BVMwwrFo.js.br +0 -0
- codex/static_root/assets/http-error-BVMwwrFo.js.gz +0 -0
- codex/static_root/assets/{index-9nBCksDQ.4561d2608773.js → index-DK0lSHDP.86f18c078fa9.js} +1 -1
- codex/static_root/assets/index-DK0lSHDP.86f18c078fa9.js.br +0 -0
- codex/static_root/assets/index-DK0lSHDP.86f18c078fa9.js.gz +0 -0
- codex/static_root/assets/{index-9nBCksDQ.js → index-DK0lSHDP.js} +1 -1
- codex/static_root/assets/index-DK0lSHDP.js.br +0 -0
- codex/static_root/assets/index-DK0lSHDP.js.gz +0 -0
- codex/static_root/assets/{library-tab-BMe3dKzy.22b6e123ecfb.js → library-tab-NhXuvZ4F.1e8ac3b7c168.js} +1 -1
- codex/static_root/assets/library-tab-NhXuvZ4F.1e8ac3b7c168.js.br +0 -0
- codex/static_root/assets/library-tab-NhXuvZ4F.1e8ac3b7c168.js.gz +0 -0
- codex/static_root/assets/{library-tab-BMe3dKzy.js → library-tab-NhXuvZ4F.js} +1 -1
- codex/static_root/assets/library-tab-NhXuvZ4F.js.br +0 -0
- codex/static_root/assets/library-tab-NhXuvZ4F.js.gz +0 -0
- codex/static_root/assets/{main-BbNUiWEb.565b616eb122.js → main-CYgubU7H.50aa39cf9565.js} +3 -3
- codex/static_root/assets/main-CYgubU7H.50aa39cf9565.js.br +0 -0
- codex/static_root/assets/main-CYgubU7H.50aa39cf9565.js.gz +0 -0
- codex/static_root/assets/{main-BbNUiWEb.js → main-CYgubU7H.js} +3 -3
- codex/static_root/assets/main-CYgubU7H.js.br +0 -0
- codex/static_root/assets/main-CYgubU7H.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.a6269ab85085.js +1 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.a6269ab85085.js.br +0 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.a6269ab85085.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.js +1 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.js.br +0 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-Dx5JwWG-.ba0e8b645dfa.js → pagination-toolbar-CeWXU_qA.abe0805da1cc.js} +1 -1
- codex/static_root/assets/pagination-toolbar-CeWXU_qA.abe0805da1cc.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-CeWXU_qA.abe0805da1cc.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-Dx5JwWG-.js → pagination-toolbar-CeWXU_qA.js} +1 -1
- codex/static_root/assets/pagination-toolbar-CeWXU_qA.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-CeWXU_qA.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-6ZE_HmLT.10d1e16abc78.js → pdf-doc-Dws_otkd.d215eca27da5.js} +1 -1
- codex/static_root/assets/pdf-doc-Dws_otkd.d215eca27da5.js.br +0 -0
- codex/static_root/assets/pdf-doc-Dws_otkd.d215eca27da5.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-6ZE_HmLT.js → pdf-doc-Dws_otkd.js} +1 -1
- codex/static_root/assets/pdf-doc-Dws_otkd.js.br +0 -0
- codex/static_root/assets/pdf-doc-Dws_otkd.js.gz +0 -0
- codex/static_root/assets/{reader-DdPKDuh5.0c55cef1e98b.js → reader-BCxYgZHF.dde3c4ac39a5.js} +2 -2
- codex/static_root/assets/reader-BCxYgZHF.dde3c4ac39a5.js.br +0 -0
- codex/static_root/assets/reader-BCxYgZHF.dde3c4ac39a5.js.gz +0 -0
- codex/static_root/assets/{reader-DdPKDuh5.js → reader-BCxYgZHF.js} +2 -2
- codex/static_root/assets/reader-BCxYgZHF.js.br +0 -0
- codex/static_root/assets/reader-BCxYgZHF.js.gz +0 -0
- codex/static_root/assets/{relation-chips-C96hi5jm.js → relation-chips-DNRRCvrw.b1bc75fb9349.js} +1 -1
- codex/static_root/assets/relation-chips-DNRRCvrw.b1bc75fb9349.js.br +0 -0
- codex/static_root/assets/relation-chips-DNRRCvrw.b1bc75fb9349.js.gz +0 -0
- codex/static_root/assets/{relation-chips-C96hi5jm.9f07c9eb533a.js → relation-chips-DNRRCvrw.js} +1 -1
- codex/static_root/assets/relation-chips-DNRRCvrw.js.br +0 -0
- codex/static_root/assets/relation-chips-DNRRCvrw.js.gz +0 -0
- codex/static_root/assets/{settings-drawer-CqbT1rid.js → settings-drawer-BuB29L5p.fe2eeea0058f.js} +2 -2
- codex/static_root/assets/settings-drawer-BuB29L5p.fe2eeea0058f.js.br +0 -0
- codex/static_root/assets/settings-drawer-BuB29L5p.fe2eeea0058f.js.gz +0 -0
- codex/static_root/assets/{settings-drawer-CqbT1rid.5639fa00b301.js → settings-drawer-BuB29L5p.js} +2 -2
- codex/static_root/assets/settings-drawer-BuB29L5p.js.br +0 -0
- codex/static_root/assets/settings-drawer-BuB29L5p.js.gz +0 -0
- codex/static_root/assets/{stats-tab-CkT2ZGUQ.b704fa46dc88.js → stats-tab-D0zymxU6.d5267113b51e.js} +1 -1
- codex/static_root/assets/stats-tab-D0zymxU6.d5267113b51e.js.br +0 -0
- codex/static_root/assets/stats-tab-D0zymxU6.d5267113b51e.js.gz +0 -0
- codex/static_root/assets/{stats-tab-CkT2ZGUQ.js → stats-tab-D0zymxU6.js} +1 -1
- codex/static_root/assets/stats-tab-D0zymxU6.js.br +0 -0
- codex/static_root/assets/stats-tab-D0zymxU6.js.gz +0 -0
- codex/static_root/assets/{task-tab-a-DcU3Tj.8c2f7bf3c4c9.js → task-tab-CI9RLdMS.120f395dc9c6.js} +1 -1
- codex/static_root/assets/task-tab-CI9RLdMS.120f395dc9c6.js.br +0 -0
- codex/static_root/assets/task-tab-CI9RLdMS.120f395dc9c6.js.gz +0 -0
- codex/static_root/assets/{task-tab-a-DcU3Tj.js → task-tab-CI9RLdMS.js} +1 -1
- codex/static_root/assets/task-tab-CI9RLdMS.js.br +0 -0
- codex/static_root/assets/task-tab-CI9RLdMS.js.gz +0 -0
- codex/static_root/assets/{unauthorized-BOl5YpL3.f3c4b52718d5.js → unauthorized-BNwg_Xvu.a894b96156e0.js} +1 -1
- codex/static_root/assets/unauthorized-BNwg_Xvu.a894b96156e0.js.br +0 -0
- codex/static_root/assets/unauthorized-BNwg_Xvu.a894b96156e0.js.gz +0 -0
- codex/static_root/assets/{unauthorized-BOl5YpL3.js → unauthorized-BNwg_Xvu.js} +1 -1
- codex/static_root/assets/unauthorized-BNwg_Xvu.js.br +0 -0
- codex/static_root/assets/unauthorized-BNwg_Xvu.js.gz +0 -0
- codex/static_root/assets/{user-tab-BBDZvD8G.aa4263a68b22.js → user-tab-w9LgIMMi.4a89c7b37486.js} +1 -1
- codex/static_root/assets/user-tab-w9LgIMMi.4a89c7b37486.js.br +0 -0
- codex/static_root/assets/user-tab-w9LgIMMi.4a89c7b37486.js.gz +0 -0
- codex/static_root/assets/{user-tab-BBDZvD8G.js → user-tab-w9LgIMMi.js} +1 -1
- codex/static_root/assets/user-tab-w9LgIMMi.js.br +0 -0
- codex/static_root/assets/user-tab-w9LgIMMi.js.gz +0 -0
- codex/static_root/{manifest.225989a17f49.json → manifest.514e63b9f805.json} +253 -253
- codex/static_root/manifest.514e63b9f805.json.br +0 -0
- codex/static_root/manifest.514e63b9f805.json.gz +0 -0
- codex/static_root/manifest.json +253 -253
- 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 +9 -12
- codex/urls/root.py +4 -3
- codex/views/admin/api_key.py +1 -4
- codex/views/admin/library.py +4 -4
- codex/views/admin/stats.py +10 -10
- codex/views/admin/tasks.py +9 -9
- codex/views/auth.py +3 -8
- codex/views/bookmark.py +3 -3
- codex/views/browser/annotate/card.py +2 -2
- codex/views/browser/annotate/order.py +6 -7
- codex/views/browser/bookmark.py +3 -1
- codex/views/browser/breadcrumbs.py +6 -5
- codex/views/browser/browser.py +2 -2
- codex/views/browser/choices.py +6 -7
- codex/views/browser/cover.py +6 -3
- codex/views/browser/download.py +2 -1
- codex/views/browser/filters/bookmark.py +1 -1
- codex/views/browser/filters/field.py +1 -1
- codex/views/browser/filters/filter.py +6 -8
- codex/views/browser/filters/group.py +8 -8
- codex/views/browser/filters/search/field/expression.py +1 -2
- codex/views/browser/filters/search/field/optimize.py +1 -1
- codex/views/browser/filters/search/field/parse.py +2 -2
- codex/views/browser/filters/search/parse.py +4 -19
- codex/views/browser/group_mtime.py +1 -1
- codex/views/browser/metadata/copy_intersections.py +1 -1
- codex/views/browser/metadata/metadata.py +1 -1
- codex/views/browser/mtime.py +1 -1
- codex/views/browser/order_by.py +3 -5
- codex/views/browser/params.py +1 -1
- codex/views/browser/settings.py +1 -1
- codex/views/browser/validate.py +8 -5
- codex/views/const.py +0 -3
- codex/views/frontend.py +1 -1
- codex/views/mixins.py +3 -2
- codex/views/opds/authentication_v1.py +1 -1
- codex/views/opds/const.py +4 -4
- codex/views/opds/util.py +3 -3
- codex/views/opds/v1/entry/entry.py +4 -2
- codex/views/opds/v1/entry/links.py +4 -5
- codex/views/opds/v1/facets.py +8 -4
- codex/views/opds/v1/feed.py +5 -5
- codex/views/opds/v1/links.py +11 -6
- codex/views/opds/v2/const.py +5 -2
- codex/views/opds/v2/feed.py +3 -3
- codex/views/opds/v2/progression.py +8 -9
- codex/views/opds/v2/publications.py +10 -20
- codex/views/public.py +1 -1
- codex/views/reader/books.py +3 -2
- codex/views/reader/page.py +3 -3
- codex/views/reader/params.py +2 -2
- codex/views/reader/reader.py +6 -6
- codex/views/reader/settings.py +1 -1
- codex/views/session.py +8 -2
- codex/views/settings.py +2 -2
- codex/views/timezone.py +2 -2
- codex/views/util.py +10 -9
- codex/views/version.py +1 -1
- {codex-1.7.3a2.dist-info → codex-1.7.4.dist-info}/METADATA +3 -1
- {codex-1.7.3a2.dist-info → codex-1.7.4.dist-info}/RECORD +409 -401
- {codex-1.7.3a2.dist-info → codex-1.7.4.dist-info}/WHEEL +1 -1
- codex/serializers/fields.py +0 -183
- codex/static_root/assets/VCheckbox-FaT6MGfu.f6732060f734.js.br +0 -0
- codex/static_root/assets/VCheckbox-FaT6MGfu.f6732060f734.js.gz +0 -0
- codex/static_root/assets/VCheckbox-FaT6MGfu.js.br +0 -0
- codex/static_root/assets/VCheckbox-FaT6MGfu.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-CZ_P-qUM.847452d574cf.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-CZ_P-qUM.847452d574cf.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-CZ_P-qUM.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-CZ_P-qUM.js.gz +0 -0
- codex/static_root/assets/VCombobox-C8QLNlSl.6f431e19a453.js.br +0 -0
- codex/static_root/assets/VCombobox-C8QLNlSl.6f431e19a453.js.gz +0 -0
- codex/static_root/assets/VCombobox-C8QLNlSl.js.br +0 -0
- codex/static_root/assets/VCombobox-C8QLNlSl.js.gz +0 -0
- codex/static_root/assets/VDialog-RVLeW7je.c0c7eef71eec.js.br +0 -0
- codex/static_root/assets/VDialog-RVLeW7je.c0c7eef71eec.js.gz +0 -0
- codex/static_root/assets/VDialog-RVLeW7je.js.br +0 -0
- codex/static_root/assets/VDialog-RVLeW7je.js.gz +0 -0
- codex/static_root/assets/VDivider-D1Ot4vR2.9dbee744fb3c.js.br +0 -0
- codex/static_root/assets/VDivider-D1Ot4vR2.9dbee744fb3c.js.gz +0 -0
- codex/static_root/assets/VDivider-D1Ot4vR2.js.br +0 -0
- codex/static_root/assets/VDivider-D1Ot4vR2.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-DQilGHZk.43f06d0a45e0.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-DQilGHZk.43f06d0a45e0.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-DQilGHZk.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-DQilGHZk.js.gz +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.81f3a5ff7ec3.js.br +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.81f3a5ff7ec3.js.gz +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.js.br +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DoayJpcS.fe5e0e74ffee.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DoayJpcS.fe5e0e74ffee.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DoayJpcS.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DoayJpcS.js.gz +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.9ab865ec0fad.js.br +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.9ab865ec0fad.js.gz +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.js.br +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-TaKCeZgb.ad6c96efe57c.js.br +0 -0
- codex/static_root/assets/VSelectionControl-TaKCeZgb.ad6c96efe57c.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-TaKCeZgb.js.br +0 -0
- codex/static_root/assets/VSelectionControl-TaKCeZgb.js.gz +0 -0
- codex/static_root/assets/VTable-BfcOiEpa.77ef3973bb54.js.br +0 -0
- codex/static_root/assets/VTable-BfcOiEpa.77ef3973bb54.js.gz +0 -0
- codex/static_root/assets/VTable-BfcOiEpa.js.br +0 -0
- codex/static_root/assets/VTable-BfcOiEpa.js.gz +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.e4c75ad78718.js.br +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.e4c75ad78718.js.gz +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.js.br +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.js.gz +0 -0
- codex/static_root/assets/admin-80eqCqtz.d6deb9edb8cb.js.br +0 -0
- codex/static_root/assets/admin-80eqCqtz.d6deb9edb8cb.js.gz +0 -0
- codex/static_root/assets/admin-80eqCqtz.js.br +0 -0
- codex/static_root/assets/admin-80eqCqtz.js.gz +0 -0
- codex/static_root/assets/admin-CBLHOrM9.8c3c2268bc96.js.br +0 -0
- codex/static_root/assets/admin-CBLHOrM9.8c3c2268bc96.js.gz +0 -0
- codex/static_root/assets/admin-CBLHOrM9.js.br +0 -0
- codex/static_root/assets/admin-CBLHOrM9.js.gz +0 -0
- codex/static_root/assets/admin-menu-_aAGknKO.0c08c9bd2e7d.js.br +0 -0
- codex/static_root/assets/admin-menu-_aAGknKO.0c08c9bd2e7d.js.gz +0 -0
- codex/static_root/assets/admin-menu-_aAGknKO.js.br +0 -0
- codex/static_root/assets/admin-menu-_aAGknKO.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-BqRFyhjf.2bb1194b21e2.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BqRFyhjf.2bb1194b21e2.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-BqRFyhjf.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BqRFyhjf.js.gz +0 -0
- codex/static_root/assets/browser-DAprXYuP.8bb92965dd9d.js +0 -1
- codex/static_root/assets/browser-DAprXYuP.8bb92965dd9d.js.br +0 -0
- codex/static_root/assets/browser-DAprXYuP.8bb92965dd9d.js.gz +0 -0
- codex/static_root/assets/browser-DAprXYuP.js +0 -1
- codex/static_root/assets/browser-DAprXYuP.js.br +0 -0
- codex/static_root/assets/browser-DAprXYuP.js.gz +0 -0
- codex/static_root/assets/browser-chTZ1CM4.521193ab0710.css.br +0 -0
- codex/static_root/assets/browser-chTZ1CM4.521193ab0710.css.gz +0 -0
- codex/static_root/assets/browser-chTZ1CM4.css.br +0 -0
- codex/static_root/assets/browser-chTZ1CM4.css.gz +0 -0
- codex/static_root/assets/change-password-dialog-1ZVP_Q2w.ae0d9e5bd42b.js.br +0 -0
- codex/static_root/assets/change-password-dialog-1ZVP_Q2w.ae0d9e5bd42b.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-1ZVP_Q2w.js.br +0 -0
- codex/static_root/assets/change-password-dialog-1ZVP_Q2w.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-DqCey9Iq.e315d7f8f752.js.br +0 -0
- codex/static_root/assets/confirm-dialog-DqCey9Iq.e315d7f8f752.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-DqCey9Iq.js.br +0 -0
- codex/static_root/assets/confirm-dialog-DqCey9Iq.js.gz +0 -0
- codex/static_root/assets/datetime-column-CBA8bYeO.17a31f189d66.js.br +0 -0
- codex/static_root/assets/datetime-column-CBA8bYeO.17a31f189d66.js.gz +0 -0
- codex/static_root/assets/datetime-column-CBA8bYeO.js.br +0 -0
- codex/static_root/assets/datetime-column-CBA8bYeO.js.gz +0 -0
- codex/static_root/assets/filter-mnO3lLPo.659442401b16.js.br +0 -0
- codex/static_root/assets/filter-mnO3lLPo.659442401b16.js.gz +0 -0
- codex/static_root/assets/filter-mnO3lLPo.js.br +0 -0
- codex/static_root/assets/filter-mnO3lLPo.js.gz +0 -0
- codex/static_root/assets/flag-tab-Bc677pNb.1b8a2f7c0dc3.js.br +0 -0
- codex/static_root/assets/flag-tab-Bc677pNb.1b8a2f7c0dc3.js.gz +0 -0
- codex/static_root/assets/flag-tab-Bc677pNb.js.br +0 -0
- codex/static_root/assets/flag-tab-Bc677pNb.js.gz +0 -0
- codex/static_root/assets/flag-tab-glFvEgEl.be8eed14384e.css +0 -1
- codex/static_root/assets/flag-tab-glFvEgEl.be8eed14384e.css.br +0 -0
- codex/static_root/assets/flag-tab-glFvEgEl.be8eed14384e.css.gz +0 -0
- codex/static_root/assets/flag-tab-glFvEgEl.css +0 -1
- codex/static_root/assets/flag-tab-glFvEgEl.css.br +0 -0
- codex/static_root/assets/flag-tab-glFvEgEl.css.gz +0 -0
- codex/static_root/assets/forwardRefs-DPRKg5wq.6f09e9d22fa6.js.br +0 -0
- codex/static_root/assets/forwardRefs-DPRKg5wq.6f09e9d22fa6.js.gz +0 -0
- codex/static_root/assets/forwardRefs-DPRKg5wq.js.br +0 -0
- codex/static_root/assets/forwardRefs-DPRKg5wq.js.gz +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.1127b51be6e7.js.br +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.1127b51be6e7.js.gz +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.js.br +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.js.gz +0 -0
- codex/static_root/assets/http-error-C9-_aEBF.d29b164e80de.js.br +0 -0
- codex/static_root/assets/http-error-C9-_aEBF.d29b164e80de.js.gz +0 -0
- codex/static_root/assets/http-error-C9-_aEBF.js.br +0 -0
- codex/static_root/assets/http-error-C9-_aEBF.js.gz +0 -0
- codex/static_root/assets/index-9nBCksDQ.4561d2608773.js.br +0 -0
- codex/static_root/assets/index-9nBCksDQ.4561d2608773.js.gz +0 -0
- codex/static_root/assets/index-9nBCksDQ.js.br +0 -0
- codex/static_root/assets/index-9nBCksDQ.js.gz +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.22b6e123ecfb.js.br +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.22b6e123ecfb.js.gz +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.js.br +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.js.gz +0 -0
- codex/static_root/assets/main-BbNUiWEb.565b616eb122.js.br +0 -0
- codex/static_root/assets/main-BbNUiWEb.565b616eb122.js.gz +0 -0
- codex/static_root/assets/main-BbNUiWEb.js.br +0 -0
- codex/static_root/assets/main-BbNUiWEb.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.6d4ec47c14f7.js +0 -1
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.6d4ec47c14f7.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.6d4ec47c14f7.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.js +0 -1
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Dx5JwWG-.ba0e8b645dfa.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-Dx5JwWG-.ba0e8b645dfa.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Dx5JwWG-.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-Dx5JwWG-.js.gz +0 -0
- codex/static_root/assets/pdf-doc-6ZE_HmLT.10d1e16abc78.js.br +0 -0
- codex/static_root/assets/pdf-doc-6ZE_HmLT.10d1e16abc78.js.gz +0 -0
- codex/static_root/assets/pdf-doc-6ZE_HmLT.js.br +0 -0
- codex/static_root/assets/pdf-doc-6ZE_HmLT.js.gz +0 -0
- codex/static_root/assets/reader-DdPKDuh5.0c55cef1e98b.js.br +0 -0
- codex/static_root/assets/reader-DdPKDuh5.0c55cef1e98b.js.gz +0 -0
- codex/static_root/assets/reader-DdPKDuh5.js.br +0 -0
- codex/static_root/assets/reader-DdPKDuh5.js.gz +0 -0
- codex/static_root/assets/relation-chips-C96hi5jm.9f07c9eb533a.js.br +0 -0
- codex/static_root/assets/relation-chips-C96hi5jm.9f07c9eb533a.js.gz +0 -0
- codex/static_root/assets/relation-chips-C96hi5jm.js.br +0 -0
- codex/static_root/assets/relation-chips-C96hi5jm.js.gz +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.5639fa00b301.js.br +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.5639fa00b301.js.gz +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.js.br +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.js.gz +0 -0
- codex/static_root/assets/stats-tab-CkT2ZGUQ.b704fa46dc88.js.br +0 -0
- codex/static_root/assets/stats-tab-CkT2ZGUQ.b704fa46dc88.js.gz +0 -0
- codex/static_root/assets/stats-tab-CkT2ZGUQ.js.br +0 -0
- codex/static_root/assets/stats-tab-CkT2ZGUQ.js.gz +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.8c2f7bf3c4c9.js.br +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.8c2f7bf3c4c9.js.gz +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.js.br +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.js.gz +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.f3c4b52718d5.js.br +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.f3c4b52718d5.js.gz +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.js.br +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.js.gz +0 -0
- codex/static_root/assets/user-tab-BBDZvD8G.aa4263a68b22.js.br +0 -0
- codex/static_root/assets/user-tab-BBDZvD8G.aa4263a68b22.js.gz +0 -0
- codex/static_root/assets/user-tab-BBDZvD8G.js.br +0 -0
- codex/static_root/assets/user-tab-BBDZvD8G.js.gz +0 -0
- codex/static_root/manifest.225989a17f49.json.br +0 -0
- codex/static_root/manifest.225989a17f49.json.gz +0 -0
- {codex-1.7.3a2.dist-info → codex-1.7.4.dist-info}/LICENSE +0 -0
- {codex-1.7.3a2.dist-info → codex-1.7.4.dist-info}/entry_points.txt +0 -0
|
@@ -9,7 +9,7 @@ from codex.views.const import (
|
|
|
9
9
|
GROUP_RELATION,
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
-
_GROUP_REL_TARGETS = frozenset({"cover", "choices"})
|
|
12
|
+
_GROUP_REL_TARGETS = frozenset({"cover", "choices", "bookmark"})
|
|
13
13
|
_PK_REL_TARGETS = frozenset({"metadata", "mtime"})
|
|
14
14
|
|
|
15
15
|
|
|
@@ -18,16 +18,16 @@ class GroupFilterView(BrowserParamsView):
|
|
|
18
18
|
|
|
19
19
|
SESSION_KEY = BrowserParamsView.BROWSER_SESSION_KEY
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
TARGET = ""
|
|
22
|
+
|
|
23
|
+
def _get_rel_for_pks(self, group, page_mtime: bool):
|
|
22
24
|
"""Get the relation from the model to the pks."""
|
|
23
|
-
|
|
24
|
-
target: str = self.TARGET # type: ignore
|
|
25
|
-
if target in _GROUP_REL_TARGETS:
|
|
25
|
+
if self.TARGET in _GROUP_REL_TARGETS:
|
|
26
26
|
rel = FILTER_ONLY_GROUP_RELATION[group]
|
|
27
|
-
elif
|
|
27
|
+
elif self.TARGET in _PK_REL_TARGETS or page_mtime:
|
|
28
28
|
# metadata, mtime, browser.page_mtime
|
|
29
29
|
rel = "pk"
|
|
30
|
-
elif
|
|
30
|
+
elif self.TARGET == "download":
|
|
31
31
|
rel = "comic__folders" if group == "f" else "pk"
|
|
32
32
|
else:
|
|
33
33
|
# browser.group, opds
|
|
@@ -36,7 +36,7 @@ class GroupFilterView(BrowserParamsView):
|
|
|
36
36
|
rel += "__in"
|
|
37
37
|
return rel
|
|
38
38
|
|
|
39
|
-
def get_group_filter(self, group=None, pks=None, page_mtime=False):
|
|
39
|
+
def get_group_filter(self, group=None, pks=None, page_mtime=False): # noqa: FBT002
|
|
40
40
|
"""Get filter for the displayed group."""
|
|
41
41
|
if group is None:
|
|
42
42
|
group = self.kwargs["group"]
|
|
@@ -22,7 +22,7 @@ if TYPE_CHECKING:
|
|
|
22
22
|
from pyparsing.helpers import InfixNotationOperatorSpec
|
|
23
23
|
|
|
24
24
|
_QUOTES_REXP = r"(?:\".*?\")"
|
|
25
|
-
_OPERATORS_REXP = "
|
|
25
|
+
_OPERATORS_REXP = "and not|or not|and|or"
|
|
26
26
|
_BEGIN_NOT_REXP = r"^\s*\(?\s*(?P<not>not)"
|
|
27
27
|
_IMPLICIT_AND_REXP = (
|
|
28
28
|
rf"{_QUOTES_REXP}|\ (?P<ok>{_OPERATORS_REXP})\ |(?P<bare>(?:\ not)?\ )\S"
|
|
@@ -183,5 +183,5 @@ def get_field_query(rel, rel_class, exp, model, many_to_many):
|
|
|
183
183
|
bool_expr = _create_context_expression(context)
|
|
184
184
|
|
|
185
185
|
parsed_result = bool_expr.parse_string(exp)
|
|
186
|
-
root_bool_operand: BoolOperand = parsed_result[0] # type:ignore
|
|
186
|
+
root_bool_operand: BoolOperand = parsed_result[0] # type:ignore[reportAssignmentType]
|
|
187
187
|
return root_bool_operand.to_query()
|
|
@@ -149,7 +149,7 @@ class SearchFilterView(BrowserFTSFilter):
|
|
|
149
149
|
|
|
150
150
|
def _preparse_search_query(self):
|
|
151
151
|
"""Preparse search fields out of query text."""
|
|
152
|
-
text = self.params.get("q")
|
|
152
|
+
text = self.params.get("q")
|
|
153
153
|
field_tokens = {}
|
|
154
154
|
if not text:
|
|
155
155
|
return field_tokens, text
|
|
@@ -177,7 +177,7 @@ class SearchFilterView(BrowserFTSFilter):
|
|
|
177
177
|
)
|
|
178
178
|
else:
|
|
179
179
|
# AND and OR
|
|
180
|
-
#
|
|
180
|
+
# Cannot do OR queries with MATCH, it decontextualizes MATCH somehow.
|
|
181
181
|
if preop == "or":
|
|
182
182
|
self.search_error = "OR preceding column tokens with operator expressions will act as AND"
|
|
183
183
|
include_q_list, exclude_q_list = self.get_search_field_filters(
|
|
@@ -227,24 +227,9 @@ class SearchFilterView(BrowserFTSFilter):
|
|
|
227
227
|
|
|
228
228
|
return include_q, exclude_q, fts_q
|
|
229
229
|
|
|
230
|
-
def _is_search_results_limited(self) -> bool:
|
|
231
|
-
"""Get search result limit from params."""
|
|
232
|
-
# user = self.request.user # type: ignore
|
|
233
|
-
# if user and user.is_authenticated:
|
|
234
|
-
# limited = bool(
|
|
235
|
-
# self.params.get( # type: ignore
|
|
236
|
-
# "search_results_limit",
|
|
237
|
-
# MAX_OBJ_PER_PAGE,
|
|
238
|
-
# )
|
|
239
|
-
# )
|
|
240
|
-
# else:
|
|
241
|
-
# limited = True
|
|
242
|
-
# return limited
|
|
243
|
-
return True
|
|
244
|
-
|
|
245
230
|
def get_search_limit(self):
|
|
246
231
|
"""Get search scores for choices and metadata."""
|
|
247
|
-
if not self.search_mode
|
|
232
|
+
if not self.search_mode:
|
|
248
233
|
return 0
|
|
249
|
-
page = self.kwargs.get("page", 1)
|
|
234
|
+
page = self.kwargs.get("page", 1)
|
|
250
235
|
return page * MAX_OBJ_PER_PAGE + 1
|
|
@@ -54,7 +54,7 @@ class BrowserGroupMtimeView(BrowserFilterView):
|
|
|
54
54
|
args["distinct"] = True
|
|
55
55
|
return agg_func(bmua_rel, **args)
|
|
56
56
|
|
|
57
|
-
def get_group_mtime(self, model, group=None, pks=None, page_mtime=False):
|
|
57
|
+
def get_group_mtime(self, model, group=None, pks=None, page_mtime=False): # noqa: FBT002
|
|
58
58
|
"""Get a filtered mtime for browser pages and mtime checker."""
|
|
59
59
|
qs = self.get_filtered_queryset(
|
|
60
60
|
model,
|
|
@@ -47,7 +47,7 @@ class MetadataCopyIntersectionsView(MetadataQueryIntersectionsView):
|
|
|
47
47
|
@classmethod
|
|
48
48
|
def _copy_m2m_intersections(cls, obj, m2m_intersections):
|
|
49
49
|
"""Copy the m2m intersections into the object."""
|
|
50
|
-
#
|
|
50
|
+
# It might even be faster to copy everything to a dict and not use the obj.
|
|
51
51
|
for key, qs in m2m_intersections.items():
|
|
52
52
|
serializer_key = (
|
|
53
53
|
f"{PREFETCH_PREFIX}{key}"
|
|
@@ -63,7 +63,7 @@ class MetadataView(MetadataCopyIntersectionsView):
|
|
|
63
63
|
obj = qs[0]
|
|
64
64
|
if not obj:
|
|
65
65
|
reason = "Empty obj"
|
|
66
|
-
raise ValueError(reason) # noqa TRY301
|
|
66
|
+
raise ValueError(reason) # noqa: TRY301
|
|
67
67
|
except (IndexError, ValueError) as exc:
|
|
68
68
|
return self._raise_not_found(exc)
|
|
69
69
|
|
codex/views/browser/mtime.py
CHANGED
|
@@ -37,7 +37,7 @@ class MtimeView(BrowserGroupMtimeView):
|
|
|
37
37
|
"""Get max mtime for all groups."""
|
|
38
38
|
max_mtime = None
|
|
39
39
|
|
|
40
|
-
for item in self.params["groups"]:
|
|
40
|
+
for item in self.params["groups"]:
|
|
41
41
|
mtime = self._get_group_mtime(item)
|
|
42
42
|
max_mtime = max_none(max_mtime, mtime)
|
|
43
43
|
return max_mtime
|
codex/views/browser/order_by.py
CHANGED
|
@@ -55,7 +55,7 @@ class BrowserOrderByView(BrowserGroupMtimeView):
|
|
|
55
55
|
order_fields_head += ["bookmark_updated_at"]
|
|
56
56
|
return order_fields_head
|
|
57
57
|
|
|
58
|
-
def add_order_by(self, qs, order_key="",
|
|
58
|
+
def add_order_by(self, qs, order_key="", comic_sort_names=None):
|
|
59
59
|
"""Create the order_by list."""
|
|
60
60
|
order_fields_head = ()
|
|
61
61
|
if qs.model is Comic:
|
|
@@ -65,11 +65,9 @@ class BrowserOrderByView(BrowserGroupMtimeView):
|
|
|
65
65
|
|
|
66
66
|
order_fields = (*order_fields_head, "pk")
|
|
67
67
|
|
|
68
|
-
prefix = "-" if
|
|
69
|
-
order_by = []
|
|
68
|
+
prefix = "-" if self.params.get("order_reverse") else ""
|
|
70
69
|
if prefix:
|
|
71
|
-
for field in order_fields
|
|
72
|
-
order_by.append(prefix + field)
|
|
70
|
+
order_by = [prefix + field for field in order_fields]
|
|
73
71
|
else:
|
|
74
72
|
order_by = order_fields
|
|
75
73
|
|
codex/views/browser/params.py
CHANGED
|
@@ -58,7 +58,7 @@ class BrowserParamsView(SessionView):
|
|
|
58
58
|
validated_data = serializer.validated_data
|
|
59
59
|
|
|
60
60
|
if validated_data:
|
|
61
|
-
params.update(validated_data)
|
|
61
|
+
params.update(validated_data)
|
|
62
62
|
self._params = MappingProxyType(params)
|
|
63
63
|
self.validate_settings()
|
|
64
64
|
return self._params
|
codex/views/browser/settings.py
CHANGED
|
@@ -9,7 +9,7 @@ class BrowserSettingsView(SettingsView):
|
|
|
9
9
|
"""Get Browser Settings."""
|
|
10
10
|
|
|
11
11
|
# Put Browser Settings is normally done through BrowserView.get()
|
|
12
|
-
serializer_class = BrowserSettingsSerializer
|
|
12
|
+
serializer_class = BrowserSettingsSerializer
|
|
13
13
|
|
|
14
14
|
SESSION_KEY = SettingsView.BROWSER_SESSION_KEY
|
|
15
15
|
|
codex/views/browser/validate.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from collections.abc import Mapping
|
|
4
4
|
from copy import deepcopy
|
|
5
5
|
from types import MappingProxyType
|
|
6
|
+
from typing import Any
|
|
6
7
|
|
|
7
8
|
from rest_framework.exceptions import NotFound
|
|
8
9
|
|
|
@@ -73,17 +74,18 @@ class BrowserValidateView(SearchFilterView):
|
|
|
73
74
|
self, reason, route_mask=None, settings_mask: Mapping | None = None
|
|
74
75
|
):
|
|
75
76
|
"""Redirect the client to a valid group url."""
|
|
76
|
-
route = mapping_to_dict(self.DEFAULT_ROUTE)
|
|
77
|
+
route: dict[str, Any] = mapping_to_dict(self.DEFAULT_ROUTE) # type:ignore[reportAssignmentType]
|
|
77
78
|
if route_mask:
|
|
78
|
-
route["params"].update(route_mask)
|
|
79
|
-
settings: dict = deepcopy(mapping_to_dict(self.params)) # type: ignore
|
|
79
|
+
route["params"].update(route_mask)
|
|
80
|
+
settings: dict[str, Any] = deepcopy(mapping_to_dict(self.params)) # type: ignore[reportAssignmentType]
|
|
80
81
|
if settings_mask:
|
|
81
82
|
settings.update(settings_mask)
|
|
82
83
|
detail = {"route": route, "settings": settings, "reason": reason}
|
|
83
84
|
raise SeeOtherRedirectError(detail=detail)
|
|
84
85
|
|
|
85
86
|
def _get_valid_browse_top_groups(self):
|
|
86
|
-
"""
|
|
87
|
+
"""
|
|
88
|
+
Get valid top groups for the current settings.
|
|
87
89
|
|
|
88
90
|
Valid top groups are determined by the Browser Settings.
|
|
89
91
|
"""
|
|
@@ -118,7 +120,8 @@ class BrowserValidateView(SearchFilterView):
|
|
|
118
120
|
self.raise_redirect(reason, route, settings_mask)
|
|
119
121
|
|
|
120
122
|
def _get_valid_browse_nav_groups(self, valid_top_groups):
|
|
121
|
-
"""
|
|
123
|
+
"""
|
|
124
|
+
Get valid nav groups for the current settings.
|
|
122
125
|
|
|
123
126
|
Valid nav groups are the top group and below that are also
|
|
124
127
|
enabled in browser settings.
|
codex/views/const.py
CHANGED
|
@@ -76,9 +76,6 @@ METADATA_GROUP_RELATION = MappingProxyType(
|
|
|
76
76
|
{
|
|
77
77
|
**GROUP_NAME_MAP,
|
|
78
78
|
COMIC_GROUP: "comic",
|
|
79
|
-
# Possible to list all groups in a non group view, but could get crazy.
|
|
80
|
-
# FOLDER_GROUP: "comic__folder",
|
|
81
|
-
# STORY_ARC_GROUP: "comic__story_arc_number__story_arc"
|
|
82
79
|
}
|
|
83
80
|
)
|
|
84
81
|
CUSTOM_COVER_GROUP_RELATION = MappingProxyType(
|
codex/views/frontend.py
CHANGED
|
@@ -17,7 +17,7 @@ class IndexView(SessionView):
|
|
|
17
17
|
SESSION_KEY = SessionView.BROWSER_SESSION_KEY
|
|
18
18
|
|
|
19
19
|
permission_classes = (AllowAny,)
|
|
20
|
-
renderer_classes: ClassVar[list] = [TemplateHTMLRenderer] # type: ignore
|
|
20
|
+
renderer_classes: ClassVar[list] = [TemplateHTMLRenderer] # type: ignore[reportIncompatibleVariableOverride]
|
|
21
21
|
template_name = "index.html"
|
|
22
22
|
|
|
23
23
|
def _get_last_route(self):
|
codex/views/mixins.py
CHANGED
|
@@ -4,6 +4,7 @@ from django.db.models.expressions import F
|
|
|
4
4
|
|
|
5
5
|
from codex.logger.logging import get_logger
|
|
6
6
|
from codex.models.comic import Comic, Imprint, Volume
|
|
7
|
+
from codex.views.browser.filters.filter import BrowserFilterView
|
|
7
8
|
from codex.views.const import GROUP_NAME_MAP
|
|
8
9
|
|
|
9
10
|
LOG = get_logger(__name__)
|
|
@@ -12,7 +13,7 @@ _GROUP_NAME_TARGETS = frozenset({"browser", "opds1", "opds2", "reader"})
|
|
|
12
13
|
_VARIABLE_SHOW = "pi"
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
class SharedAnnotationsMixin:
|
|
16
|
+
class SharedAnnotationsMixin(BrowserFilterView):
|
|
16
17
|
"""Cross view annotation methods."""
|
|
17
18
|
|
|
18
19
|
@staticmethod
|
|
@@ -54,7 +55,7 @@ class SharedAnnotationsMixin:
|
|
|
54
55
|
def annotate_group_names(cls, qs):
|
|
55
56
|
"""Annotate name fields by hoisting them up."""
|
|
56
57
|
# Optimized to only lookup what is used on the frontend
|
|
57
|
-
target = cls.TARGET
|
|
58
|
+
target = cls.TARGET
|
|
58
59
|
if target not in _GROUP_NAME_TARGETS:
|
|
59
60
|
return qs
|
|
60
61
|
group_names = {}
|
codex/views/opds/const.py
CHANGED
|
@@ -48,9 +48,9 @@ class MimeType:
|
|
|
48
48
|
|
|
49
49
|
ATOM = "application/atom+xml"
|
|
50
50
|
_PROFILE_CATALOG = "profile=opds-catalog"
|
|
51
|
-
NAV = ";
|
|
52
|
-
ACQUISITION = ";
|
|
53
|
-
ENTRY_CATALOG = ";
|
|
51
|
+
NAV = f"{ATOM};{_PROFILE_CATALOG};kind=navigation"
|
|
52
|
+
ACQUISITION = f"{ATOM};{_PROFILE_CATALOG};kind=acquisition"
|
|
53
|
+
ENTRY_CATALOG = f"{ATOM};type=entry;{_PROFILE_CATALOG}"
|
|
54
54
|
AUTHENTICATION = "application/opds-authentication+json"
|
|
55
55
|
OPENSEARCH = "application/opensearchdescription+xml"
|
|
56
56
|
STREAM = "image/jpeg"
|
|
@@ -58,7 +58,7 @@ class MimeType:
|
|
|
58
58
|
OPDS_PUB = "application/opds-publication+json"
|
|
59
59
|
PROGRESSION = "application/vnd.readium.progression+json"
|
|
60
60
|
BOOK = "http://schema.org/Book"
|
|
61
|
-
# COMIC = "https://schema.org/ComicStory"
|
|
61
|
+
# COMIC = "https://schema.org/ComicStory" unused
|
|
62
62
|
JPEG = "image/jpeg"
|
|
63
63
|
WEBP = "image/webp"
|
|
64
64
|
HTML = "text/html"
|
codex/views/opds/util.py
CHANGED
|
@@ -31,7 +31,7 @@ def update_href_query_params(href, old_query_params, new_query_params=None):
|
|
|
31
31
|
return href
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
def get_contributor_people(comic_pks, roles, exclude
|
|
34
|
+
def get_contributor_people(comic_pks, roles, exclude):
|
|
35
35
|
"""Get contributors that are not authors."""
|
|
36
36
|
people = ContributorPerson.objects.filter(
|
|
37
37
|
contributor__comic__in=comic_pks,
|
|
@@ -43,7 +43,7 @@ def get_contributor_people(comic_pks, roles, exclude=False):
|
|
|
43
43
|
return people.distinct().only("name")
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def get_contributors(comic_pks, roles, exclude
|
|
46
|
+
def get_contributors(comic_pks, roles, exclude):
|
|
47
47
|
"""Get credits that are not part of other roles."""
|
|
48
48
|
contributors = Contributor.objects.filter(comic__in=comic_pks)
|
|
49
49
|
if exclude:
|
|
@@ -78,7 +78,7 @@ def full_redirect_view(url_name):
|
|
|
78
78
|
path = request.get_full_path()
|
|
79
79
|
if path:
|
|
80
80
|
parts = path.split("?")
|
|
81
|
-
if len(parts) >= 2: # noqa PLR2004
|
|
81
|
+
if len(parts) >= 2: # noqa: PLR2004
|
|
82
82
|
parts[0] = url
|
|
83
83
|
url = "?".join(parts)
|
|
84
84
|
|
|
@@ -47,8 +47,10 @@ class OPDS1Entry(OPDS1EntryLinksMixin):
|
|
|
47
47
|
elif group == "c":
|
|
48
48
|
title = Comic.get_title(
|
|
49
49
|
self.obj,
|
|
50
|
-
|
|
50
|
+
volume=True,
|
|
51
|
+
name=True,
|
|
51
52
|
filename_fallback=self.title_filename_fallback,
|
|
53
|
+
zero_pad=self.zero_pad,
|
|
52
54
|
)
|
|
53
55
|
parts.append(title)
|
|
54
56
|
|
|
@@ -133,7 +135,7 @@ class OPDS1Entry(OPDS1EntryLinksMixin):
|
|
|
133
135
|
"""Get Author names."""
|
|
134
136
|
if not self.metadata:
|
|
135
137
|
return []
|
|
136
|
-
people = get_contributor_people(self.obj.ids, AUTHOR_ROLES)
|
|
138
|
+
people = get_contributor_people(self.obj.ids, AUTHOR_ROLES, exclude=False)
|
|
137
139
|
return self._add_url_to_obj(people, "contributors")
|
|
138
140
|
|
|
139
141
|
@property
|
|
@@ -20,7 +20,7 @@ class OPDS1EntryLinksMixin:
|
|
|
20
20
|
"""OPDS v1 Entry Links Methods."""
|
|
21
21
|
|
|
22
22
|
def __init__(
|
|
23
|
-
self, obj, query_params, data: OPDS1EntryData, title_filename_fallback
|
|
23
|
+
self, obj, query_params, data: OPDS1EntryData, title_filename_fallback: bool
|
|
24
24
|
):
|
|
25
25
|
"""Initialize params."""
|
|
26
26
|
self.obj = obj
|
|
@@ -35,7 +35,6 @@ class OPDS1EntryLinksMixin:
|
|
|
35
35
|
def _cover_link(self, rel):
|
|
36
36
|
if self.fake:
|
|
37
37
|
return None
|
|
38
|
-
# cover_pk = getattr(self.obj, "cover_pk", None)
|
|
39
38
|
try:
|
|
40
39
|
kwargs = {"group": self.obj.group, "pks": self.obj.ids}
|
|
41
40
|
ts = floor(datetime.timestamp(self.obj.updated_at))
|
|
@@ -50,7 +49,7 @@ class OPDS1EntryLinksMixin:
|
|
|
50
49
|
except Exception:
|
|
51
50
|
LOG.exception("create thumb")
|
|
52
51
|
|
|
53
|
-
def _nav_href(self, metadata
|
|
52
|
+
def _nav_href(self, metadata: bool):
|
|
54
53
|
try:
|
|
55
54
|
pks = sorted(self.obj.ids)
|
|
56
55
|
kwargs = {"group": self.obj.group, "pks": pks, "page": 1}
|
|
@@ -72,7 +71,7 @@ class OPDS1EntryLinksMixin:
|
|
|
72
71
|
LOG.exception(msg)
|
|
73
72
|
raise
|
|
74
73
|
|
|
75
|
-
def _nav_link(self, metadata
|
|
74
|
+
def _nav_link(self, metadata: bool):
|
|
76
75
|
href = self._nav_href(metadata)
|
|
77
76
|
|
|
78
77
|
group = self.obj.group
|
|
@@ -154,7 +153,7 @@ class OPDS1EntryLinksMixin:
|
|
|
154
153
|
|
|
155
154
|
if self.obj.group == "c" and not self.fake:
|
|
156
155
|
result += self._links_comic()
|
|
157
|
-
elif nav := self._nav_link():
|
|
156
|
+
elif nav := self._nav_link(metadata=False):
|
|
158
157
|
result += [nav]
|
|
159
158
|
|
|
160
159
|
except Exception:
|
codex/views/opds/v1/facets.py
CHANGED
|
@@ -169,11 +169,14 @@ class OPDS1FacetsView(BrowserView):
|
|
|
169
169
|
)
|
|
170
170
|
qps = {**self.request.GET}
|
|
171
171
|
qps.update(query_params)
|
|
172
|
-
zero_pad: int = self.obj["zero_pad"]
|
|
172
|
+
zero_pad: int = self.obj["zero_pad"]
|
|
173
173
|
data = OPDS1EntryData(
|
|
174
|
-
self.opds_acquisition_groups,
|
|
174
|
+
self.opds_acquisition_groups,
|
|
175
|
+
zero_pad,
|
|
176
|
+
metadata=False,
|
|
177
|
+
mime_type_map=self.mime_type_map,
|
|
175
178
|
)
|
|
176
|
-
return OPDS1Entry(entry_obj, qps, data)
|
|
179
|
+
return OPDS1Entry(entry_obj, qps, data, title_filename_fallback=False)
|
|
177
180
|
|
|
178
181
|
def _is_facet_active(self, facet_group, facet):
|
|
179
182
|
compare = [facet.value]
|
|
@@ -231,7 +234,8 @@ class OPDS1FacetsView(BrowserView):
|
|
|
231
234
|
facets += [facet_obj]
|
|
232
235
|
return facets
|
|
233
236
|
|
|
234
|
-
def facets(self, entries
|
|
237
|
+
def facets(self, entries: bool, root: bool):
|
|
238
|
+
# entries false, root true
|
|
235
239
|
"""Return facets."""
|
|
236
240
|
facets = []
|
|
237
241
|
group = self.kwargs.get("group")
|
codex/views/opds/v1/feed.py
CHANGED
|
@@ -75,7 +75,7 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
|
|
|
75
75
|
"""Create the feed title."""
|
|
76
76
|
result = ""
|
|
77
77
|
try:
|
|
78
|
-
browser_title: Mapping[str, Any] = self.obj.get("title")
|
|
78
|
+
browser_title: Mapping[str, Any] = self.obj.get("title", {})
|
|
79
79
|
if browser_title:
|
|
80
80
|
parent_name = browser_title.get("parent_name", "All")
|
|
81
81
|
pks = self.kwargs["pks"]
|
|
@@ -97,7 +97,7 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
|
|
|
97
97
|
try:
|
|
98
98
|
mtime = self.obj.get("mtime")
|
|
99
99
|
if mtime:
|
|
100
|
-
datestr = mtime.isoformat()
|
|
100
|
+
datestr = mtime.isoformat()
|
|
101
101
|
except Exception:
|
|
102
102
|
LOG.exception("Getting OPDS v1 updated")
|
|
103
103
|
return datestr
|
|
@@ -124,13 +124,13 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
|
|
|
124
124
|
"""Get entries by key section."""
|
|
125
125
|
entries = []
|
|
126
126
|
if objs := self.obj.get(key):
|
|
127
|
-
zero_pad: int = self.obj["zero_pad"]
|
|
127
|
+
zero_pad: int = self.obj["zero_pad"]
|
|
128
128
|
data = OPDS1EntryData(
|
|
129
129
|
self.opds_acquisition_groups, zero_pad, metadata, self.mime_type_map
|
|
130
130
|
)
|
|
131
131
|
fallback = bool(self.admin_flags.get("folder_view"))
|
|
132
132
|
import_pks = set()
|
|
133
|
-
for obj in objs:
|
|
133
|
+
for obj in objs:
|
|
134
134
|
entry = OPDS1Entry(
|
|
135
135
|
obj,
|
|
136
136
|
self.request.GET,
|
|
@@ -157,7 +157,7 @@ class OPDS1FeedView(OPDS1LinksView, OPDSTemplateView):
|
|
|
157
157
|
entries += self.add_top_links(RootTopLinks.ALL)
|
|
158
158
|
entries += self.facets(entries=True, root=at_root)
|
|
159
159
|
|
|
160
|
-
entries += self._get_entries_section("groups", False)
|
|
160
|
+
entries += self._get_entries_section("groups", metadata=False)
|
|
161
161
|
metadata = self.request.GET.get("opdsMetadata", "").lower() not in FALSY
|
|
162
162
|
entries += self._get_entries_section("books", metadata)
|
|
163
163
|
except Exception:
|
codex/views/opds/v1/links.py
CHANGED
|
@@ -105,7 +105,7 @@ class RootTopLinks:
|
|
|
105
105
|
class OPDS1LinksView(OPDS1FacetsView):
|
|
106
106
|
"""OPDS 1 Links methods."""
|
|
107
107
|
|
|
108
|
-
# overwritten in get_object
|
|
108
|
+
# overwritten in get_object method
|
|
109
109
|
DEFAULT_ROUTE = MappingProxyType(
|
|
110
110
|
{
|
|
111
111
|
**OPDS1FacetsView.DEFAULT_ROUTE,
|
|
@@ -143,7 +143,7 @@ class OPDS1LinksView(OPDS1FacetsView):
|
|
|
143
143
|
def _root_links(self):
|
|
144
144
|
"""Navigation Root Links."""
|
|
145
145
|
links = []
|
|
146
|
-
if up_route := self.get_last_route():
|
|
146
|
+
if up_route := self.get_last_route(name=True):
|
|
147
147
|
links += [self._link(up_route, Rel.UP)]
|
|
148
148
|
page = self.kwargs.get("page", 1)
|
|
149
149
|
if page > 1:
|
|
@@ -179,7 +179,7 @@ class OPDS1LinksView(OPDS1FacetsView):
|
|
|
179
179
|
for top_link in TopLinks.ALL + RootTopLinks.ALL:
|
|
180
180
|
if not self.is_top_link_displayed(top_link):
|
|
181
181
|
links += [self._top_link(top_link)]
|
|
182
|
-
if facets := self.facets():
|
|
182
|
+
if facets := self.facets(entries=False, root=True):
|
|
183
183
|
links += facets
|
|
184
184
|
except Exception:
|
|
185
185
|
LOG.exception("Getting OPDS v1 links")
|
|
@@ -194,11 +194,16 @@ class OPDS1LinksView(OPDS1FacetsView):
|
|
|
194
194
|
name=name,
|
|
195
195
|
summary=top_link.desc,
|
|
196
196
|
)
|
|
197
|
-
zero_pad: int = self.obj["zero_pad"]
|
|
197
|
+
zero_pad: int = self.obj["zero_pad"]
|
|
198
198
|
data = OPDS1EntryData(
|
|
199
|
-
self.opds_acquisition_groups,
|
|
199
|
+
self.opds_acquisition_groups,
|
|
200
|
+
zero_pad,
|
|
201
|
+
metadata=False,
|
|
202
|
+
mime_type_map=self.mime_type_map,
|
|
203
|
+
)
|
|
204
|
+
return OPDS1Entry(
|
|
205
|
+
entry_obj, top_link.query_params, data, title_filename_fallback=False
|
|
200
206
|
)
|
|
201
|
-
return OPDS1Entry(entry_obj, top_link.query_params, data)
|
|
202
207
|
|
|
203
208
|
def add_top_links(self, top_links):
|
|
204
209
|
"""Add a list of top links as entries if they should be enabled."""
|
codex/views/opds/v2/const.py
CHANGED
|
@@ -31,7 +31,10 @@ FACETS = (
|
|
|
31
31
|
"Order Direction",
|
|
32
32
|
"orderReverse",
|
|
33
33
|
"⇕",
|
|
34
|
-
(
|
|
34
|
+
(
|
|
35
|
+
Facet(query_param_value=False, title="Ascending"),
|
|
36
|
+
Facet(query_param_value=True, title="Descending"),
|
|
37
|
+
),
|
|
35
38
|
),
|
|
36
39
|
FacetGroup(
|
|
37
40
|
"Top Group",
|
|
@@ -114,5 +117,5 @@ class LinksSectionData:
|
|
|
114
117
|
|
|
115
118
|
|
|
116
119
|
TOP_NAV_GROUP_SECTION_DATA = LinksSectionData(group_kwarg=True)
|
|
117
|
-
GROUPS_SECTION_DATA = LinksSectionData("Groups", Rel.SUB, True)
|
|
120
|
+
GROUPS_SECTION_DATA = LinksSectionData("Groups", Rel.SUB, group_kwarg=True)
|
|
118
121
|
FACETS_SECTION_DATA = LinksSectionData(rel=Rel.FACET, links_key="links")
|
codex/views/opds/v2/feed.py
CHANGED
|
@@ -56,9 +56,9 @@ class OPDS2FeedView(OPDSAuthMixin, OPDS2PublicationView):
|
|
|
56
56
|
|
|
57
57
|
# def _detect_user_agent(self):
|
|
58
58
|
# """Hacks for individual clients."""
|
|
59
|
-
# user_agent = self.request.headers.get("User-Agent")
|
|
59
|
+
# user_agent = self.request.headers.get("User-Agent") # noqa: ERA001
|
|
60
60
|
# if not user_agent:
|
|
61
|
-
# return
|
|
61
|
+
# return # noqa: ERA001
|
|
62
62
|
|
|
63
63
|
@staticmethod
|
|
64
64
|
def _is_allowed(link_spec):
|
|
@@ -185,7 +185,7 @@ class OPDS2FeedView(OPDSAuthMixin, OPDS2PublicationView):
|
|
|
185
185
|
title = self._title(title)
|
|
186
186
|
number_of_items = total_count
|
|
187
187
|
current_page = self.kwargs.get("page")
|
|
188
|
-
up_route = self.get_last_route()
|
|
188
|
+
up_route = self.get_last_route(name=True)
|
|
189
189
|
links = self.get_links(up_route)
|
|
190
190
|
facets = self._get_facets()
|
|
191
191
|
|
|
@@ -38,7 +38,7 @@ class OPDS2ProgressionView(
|
|
|
38
38
|
@property
|
|
39
39
|
def modified(self):
|
|
40
40
|
"""Get modified from bookmark."""
|
|
41
|
-
return self._obj.bookmark_updated_at # type: ignore
|
|
41
|
+
return self._obj.bookmark_updated_at # type: ignore[reportAttributeAccessIssue]
|
|
42
42
|
|
|
43
43
|
@property
|
|
44
44
|
def device(self):
|
|
@@ -49,22 +49,21 @@ class OPDS2ProgressionView(
|
|
|
49
49
|
@property
|
|
50
50
|
def title(self):
|
|
51
51
|
"""The locator title is the page number."""
|
|
52
|
-
return f"Page {self._obj.page}" # type: ignore
|
|
52
|
+
return f"Page {self._obj.page}" # type: ignore[reportAttributeAccessIssue]
|
|
53
53
|
|
|
54
54
|
@property
|
|
55
55
|
def _progression_href(self):
|
|
56
56
|
"""Build a Progression HRef."""
|
|
57
57
|
acq_kwargs = {
|
|
58
58
|
"pk": self._obj.pk,
|
|
59
|
-
"page": self._obj.page, # type: ignore
|
|
59
|
+
"page": self._obj.page, # type: ignore[reportAttributeAccessIssue]
|
|
60
60
|
}
|
|
61
|
-
max_page = max_none(self._obj.page_count - 1, 0) # type: ignore
|
|
61
|
+
max_page = max_none(self._obj.page_count - 1, 0) # type: ignore[reportAttributeAccessIssue]
|
|
62
62
|
data = HrefData(
|
|
63
63
|
acq_kwargs,
|
|
64
64
|
url_name="opds:bin:page",
|
|
65
65
|
min_page=0,
|
|
66
|
-
max_page=max_page,
|
|
67
|
-
# absolute_query_params=True,
|
|
66
|
+
max_page=max_page,
|
|
68
67
|
)
|
|
69
68
|
return self.href(data)
|
|
70
69
|
|
|
@@ -72,9 +71,9 @@ class OPDS2ProgressionView(
|
|
|
72
71
|
def _locations(self):
|
|
73
72
|
"""Build the Locations object."""
|
|
74
73
|
return {
|
|
75
|
-
"position": self._obj.page, # type: ignore
|
|
76
|
-
"progression": self._obj.progress, # type: ignore
|
|
77
|
-
"total_progression": self._obj.progress, # type: ignore
|
|
74
|
+
"position": self._obj.page, # type: ignore[reportAttributeAccessIssue]
|
|
75
|
+
"progression": self._obj.progress, # type: ignore[reportAttributeAccessIssue]
|
|
76
|
+
"total_progression": self._obj.progress, # type: ignore[reportAttributeAccessIssue]
|
|
78
77
|
}
|
|
79
78
|
|
|
80
79
|
@property
|