aa-fleetfinder 0.1.0a12__py3-none-any.whl → 3.0.0b2__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_fleetfinder-3.0.0b2.dist-info/METADATA +820 -0
- aa_fleetfinder-3.0.0b2.dist-info/RECORD +86 -0
- {aa_fleetfinder-0.1.0a12.dist-info → aa_fleetfinder-3.0.0b2.dist-info}/WHEEL +1 -2
- fleetfinder/__init__.py +19 -0
- fleetfinder/app_settings.py +20 -0
- fleetfinder/apps.py +22 -0
- fleetfinder/auth_hooks.py +58 -0
- fleetfinder/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/cs_CZ/LC_MESSAGES/django.po +296 -0
- fleetfinder/locale/de/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/de/LC_MESSAGES/django.po +306 -0
- fleetfinder/locale/django.pot +303 -0
- fleetfinder/locale/es/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/es/LC_MESSAGES/django.po +319 -0
- fleetfinder/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/fr_FR/LC_MESSAGES/django.po +314 -0
- fleetfinder/locale/it_IT/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/it_IT/LC_MESSAGES/django.po +294 -0
- fleetfinder/locale/ja/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/ja/LC_MESSAGES/django.po +303 -0
- fleetfinder/locale/ko_KR/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/ko_KR/LC_MESSAGES/django.po +337 -0
- fleetfinder/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/nl_NL/LC_MESSAGES/django.po +294 -0
- fleetfinder/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/pl_PL/LC_MESSAGES/django.po +298 -0
- fleetfinder/locale/ru/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/ru/LC_MESSAGES/django.po +319 -0
- fleetfinder/locale/sk/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/sk/LC_MESSAGES/django.po +294 -0
- fleetfinder/locale/uk/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/uk/LC_MESSAGES/django.po +310 -0
- fleetfinder/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- fleetfinder/locale/zh_Hans/LC_MESSAGES/django.po +319 -0
- fleetfinder/migrations/0001_initial.py +72 -0
- fleetfinder/migrations/0002_esi_error_handling_and_verbose_names.py +92 -0
- fleetfinder/migrations/0003_alter_fleet_fleet_commander_alter_fleet_groups_and_more.py +46 -0
- fleetfinder/migrations/__init__.py +0 -0
- fleetfinder/models.py +95 -0
- fleetfinder/providers.py +32 -0
- fleetfinder/static/fleetfinder/css/fleetfinder.css +31 -0
- fleetfinder/static/fleetfinder/css/fleetfinder.min.css +2 -0
- fleetfinder/static/fleetfinder/css/fleetfinder.min.css.map +1 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.js +86 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.min.js +2 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-dashboard.min.js.map +1 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.js +154 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.min.js +2 -0
- fleetfinder/static/fleetfinder/js/fleetfinder-fleet-details.min.js.map +1 -0
- fleetfinder/static/fleetfinder/js/fleetfinder.js +23 -0
- fleetfinder/static/fleetfinder/js/fleetfinder.min.js +2 -0
- fleetfinder/static/fleetfinder/js/fleetfinder.min.js.map +1 -0
- fleetfinder/static/fleetfinder/libs/slim-select/2.6.0/css/slimselect.css +477 -0
- fleetfinder/static/fleetfinder/libs/slim-select/2.6.0/css/slimselect.min.css +2 -0
- fleetfinder/static/fleetfinder/libs/slim-select/2.6.0/css/slimselect.min.css.map +1 -0
- fleetfinder/static/fleetfinder/libs/slim-select/2.6.0/js/slimselect.min.js +1 -0
- fleetfinder/tasks.py +554 -0
- fleetfinder/templates/fleetfinder/base.html +43 -0
- fleetfinder/templates/fleetfinder/bundles/css/fleetfinder-css.html +3 -0
- fleetfinder/templates/fleetfinder/bundles/css/slim-select-css.html +3 -0
- fleetfinder/templates/fleetfinder/bundles/js/fleetfinder-js.html +9 -0
- fleetfinder/templates/fleetfinder/bundles/js/slim-select-js.html +3 -0
- fleetfinder/templates/fleetfinder/create-fleet.html +42 -0
- fleetfinder/templates/fleetfinder/dashboard.html +53 -0
- fleetfinder/templates/fleetfinder/edit-fleet.html +42 -0
- fleetfinder/templates/fleetfinder/fleet-details.html +102 -0
- fleetfinder/templates/fleetfinder/join-fleet.html +68 -0
- fleetfinder/templates/fleetfinder/modals/kick-fleet-member.html +46 -0
- fleetfinder/templates/fleetfinder/partials/body/form-fleet-details.html +50 -0
- fleetfinder/templates/fleetfinder/partials/footer/app-translation-footer.html +11 -0
- fleetfinder/templates/fleetfinder/partials/header/header-nav-left.html +9 -0
- fleetfinder/templates/fleetfinder/partials/header/header-nav-right.html +18 -0
- fleetfinder/templatetags/__init__.py +3 -0
- fleetfinder/templatetags/fleetfinder.py +33 -0
- fleetfinder/tests/__init__.py +41 -0
- fleetfinder/tests/test_access.py +74 -0
- fleetfinder/tests/test_auth_hooks.py +79 -0
- fleetfinder/tests/test_settings.py +38 -0
- fleetfinder/tests/test_tasks.py +1116 -0
- fleetfinder/tests/test_templatetags.py +65 -0
- fleetfinder/tests/test_user_agent.py +88 -0
- fleetfinder/tests/test_views.py +1184 -0
- fleetfinder/tests/utils.py +58 -0
- fleetfinder/urls.py +45 -0
- fleetfinder/views.py +631 -0
- aa_fleetfinder-0.1.0a12.dist-info/METADATA +0 -50
- aa_fleetfinder-0.1.0a12.dist-info/RECORD +0 -5
- aa_fleetfinder-0.1.0a12.dist-info/top_level.txt +0 -1
- {aa_fleetfinder-0.1.0a12.dist-info → aa_fleetfinder-3.0.0b2.dist-info/licenses}/LICENSE +0 -0
fleetfinder/views.py
ADDED
|
@@ -0,0 +1,631 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Views
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# Standard Library
|
|
6
|
+
import json
|
|
7
|
+
from http import HTTPStatus
|
|
8
|
+
|
|
9
|
+
# Django
|
|
10
|
+
from django.contrib import messages
|
|
11
|
+
from django.contrib.auth.decorators import login_required, permission_required
|
|
12
|
+
from django.core.handlers.wsgi import WSGIRequest
|
|
13
|
+
from django.db.models import Q
|
|
14
|
+
from django.http import JsonResponse
|
|
15
|
+
from django.shortcuts import redirect, render
|
|
16
|
+
from django.urls import reverse
|
|
17
|
+
from django.utils import timezone
|
|
18
|
+
from django.utils.functional import Promise
|
|
19
|
+
from django.utils.safestring import mark_safe
|
|
20
|
+
from django.utils.translation import gettext_lazy as _
|
|
21
|
+
|
|
22
|
+
# Alliance Auth
|
|
23
|
+
from allianceauth.eveonline.evelinks.eveimageserver import character_portrait_url
|
|
24
|
+
from allianceauth.eveonline.models import EveCharacter
|
|
25
|
+
from allianceauth.framework.api.user import get_all_characters_from_user
|
|
26
|
+
from allianceauth.groupmanagement.models import AuthGroup
|
|
27
|
+
from allianceauth.services.hooks import get_extension_logger
|
|
28
|
+
from esi.decorators import token_required
|
|
29
|
+
from esi.exceptions import HTTPClientError
|
|
30
|
+
from esi.models import Token
|
|
31
|
+
from esi.openapi_clients import EsiOperation
|
|
32
|
+
|
|
33
|
+
# Alliance Auth (External Libs)
|
|
34
|
+
from app_utils.logging import LoggerAddTag
|
|
35
|
+
|
|
36
|
+
# AA Fleet Finder
|
|
37
|
+
from fleetfinder import __title__
|
|
38
|
+
from fleetfinder.models import Fleet
|
|
39
|
+
from fleetfinder.providers import esi
|
|
40
|
+
from fleetfinder.tasks import get_fleet_composition, send_fleet_invitation
|
|
41
|
+
|
|
42
|
+
logger = LoggerAddTag(my_logger=get_extension_logger(name=__name__), prefix=__title__)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@login_required()
|
|
46
|
+
@permission_required(perm="fleetfinder.access_fleetfinder")
|
|
47
|
+
def _get_and_validate_fleet(token: Token, character_id: int) -> EsiOperation:
|
|
48
|
+
"""
|
|
49
|
+
Get fleet information and validate fleet commander permissions
|
|
50
|
+
|
|
51
|
+
:param token: Token object containing the access token
|
|
52
|
+
:type token: Token
|
|
53
|
+
:param character_id: The character ID of the fleet commander
|
|
54
|
+
:type character_id: int
|
|
55
|
+
:return: Fleet information from ESI
|
|
56
|
+
:rtype: GetCharactersCharacterIdFleetOperation
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
fleet_result = esi.client.Fleets.GetCharactersCharacterIdFleet(
|
|
61
|
+
character_id=token.character_id,
|
|
62
|
+
token=token,
|
|
63
|
+
).result(force_refresh=True)
|
|
64
|
+
except HTTPClientError as ex:
|
|
65
|
+
logger.debug(f"ESI fleet cannot be retrieved: {str(ex)}", exc_info=True)
|
|
66
|
+
|
|
67
|
+
raise ValueError("Fleet not found") from ex
|
|
68
|
+
except Exception as ex:
|
|
69
|
+
logger.debug(f"Error retrieving fleet from ESI: {str(ex)}", exc_info=True)
|
|
70
|
+
|
|
71
|
+
raise RuntimeError(f"Error retrieving fleet from ESI: {str(ex)}") from ex
|
|
72
|
+
|
|
73
|
+
logger.debug(f"Fleet result: {fleet_result}")
|
|
74
|
+
|
|
75
|
+
fleet_id = fleet_result.fleet_id
|
|
76
|
+
fleet_boss_id = fleet_result.fleet_boss_id
|
|
77
|
+
|
|
78
|
+
if not fleet_id:
|
|
79
|
+
fleet_commander = EveCharacter.objects.get(character_id=token.character_id)
|
|
80
|
+
|
|
81
|
+
raise ValueError(f"No fleet found for {fleet_commander.character_name}")
|
|
82
|
+
|
|
83
|
+
if fleet_boss_id != character_id:
|
|
84
|
+
fleet_commander = EveCharacter.objects.get(character_id=token.character_id)
|
|
85
|
+
|
|
86
|
+
raise ValueError(f"{fleet_commander.character_name} is not the fleet boss")
|
|
87
|
+
|
|
88
|
+
return fleet_result
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@login_required()
|
|
92
|
+
@permission_required(perm="fleetfinder.access_fleetfinder")
|
|
93
|
+
def dashboard(request):
|
|
94
|
+
"""
|
|
95
|
+
Dashboard view
|
|
96
|
+
|
|
97
|
+
:param request:
|
|
98
|
+
:return:
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
context = {}
|
|
102
|
+
|
|
103
|
+
logger.info(msg=f"Module called by {request.user}")
|
|
104
|
+
|
|
105
|
+
return render(
|
|
106
|
+
request=request,
|
|
107
|
+
template_name="fleetfinder/dashboard.html",
|
|
108
|
+
context=context,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@login_required()
|
|
113
|
+
@permission_required(perm="fleetfinder.access_fleetfinder")
|
|
114
|
+
def ajax_dashboard(request) -> JsonResponse: # pylint: disable=too-many-locals
|
|
115
|
+
"""
|
|
116
|
+
Ajax :: Dashboard information
|
|
117
|
+
|
|
118
|
+
:param request:
|
|
119
|
+
:return:
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def _create_button_style_link(
|
|
123
|
+
url: str, fa_icon_class: str, btn_title: str | Promise, btn_modifier_class: str
|
|
124
|
+
) -> str:
|
|
125
|
+
"""
|
|
126
|
+
Helper function to create a button HTML string
|
|
127
|
+
This function generates an HTML anchor tag styled as a button with an icon.
|
|
128
|
+
|
|
129
|
+
:param url: The URL the button should link to
|
|
130
|
+
:type url: str
|
|
131
|
+
:param fa_icon_class: The Font Awesome class for the icon to be displayed
|
|
132
|
+
:type fa_icon_class: str
|
|
133
|
+
:param btn_title: The title attribute for the button, typically a translation string
|
|
134
|
+
:type btn_title: str | Promise
|
|
135
|
+
:param btn_modifier_class: The Bootstrap modifier class for the button styling
|
|
136
|
+
:type btn_modifier_class: str
|
|
137
|
+
:return: An HTML string representing the button
|
|
138
|
+
:rtype: str
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
f'<a href="{url}" class="btn btn-sm {btn_modifier_class} ms-1" '
|
|
143
|
+
f'data-bs-tooltip="aa-fleetfinder" title="{btn_title}">'
|
|
144
|
+
f'<i class="{fa_icon_class}"></i></a>'
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
def _get_fleet_commander_information(fleet: Fleet) -> tuple[str, str]:
|
|
148
|
+
"""
|
|
149
|
+
Helper function to get the fleet commander's HTML representation
|
|
150
|
+
This function retrieves the fleet commander's name and portrait URL,
|
|
151
|
+
and returns an HTML string with the portrait image and name.
|
|
152
|
+
|
|
153
|
+
:param fleet: The Fleet object containing the fleet commander's information
|
|
154
|
+
:type fleet: Fleet
|
|
155
|
+
:return: A tuple containing the HTML string for the fleet commander and the name for sorting
|
|
156
|
+
:rtype: tuple[str, str]
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
commander_name = fleet.fleet_commander.character_name
|
|
160
|
+
portrait_url = character_portrait_url(
|
|
161
|
+
character_id=fleet.fleet_commander.character_id, size=32
|
|
162
|
+
)
|
|
163
|
+
portrait_img = (
|
|
164
|
+
'<img class="rounded eve-character-portrait" '
|
|
165
|
+
f'src="{portrait_url}" alt="{commander_name}" loading="lazy">'
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
return portrait_img + commander_name, commander_name
|
|
169
|
+
|
|
170
|
+
data = []
|
|
171
|
+
groups = request.user.groups.all()
|
|
172
|
+
user_characters = get_all_characters_from_user(user=request.user)
|
|
173
|
+
fleets = (
|
|
174
|
+
Fleet.objects.filter(
|
|
175
|
+
Q(groups__group__in=groups)
|
|
176
|
+
| Q(groups__isnull=True)
|
|
177
|
+
| Q(fleet_commander__in=user_characters)
|
|
178
|
+
)
|
|
179
|
+
.distinct()
|
|
180
|
+
.order_by("name")
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
can_manage_fleets = request.user.has_perm("fleetfinder.manage_fleets")
|
|
184
|
+
|
|
185
|
+
for fleet in fleets:
|
|
186
|
+
fleet_commander_html, fleet_commander_name = _get_fleet_commander_information(
|
|
187
|
+
fleet
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Create buttons
|
|
191
|
+
buttons = [
|
|
192
|
+
_create_button_style_link(
|
|
193
|
+
reverse("fleetfinder:join_fleet", args=[fleet.fleet_id]),
|
|
194
|
+
"fa-solid fa-right-to-bracket",
|
|
195
|
+
_("Join fleet"),
|
|
196
|
+
"btn-success",
|
|
197
|
+
)
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
if can_manage_fleets:
|
|
201
|
+
buttons.extend(
|
|
202
|
+
[
|
|
203
|
+
_create_button_style_link(
|
|
204
|
+
reverse("fleetfinder:fleet_details", args=[fleet.fleet_id]),
|
|
205
|
+
"fa-solid fa-eye",
|
|
206
|
+
_("View fleet details"),
|
|
207
|
+
"btn-info",
|
|
208
|
+
),
|
|
209
|
+
_create_button_style_link(
|
|
210
|
+
reverse("fleetfinder:edit_fleet", args=[fleet.fleet_id]),
|
|
211
|
+
"fa-solid fa-pen-to-square",
|
|
212
|
+
_("Edit fleet advert"),
|
|
213
|
+
"btn-warning",
|
|
214
|
+
),
|
|
215
|
+
]
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
data.append(
|
|
219
|
+
{
|
|
220
|
+
"fleet_commander": {
|
|
221
|
+
"html": fleet_commander_html,
|
|
222
|
+
"sort": fleet_commander_name,
|
|
223
|
+
},
|
|
224
|
+
"fleet_name": fleet.name,
|
|
225
|
+
"created_at": fleet.created_at,
|
|
226
|
+
"actions": "".join(buttons),
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
return JsonResponse(data=data, safe=False)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@login_required()
|
|
234
|
+
@permission_required(perm="fleetfinder.manage_fleets")
|
|
235
|
+
@token_required(scopes=("esi-fleets.read_fleet.v1", "esi-fleets.write_fleet.v1"))
|
|
236
|
+
def create_fleet(request, token):
|
|
237
|
+
"""
|
|
238
|
+
Create fleet view
|
|
239
|
+
|
|
240
|
+
:param request:
|
|
241
|
+
:param token:
|
|
242
|
+
:return:
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
# Validate the token and check if the character is in a fleet and is the fleet boss
|
|
246
|
+
try:
|
|
247
|
+
_get_and_validate_fleet(token, token.character_id)
|
|
248
|
+
except (HTTPClientError, ValueError) as ex:
|
|
249
|
+
error_detail = str(ex)
|
|
250
|
+
|
|
251
|
+
logger.debug(f"Error during fleet creation: {error_detail}", exc_info=True)
|
|
252
|
+
|
|
253
|
+
messages.error(
|
|
254
|
+
request,
|
|
255
|
+
mark_safe(
|
|
256
|
+
_(
|
|
257
|
+
"<h4>Error!</h4><p>There was an error creating the fleet: {error_detail}</p>"
|
|
258
|
+
).format(error_detail=error_detail)
|
|
259
|
+
),
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
return redirect("fleetfinder:dashboard")
|
|
263
|
+
|
|
264
|
+
if request.method != "POST":
|
|
265
|
+
return redirect("fleetfinder:dashboard")
|
|
266
|
+
|
|
267
|
+
auth_groups = AuthGroup.objects.filter(internal=False)
|
|
268
|
+
context = {"character_id": token.character_id, "auth_groups": auth_groups}
|
|
269
|
+
|
|
270
|
+
return render(
|
|
271
|
+
request=request,
|
|
272
|
+
template_name="fleetfinder/create-fleet.html",
|
|
273
|
+
context=context,
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
@login_required()
|
|
278
|
+
@permission_required(perm="fleetfinder.manage_fleets")
|
|
279
|
+
def edit_fleet(request, fleet_id):
|
|
280
|
+
"""
|
|
281
|
+
Fleet edit view
|
|
282
|
+
|
|
283
|
+
:param request:
|
|
284
|
+
:param fleet_id:
|
|
285
|
+
:return:
|
|
286
|
+
"""
|
|
287
|
+
|
|
288
|
+
try:
|
|
289
|
+
fleet = Fleet.objects.get(fleet_id=fleet_id)
|
|
290
|
+
except Fleet.DoesNotExist:
|
|
291
|
+
logger.debug(f"Fleet with ID {fleet_id} does not exist.")
|
|
292
|
+
|
|
293
|
+
messages.error(
|
|
294
|
+
request,
|
|
295
|
+
mark_safe(
|
|
296
|
+
_(
|
|
297
|
+
"<h4>Error!</h4><p>Fleet does not exist or is no longer available.</p>"
|
|
298
|
+
)
|
|
299
|
+
),
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
return redirect("fleetfinder:dashboard")
|
|
303
|
+
|
|
304
|
+
auth_groups = AuthGroup.objects.filter(internal=False)
|
|
305
|
+
|
|
306
|
+
context = {
|
|
307
|
+
"character_id": fleet.fleet_commander.character_id,
|
|
308
|
+
"auth_groups": auth_groups,
|
|
309
|
+
"fleet": fleet,
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
logger.debug(f"Context for fleet edit: {context}")
|
|
313
|
+
logger.info(msg=f"Fleet {fleet_id} edit view by {request.user}")
|
|
314
|
+
|
|
315
|
+
return render(
|
|
316
|
+
request=request,
|
|
317
|
+
template_name="fleetfinder/edit-fleet.html",
|
|
318
|
+
context=context,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
@login_required()
|
|
323
|
+
@permission_required(perm="fleetfinder.access_fleetfinder")
|
|
324
|
+
def join_fleet(request, fleet_id):
|
|
325
|
+
"""
|
|
326
|
+
Join fleet view
|
|
327
|
+
|
|
328
|
+
:param request:
|
|
329
|
+
:param fleet_id:
|
|
330
|
+
:return:
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
context = {}
|
|
334
|
+
groups = request.user.groups.all()
|
|
335
|
+
fleet = Fleet.objects.filter(
|
|
336
|
+
Q(groups__group__in=groups) | Q(groups=None), fleet_id=fleet_id
|
|
337
|
+
).count()
|
|
338
|
+
|
|
339
|
+
if fleet == 0:
|
|
340
|
+
return redirect(to="fleetfinder:dashboard")
|
|
341
|
+
|
|
342
|
+
if request.method == "POST":
|
|
343
|
+
character_ids = request.POST.getlist(key="character_ids", default=[])
|
|
344
|
+
send_fleet_invitation.delay(character_ids=character_ids, fleet_id=fleet_id)
|
|
345
|
+
|
|
346
|
+
return redirect(to="fleetfinder:dashboard")
|
|
347
|
+
|
|
348
|
+
characters = (
|
|
349
|
+
EveCharacter.objects.filter(character_ownership__user=request.user)
|
|
350
|
+
.select_related()
|
|
351
|
+
.order_by("character_name")
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
context["characters"] = characters
|
|
355
|
+
|
|
356
|
+
return render(
|
|
357
|
+
request=request,
|
|
358
|
+
template_name="fleetfinder/join-fleet.html",
|
|
359
|
+
context=context,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@login_required()
|
|
364
|
+
@permission_required("fleetfinder.manage_fleets")
|
|
365
|
+
def save_fleet(request):
|
|
366
|
+
"""
|
|
367
|
+
Save fleet
|
|
368
|
+
|
|
369
|
+
:param request:
|
|
370
|
+
:return:
|
|
371
|
+
"""
|
|
372
|
+
|
|
373
|
+
def _edit_or_create_fleet(
|
|
374
|
+
character_id: int,
|
|
375
|
+
free_move: bool,
|
|
376
|
+
name: str,
|
|
377
|
+
groups: list,
|
|
378
|
+
motd: str = None, # pylint: disable=unused-argument
|
|
379
|
+
) -> None:
|
|
380
|
+
"""
|
|
381
|
+
Edit or create a fleet from a fleet in EVE Online
|
|
382
|
+
|
|
383
|
+
:param character_id: The character ID of the fleet commander
|
|
384
|
+
:type character_id: int
|
|
385
|
+
:param free_move: Whether the fleet is free move or not
|
|
386
|
+
:type free_move: bool
|
|
387
|
+
:param name: Name of the fleet
|
|
388
|
+
:type name: str
|
|
389
|
+
:param groups: Groups that are allowed to access the fleet
|
|
390
|
+
:type groups: list[AuthGroup]
|
|
391
|
+
:param motd: Message of the Day for the fleet
|
|
392
|
+
:type motd: str
|
|
393
|
+
:return: None
|
|
394
|
+
:rtype: None
|
|
395
|
+
"""
|
|
396
|
+
|
|
397
|
+
required_scopes = ["esi-fleets.read_fleet.v1", "esi-fleets.write_fleet.v1"]
|
|
398
|
+
token = Token.get_token(character_id=character_id, scopes=required_scopes)
|
|
399
|
+
|
|
400
|
+
fleet_result = _get_and_validate_fleet(token, character_id)
|
|
401
|
+
fleet_commander = EveCharacter.objects.get(character_id=character_id)
|
|
402
|
+
fleet_id = fleet_result.fleet_id
|
|
403
|
+
|
|
404
|
+
fleet, created = Fleet.objects.get_or_create(
|
|
405
|
+
fleet_id=fleet_id,
|
|
406
|
+
defaults={
|
|
407
|
+
"created_at": timezone.now(),
|
|
408
|
+
# "motd": motd,
|
|
409
|
+
"is_free_move": free_move,
|
|
410
|
+
"fleet_commander": fleet_commander,
|
|
411
|
+
"name": name,
|
|
412
|
+
},
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
if not created:
|
|
416
|
+
fleet.is_free_move = free_move
|
|
417
|
+
fleet.name = name
|
|
418
|
+
fleet.save()
|
|
419
|
+
|
|
420
|
+
fleet.groups.set(groups)
|
|
421
|
+
|
|
422
|
+
esi.client.Fleets.PutFleetsFleetId(
|
|
423
|
+
fleet_id=fleet_id,
|
|
424
|
+
token=token,
|
|
425
|
+
# body={"is_free_move": free_move, "motd": motd},
|
|
426
|
+
body={"is_free_move": free_move},
|
|
427
|
+
).result(force_refresh=True)
|
|
428
|
+
|
|
429
|
+
if request.method != "POST":
|
|
430
|
+
return redirect("fleetfinder:dashboard")
|
|
431
|
+
|
|
432
|
+
# Extract form data
|
|
433
|
+
form_data = {
|
|
434
|
+
"character_id": int(request.POST["character_id"]),
|
|
435
|
+
"free_move": request.POST.get("free_move") == "on",
|
|
436
|
+
# "motd": request.POST.get("motd", ""),
|
|
437
|
+
"name": request.POST.get("name", ""),
|
|
438
|
+
"groups": request.POST.getlist("groups", []),
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
logger.debug(f"Form data for fleet creation: {form_data}")
|
|
442
|
+
|
|
443
|
+
try:
|
|
444
|
+
_edit_or_create_fleet(**form_data)
|
|
445
|
+
except HTTPClientError as ex:
|
|
446
|
+
esi_error = str(ex)
|
|
447
|
+
|
|
448
|
+
logger.debug(f"ESI returned 404 for fleet creation: {esi_error}", exc_info=True)
|
|
449
|
+
|
|
450
|
+
messages.error(
|
|
451
|
+
request,
|
|
452
|
+
mark_safe(
|
|
453
|
+
_(
|
|
454
|
+
"<h4>Error!</h4><p>ESI returned the following error: {esi_error}</p>"
|
|
455
|
+
).format(esi_error=esi_error)
|
|
456
|
+
),
|
|
457
|
+
)
|
|
458
|
+
except ValueError as ex:
|
|
459
|
+
logger.debug(f"Value error during fleet creation: {ex}", exc_info=True)
|
|
460
|
+
|
|
461
|
+
messages.error(
|
|
462
|
+
request,
|
|
463
|
+
mark_safe(
|
|
464
|
+
_(
|
|
465
|
+
"<h4>Error!</h4><p>There was an error creating the fleet: {ex}</p>"
|
|
466
|
+
).format(ex=str(ex))
|
|
467
|
+
),
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
return redirect("fleetfinder:dashboard")
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
@login_required()
|
|
474
|
+
@permission_required(perm="fleetfinder.manage_fleets")
|
|
475
|
+
def fleet_details(request, fleet_id):
|
|
476
|
+
"""
|
|
477
|
+
Fleet details view
|
|
478
|
+
|
|
479
|
+
:param request:
|
|
480
|
+
:param fleet_id:
|
|
481
|
+
:return:
|
|
482
|
+
"""
|
|
483
|
+
|
|
484
|
+
try:
|
|
485
|
+
fleet = Fleet.objects.get(fleet_id=fleet_id)
|
|
486
|
+
except Fleet.DoesNotExist:
|
|
487
|
+
logger.debug(f"Fleet with ID {fleet_id} does not exist.")
|
|
488
|
+
|
|
489
|
+
messages.error(
|
|
490
|
+
request,
|
|
491
|
+
mark_safe(
|
|
492
|
+
_(
|
|
493
|
+
"<h4>Error!</h4><p>Fleet does not exist or is no longer available.</p>"
|
|
494
|
+
)
|
|
495
|
+
),
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
return redirect("fleetfinder:dashboard")
|
|
499
|
+
|
|
500
|
+
context = {"fleet": fleet}
|
|
501
|
+
|
|
502
|
+
logger.info(msg=f"Fleet {fleet.fleet_id} details view called by {request.user}")
|
|
503
|
+
|
|
504
|
+
return render(
|
|
505
|
+
request=request,
|
|
506
|
+
template_name="fleetfinder/fleet-details.html",
|
|
507
|
+
context=context,
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
@login_required()
|
|
512
|
+
@permission_required(perm="fleetfinder.manage_fleets")
|
|
513
|
+
def ajax_fleet_details(
|
|
514
|
+
request, fleet_id # pylint: disable=unused-argument
|
|
515
|
+
) -> JsonResponse:
|
|
516
|
+
"""
|
|
517
|
+
Ajax :: Fleet Details
|
|
518
|
+
|
|
519
|
+
:param request:
|
|
520
|
+
:param fleet_id:
|
|
521
|
+
"""
|
|
522
|
+
|
|
523
|
+
try:
|
|
524
|
+
fleet = get_fleet_composition(fleet_id)
|
|
525
|
+
except Fleet.DoesNotExist:
|
|
526
|
+
logger.debug(f"Fleet with ID {fleet_id} does not exist.")
|
|
527
|
+
|
|
528
|
+
return JsonResponse(
|
|
529
|
+
data={
|
|
530
|
+
"error": _("Fleet with ID {fleet_id} does not exist.").format(
|
|
531
|
+
fleet_id=fleet_id
|
|
532
|
+
)
|
|
533
|
+
},
|
|
534
|
+
safe=False,
|
|
535
|
+
)
|
|
536
|
+
except RuntimeError as ex:
|
|
537
|
+
logger.debug(f"Error retrieving fleet composition: {str(ex)}", exc_info=True)
|
|
538
|
+
|
|
539
|
+
return JsonResponse(
|
|
540
|
+
data={
|
|
541
|
+
"error": _("Error retrieving fleet composition: {ex}").format(
|
|
542
|
+
ex=str(ex)
|
|
543
|
+
)
|
|
544
|
+
},
|
|
545
|
+
safe=False,
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
data = {
|
|
549
|
+
"fleet_member": list(fleet.fleet),
|
|
550
|
+
"fleet_composition": [
|
|
551
|
+
{"ship_type_name": ship, "number": number}
|
|
552
|
+
for ship, number in fleet.aggregate.items()
|
|
553
|
+
],
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return JsonResponse(data=data, safe=False)
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
@login_required()
|
|
560
|
+
@permission_required(perm="fleetfinder.manage_fleets")
|
|
561
|
+
def ajax_fleet_kick_member( # pylint: disable=too-many-return-statements
|
|
562
|
+
request: WSGIRequest, fleet_id: int
|
|
563
|
+
) -> JsonResponse:
|
|
564
|
+
"""
|
|
565
|
+
Ajax :: Kick member from fleet
|
|
566
|
+
|
|
567
|
+
:param request: WSGIRequest object containing the request data
|
|
568
|
+
:type request: WSGIRequest
|
|
569
|
+
:param fleet_id: The ID of the fleet from which to kick a member
|
|
570
|
+
:type fleet_id: int
|
|
571
|
+
:return: JsonResponse indicating success or failure of the operation
|
|
572
|
+
:rtype: JsonResponse
|
|
573
|
+
"""
|
|
574
|
+
|
|
575
|
+
if request.method != "POST":
|
|
576
|
+
return JsonResponse(
|
|
577
|
+
data={"success": False, "error": _("Method not allowed")},
|
|
578
|
+
status=HTTPStatus.METHOD_NOT_ALLOWED,
|
|
579
|
+
)
|
|
580
|
+
|
|
581
|
+
try:
|
|
582
|
+
fleet = Fleet.objects.get(fleet_id=fleet_id)
|
|
583
|
+
data = json.loads(request.body)
|
|
584
|
+
member_id = data.get("memberId")
|
|
585
|
+
|
|
586
|
+
if not member_id:
|
|
587
|
+
return JsonResponse(
|
|
588
|
+
data={"success": False, "error": _("Member ID required")},
|
|
589
|
+
status=HTTPStatus.BAD_REQUEST,
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
logger.debug(f"Request data for kicking member: {data}")
|
|
593
|
+
|
|
594
|
+
token = Token.get_token(
|
|
595
|
+
character_id=fleet.fleet_commander.character_id,
|
|
596
|
+
scopes=["esi-fleets.write_fleet.v1"],
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
esi.client.Fleets.DeleteFleetsFleetIdMembersMemberId(
|
|
600
|
+
fleet_id=fleet_id,
|
|
601
|
+
member_id=member_id,
|
|
602
|
+
token=token,
|
|
603
|
+
).result(force_refresh=True)
|
|
604
|
+
|
|
605
|
+
return JsonResponse(data={"success": True}, status=HTTPStatus.OK)
|
|
606
|
+
except Fleet.DoesNotExist:
|
|
607
|
+
return JsonResponse(
|
|
608
|
+
data={"success": False, "error": _("Fleet not found")},
|
|
609
|
+
status=HTTPStatus.NOT_FOUND,
|
|
610
|
+
)
|
|
611
|
+
except (json.JSONDecodeError, ValueError):
|
|
612
|
+
return JsonResponse(
|
|
613
|
+
data={"success": False, "error": _("Invalid request data")},
|
|
614
|
+
status=HTTPStatus.BAD_REQUEST,
|
|
615
|
+
)
|
|
616
|
+
except HTTPClientError as ex:
|
|
617
|
+
if ex.status_code == HTTPStatus.NOT_FOUND:
|
|
618
|
+
return JsonResponse(
|
|
619
|
+
data={"success": False, "error": _("Member not found in fleet")},
|
|
620
|
+
status=HTTPStatus.NOT_FOUND,
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
logger.debug(f"ESI error while kicking member: {str(ex)}", exc_info=True)
|
|
624
|
+
|
|
625
|
+
return JsonResponse(
|
|
626
|
+
data={
|
|
627
|
+
"success": False,
|
|
628
|
+
"error": _("An ESI error occurred: {ex}").format(ex=str(ex)),
|
|
629
|
+
},
|
|
630
|
+
status=ex.status_code,
|
|
631
|
+
)
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: aa-fleetfinder
|
|
3
|
-
Version: 0.1.0a12
|
|
4
|
-
Summary: Fleet finder plugin for Alliance Auth
|
|
5
|
-
Home-page: https://github.com/ppfeufer/aa-fleetfinder
|
|
6
|
-
Author: Peter Pfeufer
|
|
7
|
-
Author-email: development@ppfeufer.de
|
|
8
|
-
Maintainer: Peter Pfeufer
|
|
9
|
-
Maintainer-email: development@ppfeufer.de
|
|
10
|
-
License: GPL-3.0
|
|
11
|
-
Project-URL: Issue / Bug Reports, https://github.com/ppfeufer/aa-fleetfinder/issues
|
|
12
|
-
Project-URL: Changelog, https://github.com/ppfeufer/aa-fleetfinder/blob/master/CHANGELOG.md
|
|
13
|
-
Keywords: allianceauth,eveonline,fleetfinder
|
|
14
|
-
Platform: UNKNOWN
|
|
15
|
-
Classifier: Environment :: Web Environment
|
|
16
|
-
Classifier: Framework :: Django
|
|
17
|
-
Classifier: Framework :: Django :: 3.2
|
|
18
|
-
Classifier: Intended Audience :: Developers
|
|
19
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
20
|
-
Classifier: Operating System :: OS Independent
|
|
21
|
-
Classifier: Programming Language :: Python
|
|
22
|
-
Classifier: Programming Language :: Python :: 3
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
24
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
25
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
26
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
27
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
28
|
-
Classifier: Topic :: Internet :: WWW/HTTP
|
|
29
|
-
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
30
|
-
Requires-Python: ~=3.7
|
|
31
|
-
Description-Content-Type: text/markdown
|
|
32
|
-
License-File: LICENSE
|
|
33
|
-
Requires-Dist: allianceauth (>=2.9.4)
|
|
34
|
-
|
|
35
|
-
# AA Fleet Finder
|
|
36
|
-
|
|
37
|
-
[](https://pypi.org/project/aa-fleetfinder/)
|
|
38
|
-
[](https://github.com/ppfeufer/aa-fleetfinder/blob/master/LICENSE)
|
|
39
|
-
[](https://pypi.org/project/aa-fleetfinder/)
|
|
40
|
-
[](https://pypi.org/project/aa-fleetfinder/)
|
|
41
|
-

|
|
42
|
-
[](http://black.readthedocs.io/en/latest/)
|
|
43
|
-
[](https://discord.gg/zmh52wnfvM)
|
|
44
|
-
[](https://github.com/ppfeufer/aa-fleetfinder/actions/workflows/automated-checks.yml)
|
|
45
|
-
[](https://codecov.io/gh/ppfeufer/aa-fleetfinder)
|
|
46
|
-
[](https://github.com/ppfeufer/aa-fleetfinder/blob/master/CODE_OF_CONDUCT.md)
|
|
47
|
-
|
|
48
|
-
## Not yet publicly available
|
|
49
|
-
|
|
50
|
-
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
aa_fleetfinder-0.1.0a12.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
2
|
-
aa_fleetfinder-0.1.0a12.dist-info/METADATA,sha256=dG25cZdfhPeZ1dd7Neioz2XCTQpmFWmoLx6Bj4mLjSc,2787
|
|
3
|
-
aa_fleetfinder-0.1.0a12.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
4
|
-
aa_fleetfinder-0.1.0a12.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
5
|
-
aa_fleetfinder-0.1.0a12.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
File without changes
|