aa-structures 2.10.0__tar.gz → 2.12.0__tar.gz
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.
- {aa_structures-2.10.0 → aa_structures-2.12.0}/PKG-INFO +1 -1
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/__init__.py +1 -1
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/admin.py +43 -4
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/app_settings.py +1 -1
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/main.py +18 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/managers.py +17 -4
- aa_structures-2.12.0/structures/migrations/0006_add_ownercharacter_disabled.py +27 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/models/notifications.py +5 -1
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/models/owners.py +104 -51
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/notification_embeds/test_main.py +20 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_notifications_discord.py +21 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_owners_1.py +95 -52
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_owners_4.py +21 -5
- aa_structures-2.12.0/structures/tests/models/test_owners_6.py +31 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/test_admin.py +65 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/test_managers_2.py +3 -2
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/factories.py +3 -4
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/views/test_structures.py +58 -5
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/views/structures.py +2 -2
- {aa_structures-2.10.0 → aa_structures-2.12.0}/LICENSE +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/README.md +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/pyproject.toml +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/apps.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/auth_hooks.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/constants.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/billing_embeds.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/corporate_embeds.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/helpers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/moonmining_embeds.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/orbital_embeds.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/sov_embeds.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/structures_embeds.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/tower_embeds.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_embeds/war_embeds.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_timers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/notification_types.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/serializers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/sovereignty.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/core/starbases.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/forms.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/helpers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/de/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/de/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/django.pot +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/en/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/en/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/es/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/es/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/fr_FR/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/it_IT/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/it_IT/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/ja/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/ja/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/ko_KR/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/ko_KR/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/ru/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/ru/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/uk/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/uk/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/locale/zh_Hans/LC_MESSAGES/django.po +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/management/commands/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/management/commands/structures_load_eve.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/management/commands/structures_preload_eveuniverse.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/management/commands/structures_update_poco_planets.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/migrations/0001_initial_new.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/migrations/0002_remove_eveuniverse_relation_names.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/migrations/0003_add_localization_and_unique_key.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/migrations/0004_improve_localization.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/migrations/0005_add_notification_types.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/migrations/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/models/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/models/eveuniverse.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/models/structures_1.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/models/structures_2.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/providers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/css/global.css +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/css/main.css +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/css/public.css +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/css/statistics.css +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/css/structures.css +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/bars-rotate-fade-black-36.svg +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/bars-rotate-fade-white-36.svg +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/eve_symbol_128.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/0h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/0l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/0m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/0r.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/0s.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/1h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/1l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/1m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/1r.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/2h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/2l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/2m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/2r.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/3h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/3l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/3m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/3r.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/4h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/4l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/4m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/4s.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/5h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/5l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/5m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/5s.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/6h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/6l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/6m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/7h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/7l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/7m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/8h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/8l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/8m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/blank.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/circle.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/dustwheel.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/h.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/l.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/m.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/noship.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/r.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/tyrannis.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/tyrannis_blue.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/tyrannis_darkred.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/tyrannis_default.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/panel/tyrannis_revelations.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/img/structures_logo.png +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/js/global.js +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/js/public.js +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/js/statistics.js +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/js/structures.js +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/vendor/datatables/plugins/dataTables.rowGroup.min.js +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/vendor/datatables/plugins/datetime.js +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/vendor/datatables/plugins/filterDropDown.min.js +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/vendor/datatables/plugins/rowGroup.bootstrap.min.css +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/static/structures/vendor/datatables/plugins/rowGroup.dataTables.min.css +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tasks.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/base.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/modals/fitting_assets.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/modals/fitting_gfx.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/modals/poco_details.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/modals/starbase_detail.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/modals/structure_details.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/modals/tab_general_detail.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/modals/tab_services_detail.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/partials/menu.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/partials/public/poco_list.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/partials/statistics/structure_summary.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/partials/structures/active_tags.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/partials/structures/jump_gates_list.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/partials/structures/poco_list.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/partials/structures/starbase_list.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/partials/structures/structure_list.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/public.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/statistics.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/structures.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/templatetags/detail_title.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/templatetags/list_asset.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/templatetags/list_item.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/templatetags/list_tax_item.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templates/structures/templatetags/list_title.html +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templatetags/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/templatetags/structures.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/notification_embeds/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/notification_embeds/test_helpers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/test_notification_structuretimers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/test_notification_types.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/test_notifications_timerboard.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/test_serializers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/test_sovereignty.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/test_starbases.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/integration/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/integration/test_tasks.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/integration/test_views.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_eveuniverse.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_notifications_1.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_notifications_2.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_notifications_3.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_owners_2.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_owners_3.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_owners_5.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_structures.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/test_helpers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/test_managers_1.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/test_tasks.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/create_eveuniverse.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/entities.json +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/esi_data.json +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/eveuniverse.json +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/generate_notifications.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/generate_notifications_2.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/generate_structures.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/helpers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/load_eveuniverse.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/tasks_loadtest.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/testdata/test_generate_structures.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/views/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/views/test_public.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/views/test_service_status.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/views/test_statistics.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/views/utils.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/urls.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/views/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/views/common.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/views/public.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/views/statistics.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/views/status.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/webhooks/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/webhooks/core.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/webhooks/managers.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/webhooks/models.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/webhooks/tests/__init__.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/webhooks/tests/test_core.py +0 -0
- {aa_structures-2.10.0 → aa_structures-2.12.0}/structures/webhooks/tests/test_utils.py +0 -0
@@ -348,6 +348,29 @@ class OwnerCharacterAdminInline(admin.TabularInline):
|
|
348
348
|
return False
|
349
349
|
|
350
350
|
|
351
|
+
class DisabledCharactersFilter(admin.SimpleListFilter):
|
352
|
+
title = _("has disabled characters")
|
353
|
+
parameter_name = "has_disabled_characters"
|
354
|
+
|
355
|
+
def lookups(self, request, model_admin):
|
356
|
+
return (
|
357
|
+
("yes", _("yes")),
|
358
|
+
("no", _("no")),
|
359
|
+
)
|
360
|
+
|
361
|
+
def queryset(self, request, queryset):
|
362
|
+
"""Return the filtered queryset"""
|
363
|
+
if self.value() == "yes":
|
364
|
+
return queryset.annotate_characters_count().filter(
|
365
|
+
characters_disabled_count__gt=0
|
366
|
+
)
|
367
|
+
if self.value() == "no":
|
368
|
+
return queryset.annotate_characters_count().filter(
|
369
|
+
characters_disabled_count=0
|
370
|
+
)
|
371
|
+
return queryset
|
372
|
+
|
373
|
+
|
351
374
|
@admin.register(Owner)
|
352
375
|
class OwnerAdmin(admin.ModelAdmin):
|
353
376
|
list_display = (
|
@@ -364,6 +387,7 @@ class OwnerAdmin(admin.ModelAdmin):
|
|
364
387
|
list_filter = (
|
365
388
|
"is_active",
|
366
389
|
"is_up",
|
390
|
+
DisabledCharactersFilter,
|
367
391
|
("corporation__alliance", admin.RelatedOnlyFieldListFilter),
|
368
392
|
"has_default_pings_enabled",
|
369
393
|
"is_alliance_main",
|
@@ -376,6 +400,7 @@ class OwnerAdmin(admin.ModelAdmin):
|
|
376
400
|
"fetch_notifications",
|
377
401
|
"deactivate_owners",
|
378
402
|
"activate_owners",
|
403
|
+
"reset_characters",
|
379
404
|
)
|
380
405
|
inlines = (OwnerCharacterAdminInline,)
|
381
406
|
filter_horizontal = ("ping_groups", "webhooks")
|
@@ -485,9 +510,13 @@ class OwnerAdmin(admin.ModelAdmin):
|
|
485
510
|
def has_add_permission(self, request):
|
486
511
|
return False
|
487
512
|
|
488
|
-
@admin.display(ordering="
|
489
|
-
def _characters(self, obj: Owner) ->
|
490
|
-
|
513
|
+
@admin.display(ordering="characters_enabled_count", description=_("characters"))
|
514
|
+
def _characters(self, obj: Owner) -> str:
|
515
|
+
enabled = obj.characters_enabled_count
|
516
|
+
disabled = obj.characters_disabled_count
|
517
|
+
if not disabled:
|
518
|
+
return enabled
|
519
|
+
return f"{enabled} ({disabled})"
|
491
520
|
|
492
521
|
@admin.display(description=_("default pings"), boolean=True)
|
493
522
|
def _has_default_pings_enabled(self, obj: Owner):
|
@@ -549,6 +578,16 @@ class OwnerAdmin(admin.ModelAdmin):
|
|
549
578
|
queryset.update(is_active=False)
|
550
579
|
self.message_user(request, _("Deactivated %d owners") % queryset.count())
|
551
580
|
|
581
|
+
@admin.action(description=_("Reset disabled characters for selected owners"))
|
582
|
+
def reset_characters(self, request, queryset):
|
583
|
+
owner_pks = queryset.values_list("pk", flat=True)
|
584
|
+
OwnerCharacter.objects.filter(
|
585
|
+
owner__pk__in=list(owner_pks), is_enabled=False
|
586
|
+
).update(is_enabled=True, disabled_reason="", error_count=0)
|
587
|
+
self.message_user(
|
588
|
+
request, _("Characters have been reset for %d owners") % len(owner_pks)
|
589
|
+
)
|
590
|
+
|
552
591
|
@admin.action(description=_("Update all from EVE server for selected owners"))
|
553
592
|
def update_all(self, request, queryset):
|
554
593
|
for obj in queryset:
|
@@ -631,7 +670,7 @@ class OwnerAdmin(admin.ModelAdmin):
|
|
631
670
|
def _assets_last_update_fresh(self, obj: Owner) -> bool:
|
632
671
|
return obj.is_assets_sync_fresh
|
633
672
|
|
634
|
-
@admin.
|
673
|
+
@admin.display(description=_("structures Count"))
|
635
674
|
def _structures_count(self, obj: Owner) -> int:
|
636
675
|
return obj.structures.count()
|
637
676
|
|
@@ -55,7 +55,7 @@ STRUCTURES_FEATURE_STARBASES = clean_setting("STRUCTURES_FEATURE_STARBASES", Tru
|
|
55
55
|
STRUCTURES_ESI_DIRECTOR_ERROR_MAX_RETRIES = clean_setting(
|
56
56
|
"STRUCTURES_ESI_DIRECTOR_ERROR_MAX_RETRIES", 3
|
57
57
|
)
|
58
|
-
"""Max retries before a character is
|
58
|
+
"""Max retries before a character is disabled when ESI claims the character
|
59
59
|
is not a director (Since this sometimes is reported wrongly by ESI).
|
60
60
|
"""
|
61
61
|
|
@@ -10,6 +10,8 @@ import dhooks_lite
|
|
10
10
|
from django.conf import settings
|
11
11
|
from django.utils.translation import gettext as _
|
12
12
|
|
13
|
+
from allianceauth.services.hooks import get_extension_logger
|
14
|
+
from app_utils.logging import LoggerAddTag
|
13
15
|
from app_utils.urls import reverse_absolute, static_file_absolute_url
|
14
16
|
|
15
17
|
from structures import __title__
|
@@ -19,6 +21,8 @@ from structures.models.notifications import Notification, NotificationBase, Webh
|
|
19
21
|
|
20
22
|
from .helpers import target_datetime_formatted
|
21
23
|
|
24
|
+
logger = LoggerAddTag(get_extension_logger(__name__), __title__)
|
25
|
+
|
22
26
|
|
23
27
|
class NotificationBaseEmbed:
|
24
28
|
"""Base class for all notification embeds.
|
@@ -141,6 +145,20 @@ class NotificationBaseEmbed:
|
|
141
145
|
footer_text += f" #{my_text}"
|
142
146
|
footer_icon_url = footer_icon_url if is_absolute_url(footer_icon_url) else None
|
143
147
|
footer = dhooks_lite.Footer(text=footer_text, icon_url=footer_icon_url)
|
148
|
+
max_description = dhooks_lite.Embed.MAX_DESCRIPTION
|
149
|
+
if self._description and len(self._description) > max_description:
|
150
|
+
logger.warning(
|
151
|
+
"%s: Description of notification is too long: %s",
|
152
|
+
self,
|
153
|
+
self._description,
|
154
|
+
)
|
155
|
+
self._description = self._description[:max_description]
|
156
|
+
max_title = dhooks_lite.Embed.MAX_TITLE
|
157
|
+
if self._title and len(self._title) > max_title:
|
158
|
+
logger.warning(
|
159
|
+
"%s: Title of notification is too long: %s", self, self._title
|
160
|
+
)
|
161
|
+
self._title = self._title[:max_title]
|
144
162
|
return dhooks_lite.Embed(
|
145
163
|
author=author,
|
146
164
|
color=self._color,
|
@@ -181,14 +181,27 @@ GeneratedNotificationManager = GeneratedNotificationManagerBase.from_queryset(
|
|
181
181
|
|
182
182
|
class OwnerQuerySet(models.QuerySet):
|
183
183
|
def annotate_characters_count(self) -> models.QuerySet:
|
184
|
-
"""Add character count
|
185
|
-
|
186
|
-
|
184
|
+
"""Add character count annotations."""
|
185
|
+
qs = self.annotate(
|
186
|
+
characters_enabled_count=Count(
|
187
|
+
"characters",
|
188
|
+
filter=Q(
|
189
|
+
characters__character_ownership__isnull=False,
|
190
|
+
characters__is_enabled=True,
|
191
|
+
),
|
192
|
+
distinct=True,
|
193
|
+
)
|
194
|
+
).annotate(
|
195
|
+
characters_disabled_count=Count(
|
187
196
|
"characters",
|
188
|
-
filter=Q(
|
197
|
+
filter=Q(
|
198
|
+
characters__character_ownership__isnull=False,
|
199
|
+
characters__is_enabled=False,
|
200
|
+
),
|
189
201
|
distinct=True,
|
190
202
|
)
|
191
203
|
)
|
204
|
+
return qs
|
192
205
|
|
193
206
|
def structures_last_updated(self) -> Optional[dt.datetime]:
|
194
207
|
"""Date/time when structures were last updated for any of the active owners."""
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Generated by Django 4.0.10 on 2024-06-23 14:26
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
|
8
|
+
dependencies = [
|
9
|
+
("structures", "0005_add_notification_types"),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AddField(
|
14
|
+
model_name="ownercharacter",
|
15
|
+
name="disabled_reason",
|
16
|
+
field=models.TextField(default=""),
|
17
|
+
),
|
18
|
+
migrations.AddField(
|
19
|
+
model_name="ownercharacter",
|
20
|
+
name="is_enabled",
|
21
|
+
field=models.BooleanField(
|
22
|
+
default=True,
|
23
|
+
help_text="Disabled characters are not used for syncing owners",
|
24
|
+
verbose_name="is enabled",
|
25
|
+
),
|
26
|
+
),
|
27
|
+
]
|
@@ -410,11 +410,15 @@ class NotificationBase(models.Model):
|
|
410
410
|
try:
|
411
411
|
embed, ping_type = self._generate_embed(webhook.language_code)
|
412
412
|
except OSError as ex:
|
413
|
-
logger.
|
413
|
+
logger.error("%s: Failed to generate embed: %s", self, ex, exc_info=True)
|
414
414
|
return False
|
415
415
|
|
416
416
|
content = self._create_content_with_pings(webhook, ping_type)
|
417
417
|
content += self._add_discord_group_pings(webhook)
|
418
|
+
max_content = dhooks_lite.Webhook.MAX_CHARACTERS
|
419
|
+
if content and len(content) > max_content:
|
420
|
+
logger.error("%s: Content of notification is too long: %s", self, content)
|
421
|
+
return False
|
418
422
|
|
419
423
|
username, avatar_url = self._gen_avatar()
|
420
424
|
new_queue_size = webhook.send_message(
|
@@ -338,12 +338,15 @@ class Owner(models.Model):
|
|
338
338
|
f"Character {character_ownership.character} does not belong "
|
339
339
|
"to owner corporation."
|
340
340
|
)
|
341
|
-
obj
|
341
|
+
obj: OwnerCharacter = self.characters.get_or_create(
|
342
|
+
character_ownership=character_ownership
|
343
|
+
)[0]
|
344
|
+
obj.reset()
|
342
345
|
return obj
|
343
346
|
|
344
|
-
def
|
347
|
+
def valid_characters_count(self) -> int:
|
345
348
|
"""Count of valid owner characters."""
|
346
|
-
return self.characters.count()
|
349
|
+
return self.characters.filter(is_enabled=True).count()
|
347
350
|
|
348
351
|
def has_sov(self, eve_solar_system: EveSolarSystem) -> bool:
|
349
352
|
"""Determine whether this owner has sov in the given solar system."""
|
@@ -351,42 +354,31 @@ class Owner(models.Model):
|
|
351
354
|
eve_solar_system=eve_solar_system, corporation=self.corporation
|
352
355
|
)
|
353
356
|
|
354
|
-
def
|
357
|
+
def disable_character(
|
355
358
|
self,
|
356
359
|
character: "OwnerCharacter",
|
357
|
-
|
358
|
-
level: str = "warning",
|
360
|
+
reason: str,
|
359
361
|
max_allowed_errors: int = 0,
|
360
362
|
) -> None:
|
361
|
-
"""
|
363
|
+
"""Disable character and notify it's owner and admins about it.
|
362
364
|
|
363
365
|
Args:
|
364
|
-
- character: Character
|
365
|
-
-
|
366
|
-
-
|
367
|
-
- max_error: how many errors are permitted before character is deleted
|
366
|
+
- character: Character to disable
|
367
|
+
- reason: User friendly reason for the deletion
|
368
|
+
- max_allowed_errors: Maximum number of allowed errors for this type of error
|
368
369
|
"""
|
369
370
|
if character.error_count < max_allowed_errors:
|
370
|
-
|
371
|
-
(
|
372
|
-
"%s: Character encountered an error and will be deleted "
|
373
|
-
"if this occurs more often (%d/%d): %s"
|
374
|
-
),
|
375
|
-
character,
|
376
|
-
character.error_count + 1,
|
377
|
-
max_allowed_errors,
|
378
|
-
error,
|
379
|
-
)
|
380
|
-
with transaction.atomic():
|
381
|
-
character.error_count = F("error_count") + 1
|
382
|
-
character.save(update_fields=["error_count"])
|
371
|
+
character.increase_error_count()
|
383
372
|
return
|
384
373
|
|
385
|
-
|
374
|
+
character.disable(reason)
|
375
|
+
|
376
|
+
title = f"{__title__}: {self}: Character has been disabled"
|
377
|
+
level = "warning"
|
386
378
|
message = (
|
387
|
-
f"{character.character_ownership}: {
|
388
|
-
"
|
389
|
-
"
|
379
|
+
f"{character.character_ownership}: {reason}\n"
|
380
|
+
"This character caused too many errors and has been disabled. "
|
381
|
+
"Administrator action is required to resolve this issue."
|
390
382
|
)
|
391
383
|
notify(
|
392
384
|
user=character.character_ownership.user,
|
@@ -394,15 +386,44 @@ class Owner(models.Model):
|
|
394
386
|
message=message,
|
395
387
|
level=level,
|
396
388
|
)
|
397
|
-
if self.
|
389
|
+
if not self.valid_characters_count():
|
398
390
|
message += (
|
399
391
|
" This owner has no configured characters anymore "
|
400
392
|
"and it's services are now down."
|
401
393
|
)
|
402
394
|
level = "danger"
|
395
|
+
|
403
396
|
notify_admins(title=f"FYI: {title}", message=message, level=level)
|
397
|
+
|
398
|
+
def delete_character(self, character: "OwnerCharacter", reason: str) -> None:
|
399
|
+
"""Delete character and notify it's owner and admin about the reason
|
400
|
+
|
401
|
+
Args:
|
402
|
+
- character: Character this error refers to
|
403
|
+
- reason: User friendly reason for the deletion
|
404
|
+
"""
|
404
405
|
character.delete()
|
405
406
|
|
407
|
+
title = f"{__title__}: {self}: Invalid character has been removed"
|
408
|
+
level = "warning"
|
409
|
+
message = (
|
410
|
+
f"{character.character_ownership}: {reason}\n"
|
411
|
+
"Your character is no longer valid for syncing this owner and has been removed. "
|
412
|
+
)
|
413
|
+
notify(
|
414
|
+
user=character.character_ownership.user,
|
415
|
+
title=title,
|
416
|
+
message=message,
|
417
|
+
level=level,
|
418
|
+
)
|
419
|
+
if not self.valid_characters_count():
|
420
|
+
message += (
|
421
|
+
" This owner has no valid characters anymore "
|
422
|
+
"and it's services are now down."
|
423
|
+
)
|
424
|
+
level = "danger"
|
425
|
+
notify_admins(title=f"FYI: {title}", message=message, level=level)
|
426
|
+
|
406
427
|
def _rotate_character(
|
407
428
|
self,
|
408
429
|
character: "OwnerCharacter",
|
@@ -421,7 +442,7 @@ class Owner(models.Model):
|
|
421
442
|
)
|
422
443
|
try:
|
423
444
|
minimum_time_between_rotations = max(
|
424
|
-
rotate_characters.esi_cache_duration / self.
|
445
|
+
rotate_characters.esi_cache_duration / self.valid_characters_count(),
|
425
446
|
60,
|
426
447
|
)
|
427
448
|
except ZeroDivisionError:
|
@@ -453,14 +474,18 @@ class Owner(models.Model):
|
|
453
474
|
if rotate_characters
|
454
475
|
else "notifications_last_used_at"
|
455
476
|
)
|
456
|
-
|
477
|
+
enabled_characters: models.QuerySet[OwnerCharacter] = self.characters.filter(
|
478
|
+
is_enabled=True
|
479
|
+
).order_by(order_by_last_used)
|
480
|
+
for character in enabled_characters:
|
457
481
|
if (
|
458
482
|
character.character_ownership.character.corporation_id
|
459
483
|
!= self.corporation.corporation_id
|
460
484
|
):
|
485
|
+
corporation_name = self.corporation.corporation_name
|
461
486
|
self.delete_character(
|
462
487
|
character=character,
|
463
|
-
|
488
|
+
reason=f"Character is no longer a member of {corporation_name}",
|
464
489
|
)
|
465
490
|
continue
|
466
491
|
|
@@ -469,17 +494,17 @@ class Owner(models.Model):
|
|
469
494
|
):
|
470
495
|
self.delete_character(
|
471
496
|
character=character,
|
472
|
-
|
497
|
+
reason="Character no longer has permission to sync",
|
473
498
|
)
|
474
499
|
continue
|
475
500
|
|
476
501
|
token = character.valid_token()
|
477
502
|
if not token:
|
478
|
-
self.
|
479
|
-
character=character,
|
480
|
-
error="Character has no valid token for sync.",
|
503
|
+
self.disable_character(
|
504
|
+
character=character, reason="No valid token found for character"
|
481
505
|
)
|
482
506
|
continue
|
507
|
+
|
483
508
|
found_character = character
|
484
509
|
break # leave the for loop if we have found a valid token
|
485
510
|
|
@@ -797,6 +822,13 @@ class Owner(models.Model):
|
|
797
822
|
|
798
823
|
Return True when successful, else False.
|
799
824
|
"""
|
825
|
+
try:
|
826
|
+
character: OwnerCharacter = self.characters.get(
|
827
|
+
character_ownership__character__character_id=token.character_id
|
828
|
+
)
|
829
|
+
except ObjectDoesNotExist:
|
830
|
+
return False
|
831
|
+
|
800
832
|
structures = []
|
801
833
|
try:
|
802
834
|
starbases_data = (
|
@@ -824,21 +856,11 @@ class Owner(models.Model):
|
|
824
856
|
self._store_raw_data("starbases", structures)
|
825
857
|
|
826
858
|
except HTTPForbidden:
|
827
|
-
|
828
|
-
character
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
pass
|
833
|
-
else:
|
834
|
-
self.delete_character(
|
835
|
-
character=character,
|
836
|
-
error=(
|
837
|
-
"Character is not a director or CEO and therefore "
|
838
|
-
"can not fetch starbases."
|
839
|
-
),
|
840
|
-
max_allowed_errors=STRUCTURES_ESI_DIRECTOR_ERROR_MAX_RETRIES,
|
841
|
-
)
|
859
|
+
self.disable_character(
|
860
|
+
character=character,
|
861
|
+
reason=("This character is not a director or CEO"),
|
862
|
+
max_allowed_errors=STRUCTURES_ESI_DIRECTOR_ERROR_MAX_RETRIES,
|
863
|
+
)
|
842
864
|
return False
|
843
865
|
|
844
866
|
except OSError as ex:
|
@@ -849,6 +871,7 @@ class Owner(models.Model):
|
|
849
871
|
structures_qs=self.structures.filter_starbases(),
|
850
872
|
new_structures=structures,
|
851
873
|
)
|
874
|
+
character.reset_error_counter()
|
852
875
|
return True
|
853
876
|
|
854
877
|
def _store_updates_for_starbases(self, token, structures):
|
@@ -1337,6 +1360,12 @@ class OwnerCharacter(models.Model):
|
|
1337
1360
|
verbose_name=_("error count"),
|
1338
1361
|
help_text="Count of ESI errors which happened with this character.",
|
1339
1362
|
)
|
1363
|
+
is_enabled = models.BooleanField(
|
1364
|
+
default=True,
|
1365
|
+
verbose_name=_("is enabled"),
|
1366
|
+
help_text=_("Disabled characters are not used for syncing owners"),
|
1367
|
+
)
|
1368
|
+
disabled_reason = models.TextField(default="")
|
1340
1369
|
created_at = models.DateTimeField(auto_now_add=True)
|
1341
1370
|
|
1342
1371
|
class Meta:
|
@@ -1369,3 +1398,27 @@ class OwnerCharacter(models.Model):
|
|
1369
1398
|
.require_valid()
|
1370
1399
|
.first()
|
1371
1400
|
)
|
1401
|
+
|
1402
|
+
def reset(self) -> None:
|
1403
|
+
"""Resets a disabled owner character."""
|
1404
|
+
self.is_enabled = True
|
1405
|
+
self.disabled_reason = ""
|
1406
|
+
self.error_count = 0
|
1407
|
+
self.save()
|
1408
|
+
|
1409
|
+
def reset_error_counter(self) -> None:
|
1410
|
+
"""Reset the error counter"""
|
1411
|
+
self.error_count = 0
|
1412
|
+
self.save(update_fields=["error_count"])
|
1413
|
+
|
1414
|
+
def disable(self, reason: str = "") -> None:
|
1415
|
+
"""Disables a character."""
|
1416
|
+
self.is_enabled = False
|
1417
|
+
self.disabled_reason = reason
|
1418
|
+
self.save()
|
1419
|
+
|
1420
|
+
def increase_error_count(self):
|
1421
|
+
"""Increase error count of this character by one."""
|
1422
|
+
with transaction.atomic():
|
1423
|
+
self.error_count = F("error_count") + 1
|
1424
|
+
self.save(update_fields=["error_count"])
|
{aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/core/notification_embeds/test_main.py
RENAMED
@@ -240,6 +240,26 @@ class TestNotificationEmbedsGenerate(TestCase):
|
|
240
240
|
self.assertEqual(discord_embed.footer.text, "Structures")
|
241
241
|
self.assertIn("structures_logo.png", discord_embed.footer.icon_url)
|
242
242
|
|
243
|
+
def test_should_not_break_with_too_large_description(self):
|
244
|
+
# given
|
245
|
+
notification = Notification.objects.get(notification_id=1000000403)
|
246
|
+
notification_embed = NotificationBaseEmbed.create(notification)
|
247
|
+
notification_embed._description = "x" * 2049
|
248
|
+
# when
|
249
|
+
discord_embed = notification_embed.generate_embed()
|
250
|
+
# then
|
251
|
+
self.assertIsInstance(discord_embed, dhooks_lite.Embed)
|
252
|
+
|
253
|
+
def test_should_not_break_with_too_large_title(self):
|
254
|
+
# given
|
255
|
+
notification = Notification.objects.get(notification_id=1000000403)
|
256
|
+
notification_embed = NotificationBaseEmbed.create(notification)
|
257
|
+
notification_embed._title = "x" * 257
|
258
|
+
# when
|
259
|
+
discord_embed = notification_embed.generate_embed()
|
260
|
+
# then
|
261
|
+
self.assertIsInstance(discord_embed, dhooks_lite.Embed)
|
262
|
+
|
243
263
|
|
244
264
|
class TestNotificationEmbedsClasses(NoSocketsTestCase):
|
245
265
|
@classmethod
|
{aa_structures-2.10.0 → aa_structures-2.12.0}/structures/tests/models/test_notifications_discord.py
RENAMED
@@ -33,6 +33,7 @@ if "discord" in app_labels():
|
|
33
33
|
super().setUpClass()
|
34
34
|
load_eveuniverse()
|
35
35
|
load_eve_entities()
|
36
|
+
|
36
37
|
cls.group_1 = Group.objects.create(name="Dummy Group 1")
|
37
38
|
cls.group_2 = Group.objects.create(name="Dummy Group 2")
|
38
39
|
cls.owner = OwnerFactory()
|
@@ -140,3 +141,23 @@ if "discord" in app_labels():
|
|
140
141
|
self.assertTrue(mock_import_discord.called)
|
141
142
|
_, kwargs = mock_send_message.call_args
|
142
143
|
self.assertFalse(re.search(r"(<@&\d+>)", kwargs["content"]))
|
144
|
+
|
145
|
+
def test_should_abort_when_content_is_too_large(
|
146
|
+
self, mock_send_message, mock_import_discord
|
147
|
+
):
|
148
|
+
# given
|
149
|
+
mock_send_message.return_value = 1
|
150
|
+
mock_import_discord.return_value.objects.group_to_role.side_effect = (
|
151
|
+
self._my_group_to_role
|
152
|
+
)
|
153
|
+
webhook = WebhookFactory()
|
154
|
+
for i in range(286):
|
155
|
+
group = Group.objects.create(name=f"Group {i+1}")
|
156
|
+
webhook.ping_groups.add(group)
|
157
|
+
obj = clone_notification(
|
158
|
+
Notification.objects.get(notification_id=1000000509)
|
159
|
+
)
|
160
|
+
# when
|
161
|
+
result = obj.send_to_webhook(webhook)
|
162
|
+
# then
|
163
|
+
self.assertFalse(result)
|