aa-structures 2.12.0__py3-none-any.whl → 2.14.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.12.0.dist-info → aa_structures-2.14.0.dist-info}/METADATA +1 -1
- {aa_structures-2.12.0.dist-info → aa_structures-2.14.0.dist-info}/RECORD +37 -34
- structures/__init__.py +1 -1
- structures/admin.py +1 -1
- structures/app_settings.py +4 -0
- structures/constants.py +1 -0
- structures/core/notification_embeds/main.py +58 -31
- structures/core/notification_embeds/orbital_embeds.py +1 -1
- structures/core/notification_embeds/skyhook_embeds.py +89 -0
- structures/core/notification_embeds/structures_embeds.py +23 -12
- structures/core/notification_embeds/tower_embeds.py +1 -1
- structures/core/notification_timers.py +53 -6
- structures/core/notification_types.py +58 -36
- structures/managers.py +22 -8
- structures/migrations/0007_add_notificationtypes_skyhook_metenox.py +149 -0
- structures/migrations/0008_add_notificationtypes_skyhook_metenox.py +149 -0
- structures/models/owners.py +68 -8
- structures/models/structures_1.py +5 -0
- structures/templates/structures/public.html +2 -2
- structures/templates/structures/structures.html +3 -3
- structures/tests/core/test_notification_types.py +16 -0
- structures/tests/core/{test_notifications_timerboard.py → test_notifications_timers.py} +6 -1
- structures/tests/integration/test_tasks.py +102 -1
- structures/tests/integration/test_views.py +1 -1
- structures/tests/models/test_owners_5.py +135 -1
- structures/tests/models/test_structures.py +49 -42
- structures/tests/test_managers_1.py +11 -1
- structures/tests/testdata/create_eveuniverse.py +6 -1
- structures/tests/testdata/entities.json +71 -1
- structures/tests/testdata/eveuniverse.json +6306 -5145
- structures/tests/testdata/factories.py +21 -0
- structures/tests/testdata/generate_notifications.py +142 -157
- structures/tests/testdata/helpers.py +6 -0
- structures/tests/views/test_structures.py +12 -4
- structures/views/structures.py +6 -6
- {aa_structures-2.12.0.dist-info → aa_structures-2.14.0.dist-info}/LICENSE +0 -0
- {aa_structures-2.12.0.dist-info → aa_structures-2.14.0.dist-info}/WHEEL +0 -0
structures/models/owners.py
CHANGED
@@ -37,6 +37,7 @@ from structures.app_settings import (
|
|
37
37
|
STRUCTURES_DEVELOPER_MODE,
|
38
38
|
STRUCTURES_ESI_DIRECTOR_ERROR_MAX_RETRIES,
|
39
39
|
STRUCTURES_FEATURE_CUSTOMS_OFFICES,
|
40
|
+
STRUCTURES_FEATURE_SKYHOOKS,
|
40
41
|
STRUCTURES_FEATURE_STARBASES,
|
41
42
|
STRUCTURES_HOURS_UNTIL_STALE_NOTIFICATION,
|
42
43
|
STRUCTURES_NOTIFICATION_SYNC_GRACE_MINUTES,
|
@@ -545,14 +546,14 @@ class Owner(models.Model):
|
|
545
546
|
)
|
546
547
|
|
547
548
|
def _remove_structures_not_returned_from_esi(
|
548
|
-
self,
|
549
|
+
self, existing_structures: models.QuerySet, new_structures: Iterable[dict]
|
549
550
|
):
|
550
551
|
"""Remove structures no longer returned from ESI."""
|
551
|
-
ids_local = {x.id for x in
|
552
|
+
ids_local = {x.id for x in existing_structures}
|
552
553
|
ids_from_esi = {x["structure_id"] for x in new_structures}
|
553
554
|
ids_to_remove = ids_local - ids_from_esi
|
554
555
|
if len(ids_to_remove) > 0:
|
555
|
-
|
556
|
+
existing_structures.filter(id__in=ids_to_remove).delete()
|
556
557
|
logger.info(
|
557
558
|
"Removed %d structures which apparently no longer exist.",
|
558
559
|
len(ids_to_remove),
|
@@ -650,7 +651,7 @@ class Owner(models.Model):
|
|
650
651
|
self._store_raw_data("structures", structures)
|
651
652
|
|
652
653
|
self._remove_structures_not_returned_from_esi(
|
653
|
-
|
654
|
+
existing_structures=self.structures.filter_upwell_structures(),
|
654
655
|
new_structures=structures,
|
655
656
|
)
|
656
657
|
return is_ok
|
@@ -701,7 +702,7 @@ class Owner(models.Model):
|
|
701
702
|
return False
|
702
703
|
|
703
704
|
self._remove_structures_not_returned_from_esi(
|
704
|
-
|
705
|
+
existing_structures=self.structures.filter_customs_offices(),
|
705
706
|
new_structures=structures.values(),
|
706
707
|
)
|
707
708
|
return True
|
@@ -868,7 +869,7 @@ class Owner(models.Model):
|
|
868
869
|
return False
|
869
870
|
|
870
871
|
self._remove_structures_not_returned_from_esi(
|
871
|
-
|
872
|
+
existing_structures=self.structures.filter_starbases(),
|
872
873
|
new_structures=structures,
|
873
874
|
)
|
874
875
|
character.reset_error_counter()
|
@@ -1214,15 +1215,18 @@ class Owner(models.Model):
|
|
1214
1215
|
def update_asset_esi(self, user: Optional[User] = None):
|
1215
1216
|
"""Update assets from ESI."""
|
1216
1217
|
token = self.fetch_token()
|
1217
|
-
assets_data = self.
|
1218
|
+
assets_data = self._fetch_owner_assets_from_esi(token)
|
1218
1219
|
self._store_items_for_upwell_structures(assets_data)
|
1219
1220
|
self._store_items_for_starbases(assets_data)
|
1221
|
+
if STRUCTURES_FEATURE_SKYHOOKS:
|
1222
|
+
self._update_skyhooks_from_assets(assets_data)
|
1223
|
+
self._resolve_skyhook_planets()
|
1220
1224
|
if user:
|
1221
1225
|
self._send_report_to_user(
|
1222
1226
|
topic="assets", topic_count=self.structures.count(), user=user
|
1223
1227
|
)
|
1224
1228
|
|
1225
|
-
def
|
1229
|
+
def _fetch_owner_assets_from_esi(self, token: Token) -> dict:
|
1226
1230
|
assets_raw = esi.client.Assets.get_corporations_corporation_id_assets(
|
1227
1231
|
corporation_id=self.corporation.corporation_id,
|
1228
1232
|
token=token.valid_access_token(),
|
@@ -1306,6 +1310,62 @@ class Owner(models.Model):
|
|
1306
1310
|
)
|
1307
1311
|
structure.update_items(structure_items)
|
1308
1312
|
|
1313
|
+
def _update_skyhooks_from_assets(self, assets_data: dict):
|
1314
|
+
skyhooks = {
|
1315
|
+
item_id: item
|
1316
|
+
for item_id, item in assets_data.items()
|
1317
|
+
if item["type_id"] == EveTypeId.ORBITAL_SKYHOOK
|
1318
|
+
and item["location_type"] == "solar_system"
|
1319
|
+
and item["location_flag"] == "AutoFit"
|
1320
|
+
and item["is_singleton"]
|
1321
|
+
and item["position"]
|
1322
|
+
}
|
1323
|
+
structures = []
|
1324
|
+
for item in skyhooks.values():
|
1325
|
+
structures.append(
|
1326
|
+
{
|
1327
|
+
"corporation_id": self.corporation.corporation_id,
|
1328
|
+
"type_id": item["type_id"],
|
1329
|
+
"position": item["position"],
|
1330
|
+
"structure_id": item["item_id"],
|
1331
|
+
"system_id": item["location_id"],
|
1332
|
+
}
|
1333
|
+
)
|
1334
|
+
|
1335
|
+
for s in structures:
|
1336
|
+
Structure.objects.update_or_create_from_dict(s, self)
|
1337
|
+
|
1338
|
+
self._remove_structures_not_returned_from_esi(
|
1339
|
+
existing_structures=self.structures.filter_skyhooks(),
|
1340
|
+
new_structures=structures,
|
1341
|
+
)
|
1342
|
+
|
1343
|
+
def _resolve_skyhook_planets(self):
|
1344
|
+
"""Add planets to all unresolved Skyhooks."""
|
1345
|
+
s: Structure
|
1346
|
+
for s in self.structures.filter_skyhooks().filter(
|
1347
|
+
eve_planet__isnull=True,
|
1348
|
+
position_x__isnull=False,
|
1349
|
+
position_y__isnull=False,
|
1350
|
+
position_z__isnull=False,
|
1351
|
+
):
|
1352
|
+
try:
|
1353
|
+
celestial = s.eve_solar_system.nearest_celestial(
|
1354
|
+
x=s.position_x,
|
1355
|
+
y=s.position_y,
|
1356
|
+
z=s.position_z,
|
1357
|
+
group_id=EveGroupId.PLANET,
|
1358
|
+
)
|
1359
|
+
except OSError:
|
1360
|
+
continue
|
1361
|
+
|
1362
|
+
if not celestial or not isinstance(celestial.eve_object, EvePlanet):
|
1363
|
+
continue
|
1364
|
+
|
1365
|
+
s.eve_planet = celestial.eve_object
|
1366
|
+
s.name = celestial.eve_type.name
|
1367
|
+
s.save()
|
1368
|
+
|
1309
1369
|
@staticmethod
|
1310
1370
|
def get_esi_scopes() -> List[str]:
|
1311
1371
|
"""Return all required ESI scopes."""
|
@@ -464,6 +464,11 @@ class Structure(models.Model): # pylint: disable = too-many-public-methods
|
|
464
464
|
"""Return True if this structure is a starbase, else False."""
|
465
465
|
return starbases.is_starbase(self.eve_type)
|
466
466
|
|
467
|
+
@property
|
468
|
+
def is_skyhook(self) -> bool:
|
469
|
+
"""Return True if this structure is a skyhook, else False."""
|
470
|
+
return self.eve_type_id == EveTypeId.ORBITAL_SKYHOOK
|
471
|
+
|
467
472
|
@cached_property
|
468
473
|
def is_upwell_structure(self) -> bool:
|
469
474
|
"""Return True if this structure is an upwell structure, else False."""
|
@@ -28,7 +28,7 @@
|
|
28
28
|
<ul id="public-tabs" class="nav nav-tabs" role="tablist">
|
29
29
|
|
30
30
|
<li role="presentation" class="active">
|
31
|
-
<a href="#pocos" aria-controls="
|
31
|
+
<a href="#pocos" aria-controls="orbitals" role="tab" data-toggle="tab">
|
32
32
|
{% translate "Customs Offices" %} <small>({{ pocos_count|default:"-" }})</small>
|
33
33
|
</a>
|
34
34
|
</li>
|
@@ -39,7 +39,7 @@
|
|
39
39
|
<div class="panel-body">
|
40
40
|
<div class="tab-content">
|
41
41
|
|
42
|
-
<div role="tabpanel" class="tab-pane active" id="
|
42
|
+
<div role="tabpanel" class="tab-pane active" id="orbitals">
|
43
43
|
{% include "structures/partials/public/poco_list.html" %}
|
44
44
|
</div>
|
45
45
|
|
@@ -48,8 +48,8 @@
|
|
48
48
|
</li>
|
49
49
|
|
50
50
|
<li role="presentation">
|
51
|
-
<a href="#
|
52
|
-
{% trans "
|
51
|
+
<a href="#orbitals" aria-controls="orbitals" role="tab" data-toggle="tab">
|
52
|
+
{% trans "Orbitals" %} <small>({{ orbitals_count|default:"-" }})</small>
|
53
53
|
</a>
|
54
54
|
</li>
|
55
55
|
|
@@ -77,7 +77,7 @@
|
|
77
77
|
{% include "structures/partials/structures/structure_list.html" %}
|
78
78
|
</div>
|
79
79
|
|
80
|
-
<div role="tabpanel" class="tab-pane" id="
|
80
|
+
<div role="tabpanel" class="tab-pane" id="orbitals">
|
81
81
|
{% include "structures/partials/structures/poco_list.html" %}
|
82
82
|
</div>
|
83
83
|
|
@@ -118,6 +118,11 @@ class TestNotificationType(TestCase):
|
|
118
118
|
"CorpWarInvalidatedMsg",
|
119
119
|
"CorpWarRetractedMsg",
|
120
120
|
"CorpWarSurrenderMsg",
|
121
|
+
"CorporationGoalClosed",
|
122
|
+
"CorporationGoalCompleted",
|
123
|
+
"CorporationGoalCreated",
|
124
|
+
"CorporationGoalNameChange",
|
125
|
+
"CorporationLeft",
|
121
126
|
"CustomsMsg",
|
122
127
|
"DeclareWar",
|
123
128
|
"DistrictAttacked",
|
@@ -172,6 +177,7 @@ class TestNotificationType(TestCase):
|
|
172
177
|
"KillRightUnavailable",
|
173
178
|
"KillRightUnavailableOpen",
|
174
179
|
"KillRightUsed",
|
180
|
+
"LPAutoRedeemed",
|
175
181
|
"LocateCharMsg",
|
176
182
|
"MadeWarMutual",
|
177
183
|
"MercOfferRetractedMsg",
|
@@ -205,7 +211,14 @@ class TestNotificationType(TestCase):
|
|
205
211
|
"ReimbursementMsg",
|
206
212
|
"ResearchMissionAvailableMsg",
|
207
213
|
"RetractsWar",
|
214
|
+
"SPAutoRedeemed",
|
208
215
|
"SeasonalChallengeCompleted",
|
216
|
+
"SkinSequencingCompleted",
|
217
|
+
"SkyhookDeployed",
|
218
|
+
"SkyhookDestroyed",
|
219
|
+
"SkyhookLostShields",
|
220
|
+
"SkyhookOnline",
|
221
|
+
"SkyhookUnderAttack",
|
209
222
|
"SovAllClaimAquiredMsg",
|
210
223
|
"SovAllClaimLostMsg",
|
211
224
|
"SovCommandNodeEventStarted",
|
@@ -237,7 +250,10 @@ class TestNotificationType(TestCase):
|
|
237
250
|
"StructureItemsMovedToSafety",
|
238
251
|
"StructureLostArmor",
|
239
252
|
"StructureLostShields",
|
253
|
+
"StructureLowReagentsAlert",
|
254
|
+
"StructureNoReagentsAlert",
|
240
255
|
"StructureOnline",
|
256
|
+
"StructurePaintPurchased",
|
241
257
|
"StructureServicesOffline",
|
242
258
|
"StructureUnanchoring",
|
243
259
|
"StructureUnderAttack",
|
@@ -4,6 +4,7 @@ from app_utils.django import app_labels
|
|
4
4
|
from app_utils.testing import NoSocketsTestCase
|
5
5
|
|
6
6
|
from structures.core import notification_timers
|
7
|
+
from structures.core.notification_types import NotificationType
|
7
8
|
from structures.models import Notification
|
8
9
|
from structures.tests.testdata.factories import (
|
9
10
|
GeneratedNotificationFactory,
|
@@ -107,7 +108,11 @@ if "timerboard" in app_labels():
|
|
107
108
|
@patch(MODULE_PATH + ".STRUCTURES_MOON_EXTRACTION_TIMERS_ENABLED", True)
|
108
109
|
def test_run_all(self):
|
109
110
|
for obj in Notification.objects.all():
|
110
|
-
|
111
|
+
timer_types = NotificationType.relevant_for_timerboard()
|
112
|
+
with self.subTest(notif_type=obj.notif_type):
|
113
|
+
is_timer = obj.notif_type in timer_types
|
114
|
+
is_added = obj.add_or_remove_timer()
|
115
|
+
self.assertEqual(is_timer, is_added)
|
111
116
|
|
112
117
|
@patch(MODULE_PATH + ".STRUCTURES_TIMERS_ARE_CORP_RESTRICTED", False)
|
113
118
|
def test_corp_restriction_1(self):
|
@@ -7,7 +7,7 @@ import yaml
|
|
7
7
|
|
8
8
|
from django.test import TestCase, override_settings
|
9
9
|
from django.utils.timezone import now
|
10
|
-
from eveuniverse.models import EveSolarSystem
|
10
|
+
from eveuniverse.models import EvePlanet, EveSolarSystem
|
11
11
|
|
12
12
|
from app_utils.django import app_labels
|
13
13
|
from app_utils.esi import EsiStatus
|
@@ -22,11 +22,13 @@ from structures.tests.testdata.factories import (
|
|
22
22
|
NotificationFactory,
|
23
23
|
OwnerFactory,
|
24
24
|
RawNotificationFactory,
|
25
|
+
SkyhookFactory,
|
25
26
|
StarbaseFactory,
|
26
27
|
StructureFactory,
|
27
28
|
WebhookFactory,
|
28
29
|
datetime_to_esi,
|
29
30
|
)
|
31
|
+
from structures.tests.testdata.helpers import NearestCelestial
|
30
32
|
from structures.tests.testdata.load_eveuniverse import load_eveuniverse
|
31
33
|
|
32
34
|
if "structuretimers" in app_labels():
|
@@ -613,3 +615,102 @@ class TestTasks(TestCase):
|
|
613
615
|
self.assertEqual(len(embeds), 1)
|
614
616
|
embed = embeds[0]
|
615
617
|
self.assertIn("Territorial Claim Unit", embed.title)
|
618
|
+
|
619
|
+
@patch(OWNERS_PATH + ".STRUCTURES_FEATURE_SKYHOOKS", True)
|
620
|
+
def test_should_fetch_new_skyhooks_from_esi(
|
621
|
+
self, mock_esi_2, mock_esi, mock_execute
|
622
|
+
):
|
623
|
+
# given
|
624
|
+
owner = OwnerFactory()
|
625
|
+
structure = SkyhookFactory(owner=owner)
|
626
|
+
eve_planet = EvePlanet.objects.get(id=40161469)
|
627
|
+
corporation_id = owner.corporation.corporation_id
|
628
|
+
endpoints = [
|
629
|
+
EsiEndpoint(
|
630
|
+
"Assets",
|
631
|
+
"get_corporations_corporation_id_assets",
|
632
|
+
"corporation_id",
|
633
|
+
needs_token=True,
|
634
|
+
data={
|
635
|
+
str(corporation_id): [
|
636
|
+
{
|
637
|
+
"is_singleton": True,
|
638
|
+
"item_id": structure.id,
|
639
|
+
"location_flag": "AutoFit",
|
640
|
+
"location_id": 30002537,
|
641
|
+
"location_type": "solar_system",
|
642
|
+
"quantity": 1,
|
643
|
+
"type_id": 81080,
|
644
|
+
},
|
645
|
+
]
|
646
|
+
},
|
647
|
+
),
|
648
|
+
EsiEndpoint(
|
649
|
+
"Assets",
|
650
|
+
"post_corporations_corporation_id_assets_names",
|
651
|
+
"corporation_id",
|
652
|
+
needs_token=True,
|
653
|
+
data={str(corporation_id): []},
|
654
|
+
),
|
655
|
+
EsiEndpoint(
|
656
|
+
"Assets",
|
657
|
+
"post_corporations_corporation_id_assets_locations",
|
658
|
+
"corporation_id",
|
659
|
+
needs_token=True,
|
660
|
+
data={
|
661
|
+
str(corporation_id): [
|
662
|
+
{"item_id": structure.id, "position": {"x": 1, "y": 2, "z": 3}}
|
663
|
+
]
|
664
|
+
},
|
665
|
+
),
|
666
|
+
EsiEndpoint(
|
667
|
+
"Corporation",
|
668
|
+
"get_corporations_corporation_id_starbases",
|
669
|
+
"corporation_id",
|
670
|
+
needs_token=True,
|
671
|
+
data={str(corporation_id): []},
|
672
|
+
),
|
673
|
+
EsiEndpoint(
|
674
|
+
"Corporation",
|
675
|
+
"get_corporations_corporation_id_structures",
|
676
|
+
"corporation_id",
|
677
|
+
needs_token=True,
|
678
|
+
data={str(corporation_id): []},
|
679
|
+
),
|
680
|
+
EsiEndpoint(
|
681
|
+
"Planetary_Interaction",
|
682
|
+
"get_corporations_corporation_id_customs_offices",
|
683
|
+
"corporation_id",
|
684
|
+
needs_token=True,
|
685
|
+
data={str(corporation_id): []},
|
686
|
+
),
|
687
|
+
EsiEndpoint(
|
688
|
+
"Sovereignty",
|
689
|
+
"get_sovereignty_map",
|
690
|
+
needs_token=False,
|
691
|
+
data=[],
|
692
|
+
),
|
693
|
+
EsiEndpoint(
|
694
|
+
"Universe",
|
695
|
+
"get_universe_structures_structure_id",
|
696
|
+
"structure_id",
|
697
|
+
needs_token=True,
|
698
|
+
data={},
|
699
|
+
),
|
700
|
+
]
|
701
|
+
mock_esi.client = mock_esi_2.client = EsiClientStub.create_from_endpoints(
|
702
|
+
endpoints
|
703
|
+
)
|
704
|
+
structure_id = structure.id
|
705
|
+
structure.delete()
|
706
|
+
# when
|
707
|
+
|
708
|
+
with patch(OWNERS_PATH + ".EveSolarSystem.nearest_celestial") as m:
|
709
|
+
m.return_value = NearestCelestial(
|
710
|
+
eve_object=eve_planet,
|
711
|
+
distance=35_000_000,
|
712
|
+
eve_type=eve_planet.eve_type,
|
713
|
+
)
|
714
|
+
tasks.update_all_structures.delay()
|
715
|
+
# then
|
716
|
+
self.assertTrue(owner.structures.filter(id=structure_id).exists())
|
@@ -46,7 +46,7 @@ class TestStructureListView(TestCase):
|
|
46
46
|
# then
|
47
47
|
self.assertEqual(response.status_code, 200)
|
48
48
|
self.assertEqual(response.context["structures_count"], 2)
|
49
|
-
self.assertEqual(response.context["
|
49
|
+
self.assertEqual(response.context["orbitals_count"], 1)
|
50
50
|
self.assertEqual(response.context["starbases_count"], 1)
|
51
51
|
self.assertEqual(response.context["jump_gates_count"], 1)
|
52
52
|
self.assertIn("data_export", response.context)
|
@@ -7,18 +7,20 @@ from pytz import utc
|
|
7
7
|
from django.test import override_settings
|
8
8
|
from django.utils.timezone import now
|
9
9
|
from esi.models import Token
|
10
|
+
from eveuniverse.models import EvePlanet
|
10
11
|
|
11
12
|
from app_utils.esi_testing import EsiClientStub, EsiEndpoint
|
12
13
|
from app_utils.testing import BravadoResponseStub, NoSocketsTestCase, queryset_pks
|
13
14
|
|
14
15
|
from structures.core.notification_types import NotificationType
|
15
|
-
from structures.models import Notification, StructureItem
|
16
|
+
from structures.models import Notification, Structure, StructureItem
|
16
17
|
from structures.tests.testdata.factories import (
|
17
18
|
EveCharacterFactory,
|
18
19
|
EveCorporationInfoFactory,
|
19
20
|
EveEntityCorporationFactory,
|
20
21
|
JumpFuelAlertConfigFactory,
|
21
22
|
OwnerFactory,
|
23
|
+
SkyhookFactory,
|
22
24
|
StarbaseFactory,
|
23
25
|
StructureFactory,
|
24
26
|
StructureItemFactory,
|
@@ -27,6 +29,7 @@ from structures.tests.testdata.factories import (
|
|
27
29
|
datetime_to_esi,
|
28
30
|
)
|
29
31
|
from structures.tests.testdata.helpers import (
|
32
|
+
NearestCelestial,
|
30
33
|
load_eve_entities,
|
31
34
|
load_notification_entities,
|
32
35
|
)
|
@@ -711,6 +714,137 @@ class TestOwnerUpdateAssetEsi(NoSocketsTestCase):
|
|
711
714
|
self.assertTrue(structure.items.filter(id=1300000003001).exists())
|
712
715
|
|
713
716
|
|
717
|
+
@patch(OWNERS_PATH + ".STRUCTURES_FEATURE_SKYHOOKS", True)
|
718
|
+
@patch(OWNERS_PATH + ".EveSolarSystem.nearest_celestial")
|
719
|
+
@patch(OWNERS_PATH + ".esi")
|
720
|
+
class TestOwnerUpdateSkyhooks(NoSocketsTestCase):
|
721
|
+
@classmethod
|
722
|
+
def setUpClass(cls):
|
723
|
+
super().setUpClass()
|
724
|
+
load_eveuniverse()
|
725
|
+
cls.corporation = EveCharacterFactory()
|
726
|
+
character = EveCharacterFactory(corporation=cls.corporation)
|
727
|
+
cls.user = UserMainDefaultOwnerFactory(main_character__character=character)
|
728
|
+
cls.planet = EvePlanet.objects.get(id=40161469)
|
729
|
+
endpoints = [
|
730
|
+
EsiEndpoint(
|
731
|
+
"Assets",
|
732
|
+
"get_corporations_corporation_id_assets",
|
733
|
+
"corporation_id",
|
734
|
+
needs_token=True,
|
735
|
+
data={
|
736
|
+
f"{cls.corporation.corporation_id}": [
|
737
|
+
{
|
738
|
+
"is_singleton": True,
|
739
|
+
"item_id": 1000000010001,
|
740
|
+
"location_flag": "AutoFit",
|
741
|
+
"location_id": 30002537,
|
742
|
+
"location_type": "solar_system",
|
743
|
+
"quantity": 1,
|
744
|
+
"type_id": 81080,
|
745
|
+
},
|
746
|
+
],
|
747
|
+
},
|
748
|
+
),
|
749
|
+
EsiEndpoint(
|
750
|
+
"Assets",
|
751
|
+
"post_corporations_corporation_id_assets_locations",
|
752
|
+
"corporation_id",
|
753
|
+
needs_token=True,
|
754
|
+
data={
|
755
|
+
f"{cls.corporation.corporation_id}": [
|
756
|
+
{"item_id": 1000000010001, "position": {"x": 1, "y": 2, "z": 3}}
|
757
|
+
]
|
758
|
+
},
|
759
|
+
),
|
760
|
+
]
|
761
|
+
cls.esi_client_stub = EsiClientStub.create_from_endpoints(endpoints)
|
762
|
+
|
763
|
+
def test_should_create_new_skyhooks_from_scratch(
|
764
|
+
self, mock_esi, mock_nearest_celestial
|
765
|
+
):
|
766
|
+
# given
|
767
|
+
mock_esi.client = self.esi_client_stub
|
768
|
+
mock_nearest_celestial.return_value = NearestCelestial(
|
769
|
+
eve_object=self.planet, distance=35_000_000, eve_type=self.planet.eve_type
|
770
|
+
)
|
771
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
772
|
+
# when
|
773
|
+
owner.update_asset_esi()
|
774
|
+
# then
|
775
|
+
owner.refresh_from_db()
|
776
|
+
self.assertEqual(owner.structures.count(), 1)
|
777
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
778
|
+
self.assertTrue(obj.is_skyhook)
|
779
|
+
self.assertEqual(obj.eve_planet, self.planet)
|
780
|
+
|
781
|
+
def test_should_remove_obsolete_skyhooks(self, mock_esi, mock_nearest_celestial):
|
782
|
+
# given
|
783
|
+
mock_esi.client = self.esi_client_stub
|
784
|
+
mock_nearest_celestial.return_value = NearestCelestial(
|
785
|
+
eve_object=self.planet, distance=35_000_000, eve_type=self.planet.eve_type
|
786
|
+
)
|
787
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
788
|
+
SkyhookFactory.create(owner=owner)
|
789
|
+
# when
|
790
|
+
owner.update_asset_esi()
|
791
|
+
# then
|
792
|
+
owner.refresh_from_db()
|
793
|
+
self.assertEqual(owner.structures.count(), 1)
|
794
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
795
|
+
self.assertTrue(obj.is_skyhook)
|
796
|
+
self.assertEqual(obj.eve_planet, self.planet)
|
797
|
+
|
798
|
+
def test_should_update_existing_skyhook(self, mock_esi, mock_nearest_celestial):
|
799
|
+
# given
|
800
|
+
mock_esi.client = self.esi_client_stub
|
801
|
+
mock_nearest_celestial.return_value = NearestCelestial(
|
802
|
+
eve_object=self.planet, distance=35_000_000, eve_type=self.planet.eve_type
|
803
|
+
)
|
804
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
805
|
+
SkyhookFactory.create(owner=owner, id=1000000010001, eve_planet_name="Thera I")
|
806
|
+
# when
|
807
|
+
owner.update_asset_esi()
|
808
|
+
# then
|
809
|
+
owner.refresh_from_db()
|
810
|
+
self.assertEqual(owner.structures.count(), 1)
|
811
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
812
|
+
self.assertTrue(obj.is_skyhook)
|
813
|
+
self.assertEqual(obj.eve_planet, self.planet)
|
814
|
+
|
815
|
+
def test_should_ignore_os_error_when_resolving_planet(
|
816
|
+
self, mock_esi, mock_nearest_celestial
|
817
|
+
):
|
818
|
+
# given
|
819
|
+
mock_esi.client = self.esi_client_stub
|
820
|
+
mock_nearest_celestial.side_effect = OSError
|
821
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
822
|
+
# when
|
823
|
+
owner.update_asset_esi()
|
824
|
+
# then
|
825
|
+
owner.refresh_from_db()
|
826
|
+
self.assertEqual(owner.structures.count(), 1)
|
827
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
828
|
+
self.assertTrue(obj.is_skyhook)
|
829
|
+
self.assertIsNone(obj.eve_planet)
|
830
|
+
|
831
|
+
def test_should_ignore_no_reply_when_resolving_planet(
|
832
|
+
self, mock_esi, mock_nearest_celestial
|
833
|
+
):
|
834
|
+
# given
|
835
|
+
mock_esi.client = self.esi_client_stub
|
836
|
+
mock_nearest_celestial.return_value = None
|
837
|
+
owner = OwnerFactory(user=self.user, assets_last_update_at=None)
|
838
|
+
# when
|
839
|
+
owner.update_asset_esi()
|
840
|
+
# then
|
841
|
+
owner.refresh_from_db()
|
842
|
+
self.assertEqual(owner.structures.count(), 1)
|
843
|
+
obj: Structure = owner.structures.get(pk=1000000010001)
|
844
|
+
self.assertTrue(obj.is_skyhook)
|
845
|
+
self.assertIsNone(obj.eve_planet)
|
846
|
+
|
847
|
+
|
714
848
|
class TestOwnerToken(NoSocketsTestCase):
|
715
849
|
def test_should_return_valid_token(self):
|
716
850
|
# given
|
@@ -29,6 +29,7 @@ from structures.tests.testdata.factories import (
|
|
29
29
|
OwnerFactory,
|
30
30
|
PocoDetailsFactory,
|
31
31
|
PocoFactory,
|
32
|
+
SkyhookFactory,
|
32
33
|
StarbaseFactory,
|
33
34
|
StructureFactory,
|
34
35
|
StructureItemFactory,
|
@@ -367,48 +368,6 @@ class TestStructure(NoSocketsTestCase):
|
|
367
368
|
# when/then
|
368
369
|
self.assertEqual(obj.location_name, "?")
|
369
370
|
|
370
|
-
def test_is_poco(self):
|
371
|
-
# given
|
372
|
-
structure = StructureFactory.build(owner=self.owner)
|
373
|
-
poco = PocoFactory.build(owner=self.owner)
|
374
|
-
starbase = StarbaseFactory.build(owner=self.owner)
|
375
|
-
# then
|
376
|
-
self.assertFalse(structure.is_poco)
|
377
|
-
self.assertTrue(poco.is_poco)
|
378
|
-
self.assertFalse(starbase.is_poco)
|
379
|
-
|
380
|
-
def test_is_starbase(self):
|
381
|
-
# given
|
382
|
-
structure = StructureFactory.build(owner=self.owner)
|
383
|
-
poco = PocoFactory.build(owner=self.owner)
|
384
|
-
starbase = StarbaseFactory.build(owner=self.owner)
|
385
|
-
# then
|
386
|
-
self.assertFalse(structure.is_starbase)
|
387
|
-
self.assertFalse(poco.is_starbase)
|
388
|
-
self.assertTrue(starbase.is_starbase)
|
389
|
-
|
390
|
-
def test_is_upwell_structure(self):
|
391
|
-
# given
|
392
|
-
structure = StructureFactory.build(owner=self.owner)
|
393
|
-
poco = PocoFactory.build(owner=self.owner)
|
394
|
-
starbase = StarbaseFactory.build(owner=self.owner)
|
395
|
-
# then
|
396
|
-
self.assertTrue(structure.is_upwell_structure)
|
397
|
-
self.assertFalse(poco.is_upwell_structure)
|
398
|
-
self.assertFalse(starbase.is_upwell_structure)
|
399
|
-
|
400
|
-
def test_is_jump_gate(self):
|
401
|
-
# given
|
402
|
-
normal_structure = StructureFactory.build(owner=self.owner)
|
403
|
-
poco = PocoFactory.build(owner=self.owner)
|
404
|
-
starbase = StarbaseFactory.build(owner=self.owner)
|
405
|
-
jump_gate = JumpGateFactory.build(owner=self.owner)
|
406
|
-
# then
|
407
|
-
self.assertFalse(normal_structure.is_jump_gate)
|
408
|
-
self.assertFalse(poco.is_jump_gate)
|
409
|
-
self.assertFalse(starbase.is_jump_gate)
|
410
|
-
self.assertTrue(jump_gate.is_jump_gate)
|
411
|
-
|
412
371
|
# TODO: activate
|
413
372
|
# def test_is_upwell_structure_data_error(self):
|
414
373
|
# # group without a category
|
@@ -490,6 +449,54 @@ class TestStructure(NoSocketsTestCase):
|
|
490
449
|
self.assertFalse(obj.owner_has_sov())
|
491
450
|
|
492
451
|
|
452
|
+
class TestStructureIsX(NoSocketsTestCase):
|
453
|
+
@classmethod
|
454
|
+
def setUpClass(cls):
|
455
|
+
super().setUpClass()
|
456
|
+
load_eveuniverse()
|
457
|
+
cls.owner = OwnerFactory()
|
458
|
+
cls.jump_gate = JumpGateFactory.build(owner=cls.owner)
|
459
|
+
cls.poco = PocoFactory.build(owner=cls.owner)
|
460
|
+
cls.skyhook = SkyhookFactory.build(owner=cls.owner)
|
461
|
+
cls.starbase = StarbaseFactory.build(owner=cls.owner)
|
462
|
+
cls.upwell_structure = StructureFactory.build(owner=cls.owner)
|
463
|
+
|
464
|
+
def test_is_jump_gate(self):
|
465
|
+
self.assertFalse(self.upwell_structure.is_jump_gate)
|
466
|
+
self.assertFalse(self.poco.is_jump_gate)
|
467
|
+
self.assertFalse(self.starbase.is_jump_gate)
|
468
|
+
self.assertTrue(self.jump_gate.is_jump_gate)
|
469
|
+
self.assertFalse(self.skyhook.is_jump_gate)
|
470
|
+
|
471
|
+
def test_is_poco(self):
|
472
|
+
self.assertFalse(self.upwell_structure.is_poco)
|
473
|
+
self.assertTrue(self.poco.is_poco)
|
474
|
+
self.assertFalse(self.starbase.is_poco)
|
475
|
+
self.assertFalse(self.jump_gate.is_poco)
|
476
|
+
self.assertFalse(self.skyhook.is_poco)
|
477
|
+
|
478
|
+
def test_is_starbase(self):
|
479
|
+
self.assertFalse(self.upwell_structure.is_starbase)
|
480
|
+
self.assertFalse(self.poco.is_starbase)
|
481
|
+
self.assertTrue(self.starbase.is_starbase)
|
482
|
+
self.assertFalse(self.jump_gate.is_starbase)
|
483
|
+
self.assertFalse(self.skyhook.is_starbase)
|
484
|
+
|
485
|
+
def test_is_skyhook(self):
|
486
|
+
self.assertFalse(self.upwell_structure.is_skyhook)
|
487
|
+
self.assertFalse(self.poco.is_skyhook)
|
488
|
+
self.assertFalse(self.starbase.is_skyhook)
|
489
|
+
self.assertFalse(self.jump_gate.is_skyhook)
|
490
|
+
self.assertTrue(self.skyhook.is_skyhook)
|
491
|
+
|
492
|
+
def test_is_upwell_structure(self):
|
493
|
+
self.assertTrue(self.upwell_structure.is_upwell_structure)
|
494
|
+
self.assertFalse(self.poco.is_upwell_structure)
|
495
|
+
self.assertFalse(self.starbase.is_upwell_structure)
|
496
|
+
self.assertTrue(self.jump_gate.is_upwell_structure)
|
497
|
+
self.assertFalse(self.skyhook.is_upwell_structure)
|
498
|
+
|
499
|
+
|
493
500
|
class TestStructureFuel(NoSocketsTestCase):
|
494
501
|
@classmethod
|
495
502
|
def setUpClass(cls):
|