aa-structures 2.14.1__py3-none-any.whl → 2.16.0__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.
- {aa_structures-2.14.1.dist-info → aa_structures-2.16.0.dist-info}/METADATA +1 -1
- {aa_structures-2.14.1.dist-info → aa_structures-2.16.0.dist-info}/RECORD +15 -14
- structures/__init__.py +1 -1
- structures/admin.py +40 -0
- structures/constants.py +6 -3
- structures/managers.py +1 -1
- structures/models/owners.py +96 -56
- structures/tests/models/test_owners_2.py +103 -59
- structures/tests/test_admin.py +19 -0
- structures/tests/testdata/constants.py +22 -0
- structures/tests/testdata/create_eveuniverse.py +1 -3
- structures/tests/testdata/eveuniverse.json +15503 -6784
- structures/webhooks/core.py +1 -1
- {aa_structures-2.14.1.dist-info → aa_structures-2.16.0.dist-info}/LICENSE +0 -0
- {aa_structures-2.14.1.dist-info → aa_structures-2.16.0.dist-info}/WHEEL +0 -0
@@ -1,12 +1,12 @@
|
|
1
|
-
structures/__init__.py,sha256=
|
2
|
-
structures/admin.py,sha256=
|
1
|
+
structures/__init__.py,sha256=Z3bIPmcm4sX1w_r8VxYDVpCP0rbtGGuzUzh7wP8la5c,204
|
2
|
+
structures/admin.py,sha256=K7wh8mHFfGHONn7oLdqXsBAxq0rmYrwbZ7S3uIOuMtg,41303
|
3
3
|
structures/app_settings.py,sha256=aWA2bTcv_vVwIyisx-G7GBSpfM6JDyt2MWcXKtHnjK0,6651
|
4
4
|
structures/apps.py,sha256=MNZH9l3qWCwuS7OGiKGkBVrDzKoOFlqwDdEgyEFzxVA,195
|
5
5
|
structures/auth_hooks.py,sha256=nRbrixFkAE5gphDokB1E8xhH8FY2VtXVwu0XMmSGBAw,1013
|
6
|
-
structures/constants.py,sha256=
|
6
|
+
structures/constants.py,sha256=k5rfD29ZjR7ToRmJw4WnLVd4LmoZvDw4OK5IoiiyJ6w,1063
|
7
7
|
structures/forms.py,sha256=kXs-SGIIj-D9xtFCILKe_PMRU4eHl3-HLNWRhaZKmnQ,391
|
8
8
|
structures/helpers.py,sha256=_dw7j7yobpcV70VwWxoQiptk69b3ksvaDlRQKHg8Kmg,2344
|
9
|
-
structures/managers.py,sha256=
|
9
|
+
structures/managers.py,sha256=_XZhsWb4is7LpQTUmGZwxQeJzyZnsB3n21EETgEIlzU,20062
|
10
10
|
structures/providers.py,sha256=9QYHd8X5HwBhrbgbX3LUrXXV1KGM3hFhcxK6qIJjJtg,317
|
11
11
|
structures/tasks.py,sha256=INZ3soMYHYfxrQsyTO-ozoxbVX6lpMnF3AUo8ybWIoA,9083
|
12
12
|
structures/urls.py,sha256=An5v27AD_NXMNL66cMVtQNci1C_Aqry32rrvDkMpgYo,1467
|
@@ -65,7 +65,7 @@ structures/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
65
65
|
structures/models/__init__.py,sha256=Da0-Z4BtsZ_mlnI6XtyvoE0UtTuOA0psGCuVhVPVKrM,916
|
66
66
|
structures/models/eveuniverse.py,sha256=vTIfzZL9guEDuZHQvRdG6pI4zSEdMqfVE-2SkHdqbRo,2213
|
67
67
|
structures/models/notifications.py,sha256=HwQc-ChdP0ULuJgxUym9_CBsCWCmcHT7whlk9tB2vzw,35364
|
68
|
-
structures/models/owners.py,sha256=
|
68
|
+
structures/models/owners.py,sha256=Oxs9LDtoKRvpqGtvZehNDyBPKgW_UIrUntZPe6LVPzY,59611
|
69
69
|
structures/models/structures_1.py,sha256=zk380uG2DuQ7exO7THbq5TE5Ro2jr6EyVCIxRJXHIJI,29958
|
70
70
|
structures/models/structures_2.py,sha256=g5Pct5jNmZC-n7fnpLs5UyiP9JLrGdI1vjYucHTV_wQ,10371
|
71
71
|
structures/static/structures/css/global.css,sha256=R4LEH9PwLoN77qkqBK7u2y_vzRC3fq8X_zKnAW7yhiA,1165
|
@@ -160,7 +160,7 @@ structures/templates/structures/templatetags/list_title.html,sha256=C2NWwo27TGfG
|
|
160
160
|
structures/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
161
161
|
structures/templatetags/structures.py,sha256=vSt5AnfYuo11q1SxiskT4oshSMsZ9ZgM0nYpYiMl8bA,1637
|
162
162
|
structures/tests/__init__.py,sha256=9MrJzKr8DdsQY3-79v188pTpwqT4TDQ46vKnBJAGqic,75
|
163
|
-
structures/tests/test_admin.py,sha256=
|
163
|
+
structures/tests/test_admin.py,sha256=aDd88Ry0ahitpYyF_wa1jG_pWJ5m5w3jsat45sBhEmo,27493
|
164
164
|
structures/tests/test_helpers.py,sha256=BQC-4H-9-v5qW4nugqy0bkxuGlA3UO2clYY2lI2LjoY,4893
|
165
165
|
structures/tests/test_managers_1.py,sha256=4dnlK7Le04eJUPjJc9ex5BxZWIJGAyEvdKuuYXU2gqY,34846
|
166
166
|
structures/tests/test_managers_2.py,sha256=FISr_NT1Qnu9j1JYYTceNsUk8k9rfCTKwjKi5WUVbPs,3025
|
@@ -185,17 +185,18 @@ structures/tests/models/test_notifications_2.py,sha256=wBoB6lHMK4yrd63DSkZ570yXW
|
|
185
185
|
structures/tests/models/test_notifications_3.py,sha256=u11s0k9EmtFgL3kyb4zDyLVliQLOps701ZgEA2T2i0Y,7257
|
186
186
|
structures/tests/models/test_notifications_discord.py,sha256=6maDXjl2C5yH2XRgsvMtb3P-tfOdZLQDaksffiqS8OM,6312
|
187
187
|
structures/tests/models/test_owners_1.py,sha256=o8AJasQ0-Pdb0FRFZcmNcMGjaIk8fH3OZIZw4paJiDw,24433
|
188
|
-
structures/tests/models/test_owners_2.py,sha256=
|
188
|
+
structures/tests/models/test_owners_2.py,sha256=RSaeLz6S6ncoikWwDjNh6YZftpBN8TGdzAl8E2tgkqA,24527
|
189
189
|
structures/tests/models/test_owners_3.py,sha256=cpDkfFkVvC1v4uuXha1vGUmWZ163huYTUDuZyed9Rdc,16947
|
190
190
|
structures/tests/models/test_owners_4.py,sha256=_VP4QsPYGwBnn_bVN4aNX2ZVeJzMAzWObZrgCJkOPgY,19496
|
191
191
|
structures/tests/models/test_owners_5.py,sha256=TIF_SqJqyGja8FBV2lQNAC4yff1usmJ4e0QW7e68zTg,36929
|
192
192
|
structures/tests/models/test_owners_6.py,sha256=R9UE2QGwiGTWLHzzOZwGQPWJrAPwIIl7UwrHH-ki4Ak,940
|
193
193
|
structures/tests/models/test_structures.py,sha256=iCCa0yYyPHieNfj8TQbdoIv141oLc6hlICZ6AsTnHAw,41849
|
194
194
|
structures/tests/testdata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
195
|
-
structures/tests/testdata/
|
195
|
+
structures/tests/testdata/constants.py,sha256=iab-9cHjAO4RBM88UeWbBypRm9qoZcViwZ8BPY17p1Q,441
|
196
|
+
structures/tests/testdata/create_eveuniverse.py,sha256=a5DHYAxxsytOeevAL53RDoeDWObKwViqfpXRlmZeOHY,2157
|
196
197
|
structures/tests/testdata/entities.json,sha256=vmb0uhwTpD0gycGAakgYidr3qSbnHiMubAd4u7T2l70,36053
|
197
198
|
structures/tests/testdata/esi_data.json,sha256=DX47oSlRZIPxlPueMfiNElbZbAip2cp3LAUmv8GAPJ0,13864
|
198
|
-
structures/tests/testdata/eveuniverse.json,sha256=
|
199
|
+
structures/tests/testdata/eveuniverse.json,sha256=7RA5qeaPYx78Mk5_zixL2XYd-Oa4omhUihjgAbgNLyc,1616628
|
199
200
|
structures/tests/testdata/factories.py,sha256=UF7Zao2-DjVFLZLEBWaJv4Pg1uw5D6p0TO8ZKuoAI_8,25293
|
200
201
|
structures/tests/testdata/generate_notifications.py,sha256=lhcnbsnE4O6g0OFUAYO2sCfu8vmwBcFtxn-TuTLtFnM,5417
|
201
202
|
structures/tests/testdata/generate_notifications_2.py,sha256=mdoGXd9vgy_opmrwTr9MfGe-QieHV4BHtRA7VFzxFKM,1413
|
@@ -217,13 +218,13 @@ structures/views/statistics.py,sha256=7jj8b9ATsYwE7Cg6gMp-bYx29nV43GdWYun9WBggGk
|
|
217
218
|
structures/views/status.py,sha256=gcahbk6dPIZDqkaNHDAsEHyDWLzicTK18Fom0A6xx3c,718
|
218
219
|
structures/views/structures.py,sha256=Wb57jFfRa0Zxo6TxKmOCQ-jtopzPtHe0go6gnJn40CA,22584
|
219
220
|
structures/webhooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
220
|
-
structures/webhooks/core.py,sha256=
|
221
|
+
structures/webhooks/core.py,sha256=kvbMQ_kjJleQanlFFoiN52wIkBG_4u0ONfcHfCU5lgA,6604
|
221
222
|
structures/webhooks/managers.py,sha256=L3G3AmsyDeif_lfpWshmAxQ61UGJ9w8i9lZaF2jbOtQ,1117
|
222
223
|
structures/webhooks/models.py,sha256=kUkt9rnRQIJIrU9Bjcs34rvkb-TMbUubHdn-kny08kI,2067
|
223
224
|
structures/webhooks/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
224
225
|
structures/webhooks/tests/test_core.py,sha256=4NcEAQgK2KhQkFOxYh2ad0S-qUWh1DNGDmLo5Mo5opI,6762
|
225
226
|
structures/webhooks/tests/test_utils.py,sha256=ekADFv0JOEtXeqdiejbeqrABO__Q1flJHzVieQ7L9e0,459
|
226
|
-
aa_structures-2.
|
227
|
-
aa_structures-2.
|
228
|
-
aa_structures-2.
|
229
|
-
aa_structures-2.
|
227
|
+
aa_structures-2.16.0.dist-info/LICENSE,sha256=XZiwB_S_40_HhnvLg5xvtBb3g1oGjPrk0rpFwk8iInE,1070
|
228
|
+
aa_structures-2.16.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
229
|
+
aa_structures-2.16.0.dist-info/METADATA,sha256=1Aqt2HSauvphDqPjDpuv3s2Pkht-0ezvNuQWA7Op4hI,5972
|
230
|
+
aa_structures-2.16.0.dist-info/RECORD,,
|
structures/__init__.py
CHANGED
structures/admin.py
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
"""Admin site for Structures."""
|
2
2
|
|
3
|
+
import functools
|
3
4
|
import statistics
|
4
5
|
from typing import Optional
|
5
6
|
|
7
|
+
from django import forms
|
6
8
|
from django.conf import settings
|
7
9
|
from django.contrib import admin
|
10
|
+
from django.contrib.admin.widgets import FilteredSelectMultiple
|
8
11
|
from django.db import models
|
9
12
|
from django.db.models import Prefetch
|
10
13
|
from django.db.models.functions import Lower
|
@@ -1028,8 +1031,44 @@ class StructureAdmin(admin.ModelAdmin):
|
|
1028
1031
|
)
|
1029
1032
|
|
1030
1033
|
|
1034
|
+
class WebhookAdminForm(forms.ModelForm):
|
1035
|
+
owners = forms.ModelMultipleChoiceField(
|
1036
|
+
queryset=Owner.objects.order_by(Lower("corporation__corporation_name")),
|
1037
|
+
required=False,
|
1038
|
+
widget=FilteredSelectMultiple(verbose_name=_("Users"), is_stacked=False),
|
1039
|
+
)
|
1040
|
+
|
1041
|
+
def __init__(self, *args, **kwargs):
|
1042
|
+
super().__init__(*args, **kwargs)
|
1043
|
+
|
1044
|
+
if self.instance and self.instance.pk:
|
1045
|
+
self.fields["owners"].initial = self.instance.owners.all()
|
1046
|
+
|
1047
|
+
def save(self, commit=True):
|
1048
|
+
webhook: Webhook = super().save(commit=False)
|
1049
|
+
|
1050
|
+
if commit:
|
1051
|
+
webhook.save()
|
1052
|
+
|
1053
|
+
owners = self.cleaned_data["owners"]
|
1054
|
+
if webhook.pk:
|
1055
|
+
self._save_m2m_and_users(webhook, owners)
|
1056
|
+
else:
|
1057
|
+
self.save_m2m = functools.partial(
|
1058
|
+
self._save_m2m_and_users, webhook=webhook, owners=owners
|
1059
|
+
)
|
1060
|
+
|
1061
|
+
return webhook
|
1062
|
+
|
1063
|
+
def _save_m2m_and_users(self, webhook, owners):
|
1064
|
+
"""Save m2m relations incl. users."""
|
1065
|
+
webhook.owners.set(owners)
|
1066
|
+
self._save_m2m()
|
1067
|
+
|
1068
|
+
|
1031
1069
|
@admin.register(Webhook)
|
1032
1070
|
class WebhookAdmin(admin.ModelAdmin):
|
1071
|
+
form = WebhookAdminForm
|
1033
1072
|
list_display = (
|
1034
1073
|
"name",
|
1035
1074
|
"_ping_groups",
|
@@ -1057,6 +1096,7 @@ class WebhookAdmin(admin.ModelAdmin):
|
|
1057
1096
|
"name",
|
1058
1097
|
"url",
|
1059
1098
|
"notes",
|
1099
|
+
"owners",
|
1060
1100
|
"notification_types",
|
1061
1101
|
"ping_groups",
|
1062
1102
|
"is_active",
|
structures/constants.py
CHANGED
@@ -16,6 +16,7 @@ class EveCategoryId(IntEnum):
|
|
16
16
|
ORBITAL = 46
|
17
17
|
STARBASE = 23
|
18
18
|
STRUCTURE = 65
|
19
|
+
STRUCTURE_MODULE = 66
|
19
20
|
|
20
21
|
|
21
22
|
class EveGroupId(IntEnum):
|
@@ -26,11 +27,13 @@ class EveGroupId(IntEnum):
|
|
26
27
|
ENGINEERING_COMPLEX = 1404
|
27
28
|
FUEL_BLOCK = 1136
|
28
29
|
ICE_PRODUCT = 423
|
29
|
-
|
30
|
+
MOON = 8
|
30
31
|
PLANET = 7
|
32
|
+
QUANTUM_CORES = 4086
|
33
|
+
REFINERY = 1406
|
31
34
|
STRUCTURE_CITADEL_SERVICE_MODULE = 1321
|
32
35
|
UNCOMMON_MOON_ASTEROIDS = 1921
|
33
|
-
|
36
|
+
UPWELL_MOON_DRILL = 4744
|
34
37
|
|
35
38
|
|
36
39
|
class EveTypeId(IntEnum):
|
@@ -42,8 +45,8 @@ class EveTypeId(IntEnum):
|
|
42
45
|
IHUB = 32458
|
43
46
|
JUMP_GATE = 35841
|
44
47
|
LIQUID_OZONE = 16273
|
45
|
-
ORBITAL_SKYHOOK = 81080
|
46
48
|
NITROGEN_FUEL_BLOCK = 4051
|
49
|
+
ORBITAL_SKYHOOK = 81080
|
47
50
|
STRONTIUM = 16275
|
48
51
|
TCU = 32226
|
49
52
|
|
structures/managers.py
CHANGED
@@ -392,7 +392,7 @@ class StructureManagerBase(models.Manager):
|
|
392
392
|
def update_or_create_from_dict(
|
393
393
|
self, structure: dict, owner: Owner
|
394
394
|
) -> Tuple[Any, bool]:
|
395
|
-
"""
|
395
|
+
"""Update or create a structure from a dict."""
|
396
396
|
|
397
397
|
eve_type: EveType = EveType.objects.get_or_create_esi(id=structure["type_id"])[
|
398
398
|
0
|
structures/models/owners.py
CHANGED
@@ -585,14 +585,10 @@ class Owner(models.Model):
|
|
585
585
|
return positions
|
586
586
|
|
587
587
|
def _fetch_upwell_structures(self, token: Token) -> bool:
|
588
|
-
"""
|
589
|
-
|
590
|
-
Return True if successful, else False.
|
591
|
-
"""
|
592
|
-
is_ok = True
|
588
|
+
"""Fetches Upwell structures from ESI an reports whether it was successful."""
|
593
589
|
# fetch main list of structure for this corporation
|
594
590
|
try:
|
595
|
-
structures
|
591
|
+
structures = (
|
596
592
|
esi.client.Corporation.get_corporations_corporation_id_structures(
|
597
593
|
corporation_id=self.corporation.corporation_id,
|
598
594
|
token=token.valid_access_token(),
|
@@ -604,58 +600,12 @@ class Owner(models.Model):
|
|
604
600
|
|
605
601
|
# fetch additional information for structures
|
606
602
|
if not structures:
|
603
|
+
is_ok = True
|
607
604
|
logger.info("%s: No Upwell structures retrieved from ESI", self)
|
608
605
|
else:
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
len(structures),
|
613
|
-
)
|
614
|
-
for structure in structures:
|
615
|
-
try:
|
616
|
-
structure_info = (
|
617
|
-
esi.client.Universe.get_universe_structures_structure_id(
|
618
|
-
structure_id=structure["structure_id"],
|
619
|
-
token=token.valid_access_token(),
|
620
|
-
)
|
621
|
-
).results()
|
622
|
-
except OSError as ex:
|
623
|
-
if isinstance(ex, HTTPForbidden):
|
624
|
-
logger.error(
|
625
|
-
"Failed to fetch structure with ID #%d belonging to %s, "
|
626
|
-
"because the character '%s' is missing "
|
627
|
-
"docking rights for it.",
|
628
|
-
structure["structure_id"],
|
629
|
-
self,
|
630
|
-
token.character_name,
|
631
|
-
)
|
632
|
-
else:
|
633
|
-
self._report_esi_issue(
|
634
|
-
f"fetch structure #{structure['structure_id']}", ex, token
|
635
|
-
)
|
636
|
-
structure["name"] = "(no data)"
|
637
|
-
is_ok = False
|
638
|
-
else:
|
639
|
-
structure["name"] = Structure.extract_name_from_esi_response(
|
640
|
-
structure_info["name"]
|
641
|
-
)
|
642
|
-
structure["position"] = structure_info["position"]
|
643
|
-
|
644
|
-
logger.info(
|
645
|
-
"%s: Storing updates for %d upwell structures",
|
646
|
-
self,
|
647
|
-
len(structures),
|
648
|
-
)
|
649
|
-
for structure in structures:
|
650
|
-
try:
|
651
|
-
Structure.objects.update_or_create_from_dict(structure, self)
|
652
|
-
except OSError:
|
653
|
-
logger.warning(
|
654
|
-
"%s: Failed to store update for structure with ID %s",
|
655
|
-
self,
|
656
|
-
structure["structure_id"],
|
657
|
-
)
|
658
|
-
is_ok = False
|
606
|
+
is_ok = self._fetch_universe_infos_for_structures(token, structures)
|
607
|
+
is_ok &= self._store_structure_updates(structures)
|
608
|
+
self._resolve_metenox_moons()
|
659
609
|
|
660
610
|
if STRUCTURES_DEVELOPER_MODE:
|
661
611
|
self._store_raw_data("structures", structures)
|
@@ -666,6 +616,95 @@ class Owner(models.Model):
|
|
666
616
|
)
|
667
617
|
return is_ok
|
668
618
|
|
619
|
+
def _fetch_universe_infos_for_structures(
|
620
|
+
self, token, structures: List[dict]
|
621
|
+
) -> bool:
|
622
|
+
count = 0
|
623
|
+
for s in structures:
|
624
|
+
try:
|
625
|
+
structure_info = (
|
626
|
+
esi.client.Universe.get_universe_structures_structure_id(
|
627
|
+
structure_id=s["structure_id"],
|
628
|
+
token=token.valid_access_token(),
|
629
|
+
)
|
630
|
+
).results()
|
631
|
+
except OSError as ex:
|
632
|
+
if isinstance(ex, HTTPForbidden):
|
633
|
+
logger.error(
|
634
|
+
"Failed to fetch structure with ID #%d belonging to %s, "
|
635
|
+
"because the character '%s' is missing docking rights.",
|
636
|
+
s["structure_id"],
|
637
|
+
self,
|
638
|
+
token.character_name,
|
639
|
+
)
|
640
|
+
else:
|
641
|
+
self._report_esi_issue(
|
642
|
+
f"fetch structure #{s['structure_id']}", ex, token
|
643
|
+
)
|
644
|
+
s["name"] = "(no data)"
|
645
|
+
else:
|
646
|
+
count += 1
|
647
|
+
s["name"] = Structure.extract_name_from_esi_response(
|
648
|
+
structure_info["name"]
|
649
|
+
)
|
650
|
+
s["position"] = structure_info["position"]
|
651
|
+
|
652
|
+
logger.info(
|
653
|
+
"%s: Fetched universe infos for %d / %d Upwell structures from ESI",
|
654
|
+
self,
|
655
|
+
count,
|
656
|
+
len(structures),
|
657
|
+
)
|
658
|
+
return count == len(structures)
|
659
|
+
|
660
|
+
def _store_structure_updates(self, structures: List[dict]) -> bool:
|
661
|
+
count = 0
|
662
|
+
for s in structures:
|
663
|
+
try:
|
664
|
+
Structure.objects.update_or_create_from_dict(s, self)
|
665
|
+
except OSError:
|
666
|
+
logger.warning(
|
667
|
+
"%s: Failed to store update for structure with ID %s",
|
668
|
+
self,
|
669
|
+
s["structure_id"],
|
670
|
+
)
|
671
|
+
else:
|
672
|
+
count += 1
|
673
|
+
logger.info(
|
674
|
+
"%s: Stored updates for %d/%d upwell structures",
|
675
|
+
self,
|
676
|
+
count,
|
677
|
+
len(structures),
|
678
|
+
)
|
679
|
+
return count == len(structures)
|
680
|
+
|
681
|
+
def _resolve_metenox_moons(self):
|
682
|
+
"""Add moons to all unresolved metenox structures."""
|
683
|
+
s: Structure
|
684
|
+
for s in self.structures.filter(
|
685
|
+
eve_type__eve_group=EveGroupId.UPWELL_MOON_DRILL,
|
686
|
+
eve_moon__isnull=True,
|
687
|
+
position_x__isnull=False,
|
688
|
+
position_y__isnull=False,
|
689
|
+
position_z__isnull=False,
|
690
|
+
):
|
691
|
+
try:
|
692
|
+
celestial = s.eve_solar_system.nearest_celestial(
|
693
|
+
x=s.position_x,
|
694
|
+
y=s.position_y,
|
695
|
+
z=s.position_z,
|
696
|
+
group_id=EveGroupId.MOON,
|
697
|
+
)
|
698
|
+
except OSError:
|
699
|
+
continue
|
700
|
+
|
701
|
+
if not celestial or not isinstance(celestial.eve_object, EveMoon):
|
702
|
+
continue
|
703
|
+
|
704
|
+
s.eve_moon = celestial.eve_object
|
705
|
+
s.save()
|
706
|
+
logger.info("%s: Resolved moon for Metenox: %d", self, s.name)
|
707
|
+
|
669
708
|
def _fetch_custom_offices(self, token: Token) -> bool:
|
670
709
|
"""Fetch custom offices from ESI for this owner.
|
671
710
|
|
@@ -1375,6 +1414,7 @@ class Owner(models.Model):
|
|
1375
1414
|
s.eve_planet = celestial.eve_object
|
1376
1415
|
s.name = celestial.eve_type.name
|
1377
1416
|
s.save()
|
1417
|
+
logger.info("%s: Resolved moon for Skyhook at: %s", self, s.eve_planet.name)
|
1378
1418
|
|
1379
1419
|
@staticmethod
|
1380
1420
|
def get_esi_scopes() -> List[str]:
|
@@ -2,6 +2,7 @@ import datetime as dt
|
|
2
2
|
from unittest.mock import patch
|
3
3
|
|
4
4
|
from django.utils.timezone import now, utc
|
5
|
+
from eveuniverse.models import EveMoon
|
5
6
|
|
6
7
|
from app_utils.esi_testing import EsiClientStub, EsiEndpoint
|
7
8
|
from app_utils.testing import NoSocketsTestCase
|
@@ -10,6 +11,7 @@ from structures.constants import EveCorporationId
|
|
10
11
|
from structures.core.notification_types import NotificationType
|
11
12
|
from structures.models import Structure, StructureService
|
12
13
|
from structures.tests import to_json
|
14
|
+
from structures.tests.testdata.constants import EveMoonId, EveSolarSystemId, EveTypeId
|
13
15
|
from structures.tests.testdata.factories import (
|
14
16
|
EveEntityCorporationFactory,
|
15
17
|
FuelAlertConfigFactory,
|
@@ -20,6 +22,7 @@ from structures.tests.testdata.factories import (
|
|
20
22
|
UserMainDefaultOwnerFactory,
|
21
23
|
WebhookFactory,
|
22
24
|
)
|
25
|
+
from structures.tests.testdata.helpers import NearestCelestial
|
23
26
|
from structures.tests.testdata.load_eveuniverse import load_eveuniverse
|
24
27
|
|
25
28
|
MODULE_PATH = "structures.models.owners"
|
@@ -40,54 +43,6 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
40
43
|
id=EveCorporationId.DED, name="DED"
|
41
44
|
) # for notifications
|
42
45
|
cls.endpoints = [
|
43
|
-
EsiEndpoint(
|
44
|
-
"Assets",
|
45
|
-
"get_corporations_corporation_id_assets",
|
46
|
-
"corporation_id",
|
47
|
-
needs_token=True,
|
48
|
-
data={
|
49
|
-
str(cls.corporation_id): [
|
50
|
-
{
|
51
|
-
"is_singleton": False,
|
52
|
-
"item_id": 1300000001001,
|
53
|
-
"location_flag": "QuantumCoreRoom",
|
54
|
-
"location_id": 1000000000001,
|
55
|
-
"location_type": "item",
|
56
|
-
"quantity": 1,
|
57
|
-
"type_id": 56201, # Astrahus Upwell Quantum Core
|
58
|
-
},
|
59
|
-
{
|
60
|
-
"is_singleton": True,
|
61
|
-
"item_id": 1300000001002,
|
62
|
-
"location_flag": "ServiceSlot0",
|
63
|
-
"location_id": 1000000000001,
|
64
|
-
"location_type": "item",
|
65
|
-
"quantity": 1,
|
66
|
-
"type_id": 35894, # Standup Cloning Center I
|
67
|
-
},
|
68
|
-
{
|
69
|
-
"is_singleton": True,
|
70
|
-
"item_id": 1300000002001,
|
71
|
-
"location_flag": "ServiceSlot0",
|
72
|
-
"location_id": 1000000000002,
|
73
|
-
"location_type": "item",
|
74
|
-
"quantity": 1,
|
75
|
-
"type_id": 35894, # Standup Cloning Center I
|
76
|
-
},
|
77
|
-
],
|
78
|
-
"2102": [
|
79
|
-
{
|
80
|
-
"is_singleton": False,
|
81
|
-
"item_id": 1300000003001,
|
82
|
-
"location_flag": "StructureFuel",
|
83
|
-
"location_id": 1000000000004,
|
84
|
-
"location_type": "item",
|
85
|
-
"quantity": 5000,
|
86
|
-
"type_id": 16273, # Liquid Ozone
|
87
|
-
}
|
88
|
-
],
|
89
|
-
},
|
90
|
-
),
|
91
46
|
EsiEndpoint(
|
92
47
|
"Corporation",
|
93
48
|
"get_corporations_corporation_id_structures",
|
@@ -110,8 +65,8 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
110
65
|
"state_timer_end": None,
|
111
66
|
"state_timer_start": None,
|
112
67
|
"structure_id": 1000000000002,
|
113
|
-
"system_id":
|
114
|
-
"type_id":
|
68
|
+
"system_id": EveSolarSystemId.AMAMAKE,
|
69
|
+
"type_id": EveTypeId.ATHANOR,
|
115
70
|
"unanchors_at": None,
|
116
71
|
},
|
117
72
|
{
|
@@ -131,8 +86,8 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
131
86
|
2020, 4, 5, 6, 30, tzinfo=utc
|
132
87
|
),
|
133
88
|
"structure_id": 1000000000001,
|
134
|
-
"system_id":
|
135
|
-
"type_id":
|
89
|
+
"system_id": EveSolarSystemId.AMAMAKE,
|
90
|
+
"type_id": EveTypeId.ASTRAHUS,
|
136
91
|
"unanchors_at": dt.datetime(2020, 5, 5, 6, 30, tzinfo=utc),
|
137
92
|
},
|
138
93
|
{
|
@@ -148,7 +103,7 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
148
103
|
"state_timer_start": None,
|
149
104
|
"structure_id": 1000000000003,
|
150
105
|
"system_id": 30000476,
|
151
|
-
"type_id":
|
106
|
+
"type_id": EveTypeId.ASTRAHUS,
|
152
107
|
"unanchors_at": None,
|
153
108
|
},
|
154
109
|
],
|
@@ -168,8 +123,8 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
168
123
|
"y": 7310316270.0,
|
169
124
|
"z": -163686684205.0,
|
170
125
|
},
|
171
|
-
"solar_system_id":
|
172
|
-
"type_id":
|
126
|
+
"solar_system_id": EveSolarSystemId.AMAMAKE,
|
127
|
+
"type_id": EveTypeId.ASTRAHUS,
|
173
128
|
},
|
174
129
|
"1000000000002": {
|
175
130
|
"corporation_id": cls.corporation_id,
|
@@ -179,8 +134,8 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
179
134
|
"y": -130157937025.56424,
|
180
135
|
"z": -442026427345.6355,
|
181
136
|
},
|
182
|
-
"solar_system_id":
|
183
|
-
"type_id":
|
137
|
+
"solar_system_id": EveSolarSystemId.AMAMAKE,
|
138
|
+
"type_id": EveTypeId.ATHANOR,
|
184
139
|
},
|
185
140
|
"1000000000003": {
|
186
141
|
"corporation_id": cls.corporation_id,
|
@@ -191,7 +146,7 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
191
146
|
"z": -442026427345.6355,
|
192
147
|
},
|
193
148
|
"solar_system_id": 30000476,
|
194
|
-
"type_id":
|
149
|
+
"type_id": EveTypeId.ASTRAHUS,
|
195
150
|
},
|
196
151
|
},
|
197
152
|
),
|
@@ -221,7 +176,7 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
221
176
|
self.assertEqual(structure.position_x, 55028384780.0)
|
222
177
|
self.assertEqual(structure.position_y, 7310316270.0)
|
223
178
|
self.assertEqual(structure.position_z, -163686684205.0)
|
224
|
-
self.assertEqual(structure.eve_solar_system_id,
|
179
|
+
self.assertEqual(structure.eve_solar_system_id, EveSolarSystemId.AMAMAKE)
|
225
180
|
self.assertEqual(structure.eve_type_id, 35832)
|
226
181
|
self.assertEqual(
|
227
182
|
int(structure.owner.corporation.corporation_id), self.corporation_id
|
@@ -550,3 +505,92 @@ class TestUpdateStructuresEsi(NoSocketsTestCase):
|
|
550
505
|
owner.update_structures_esi()
|
551
506
|
# then
|
552
507
|
self.assertEqual(structure.structure_fuel_alerts.count(), 0)
|
508
|
+
|
509
|
+
|
510
|
+
@patch(MODULE_PATH + ".STRUCTURES_FEATURE_STARBASES", False)
|
511
|
+
@patch(MODULE_PATH + ".STRUCTURES_FEATURE_CUSTOMS_OFFICES", False)
|
512
|
+
@patch(MODULE_PATH + ".esi")
|
513
|
+
class TestUpdateSpecificUpwellStructuresEsi(NoSocketsTestCase):
|
514
|
+
@classmethod
|
515
|
+
def setUpClass(cls):
|
516
|
+
super().setUpClass()
|
517
|
+
load_eveuniverse()
|
518
|
+
cls.user = UserMainDefaultOwnerFactory()
|
519
|
+
cls.owner = OwnerFactory(user=cls.user, structures_last_update_at=None)
|
520
|
+
cls.corporation_id = cls.owner.corporation.corporation_id
|
521
|
+
EveEntityCorporationFactory(
|
522
|
+
id=EveCorporationId.DED, name="DED"
|
523
|
+
) # for notifications
|
524
|
+
|
525
|
+
def test_can_update_metenox(self, mock_esi):
|
526
|
+
structure_id = 1000000000111
|
527
|
+
type_id = EveTypeId.METENOX
|
528
|
+
solar_system_id = EveSolarSystemId.AMAMAKE
|
529
|
+
endpoints = [
|
530
|
+
EsiEndpoint(
|
531
|
+
"Corporation",
|
532
|
+
"get_corporations_corporation_id_structures",
|
533
|
+
"corporation_id",
|
534
|
+
needs_token=True,
|
535
|
+
data={
|
536
|
+
str(self.corporation_id): [
|
537
|
+
{
|
538
|
+
"corporation_id": self.corporation_id,
|
539
|
+
"fuel_expires": dt.datetime(2020, 3, 5, 5, tzinfo=utc),
|
540
|
+
"next_reinforce_apply": None,
|
541
|
+
"next_reinforce_hour": None,
|
542
|
+
"profile_id": 101853,
|
543
|
+
"reinforce_hour": 18,
|
544
|
+
"services": [
|
545
|
+
{"name": "Moon Drill", "state": "online"},
|
546
|
+
],
|
547
|
+
"state": "shield_vulnerable",
|
548
|
+
"state_timer_end": dt.datetime(2020, 4, 5, 7, tzinfo=utc),
|
549
|
+
"state_timer_start": dt.datetime(
|
550
|
+
2020, 4, 5, 6, 30, tzinfo=utc
|
551
|
+
),
|
552
|
+
"structure_id": structure_id,
|
553
|
+
"system_id": solar_system_id,
|
554
|
+
"type_id": type_id,
|
555
|
+
"unanchors_at": dt.datetime(2020, 5, 5, 6, 30, tzinfo=utc),
|
556
|
+
},
|
557
|
+
],
|
558
|
+
},
|
559
|
+
),
|
560
|
+
EsiEndpoint(
|
561
|
+
"Universe",
|
562
|
+
"get_universe_structures_structure_id",
|
563
|
+
"structure_id",
|
564
|
+
needs_token=True,
|
565
|
+
data={
|
566
|
+
str(structure_id): {
|
567
|
+
"corporation_id": self.corporation_id,
|
568
|
+
"name": "Amamake - Mining",
|
569
|
+
"position": {
|
570
|
+
"x": 55028384780.0,
|
571
|
+
"y": 7310316270.0,
|
572
|
+
"z": -163686684205.0,
|
573
|
+
},
|
574
|
+
"solar_system_id": solar_system_id,
|
575
|
+
"type_id": type_id,
|
576
|
+
},
|
577
|
+
},
|
578
|
+
),
|
579
|
+
]
|
580
|
+
# given
|
581
|
+
mock_esi.client = EsiClientStub.create_from_endpoints(endpoints)
|
582
|
+
owner = OwnerFactory(user=self.user, structures_last_update_at=None)
|
583
|
+
moon = EveMoon.objects.get(id=EveMoonId.AMAMAKE_P2_M1)
|
584
|
+
# when
|
585
|
+
with patch(MODULE_PATH + ".EveSolarSystem.nearest_celestial") as m:
|
586
|
+
m.return_value = NearestCelestial(None, moon, 100)
|
587
|
+
owner.update_structures_esi()
|
588
|
+
# then
|
589
|
+
owner.refresh_from_db()
|
590
|
+
self.assertTrue(owner.is_structure_sync_fresh)
|
591
|
+
s = Structure.objects.get(id=structure_id)
|
592
|
+
self.assertEqual(s.name, "Mining")
|
593
|
+
self.assertEqual(s.eve_solar_system.id, EveSolarSystemId.AMAMAKE)
|
594
|
+
services = set(s.services.values_list("name", flat=True))
|
595
|
+
self.assertSetEqual({"Moon Drill"}, services)
|
596
|
+
self.assertEqual(s.eve_moon, moon)
|
structures/tests/test_admin.py
CHANGED
@@ -719,3 +719,22 @@ class TestWebhookAdmin(TestCase):
|
|
719
719
|
webhook.refresh_from_db()
|
720
720
|
self.assertFalse(webhook.is_active)
|
721
721
|
self.assertTrue(mock_message_user.called)
|
722
|
+
|
723
|
+
def test_can_assign_owner(self):
|
724
|
+
# given
|
725
|
+
owner = OwnerFactory()
|
726
|
+
webhook = WebhookFactory()
|
727
|
+
self.client.force_login(self.user)
|
728
|
+
data = {
|
729
|
+
"name": webhook.name,
|
730
|
+
"notification_types": NotificationType.webhook_defaults(),
|
731
|
+
"owners": [owner.pk],
|
732
|
+
"url": webhook.url,
|
733
|
+
"webhook_type": webhook.webhook_type,
|
734
|
+
}
|
735
|
+
r = self.client.post(
|
736
|
+
f"/admin/structures/webhook/{webhook.pk}/change/", data=data
|
737
|
+
)
|
738
|
+
self.assertEqual(r.status_code, 302)
|
739
|
+
webhook.refresh_from_db()
|
740
|
+
self.assertIn(owner, webhook.owners.all())
|