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.
Files changed (37) hide show
  1. {aa_structures-2.12.0.dist-info → aa_structures-2.14.0.dist-info}/METADATA +1 -1
  2. {aa_structures-2.12.0.dist-info → aa_structures-2.14.0.dist-info}/RECORD +37 -34
  3. structures/__init__.py +1 -1
  4. structures/admin.py +1 -1
  5. structures/app_settings.py +4 -0
  6. structures/constants.py +1 -0
  7. structures/core/notification_embeds/main.py +58 -31
  8. structures/core/notification_embeds/orbital_embeds.py +1 -1
  9. structures/core/notification_embeds/skyhook_embeds.py +89 -0
  10. structures/core/notification_embeds/structures_embeds.py +23 -12
  11. structures/core/notification_embeds/tower_embeds.py +1 -1
  12. structures/core/notification_timers.py +53 -6
  13. structures/core/notification_types.py +58 -36
  14. structures/managers.py +22 -8
  15. structures/migrations/0007_add_notificationtypes_skyhook_metenox.py +149 -0
  16. structures/migrations/0008_add_notificationtypes_skyhook_metenox.py +149 -0
  17. structures/models/owners.py +68 -8
  18. structures/models/structures_1.py +5 -0
  19. structures/templates/structures/public.html +2 -2
  20. structures/templates/structures/structures.html +3 -3
  21. structures/tests/core/test_notification_types.py +16 -0
  22. structures/tests/core/{test_notifications_timerboard.py → test_notifications_timers.py} +6 -1
  23. structures/tests/integration/test_tasks.py +102 -1
  24. structures/tests/integration/test_views.py +1 -1
  25. structures/tests/models/test_owners_5.py +135 -1
  26. structures/tests/models/test_structures.py +49 -42
  27. structures/tests/test_managers_1.py +11 -1
  28. structures/tests/testdata/create_eveuniverse.py +6 -1
  29. structures/tests/testdata/entities.json +71 -1
  30. structures/tests/testdata/eveuniverse.json +6306 -5145
  31. structures/tests/testdata/factories.py +21 -0
  32. structures/tests/testdata/generate_notifications.py +142 -157
  33. structures/tests/testdata/helpers.py +6 -0
  34. structures/tests/views/test_structures.py +12 -4
  35. structures/views/structures.py +6 -6
  36. {aa_structures-2.12.0.dist-info → aa_structures-2.14.0.dist-info}/LICENSE +0 -0
  37. {aa_structures-2.12.0.dist-info → aa_structures-2.14.0.dist-info}/WHEEL +0 -0
@@ -476,6 +476,27 @@ class PocoDetailsFactory(
476
476
  standing_level = PocoDetails.StandingLevel.BAD
477
477
 
478
478
 
479
+ class SkyhookFactory(StructureFactory):
480
+ class Params:
481
+ eve_planet_name = "Amamake V"
482
+
483
+ has_fitting = None
484
+ has_core = None
485
+ state = Structure.State.NA
486
+
487
+ @factory.lazy_attribute
488
+ def eve_planet(self):
489
+ return EvePlanet.objects.get(name=self.eve_planet_name)
490
+
491
+ @factory.lazy_attribute
492
+ def eve_solar_system(self):
493
+ return self.eve_planet.eve_solar_system
494
+
495
+ @factory.lazy_attribute
496
+ def eve_type(self):
497
+ return EveType.objects.get(id=EveTypeId.ORBITAL_SKYHOOK)
498
+
499
+
479
500
  class JumpGateFactory(StructureFactory):
480
501
  @factory.lazy_attribute
481
502
  def eve_type(self):
@@ -3,177 +3,162 @@
3
3
  this scripts create a test owner and adds test notifications to it
4
4
  """
5
5
 
6
- import inspect
6
+ import datetime as dt
7
7
  import json
8
- import os
9
- import sys
10
- from datetime import timedelta
11
-
12
- currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
13
- myauth_dir = (
14
- os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(currentdir))))
15
- + "/myauth"
16
- )
17
- sys.path.insert(0, myauth_dir)
18
-
19
-
20
- import django
21
- from django.apps import apps
22
- from django.db import transaction
23
- from django.utils.timezone import now
24
-
25
- # init and setup django project
26
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myauth.settings.local")
27
- django.setup()
28
-
29
- if not apps.is_installed("structures"):
30
- raise RuntimeError("The app structures is not installed")
31
-
32
- from esi.clients import esi_client_factory
33
- from eveuniverse.models import EveEntity
34
-
35
- from allianceauth.eveonline.models import EveCorporationInfo
36
-
37
- from structures.models import Notification, Owner, Structure, Webhook
38
-
39
- # corporation / structure the notifications will be added to
40
- CORPORATION_ID = 98587692 # RABIS
41
-
42
- print(
43
- "load_test_notifications - "
44
- "script loads test notification into the local database "
45
- )
46
-
47
- print("Connecting to ESI ...")
48
- client = esi_client_factory()
49
-
50
- print("Creating base data ...")
51
- try:
52
- corporation = EveCorporationInfo.objects.get(corporation_id=CORPORATION_ID)
53
- except EveCorporationInfo.DoesNotExist:
54
- corporation = EveCorporationInfo.objects.create_corporation(CORPORATION_ID)
55
-
56
- owner, created = Owner.objects.get_or_create(
57
- corporation=corporation, defaults={"is_active": False}
58
- )
59
- if created and not owner.webhooks.exists():
60
- webhook = Webhook.objects.filter(is_active=True, is_default=True).first()
61
- if webhook:
62
- owner.webhooks.add(webhook)
63
-
64
- structure = {
65
- "fuel_expires": None,
66
- "name": "Test Structure Alpha",
67
- "next_reinforce_apply": None,
68
- "next_reinforce_hour": None,
69
- "position": {"x": 55028384780.0, "y": 7310316270.0, "z": -163686684205.0},
70
- "profile_id": 101853,
71
- "reinforce_hour": 18,
72
- "services": [
73
- {
74
- "name": "Clone Bay",
75
- "name_de": "Clone Bay_de",
76
- "name_ko": "Clone Bay_ko",
77
- "state": "online",
78
- },
79
- {
80
- "name": "Market Hub",
81
- "name_de": "Market Hub_de",
82
- "name_ko": "Market Hub_ko",
83
- "state": "offline",
84
- },
85
- ],
86
- "state": "shield_vulnerable",
87
- "state_timer_end": None,
88
- "state_timer_start": None,
89
- "structure_id": 1999999999999,
90
- "system_id": 30002537,
91
- "type_id": 35832,
92
- "unanchors_at": None,
93
- }
94
- structure, _ = Structure.objects.update_or_create_from_dict(structure, owner)
95
-
96
- with open(file=currentdir + "/entities.json", mode="r", encoding="utf-8") as fp:
97
- data = json.load(fp)
98
-
99
- notifications = data["Notification"]
100
- for notification in notifications:
101
- if notification["sender_id"] == 2901:
102
- notification["sender_id"] = 1000137 # DED
103
- if notification["sender_id"] == 2902:
104
- notification["sender_id"] = 1000125 # Concord
105
- elif notification["sender_id"] == 1011:
106
- notification["sender_id"] = 3004029
107
- elif notification["sender_id"] == 2022:
108
- notification["sender_id"] = 1000127 # Guristas
109
- elif notification["sender_id"] == 3001:
110
- notification["sender_id"] = 99010298
111
- notification["text"] = notification["text"].replace(
112
- "1000000000001", str(structure.id)
113
- )
114
- notification["text"] = notification["text"].replace(
115
- "35835", str(structure.eve_type_id)
116
- )
117
- notification["text"] = notification["text"].replace(
118
- "35835", str(structure.eve_type_id)
8
+ from pathlib import Path
9
+
10
+ from app_utils.scripts import start_django
11
+
12
+ start_django()
13
+
14
+
15
+ def main():
16
+
17
+ from django.utils.timezone import now
18
+ from esi.clients import esi_client_factory
19
+ from eveuniverse.models import EveEntity
20
+
21
+ from allianceauth.eveonline.models import EveCorporationInfo
22
+
23
+ from structures.core.notification_types import NotificationType
24
+ from structures.models import Notification, Owner, Structure, Webhook
25
+
26
+ # corporation / structure the notifications will be added to
27
+ CORPORATION_ID = 1000127 # Guristas
28
+
29
+ print(
30
+ "load_test_notifications - "
31
+ "script loads test notification into the local database "
119
32
  )
120
- notification["text"] = notification["text"].replace(
121
- "30002537", str(structure.eve_solar_system_id)
33
+
34
+ print("Connecting to ESI ...")
35
+ client = esi_client_factory()
36
+
37
+ print("Creating base data ...")
38
+ try:
39
+ corporation = EveCorporationInfo.objects.get(corporation_id=CORPORATION_ID)
40
+ except EveCorporationInfo.DoesNotExist:
41
+ corporation = EveCorporationInfo.objects.create_corporation(CORPORATION_ID)
42
+
43
+ owner, created = Owner.objects.get_or_create(
44
+ corporation=corporation, defaults={"is_active": False}
122
45
  )
123
- notification["text"] = notification["text"].replace("1001", "3004037")
124
- notification["text"] = notification["text"].replace("1002", "3019491")
125
- notification["text"] = notification["text"].replace("1011", "3004029")
126
- notification["text"] = notification["text"].replace("2001", "98394960")
127
- notification["text"] = notification["text"].replace(
128
- "2002", "1000134"
129
- ) # Blood Raiders
130
- notification["text"] = notification["text"].replace("3001", "99005502")
131
- notification["text"] = notification["text"].replace("3002", "99009333")
132
- notification["text"] = notification["text"].replace("3011", "1354830081")
133
-
134
- with transaction.atomic():
135
- timestamp_start = now() - timedelta(hours=2)
136
- for notification in notifications:
137
- if notification["sender_type"] != "other":
138
- continue
139
-
140
- sender, _ = EveEntity.objects.get_or_create_esi(id=notification["sender_id"])
141
- text = notification["text"] if "text" in notification else None
142
- is_read = notification["is_read"] if "is_read" in notification else None
143
- timestamp_start = timestamp_start + timedelta(minutes=5)
144
- obj = Notification.objects.update_or_create(
145
- notification_id=notification["notification_id"],
46
+ if created and not owner.webhooks.exists():
47
+ webhook = Webhook.objects.filter(is_active=True, is_default=True).first()
48
+ if webhook:
49
+ owner.webhooks.add(webhook)
50
+
51
+ structure = {
52
+ "fuel_expires": None,
53
+ "name": "Test Structure Alpha",
54
+ "next_reinforce_apply": None,
55
+ "next_reinforce_hour": None,
56
+ "position": {"x": 55028384780.0, "y": 7310316270.0, "z": -163686684205.0},
57
+ "profile_id": 101853,
58
+ "reinforce_hour": 18,
59
+ "services": [
60
+ {
61
+ "name": "Clone Bay",
62
+ "name_de": "Clone Bay_de",
63
+ "name_ko": "Clone Bay_ko",
64
+ "state": "online",
65
+ },
66
+ {
67
+ "name": "Market Hub",
68
+ "name_de": "Market Hub_de",
69
+ "name_ko": "Market Hub_ko",
70
+ "state": "offline",
71
+ },
72
+ ],
73
+ "state": "shield_vulnerable",
74
+ "state_timer_end": None,
75
+ "state_timer_start": None,
76
+ "structure_id": 1999999999999,
77
+ "system_id": 30002537,
78
+ "type_id": 35832,
79
+ "unanchors_at": None,
80
+ }
81
+ structure, _ = Structure.objects.update_or_create_from_dict(structure, owner)
82
+
83
+ p = Path(__file__).parent / "/entities.json"
84
+ with p.open(mode="r", encoding="utf-8") as fp:
85
+ data = json.load(fp)
86
+
87
+ notifications = data["Notification"]
88
+ for n in notifications:
89
+ if n["sender_id"] == 2901:
90
+ n["sender_id"] = 1000137 # DED
91
+ if n["sender_id"] == 2902:
92
+ n["sender_id"] = 1000125 # Concord
93
+ elif n["sender_id"] == 1011:
94
+ n["sender_id"] = 3004029
95
+ elif n["sender_id"] == 2022:
96
+ n["sender_id"] = 1000127 # Guristas
97
+ elif n["sender_id"] == 3001:
98
+ n["sender_id"] = 99010298
99
+ n["text"] = n["text"].replace("1000000000001", str(structure.id))
100
+ n["text"] = n["text"].replace("35835", str(structure.eve_type_id))
101
+ n["text"] = n["text"].replace("35835", str(structure.eve_type_id))
102
+ n["text"] = n["text"].replace("30002537", str(structure.eve_solar_system_id))
103
+ n["text"] = n["text"].replace("1001", "3004037")
104
+ n["text"] = n["text"].replace("1002", "3019491")
105
+ n["text"] = n["text"].replace("1011", "3004029")
106
+ n["text"] = n["text"].replace("2001", "98394960")
107
+ n["text"] = n["text"].replace("2002", "1000134") # Blood Raiders
108
+ n["text"] = n["text"].replace("3001", "99005502")
109
+ n["text"] = n["text"].replace("3002", "99009333")
110
+ n["text"] = n["text"].replace("3011", "1354830081")
111
+
112
+ timestamp_start = now() - dt.timedelta(hours=2)
113
+
114
+ for n in notifications:
115
+ notif_type = n["type"]
116
+ if notif_type not in NotificationType.values:
117
+ print(f"Skipping unsupported: {notif_id} {notif_type}")
118
+
119
+ notif_id = n["notification_id"]
120
+ sender, _ = EveEntity.objects.get_or_create_esi(id=n["sender_id"])
121
+ text = n["text"] if "text" in n else None
122
+ is_read = n["is_read"] if "is_read" in n else None
123
+ timestamp_start = timestamp_start + dt.timedelta(minutes=5)
124
+ obj, created = Notification.objects.update_or_create(
125
+ notification_id=notif_id,
146
126
  owner=owner,
147
127
  defaults={
148
128
  "sender": sender,
149
129
  "timestamp": timestamp_start,
150
- "notif_type": notification["type"],
130
+ "notif_type": notif_type,
151
131
  "text": text,
152
132
  "is_read": is_read,
153
133
  "last_updated": now(),
154
134
  "is_sent": False,
155
135
  },
156
136
  )
137
+ if created:
138
+ print(f"Created: {notif_id} {notif_type}")
157
139
 
158
- print("DONE")
140
+ print("DONE")
159
141
 
142
+ """
143
+ for notification in notifications:
144
+ dt = datetime.datetime.utcfromtimestamp(notification['timestamp'])
145
+ dt = pytz.utc.localize(dt)
146
+ notification['timestamp'] = dt.isoformat()
147
+
148
+ with open(
149
+ file=currentdir + '/td_notifications_2.json',
150
+ mode='w',
151
+ encoding='utf-8'
152
+ ) as f:
153
+ json.dump(
154
+ notifications,
155
+ f,
156
+ sort_keys=True,
157
+ indent=4
158
+ )
160
159
 
161
- """
162
- for notification in notifications:
163
- dt = datetime.datetime.utcfromtimestamp(notification['timestamp'])
164
- dt = pytz.utc.localize(dt)
165
- notification['timestamp'] = dt.isoformat()
166
-
167
- with open(
168
- file=currentdir + '/td_notifications_2.json',
169
- mode='w',
170
- encoding='utf-8'
171
- ) as f:
172
- json.dump(
173
- notifications,
174
- f,
175
- sort_keys=True,
176
- indent=4
177
- )
160
+ """
178
161
 
179
- """
162
+
163
+ if __name__ == "__main__":
164
+ main()
@@ -4,6 +4,7 @@ import datetime as dt
4
4
  import json
5
5
  import logging
6
6
  import unicodedata
7
+ from collections import namedtuple
7
8
  from pathlib import Path
8
9
  from random import randrange
9
10
 
@@ -192,3 +193,8 @@ def datetime_to_ldap(my_dt: dt.datetime) -> int:
192
193
  ((my_dt - dt.datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds())
193
194
  + 11644473600
194
195
  ) * 10000000
196
+
197
+
198
+ NearestCelestial = namedtuple(
199
+ "NearestCelestial", ["eve_type", "eve_object", "distance"]
200
+ )
@@ -19,6 +19,7 @@ from structures.tests.testdata.factories import (
19
19
  JumpGateFactory,
20
20
  OwnerFactory,
21
21
  PocoFactory,
22
+ SkyhookFactory,
22
23
  StarbaseFactory,
23
24
  StructureFactory,
24
25
  StructureTagFactory,
@@ -148,6 +149,7 @@ class TestStructureListDataFilterVariant(TestCase):
148
149
  owner = OwnerFactory(user=cls.user)
149
150
  cls.structure = StructureFactory(owner=owner)
150
151
  cls.poco = PocoFactory(owner=owner)
152
+ cls.skyhook = SkyhookFactory(owner=owner)
151
153
  cls.starbase = StarbaseFactory(owner=owner)
152
154
  cls.jump_gate = JumpGateFactory(owner=owner)
153
155
 
@@ -163,17 +165,17 @@ class TestStructureListDataFilterVariant(TestCase):
163
165
  structure_ids = set(data.keys())
164
166
  self.assertSetEqual(structure_ids, {self.structure.id, self.jump_gate.id})
165
167
 
166
- def test_should_return_pocos_only(self):
168
+ def test_should_return_orbitals_only(self):
167
169
  # given
168
170
  request = self.factory.get("/")
169
171
  request.user = self.user
170
172
  # when
171
- response = structures.structure_list_data(request, "pocos")
173
+ response = structures.structure_list_data(request, "orbitals")
172
174
  # then
173
175
  self.assertEqual(response.status_code, 200)
174
176
  data = json_response_to_dict(response)
175
177
  structure_ids = set(data.keys())
176
- self.assertSetEqual(structure_ids, {self.poco.id})
178
+ self.assertSetEqual(structure_ids, {self.poco.id, self.skyhook.id})
177
179
 
178
180
  def test_should_return_starbases_only(self):
179
181
  # given
@@ -211,7 +213,13 @@ class TestStructureListDataFilterVariant(TestCase):
211
213
  structure_ids = set(data.keys())
212
214
  self.assertSetEqual(
213
215
  structure_ids,
214
- {self.structure.id, self.poco.id, self.starbase.id, self.jump_gate.id},
216
+ {
217
+ self.structure.id,
218
+ self.poco.id,
219
+ self.starbase.id,
220
+ self.jump_gate.id,
221
+ self.skyhook.id,
222
+ },
215
223
  )
216
224
 
217
225
  def test_should_raise_error_when_invalid_variant_requested(self):
@@ -58,7 +58,7 @@ class StructureSelection(str, Enum):
58
58
  """A pre-defined selection to filter structures data."""
59
59
 
60
60
  STRUCTURES = "structures"
61
- POCOS = "pocos"
61
+ ORBITALS = "orbitals"
62
62
  STARBASES = "starbases"
63
63
  JUMP_GATES = "jump_gates"
64
64
  ALL = "all"
@@ -118,8 +118,8 @@ def structure_list(request: HttpRequest):
118
118
  structures_count = _structures_query(
119
119
  request.user, StructureSelection.STRUCTURES, tags
120
120
  ).count()
121
- pocos_count = _structures_query(
122
- request.user, StructureSelection.POCOS, tags
121
+ orbitals_count = _structures_query(
122
+ request.user, StructureSelection.ORBITALS, tags
123
123
  ).count()
124
124
  starbases_count = _structures_query(
125
125
  request.user, StructureSelection.STARBASES, tags
@@ -136,7 +136,7 @@ def structure_list(request: HttpRequest):
136
136
  "tags_exist": StructureTag.objects.exists(),
137
137
  "show_jump_gates_tab": STRUCTURES_SHOW_JUMP_GATES,
138
138
  "structures_count": structures_count,
139
- "pocos_count": pocos_count,
139
+ "orbitals_count": orbitals_count,
140
140
  "starbases_count": starbases_count,
141
141
  "jump_gates_count": jump_gates_count,
142
142
  "data_export": data_export,
@@ -146,7 +146,7 @@ def structure_list(request: HttpRequest):
146
146
 
147
147
  def _construct_data_export(request, tags):
148
148
  structures_ajax_url = _construct_ajax_url(StructureSelection.STRUCTURES, tags)
149
- pocos_ajax_url = _construct_ajax_url(StructureSelection.POCOS, tags)
149
+ pocos_ajax_url = _construct_ajax_url(StructureSelection.ORBITALS, tags)
150
150
  starbases_ajax_url = _construct_ajax_url(StructureSelection.STARBASES, tags)
151
151
  jump_gates_ajax_url = _construct_ajax_url(StructureSelection.JUMP_GATES, tags)
152
152
 
@@ -213,7 +213,7 @@ def _structures_query(
213
213
  eve_type__eve_group__eve_category_id=EveCategoryId.STRUCTURE
214
214
  )
215
215
 
216
- elif selection == StructureSelection.POCOS:
216
+ elif selection == StructureSelection.ORBITALS:
217
217
  structures_qs = structures_qs.filter(
218
218
  eve_type__eve_group__eve_category_id=EveCategoryId.ORBITAL
219
219
  ).annotate_has_poco_details()