aa-bb 3.2.4__tar.gz → 3.2.4b2__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_bb-3.2.4 → aa_bb-3.2.4b2}/PKG-INFO +1 -1
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/__init__.py +1 -1
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/admin.py +0 -3
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/app_settings.py +15 -462
- aa_bb-3.2.4b2/aa_bb/apps.py +271 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/add_to_blacklist.py +2 -6
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/awox.py +6 -10
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/clone_state.py +1 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/hostile_assets.py +13 -18
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/hostile_clones.py +16 -24
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/sus_contacts.py +6 -9
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/sus_contracts.py +21 -80
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/sus_mails.py +39 -67
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/sus_trans.py +38 -94
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks_cb/hostile_assets.py +9 -19
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks_cb/sus_contracts.py +2 -47
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks_cb/sus_trans.py +24 -61
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/models.py +205 -226
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/signals.py +4 -20
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tasks.py +220 -73
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tasks_bot.py +2 -29
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tasks_cb.py +324 -117
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tasks_ct.py +5 -18
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tasks_other.py +27 -56
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tasks_tickets.py +32 -84
- aa_bb-3.2.4b2/aa_bb/tasks_utils.py +115 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/loa/admin.html +17 -18
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/views.py +27 -106
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/views_cb.py +2 -11
- aa_bb-3.2.4/aa_bb/apps.py +0 -68
- aa_bb-3.2.4/aa_bb/migrations/0094_bigbrotherconfig_corp_compliance_webhook_and_more.py +0 -28
- aa_bb-3.2.4/aa_bb/migrations/0095_alter_bigbrotherconfig_limit_to_main_corp.py +0 -18
- aa_bb-3.2.4/aa_bb/migrations/0096_bigbrotherconfig_clone_state_notify_and_more.py +0 -23
- aa_bb-3.2.4/aa_bb/tasks_utils.py +0 -328
- aa_bb-3.2.4/aa_bb/tests/test_sus_trans.py +0 -226
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/.gitignore +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/LICENSE +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/README.md +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/auth_hooks.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/celery.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/__init__.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/alliance_blacklist.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/alpha_skills.json +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/coalition_blacklist.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/corp_changes.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/cyno.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/roles_and_tokens.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/skills.json +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks/skills.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/checks_cb/__init__.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/esi_cache.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/esi_client.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/forms.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/locale/.gitkeep +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/management/__init__.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/management/commands/__init__.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0001_initial.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0002_bigbrotherconfig_userstatus.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0003_alter_bigbrotherconfig_pingroleid.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0004_alter_bigbrotherconfig_is_active_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0005_alter_bigbrotherconfig_hostile_alliances.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0006_alter_bigbrotherconfig_pingroleid.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0007_alter_general_options.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0008_alliance_names_corporation_names.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0009_userstatus_sus_contacts_userstatus_sus_contracts_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0010_alter_userstatus_awox_kill_links_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0011_character_names.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0012_id_types.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0013_bigbrotherconfig_mail_keywords.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0014_processedcontract_processedmail_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0015_processedtransaction_sustransactionnote.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0016_warmprogress.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0017_entityinfocache.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0018_userstatus_cyno_userstatus_has_skills_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0019_bigbrotherconfig_whitelist_alliances_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0020_messages_bigbrotherconfig_are_daily_messages_active_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0021_alter_messages_id_alter_messages_text.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0022_messages_sent_in_cycle.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0023_optmessages1_optmessages2_optmessages3_optmessages4_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0024_bigbrotherconfig_dailyschedule_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0025_alter_messages_options_alter_optmessages1_options_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0026_alter_general_options_alter_bigbrotherconfig_id_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0027_alter_general_options_bigbrotherconfig_is_loa_active_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0028_alter_bigbrotherconfig_is_loa_active.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0029_leaverequest_main_character.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0030_alter_general_options.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0031_bigbrotherconfig_loa_max_logoff_days_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0032_alter_leaverequest_status.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0033_messagetype_bigbrotherconfig_pingroleid2_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0034_rename_last_updated_userstatus_updated.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0035_alter_userstatus_options.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0036_alter_general_options.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0037_corpstatus.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0038_bigbrotherconfig_ignored_corporations.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0039_alter_bigbrotherconfig_ignored_corporations.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0040_sovereigntymapcache_corporationinfocache_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0041_bigbrotherconfig_is_warmer_active.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0042_alter_general_options_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0043_bigbrotherconfig_bb_member_states_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0044_bigbrotherconfig_character_scopes_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0045_userstatus_sp_age_ratio_result.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0046_bigbrotherconfig_member_corporations.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0047_bigbrotherconfig_member_alliances.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0048_characteraccountstate.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0049_userstatus_clone_status.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0050_alter_general_options_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0051_monthlypapstats.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0052_papsconfig_delete_monthlypapstats.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0053_alter_papsconfig_corp_modifier_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0054_alter_general_options.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0055_papsconfig_group_paps_papsconfig_group_paps_modifier.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0056_alter_papsconfig_group_paps.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0057_papsconfig_excluded_groups_papsconfig_excluded_users_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0058_papsconfig_excluded_groups_get_paps_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0059_alter_papsconfig_excluded_groups_get_paps.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0060_papsconfig_cap_group_papsconfig_cap_group_paps_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0061_remove_papsconfig_cap_group_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0062_complianceticket.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0063_alter_complianceticket_user.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0064_alter_complianceticket_reason.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0065_alter_complianceticket_reason_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0066_tickettoolconfig_papcompliance.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0067_remove_tickettoolconfig_category_id_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0068_tickettoolconfig_category_id_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0069_tickettoolconfig_ticket_counter.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0070_remove_tickettoolconfig_role_id_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0071_tickettoolconfig_role_id.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0072_alter_complianceticket_reason.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0073_tickettoolconfig_starting_pap_compliance.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0074_alter_bigbrotherconfig_hostile_alliances.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0075_bbupdatestate_tickettoolconfig_afk_check_frequency_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0076_id_types_last_accessed_frequentcorpchangescache_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0077_complianceticket_ticket_id_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0078_tickettoolconfig_awox_monitor_enabled.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0079_helptext_guidance.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0080_bigbrotherconfig_dlc_flags.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0081_remove_papsconfig_imp_modifier_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0082_remove_bigbrotherconfig_token_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0083_alter_bigbrotherredditmessage_options_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0084_bigbrotherconfig_consider_all_structures_hostile_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0085_bigbrotherconfig_awox_notify_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0086_bigbrotherconfig_are_recurring_stats_active_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0087_bigbrotherconfig_dlc_are_recurring_stats_active.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0088_bigbrotherconfig_cyno_notify.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0089_bigbrotherconfig_asset_notify_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0090_alter_papsconfig_options_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0091_remove_bigbrotherconfig_dlc_are_recurring_stats_active_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0092_userstatus_baseline_initialized.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/0093_eveitemprice_delete_bigbrotherredditmessage_and_more.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/migrations/__init__.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/static/aa_bb/.gitkeep +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/static/aa_bb/js/admin_market_toggle.js +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/aa_bb/base.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/aa_bb/disabled.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/aa_bb/index.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/aa_cb/base.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/aa_cb/disabled.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/aa_cb/index.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/base.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/cards.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/faq.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/menu.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/modules.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/settings_bigbrother.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/settings_nav.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/settings_paps.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/settings_stats.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/faq/settings_tickets.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/loa/_loa_subtabs.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/loa/base.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/loa/disabled.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/loa/index.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/loa/menu.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/loa/request.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/paps/base.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/paps/disabled.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/paps/history.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/paps/index.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/templates/paps/menu.html +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tests/__init__.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tests/test_clone_state_logic.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tests/test_performance.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tests/test_price_timer.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tests/test_task_setup.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tests/test_tasks_notifications.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/tests/test_views.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/urls.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/urls_cb.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/urls_loa.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/urls_paps.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/views_faq.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/aa_bb/views_paps.py +0 -0
- {aa_bb-3.2.4 → aa_bb-3.2.4b2}/pyproject.toml +0 -0
|
@@ -63,7 +63,6 @@ class BB_ConfigAdmin(SingletonModelAdmin):
|
|
|
63
63
|
"cyno_notify",
|
|
64
64
|
"sp_inject_notify",
|
|
65
65
|
"clone_notify",
|
|
66
|
-
"clone_state_notify",
|
|
67
66
|
"asset_notify",
|
|
68
67
|
"contact_notify",
|
|
69
68
|
"contract_notify",
|
|
@@ -140,8 +139,6 @@ class BB_ConfigAdmin(SingletonModelAdmin):
|
|
|
140
139
|
"optwebhook3",
|
|
141
140
|
"optwebhook4",
|
|
142
141
|
"optwebhook5",
|
|
143
|
-
"user_compliance_webhook",
|
|
144
|
-
"corp_compliance_webhook",
|
|
145
142
|
"stats_webhook",
|
|
146
143
|
)
|
|
147
144
|
},
|
|
@@ -19,7 +19,6 @@ from django.apps import apps
|
|
|
19
19
|
from django.utils import timezone
|
|
20
20
|
from typing import Optional, Dict, Tuple, Any, List
|
|
21
21
|
from django.db import transaction, IntegrityError, OperationalError
|
|
22
|
-
from django.db.models import Q
|
|
23
22
|
|
|
24
23
|
from .models import (
|
|
25
24
|
Alliance_names, Corporation_names, Character_names, BigBrotherConfig, id_types,
|
|
@@ -933,120 +932,33 @@ def resolve_character_name(char_id: int) -> str:
|
|
|
933
932
|
return f"Unresolvable eve map{e_short}{e_detail}"
|
|
934
933
|
|
|
935
934
|
|
|
936
|
-
def get_system_owner(system:
|
|
935
|
+
def get_system_owner(system: str) -> Dict[str, str]:
|
|
937
936
|
"""
|
|
938
937
|
Get sovereignty owner of an EVE system by name.
|
|
939
|
-
Always returns a dict with keys: owner_id, owner_name, owner_type
|
|
938
|
+
Always returns a dict with keys: owner_id, owner_name, owner_type.
|
|
940
939
|
"""
|
|
941
940
|
owner_id = "0"
|
|
942
|
-
owner_name = "Unresolvable Init"
|
|
941
|
+
owner_name = f"Unresolvable Init"
|
|
943
942
|
owner_type = "unknown"
|
|
944
|
-
region_id = "0"
|
|
945
|
-
region_name = "Unknown Region"
|
|
946
943
|
|
|
947
944
|
# 1) Pull name and ID from the passed-in dict
|
|
948
|
-
|
|
949
|
-
try:
|
|
950
|
-
system_id = int(system_id_raw) if system_id_raw is not None else None
|
|
951
|
-
except (ValueError, TypeError):
|
|
952
|
-
system_id = None
|
|
953
|
-
|
|
945
|
+
system_id = system.get("id")
|
|
954
946
|
system_nam = system.get("name")
|
|
955
947
|
system_name = str()
|
|
956
948
|
if system_nam: # Convert the provided name into a proper string when available.
|
|
957
949
|
system_name = str(system_nam)
|
|
958
950
|
|
|
959
951
|
try:
|
|
960
|
-
# Resolve parent system if this is a location
|
|
961
|
-
parent_system_id = resolve_location_system_id(system_id)
|
|
962
|
-
if parent_system_id:
|
|
963
|
-
try:
|
|
964
|
-
from eveuniverse.models import EveSolarSystem
|
|
965
|
-
sys_obj = EveSolarSystem.objects.select_related("eve_constellation__eve_region").get(id=parent_system_id)
|
|
966
|
-
region_id = str(sys_obj.eve_constellation.eve_region.id)
|
|
967
|
-
region_name = sys_obj.eve_constellation.eve_region.name
|
|
968
|
-
except Exception:
|
|
969
|
-
pass
|
|
970
|
-
|
|
971
952
|
sov_map = _get_sov_map()
|
|
972
|
-
|
|
973
|
-
target_sov_id = parent_system_id or system_id
|
|
974
|
-
entry = next((s for s in sov_map if s.get("system_id") == target_sov_id), None)
|
|
953
|
+
entry = next((s for s in sov_map if s.get("system_id") == system_id), None)
|
|
975
954
|
if not entry:
|
|
976
|
-
|
|
977
|
-
# or for NPC stations.
|
|
978
|
-
if target_sov_id:
|
|
979
|
-
if 30000000 <= target_sov_id <= 34000000:
|
|
980
|
-
try:
|
|
981
|
-
from eveuniverse.models import EveSolarSystem
|
|
982
|
-
sys_obj = EveSolarSystem.objects.get(id=target_sov_id)
|
|
983
|
-
return {
|
|
984
|
-
"owner_id": "0",
|
|
985
|
-
"owner_name": "Unclaimed",
|
|
986
|
-
"owner_type": "unknown",
|
|
987
|
-
"region_id": region_id,
|
|
988
|
-
"region_name": region_name
|
|
989
|
-
}
|
|
990
|
-
except Exception:
|
|
991
|
-
pass
|
|
992
|
-
elif 60000000 <= target_sov_id <= 64000000:
|
|
993
|
-
try:
|
|
994
|
-
from eveuniverse.models import EveStation
|
|
995
|
-
station_obj = EveStation.objects.get(id=target_sov_id)
|
|
996
|
-
if station_obj.owner_id:
|
|
997
|
-
return {
|
|
998
|
-
"owner_id": str(station_obj.owner_id),
|
|
999
|
-
"owner_name": resolve_corporation_name(station_obj.owner_id),
|
|
1000
|
-
"owner_type": "corporation",
|
|
1001
|
-
"region_id": region_id,
|
|
1002
|
-
"region_name": region_name
|
|
1003
|
-
}
|
|
1004
|
-
except Exception:
|
|
1005
|
-
pass
|
|
1006
|
-
|
|
1007
|
-
# If it's specifically a player structure ID that we can't resolve owner for
|
|
1008
|
-
if system_id and is_player_structure(system_id):
|
|
1009
|
-
try:
|
|
1010
|
-
from corptools.models import Structure
|
|
1011
|
-
struct = Structure.objects.filter(structure_id=system_id).select_related("corporation__corporation").first()
|
|
1012
|
-
if struct and struct.corporation and struct.corporation.corporation:
|
|
1013
|
-
return {
|
|
1014
|
-
"owner_id": str(struct.corporation.corporation.corporation_id),
|
|
1015
|
-
"owner_name": struct.corporation.corporation.corporation_name,
|
|
1016
|
-
"owner_type": "corporation",
|
|
1017
|
-
"region_id": region_id,
|
|
1018
|
-
"region_name": region_name
|
|
1019
|
-
}
|
|
1020
|
-
except Exception:
|
|
1021
|
-
pass
|
|
1022
|
-
|
|
1023
|
-
return {
|
|
1024
|
-
"owner_id": owner_id,
|
|
1025
|
-
"owner_name": "Unresolvable structure due to lack of docking rights",
|
|
1026
|
-
"owner_type": owner_type,
|
|
1027
|
-
"region_id": region_id,
|
|
1028
|
-
"region_name": region_name
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
return {
|
|
1032
|
-
"owner_id": owner_id,
|
|
1033
|
-
"owner_name": "Unresolvable location",
|
|
1034
|
-
"owner_type": owner_type,
|
|
1035
|
-
"region_id": region_id,
|
|
1036
|
-
"region_name": region_name
|
|
1037
|
-
}
|
|
955
|
+
return {"owner_id": owner_id, "owner_name": f"Unresolvable structure due to lack of docking rights", "owner_type": owner_type}
|
|
1038
956
|
|
|
1039
957
|
except Exception as e:
|
|
1040
958
|
logger.exception(f"Failed to fetch sovereignty for system ID {system_id}: {e}")
|
|
1041
959
|
e_short = e.__class__.__name__
|
|
1042
960
|
e_detail = getattr(e, 'code', None) or getattr(e, 'status', None) or str(e)
|
|
1043
|
-
return {
|
|
1044
|
-
"owner_id": owner_id,
|
|
1045
|
-
"owner_name": f"Unresolvable sov, {e_short}{e_detail}",
|
|
1046
|
-
"owner_type": owner_type,
|
|
1047
|
-
"region_id": region_id,
|
|
1048
|
-
"region_name": region_name
|
|
1049
|
-
}
|
|
961
|
+
return {"owner_id": owner_id, "owner_name": f"Unresolvable sov, {e_short}{e_detail}", "owner_type": owner_type}
|
|
1050
962
|
|
|
1051
963
|
# 3) Determine owner ID and type
|
|
1052
964
|
alliance_id = entry.get("alliance_id")
|
|
@@ -1058,13 +970,7 @@ def get_system_owner(system: Dict) -> Dict[str, str]:
|
|
|
1058
970
|
owner_id = str(faction_id)
|
|
1059
971
|
owner_type = "faction"
|
|
1060
972
|
else:
|
|
1061
|
-
return {
|
|
1062
|
-
"owner_id": "0",
|
|
1063
|
-
"owner_name": "Unclaimed",
|
|
1064
|
-
"owner_type": "unknown",
|
|
1065
|
-
"region_id": region_id,
|
|
1066
|
-
"region_name": region_name
|
|
1067
|
-
}
|
|
973
|
+
return {"owner_id": "0", "owner_name": "Unclaimed", "owner_type": "unknown"}
|
|
1068
974
|
|
|
1069
975
|
# 4) Resolve owner name
|
|
1070
976
|
try:
|
|
@@ -1073,88 +979,7 @@ def get_system_owner(system: Dict) -> Dict[str, str]:
|
|
|
1073
979
|
owner_name = "Unresolvable owner"
|
|
1074
980
|
owner_id = "0"
|
|
1075
981
|
owner_type = "unknown"
|
|
1076
|
-
|
|
1077
|
-
return {
|
|
1078
|
-
"owner_id": owner_id,
|
|
1079
|
-
"owner_name": owner_name,
|
|
1080
|
-
"owner_type": owner_type,
|
|
1081
|
-
"region_id": region_id,
|
|
1082
|
-
"region_name": region_name
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
def is_location_hostile(location_id: int, system_id: int = None) -> bool:
|
|
1087
|
-
"""
|
|
1088
|
-
Determines if a given location (structure, station, or system) is considered hostile.
|
|
1089
|
-
Returns True if hostile, False if safe.
|
|
1090
|
-
"""
|
|
1091
|
-
if not location_id and not system_id:
|
|
1092
|
-
return False
|
|
1093
|
-
|
|
1094
|
-
cfg = BigBrotherConfig.get_solo()
|
|
1095
|
-
safe_entities = get_safe_entities()
|
|
1096
|
-
hostile_alli_ids = {int(s) for s in (cfg.hostile_alliances or "").split(",") if s.strip().isdigit()}
|
|
1097
|
-
hostile_corp_ids = {int(s) for s in (cfg.hostile_corporations or "").split(",") if s.strip().isdigit()}
|
|
1098
|
-
|
|
1099
|
-
# Resolve location owner
|
|
1100
|
-
owner_info = get_system_owner({"id": location_id or system_id})
|
|
1101
|
-
oid = None
|
|
1102
|
-
oname = ""
|
|
1103
|
-
if owner_info:
|
|
1104
|
-
try:
|
|
1105
|
-
oid = int(owner_info.get("owner_id", 0))
|
|
1106
|
-
except (ValueError, TypeError):
|
|
1107
|
-
oid = None
|
|
1108
|
-
oname = owner_info.get("owner_name", "")
|
|
1109
|
-
|
|
1110
|
-
# If it's a structure
|
|
1111
|
-
if location_id and is_player_structure(location_id):
|
|
1112
|
-
# Friendly structure overrides system hostility
|
|
1113
|
-
if oid and oid in safe_entities:
|
|
1114
|
-
return False
|
|
1115
|
-
# Hostile structure
|
|
1116
|
-
if oid and (oid in hostile_alli_ids or oid in hostile_corp_ids):
|
|
1117
|
-
return True
|
|
1118
|
-
if "Unresolvable" in oname:
|
|
1119
|
-
return True
|
|
1120
|
-
|
|
1121
|
-
# Check system-level hostility
|
|
1122
|
-
target_system = system_id or (resolve_location_system_id(location_id) if location_id else None)
|
|
1123
|
-
if target_system:
|
|
1124
|
-
# If the location we checked was a structure, oid is structure owner.
|
|
1125
|
-
# We might also need to check system (sov) owner for nullsec flags.
|
|
1126
|
-
if target_system != location_id:
|
|
1127
|
-
sys_owner_info = get_system_owner({"id": target_system})
|
|
1128
|
-
try:
|
|
1129
|
-
soid = int(sys_owner_info.get("owner_id", 0))
|
|
1130
|
-
except (ValueError, TypeError):
|
|
1131
|
-
soid = None
|
|
1132
|
-
else:
|
|
1133
|
-
soid = oid
|
|
1134
|
-
|
|
1135
|
-
# Base hostility from system owner
|
|
1136
|
-
if soid:
|
|
1137
|
-
if soid in hostile_alli_ids or soid in hostile_corp_ids:
|
|
1138
|
-
return True
|
|
1139
|
-
|
|
1140
|
-
# Consider nullsec hostile
|
|
1141
|
-
if cfg.consider_nullsec_hostile and is_nullsec(target_system):
|
|
1142
|
-
# Safe if system is owned by us/allies
|
|
1143
|
-
if soid is not None and soid in safe_entities:
|
|
1144
|
-
return False
|
|
1145
|
-
# Otherwise, if we are in a friendly structure (handled above), it's safe.
|
|
1146
|
-
# If we are here, it's either an NPC station or a hostile/unknown structure.
|
|
1147
|
-
return True
|
|
1148
|
-
|
|
1149
|
-
# General fallback for hostile lists if not already caught
|
|
1150
|
-
if oid:
|
|
1151
|
-
if oid in hostile_alli_ids or oid in hostile_corp_ids:
|
|
1152
|
-
return True
|
|
1153
|
-
|
|
1154
|
-
if "Unresolvable" in oname:
|
|
1155
|
-
return True
|
|
1156
|
-
|
|
1157
|
-
return False
|
|
982
|
+
return {"owner_id": owner_id, "owner_name": owner_name, "owner_type": owner_type}
|
|
1158
983
|
|
|
1159
984
|
|
|
1160
985
|
|
|
@@ -1166,10 +991,8 @@ def get_users():
|
|
|
1166
991
|
member_states = cfg.bb_member_states.all()
|
|
1167
992
|
qs = UserProfile.objects.filter(state__in=member_states).exclude(main_character=None)
|
|
1168
993
|
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
if member_corps or member_allis:
|
|
1172
|
-
qs = qs.filter(Q(main_character__corporation_id__in=member_corps) | Q(main_character__alliance_id__in=member_allis))
|
|
994
|
+
if cfg.limit_to_main_corp and cfg.main_corporation_id:
|
|
995
|
+
qs = qs.filter(main_character__corporation_id=cfg.main_corporation_id)
|
|
1173
996
|
|
|
1174
997
|
users = list(
|
|
1175
998
|
qs.values_list("main_character__character_name", flat=True)
|
|
@@ -1183,10 +1006,8 @@ def get_user_profiles():
|
|
|
1183
1006
|
member_states = cfg.bb_member_states.all()
|
|
1184
1007
|
qs = UserProfile.objects.filter(state__in=member_states).exclude(main_character=None)
|
|
1185
1008
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
if member_corps or member_allis:
|
|
1189
|
-
qs = qs.filter(Q(main_character__corporation_id__in=member_corps) | Q(main_character__alliance_id__in=member_allis))
|
|
1009
|
+
if cfg.limit_to_main_corp and cfg.main_corporation_id:
|
|
1010
|
+
qs = qs.filter(main_character__corporation_id=cfg.main_corporation_id)
|
|
1190
1011
|
|
|
1191
1012
|
users = (
|
|
1192
1013
|
qs.select_related("main_character", "user") # optimization
|
|
@@ -1204,10 +1025,9 @@ def get_user_id(character_name):
|
|
|
1204
1025
|
|
|
1205
1026
|
def is_nullsec(system_id):
|
|
1206
1027
|
try:
|
|
1207
|
-
system_id = int(system_id)
|
|
1208
1028
|
sys = EveSolarSystem.objects.get(id=system_id)
|
|
1209
1029
|
return sys.security_status <= 0.0
|
|
1210
|
-
except
|
|
1030
|
+
except EveSolarSystem.DoesNotExist:
|
|
1211
1031
|
return False
|
|
1212
1032
|
|
|
1213
1033
|
def is_player_structure(location_id):
|
|
@@ -1216,104 +1036,7 @@ def is_player_structure(location_id):
|
|
|
1216
1036
|
(Citadel, Engineering Complex, Refinery) rather than an NPC station.
|
|
1217
1037
|
Structure IDs are typically large (>= 1,000,000,000,000).
|
|
1218
1038
|
"""
|
|
1219
|
-
|
|
1220
|
-
return int(location_id) >= 1_000_000_000_000
|
|
1221
|
-
except (ValueError, TypeError):
|
|
1222
|
-
return False
|
|
1223
|
-
|
|
1224
|
-
def resolve_location_name(location_id: int) -> Optional[str]:
|
|
1225
|
-
"""
|
|
1226
|
-
Attempts to resolve a location_id to a human-readable name.
|
|
1227
|
-
1) Solar System (30M-34M)
|
|
1228
|
-
2) NPC Station (60M-64M)
|
|
1229
|
-
3) Player Structure (>= 1T)
|
|
1230
|
-
"""
|
|
1231
|
-
if not location_id:
|
|
1232
|
-
return None
|
|
1233
|
-
|
|
1234
|
-
try:
|
|
1235
|
-
location_id = int(location_id)
|
|
1236
|
-
except (ValueError, TypeError):
|
|
1237
|
-
return None
|
|
1238
|
-
|
|
1239
|
-
# 1) Solar System
|
|
1240
|
-
if 30000000 <= location_id <= 34000000:
|
|
1241
|
-
try:
|
|
1242
|
-
from eveuniverse.models import EveSolarSystem
|
|
1243
|
-
return EveSolarSystem.objects.get(id=location_id).name
|
|
1244
|
-
except Exception:
|
|
1245
|
-
pass
|
|
1246
|
-
|
|
1247
|
-
# 2) NPC Station
|
|
1248
|
-
if 60000000 <= location_id <= 64000000:
|
|
1249
|
-
try:
|
|
1250
|
-
from eveuniverse.models import EveStation
|
|
1251
|
-
return EveStation.objects.get(id=location_id).name
|
|
1252
|
-
except Exception:
|
|
1253
|
-
pass
|
|
1254
|
-
|
|
1255
|
-
# 3) Player Structure
|
|
1256
|
-
if is_player_structure(location_id):
|
|
1257
|
-
try:
|
|
1258
|
-
from corptools.models import Structure
|
|
1259
|
-
struct = Structure.objects.filter(structure_id=location_id).first()
|
|
1260
|
-
if struct:
|
|
1261
|
-
return struct.name
|
|
1262
|
-
except Exception:
|
|
1263
|
-
pass
|
|
1264
|
-
|
|
1265
|
-
# Fallback to EveLocation
|
|
1266
|
-
try:
|
|
1267
|
-
from corptools.models import EveLocation
|
|
1268
|
-
loc = EveLocation.objects.filter(location_id=location_id).first()
|
|
1269
|
-
if loc:
|
|
1270
|
-
return loc.location_name
|
|
1271
|
-
except Exception:
|
|
1272
|
-
pass
|
|
1273
|
-
|
|
1274
|
-
return None
|
|
1275
|
-
|
|
1276
|
-
def resolve_location_system_id(location_id: int) -> Optional[int]:
|
|
1277
|
-
"""
|
|
1278
|
-
Attempts to resolve a location_id to its parent solar system ID.
|
|
1279
|
-
"""
|
|
1280
|
-
if not location_id:
|
|
1281
|
-
return None
|
|
1282
|
-
|
|
1283
|
-
try:
|
|
1284
|
-
location_id = int(location_id)
|
|
1285
|
-
except (ValueError, TypeError):
|
|
1286
|
-
return None
|
|
1287
|
-
|
|
1288
|
-
# 1) Solar System
|
|
1289
|
-
if 30000000 <= location_id <= 34000000:
|
|
1290
|
-
return location_id
|
|
1291
|
-
|
|
1292
|
-
# 2) NPC Station
|
|
1293
|
-
if 60000000 <= location_id <= 64000000:
|
|
1294
|
-
try:
|
|
1295
|
-
from eveuniverse.models import EveStation
|
|
1296
|
-
station = EveStation.objects.get(id=location_id)
|
|
1297
|
-
return station.eve_solar_system_id
|
|
1298
|
-
except Exception:
|
|
1299
|
-
pass
|
|
1300
|
-
|
|
1301
|
-
# 3) Player Structure
|
|
1302
|
-
if is_player_structure(location_id):
|
|
1303
|
-
try:
|
|
1304
|
-
from corptools.models import Structure, EveLocation
|
|
1305
|
-
struct = Structure.objects.filter(structure_id=location_id).first()
|
|
1306
|
-
if struct:
|
|
1307
|
-
return struct.system_id
|
|
1308
|
-
|
|
1309
|
-
# Fallback to EveLocation for non-owned structures
|
|
1310
|
-
loc = EveLocation.objects.filter(location_id=location_id).first()
|
|
1311
|
-
if loc and loc.system_id:
|
|
1312
|
-
return loc.system_id
|
|
1313
|
-
except Exception:
|
|
1314
|
-
pass
|
|
1315
|
-
|
|
1316
|
-
return None
|
|
1039
|
+
return location_id >= 1_000_000_000_000
|
|
1317
1040
|
|
|
1318
1041
|
def is_ship(type_id):
|
|
1319
1042
|
"""Checks if a type_id belongs to a ship."""
|
|
@@ -1641,173 +1364,3 @@ def send_message(message, hook: str = None):
|
|
|
1641
1364
|
len(buffer),
|
|
1642
1365
|
)
|
|
1643
1366
|
_post_with_retries({"content": buffer})
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
def send_status_embed(
|
|
1647
|
-
subject: str,
|
|
1648
|
-
lines: List[str],
|
|
1649
|
-
*,
|
|
1650
|
-
override_title: Optional[str] = None,
|
|
1651
|
-
color: int = 0xED4245, # Discord red
|
|
1652
|
-
hook: Optional[str] = None,
|
|
1653
|
-
) -> None:
|
|
1654
|
-
"""
|
|
1655
|
-
Send a Discord embed via the existing send_message() webhook.
|
|
1656
|
-
|
|
1657
|
-
- subject: usually the corp name
|
|
1658
|
-
- lines: list of lines to go into embed description
|
|
1659
|
-
- override_title: optional explicit title
|
|
1660
|
-
- color: embed accent color (int)
|
|
1661
|
-
- hook: optional webhook URL override
|
|
1662
|
-
"""
|
|
1663
|
-
|
|
1664
|
-
if VERBOSE_WEBHOOK_LOGGING:
|
|
1665
|
-
logger.debug(
|
|
1666
|
-
"✅ [AA-BB] - [Embed] - send_status_embed called | subject=%r | lines=%d",
|
|
1667
|
-
subject,
|
|
1668
|
-
len(lines) if lines else 0,
|
|
1669
|
-
)
|
|
1670
|
-
|
|
1671
|
-
# Defensive: never send empty embeds
|
|
1672
|
-
if not lines:
|
|
1673
|
-
if VERBOSE_WEBHOOK_LOGGING:
|
|
1674
|
-
logger.debug("ℹ️ [AA-BB] - [Embed] - aborted: no lines supplied")
|
|
1675
|
-
return
|
|
1676
|
-
|
|
1677
|
-
# Discord limits
|
|
1678
|
-
MAX_DESC = 4096
|
|
1679
|
-
MAX_LINES = 50
|
|
1680
|
-
|
|
1681
|
-
title = override_title if override_title is not None else subject
|
|
1682
|
-
|
|
1683
|
-
if VERBOSE_WEBHOOK_LOGGING:
|
|
1684
|
-
logger.debug(
|
|
1685
|
-
"✅ [AA-BB] - [Embed] - title resolved | title=%r | color=%#x",
|
|
1686
|
-
title,
|
|
1687
|
-
color,
|
|
1688
|
-
)
|
|
1689
|
-
|
|
1690
|
-
# Trim excessive lines but keep tables / sections intact
|
|
1691
|
-
safe_lines = lines[:MAX_LINES]
|
|
1692
|
-
if len(lines) > MAX_LINES:
|
|
1693
|
-
logger.warning(
|
|
1694
|
-
"ℹ️ [AA-BB] - [Embed] - line cap exceeded | original=%d | capped=%d",
|
|
1695
|
-
len(lines),
|
|
1696
|
-
MAX_LINES,
|
|
1697
|
-
)
|
|
1698
|
-
|
|
1699
|
-
description = "\n".join(safe_lines)
|
|
1700
|
-
|
|
1701
|
-
# Hard truncate if someone messed up
|
|
1702
|
-
if len(description) > MAX_DESC:
|
|
1703
|
-
logger.error(
|
|
1704
|
-
"ℹ️ [AA-BB] - [Embed] - description overflow | chars=%d | truncating",
|
|
1705
|
-
len(description),
|
|
1706
|
-
)
|
|
1707
|
-
description = description[: MAX_DESC - 3] + "..."
|
|
1708
|
-
|
|
1709
|
-
if VERBOSE_WEBHOOK_LOGGING:
|
|
1710
|
-
logger.debug(
|
|
1711
|
-
"✅ [AA-BB] - [Embed] - payload ready | lines=%d | chars=%d",
|
|
1712
|
-
len(safe_lines),
|
|
1713
|
-
len(description),
|
|
1714
|
-
)
|
|
1715
|
-
|
|
1716
|
-
embed = {
|
|
1717
|
-
"embeds": [
|
|
1718
|
-
{
|
|
1719
|
-
"title": title,
|
|
1720
|
-
"description": description,
|
|
1721
|
-
"color": color,
|
|
1722
|
-
}
|
|
1723
|
-
]
|
|
1724
|
-
}
|
|
1725
|
-
|
|
1726
|
-
if VERBOSE_WEBHOOK_LOGGING:
|
|
1727
|
-
logger.debug("✅ [AA-BB] - [Embed] - sending embed payload")
|
|
1728
|
-
|
|
1729
|
-
time.sleep(0.25)
|
|
1730
|
-
send_message(embed, hook=hook)
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
def _chunk_embed_lines(lines, max_chars=1900):
|
|
1734
|
-
"""
|
|
1735
|
-
Split a list of lines into chunks whose joined text length
|
|
1736
|
-
is <= max_chars, without breaking ``` code blocks.
|
|
1737
|
-
|
|
1738
|
-
Returns: List[List[str]] – each inner list is one embed body.
|
|
1739
|
-
"""
|
|
1740
|
-
# First, group into "segments": either a full code block or a run of normal lines
|
|
1741
|
-
segments = []
|
|
1742
|
-
current_segment = []
|
|
1743
|
-
in_code = False
|
|
1744
|
-
|
|
1745
|
-
for line in lines:
|
|
1746
|
-
stripped = line.strip()
|
|
1747
|
-
|
|
1748
|
-
if stripped.startswith("```"):
|
|
1749
|
-
# Starting a new code block
|
|
1750
|
-
if not in_code:
|
|
1751
|
-
# flush any accumulated non-code segment
|
|
1752
|
-
if current_segment:
|
|
1753
|
-
segments.append(current_segment)
|
|
1754
|
-
current_segment = []
|
|
1755
|
-
in_code = True
|
|
1756
|
-
current_segment = [line]
|
|
1757
|
-
else:
|
|
1758
|
-
# closing an existing code block
|
|
1759
|
-
current_segment.append(line)
|
|
1760
|
-
segments.append(current_segment)
|
|
1761
|
-
current_segment = []
|
|
1762
|
-
in_code = False
|
|
1763
|
-
elif not in_code and (line.startswith("#") or line.startswith("- ") or line.startswith("* ") or line.startswith(" - ") or line.startswith(" * ")):
|
|
1764
|
-
# Break at top-level bullet points or headers to keep related indented lines together
|
|
1765
|
-
if current_segment:
|
|
1766
|
-
segments.append(current_segment)
|
|
1767
|
-
current_segment = [line]
|
|
1768
|
-
else:
|
|
1769
|
-
current_segment.append(line)
|
|
1770
|
-
|
|
1771
|
-
if current_segment:
|
|
1772
|
-
segments.append(current_segment)
|
|
1773
|
-
|
|
1774
|
-
# Now pack segments into chunks by total char length
|
|
1775
|
-
chunks = []
|
|
1776
|
-
current_chunk = []
|
|
1777
|
-
current_len = 0
|
|
1778
|
-
|
|
1779
|
-
for seg in segments:
|
|
1780
|
-
# Estimate length if we add this segment (with newlines)
|
|
1781
|
-
seg_text = "\n".join(seg)
|
|
1782
|
-
seg_len = len(seg_text) + (1 if current_chunk else 0) # +1 for newline before segment
|
|
1783
|
-
|
|
1784
|
-
if seg_len > max_chars:
|
|
1785
|
-
# Segment itself is huge; fall back to splitting inside it line-by-line
|
|
1786
|
-
for line in seg:
|
|
1787
|
-
line_len = len(line) + (1 if current_chunk else 0)
|
|
1788
|
-
if current_len + line_len > max_chars and current_chunk:
|
|
1789
|
-
chunks.append(current_chunk)
|
|
1790
|
-
current_chunk = [line]
|
|
1791
|
-
current_len = len(line)
|
|
1792
|
-
else:
|
|
1793
|
-
current_chunk.append(line)
|
|
1794
|
-
current_len += line_len
|
|
1795
|
-
continue
|
|
1796
|
-
|
|
1797
|
-
if current_len + seg_len > max_chars and current_chunk:
|
|
1798
|
-
# Start a new chunk
|
|
1799
|
-
chunks.append(current_chunk)
|
|
1800
|
-
current_chunk = list(seg)
|
|
1801
|
-
current_len = len(seg_text)
|
|
1802
|
-
else:
|
|
1803
|
-
# Add segment to current chunk
|
|
1804
|
-
if current_chunk:
|
|
1805
|
-
current_chunk.append("") # ensure a blank line between segments
|
|
1806
|
-
current_len += 1
|
|
1807
|
-
current_chunk.extend(seg)
|
|
1808
|
-
current_len += len(seg_text)
|
|
1809
|
-
|
|
1810
|
-
if current_chunk:
|
|
1811
|
-
chunks.append(current_chunk)
|
|
1812
|
-
|
|
1813
|
-
return chunks
|