being moving some of corputils to openapi

This commit is contained in:
Joel Falknau committed 2026-02-24 22:25:38 +10:00
1 parent 3cc467ac2a
commit e0010c7dcc
5 files changed
+87 -44

No files matched your search

+1
View File
@@ -0,0 +1 @@
__esi_compatibility_date__ = "2025-12-16"
+33 -38
View File
@@ -1,31 +1,23 @@
import logging
import os
from typing import ClassVar
from bravado.exception import HTTPForbidden
from django.db import models
from esi.errors import TokenError
from esi.exceptions import HTTPClientError
from esi.models import Token
from allianceauth.authentication.models import CharacterOwnership, UserProfile
from allianceauth.corputils.managers import CorpStatsManager
from allianceauth.eveonline.models import EveAllianceInfo, EveCharacter, EveCorporationInfo
from allianceauth.corputils.providers import (
get_characters_character_id, get_corporations_corporation_id_members,
post_universe_names,
)
from allianceauth.eveonline.models import (
EveAllianceInfo, EveCharacter, EveCorporationInfo,
)
from allianceauth.notifications import notify
SWAGGER_SPEC_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'swagger.json')
"""
Swagger spec operations:
Character
get_characters_character_id
get_corporations_corporation_id_members
Universe
post_universe_names
"""
logger = logging.getLogger(__name__)
@@ -33,8 +25,9 @@ class CorpStats(models.Model):
token = models.ForeignKey(Token, on_delete=models.CASCADE)
corp = models.OneToOneField(EveCorporationInfo, on_delete=models.CASCADE)
last_update = models.DateTimeField(auto_now=True)
members: models.QuerySet["CorpMember"]
objects: ClassVar[CorpStatsManager] = CorpStatsManager()
objects: ClassVar[CorpStatsManager] = CorpStatsManager() # pyright: ignore[reportIncompatibleVariableOverride]
class Meta:
permissions = (
@@ -42,24 +35,22 @@ class CorpStats(models.Model):
('view_alliance_corpstats', 'Can view corp stats of members of their alliance.'),
('view_state_corpstats', 'Can view corp stats of members of their auth state.'),
)
verbose_name = "corp stats"
verbose_name_plural = "corp stats"
verbose_name = "Corp Stat"
verbose_name_plural = "Corp Stats"
def __str__(self) -> str:
return f"{self.__class__.__name__} for {self.corp}"
def update(self) -> None:
try:
c = self.token.get_esi_client(spec_file=SWAGGER_SPEC_PATH)
assert c.Character.get_characters_character_id(character_id=self.token.character_id).result()['corporation_id'] == int(self.corp.corporation_id)
member_ids = c.Corporation.get_corporations_corporation_id_members(
corporation_id=self.corp.corporation_id).result()
assert get_characters_character_id(self.token.character_id).corporation_id == int(self.corp.corporation_id)
member_ids = get_corporations_corporation_id_members(corporation_id=self.corp.corporation_id, token=self.token)
# requesting too many ids per call results in a HTTP400
# the swagger spec doesn't have a maxItems count
# manual testing says we can do over 350, but let's not risk it
member_id_chunks = [member_ids[i:i + 255] for i in range(0, len(member_ids), 255)]
member_name_chunks = [c.Universe.post_universe_names(ids=id_chunk).result() for id_chunk in member_id_chunks]
member_name_chunks = [post_universe_names(ids=id_chunk).result() for id_chunk in member_id_chunks]
member_list = {}
for name_chunk in member_name_chunks:
member_list.update({m['id']: m['name'] for m in name_chunk})
@@ -83,11 +74,12 @@ class CorpStats(models.Model):
message="Your token has expired or is no longer valid. Please add a new one to create a new CorpStats.",
level="error")
self.delete()
except HTTPForbidden as e:
logger.warning(f"{self} failed to update: {e}")
if self.token.user:
notify(self.token.user, f"{self} failed to update with your ESI token.", message=f"{e.status_code}: {e.message}", level="error")
self.delete()
except HTTPClientError as e:
if e.status_code == 403:
logger.warning(f"{self} failed to update: {e}")
if self.token.user:
notify(self.token.user, f"{self} failed to update with your ESI token.", message=f"{e.status_code}", level="error")
self.delete()
except AssertionError:
logger.warning(f"{self} token character no longer in corp.")
if self.token.user:
@@ -97,7 +89,7 @@ class CorpStats(models.Model):
self.delete()
@property
def member_count(self):
def member_count(self) -> int:
return self.members.count()
@property
@@ -109,15 +101,15 @@ class CorpStats(models.Model):
return len(self.registered_members)
@property
def registered_members(self):
def registered_members(self) -> models.QuerySet["CorpMember"]:
return self.members.filter(pk__in=[m.pk for m in self.members.all() if m.registered])
@property
def unregistered_member_count(self):
def unregistered_member_count(self) -> int:
return self.member_count - self.registered_member_count
@property
def unregistered_members(self):
def unregistered_members(self) -> models.QuerySet["CorpMember"]:
return self.members.filter(pk__in=[m.pk for m in self.members.all() if not m.registered])
@property
@@ -125,13 +117,13 @@ class CorpStats(models.Model):
return len(self.mains)
@property
def mains(self):
def mains(self) -> models.QuerySet["CorpMember"]:
return self.members.filter(pk__in=[m.pk for m in self.members.all() if m.main_character and int(m.main_character.character_id) == int(m.character_id)])
def visible_to(self, user):
def visible_to(self, user) -> bool:
return CorpStats.objects.filter(pk=self.pk).visible_to(user).exists()
def can_update(self, user):
def can_update(self, user) -> bool:
return self.token.user == user or self.visible_to(user)
def corp_logo(self, size=128) -> str:
@@ -150,6 +142,9 @@ class CorpMember(models.Model):
corpstats = models.ForeignKey(CorpStats, on_delete=models.CASCADE, related_name='members')
class Meta:
permissions = ()
verbose_name = "Corp Member"
verbose_name_plural = "Corp Members"
# not making character_id unique in case a character moves between two corps while only one updates
unique_together = ('corpstats', 'character_id')
ordering = ['character_name']
@@ -165,14 +160,14 @@ class CorpMember(models.Model):
return None
@property
def main_character(self):
def main_character(self) -> EveCharacter | None:
try:
return self.character.character_ownership.user.profile.main_character
except (CharacterOwnership.DoesNotExist, UserProfile.DoesNotExist, AttributeError):
return None
@property
def alts(self):
def alts(self) -> list["EveCharacter"]:
if self.main_character:
return [co.character for co in self.main_character.character_ownership.user.character_ownerships.all()]
else:
+47
View File
@@ -0,0 +1,47 @@
from typing import TYPE_CHECKING
from esi.models import Token
from esi.openapi_clients import ESIClientProvider
from esi.stubs import PostUniverseNamesOperation
from .. import __title__, __url__, __version__
from . import __esi_compatibility_date__
if TYPE_CHECKING:
from esi.stubs import (
CharactersDetail, CorporationsCorporationIdMembersGet,
PostUniverseNamesOperationBody,
)
esi = ESIClientProvider(
ua_appname=__title__,
ua_version=__version__,
ua_url=__url__,
compatibility_date=__esi_compatibility_date__,
operations=[
"GetCharactersCharacterId",
"GetCorporationsCorporationIdMembers"
"PostUniverseNames",
])
"""
Swagger spec operations:
Character
get_characters_character_id
get_corporations_corporation_id_members
Universe
post_universe_names
"""
def get_characters_character_id(character_id: int) -> CharactersDetail:
return esi.client.Character.GetCharactersCharacterId(character_id).result()
def get_corporations_corporation_id_members(corporation_id: int, token: Token) -> CorporationsCorporationIdMembersGet:
return esi.client.Corporation.GetCorporationsCorporationIdMembers(corporation_id=corporation_id, token=token).result()
def post_universe_names(ids: PostUniverseNamesOperationBody) -> PostUniverseNamesOperation:
return esi.client.Universe.PostUniverseNames(body=ids).result()
+3 -3
View File
@@ -1,7 +1,5 @@
from unittest import mock
from bravado.exception import HTTPForbidden
from django.contrib.auth.models import Permission
from django.test import TestCase
@@ -9,7 +7,9 @@ from esi.errors import TokenError
from esi.models import Token
from allianceauth.authentication.models import CharacterOwnership
from allianceauth.eveonline.models import EveAllianceInfo, EveCharacter, EveCorporationInfo
from allianceauth.eveonline.models import (
EveAllianceInfo, EveCharacter, EveCorporationInfo,
)
from allianceauth.tests.auth_utils import AuthUtils
from .models import CorpMember, CorpStats
+3 -3
View File
@@ -1,9 +1,9 @@
import os
from bravado.exception import HTTPError
from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
from django.contrib.auth.decorators import (
login_required, permission_required, user_passes_test,
)
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db import IntegrityError
from django.shortcuts import get_object_or_404, redirect, render