diff --git a/allianceauth/eveonline/evelinks/__init__.py b/allianceauth/eveonline/evelinks/__init__.py new file mode 100644 index 00000000..cc9ee19b --- /dev/null +++ b/allianceauth/eveonline/evelinks/__init__.py @@ -0,0 +1,17 @@ +# this package generates profile URL for eve entities +# on 3rd party websites like evewho and zKillboard +# +# It contains of modules for views and templatetags for templates + +# list of all eve entity categories as defined in ESI +ESI_CATEGORY_AGENT = "agent" +ESI_CATEGORY_ALLIANCE = "alliance" +ESI_CATEGORY_CHARACTER = "character" +ESI_CATEGORY_CONSTELLATION = "constellation" +ESI_CATEGORY_CORPORATION = "corporation" +ESI_CATEGORY_FACTION = "faction" +ESI_CATEGORY_INVENTORYTYPE = "inventory_type" +ESI_CATEGORY_REGION = "region" +ESI_CATEGORY_SOLARSYSTEM = "solar_system" +ESI_CATEGORY_STATION = "station" +ESI_CATEGORY_WORMHOLE = "wormhole" diff --git a/allianceauth/eveonline/evelinks/dotlan.py b/allianceauth/eveonline/evelinks/dotlan.py new file mode 100644 index 00000000..a1482ef9 --- /dev/null +++ b/allianceauth/eveonline/evelinks/dotlan.py @@ -0,0 +1,52 @@ +# this module generates profile URLs for dotlan + +from urllib.parse import urljoin, quote + +from . import * + +BASE_URL = 'http://evemaps.dotlan.net' + + +def _build_url(category: str, name: str) -> str: + """return url to profile page for an eve entity""" + + if category == ESI_CATEGORY_ALLIANCE: + partial = 'alliance' + + elif category == ESI_CATEGORY_CORPORATION: + partial = 'corp' + + elif category == ESI_CATEGORY_REGION: + partial = 'map' + + elif category == ESI_CATEGORY_SOLARSYSTEM: + partial = 'system' + + else: + raise NotImplementedError( + "Not implemented yet for category:" + category + ) + + url = urljoin( + BASE_URL, + '{}/{}'.format(partial, quote(str(name).replace(" ", "_"))) + + ) + return url + + +def alliance_url(name: str) -> str: + """url for page about given alliance on dotlan""" + return _build_url(ESI_CATEGORY_ALLIANCE, name) + +def corporation_url(name: str) -> str: + """url for page about given corporation on dotlan""" + return _build_url(ESI_CATEGORY_CORPORATION, name) + +def region_url(name: str) -> str: + """url for page about given region on dotlan""" + return _build_url(ESI_CATEGORY_REGION, name) + +def solar_system_url(name: str) -> str: + """url for page about given solar system on dotlan""" + return _build_url(ESI_CATEGORY_SOLARSYSTEM, name) \ No newline at end of file diff --git a/allianceauth/eveonline/evelinks/evewho.py b/allianceauth/eveonline/evelinks/evewho.py new file mode 100644 index 00000000..4f96fd4b --- /dev/null +++ b/allianceauth/eveonline/evelinks/evewho.py @@ -0,0 +1,44 @@ +# this module generates profile URLs for evewho + +from urllib.parse import urljoin, quote + +from . import * + +BASE_URL = 'https://evewho.com' + + +def _build_url(category: str, eve_id: int) -> str: + """return url to profile page for an eve entity""" + + if category == ESI_CATEGORY_ALLIANCE: + partial = 'alliance' + + elif category == ESI_CATEGORY_CORPORATION: + partial = 'corporation' + + elif category == ESI_CATEGORY_CHARACTER: + partial = 'character' + + else: + raise NotImplementedError( + "Not implemented yet for category:" + category + ) + + url = urljoin( + BASE_URL, + '{}/{}'.format(partial, int(eve_id)) + ) + return url + + +def alliance_url(eve_id: int) -> str: + """url for page about given alliance on evewho""" + return _build_url(ESI_CATEGORY_ALLIANCE, eve_id) + +def character_url(eve_id: int) -> str: + """url for page about given character on evewho""" + return _build_url(ESI_CATEGORY_CHARACTER, eve_id) + +def corporation_url(eve_id: int) -> str: + """url for page about given corporation on evewho""" + return _build_url(ESI_CATEGORY_CORPORATION, eve_id) diff --git a/allianceauth/eveonline/evelinks/tests/__init__.py b/allianceauth/eveonline/evelinks/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/allianceauth/eveonline/evelinks/tests/test_evelinks.py b/allianceauth/eveonline/evelinks/tests/test_evelinks.py new file mode 100644 index 00000000..cd69f810 --- /dev/null +++ b/allianceauth/eveonline/evelinks/tests/test_evelinks.py @@ -0,0 +1,92 @@ +from django.test import TestCase + +from ...models import EveCharacter, EveCorporationInfo, EveAllianceInfo +from .. import dotlan, zkillboard, evewho +from ...templatetags import evelinks + + +class TestEveWho(TestCase): + + def test_alliance_url(self): + self.assertEqual( + evewho.alliance_url(12345678), + 'https://evewho.com/alliance/12345678' + ) + + def test_corporation_url(self): + self.assertEqual( + evewho.corporation_url(12345678), + 'https://evewho.com/corporation/12345678' + ) + + def test_character_url(self): + self.assertEqual( + evewho.character_url(12345678), + 'https://evewho.com/character/12345678' + ) + + +class TestDotlan(TestCase): + + def test_alliance_url(self): + self.assertEqual( + dotlan.alliance_url('Wayne Enterprices'), + 'http://evemaps.dotlan.net/alliance/Wayne_Enterprices' + ) + + def test_corporation_url(self): + self.assertEqual( + dotlan.corporation_url('Wayne Technology'), + 'http://evemaps.dotlan.net/corp/Wayne_Technology' + ) + self.assertEqual( + dotlan.corporation_url('Crédit Agricole'), + 'http://evemaps.dotlan.net/corp/Cr%C3%A9dit_Agricole' + ) + + def test_region_url(self): + self.assertEqual( + dotlan.region_url('Black Rise'), + 'http://evemaps.dotlan.net/map/Black_Rise' + ) + + def test_solar_system_url(self): + self.assertEqual( + dotlan.solar_system_url('Jita'), + 'http://evemaps.dotlan.net/system/Jita' + ) + + +class TestZkillboard(TestCase): + + def test_alliance_url(self): + self.assertEqual( + zkillboard.alliance_url(12345678), + 'https://zkillboard.com/alliance/12345678/' + ) + + def test_corporation_url(self): + self.assertEqual( + zkillboard.corporation_url(12345678), + 'https://zkillboard.com/corporation/12345678/' + ) + + def test_character_url(self): + self.assertEqual( + zkillboard.character_url(12345678), + 'https://zkillboard.com/character/12345678/' + ) + + + def test_region_url(self): + self.assertEqual( + zkillboard.region_url(12345678), + 'https://zkillboard.com/region/12345678/' + ) + + def test_solar_system_url(self): + self.assertEqual( + zkillboard.solar_system_url(12345678), + 'https://zkillboard.com/system/12345678/' + ) + diff --git a/allianceauth/eveonline/evelinks/tests/test_templatetags.py b/allianceauth/eveonline/evelinks/tests/test_templatetags.py new file mode 100644 index 00000000..80da287d --- /dev/null +++ b/allianceauth/eveonline/evelinks/tests/test_templatetags.py @@ -0,0 +1,334 @@ +from django.test import TestCase + +from ...models import EveCharacter, EveCorporationInfo, EveAllianceInfo +from .. import dotlan, zkillboard, evewho +from ...templatetags import evelinks + + +class TestTemplateTags(TestCase): + + def setUp(self): + self.my_character = EveCharacter.objects.create( + character_id=1001, + character_name='Bruce Wayne', + corporation_id=2001, + corporation_name='Dummy Corporation 1', + corporation_ticker='DC1', + alliance_id=3001, + alliance_name='Dummy Alliance 1', + alliance_ticker='DA1', + ) + self.my_character_2 = EveCharacter.objects.create( + character_id=1002, + character_name='Peter Parker', + corporation_id=2002, + corporation_name='Dummy Corporation 2', + corporation_ticker='DC2', + ) + self.my_alliance = EveAllianceInfo.objects.create( + alliance_id=3001, + alliance_name='Dummy Alliance 1', + alliance_ticker='DA1', + executor_corp_id=2001 + ) + self.my_corporation = EveCorporationInfo( + corporation_id=2001, + corporation_name='Dummy Corporation 1', + corporation_ticker='DC1', + member_count=42, + alliance=self.my_alliance + ) + + self.my_region_id = 8001 + self.my_region_name = 'Southpark' + + self.my_solar_system_id = 9001 + self.my_solar_system_name = 'Gotham' + + + def test_evewho_character_url(self): + self.assertEqual( + evelinks.evewho_character_url(self.my_character), + evewho.character_url(self.my_character.character_id), + ) + self.assertEqual( + evelinks.evewho_character_url(None), + '' + ) + self.assertEqual( + evelinks.evewho_character_url(self.my_character.character_id), + evewho.character_url(self.my_character.character_id), + ) + + + def test_evewho_corporation_url(self): + self.assertEqual( + evelinks.evewho_corporation_url(self.my_character), + evewho.corporation_url(self.my_character.corporation_id), + ) + self.assertEqual( + evelinks.evewho_corporation_url(self.my_corporation), + evewho.corporation_url(self.my_corporation.corporation_id), + ) + self.assertEqual( + evelinks.evewho_corporation_url(None), + '' + ) + self.assertEqual( + evelinks.evewho_corporation_url(self.my_character.corporation_id), + evewho.corporation_url(self.my_character.corporation_id), + ) + + + def test_evewho_alliance_url(self): + self.assertEqual( + evelinks.evewho_alliance_url(self.my_character), + evewho.alliance_url(self.my_character.alliance_id), + ) + self.assertEqual( + evelinks.evewho_alliance_url(self.my_character_2), + '', + ) + self.assertEqual( + evelinks.evewho_alliance_url(self.my_alliance), + evewho.alliance_url(self.my_alliance.alliance_id), + ) + self.assertEqual( + evelinks.evewho_alliance_url(None), + '' + ) + self.assertEqual( + evelinks.evewho_alliance_url(self.my_character.alliance_id), + evewho.alliance_url(self.my_character.alliance_id), + ) + + + # dotlan + + def test_dotlan_corporation_url(self): + self.assertEqual( + evelinks.dotlan_corporation_url(self.my_character), + dotlan.corporation_url(self.my_character.corporation_name), + ) + self.assertEqual( + evelinks.dotlan_corporation_url(self.my_corporation), + dotlan.corporation_url(self.my_corporation.corporation_name), + ) + self.assertEqual( + evelinks.dotlan_corporation_url(None), + '' + ) + self.assertEqual( + evelinks.dotlan_corporation_url(self.my_character.corporation_name), + dotlan.corporation_url(self.my_character.corporation_name), + ) + + + def test_dotlan_alliance_url(self): + self.assertEqual( + evelinks.dotlan_alliance_url(self.my_character), + dotlan.alliance_url(self.my_character.alliance_name), + ) + self.assertEqual( + evelinks.dotlan_alliance_url(self.my_character_2), + '', + ) + self.assertEqual( + evelinks.dotlan_alliance_url(self.my_alliance), + dotlan.alliance_url(self.my_alliance.alliance_name), + ) + self.assertEqual( + evelinks.dotlan_alliance_url(None), + '' + ) + self.assertEqual( + evelinks.dotlan_alliance_url(self.my_character.alliance_name), + dotlan.alliance_url(self.my_character.alliance_name), + ) + + def test_dotlan_region_url(self): + self.assertEqual( + evelinks.dotlan_region_url(self.my_region_name), + dotlan.region_url(self.my_region_name), + ) + self.assertEqual( + evelinks.dotlan_region_url(None), + '' + ) + + def test_dotlan_solar_system_url(self): + self.assertEqual( + evelinks.dotlan_solar_system_url(self.my_solar_system_name), + dotlan.solar_system_url(self.my_solar_system_name), + ) + self.assertEqual( + evelinks.dotlan_solar_system_url(None), + '' + ) + + + # zkillboard + + def test_zkillboard_character_url(self): + self.assertEqual( + evelinks.zkillboard_character_url(self.my_character), + zkillboard.character_url(self.my_character.character_id), + ) + self.assertEqual( + evelinks.zkillboard_character_url(None), + '' + ) + self.assertEqual( + evelinks.zkillboard_character_url(self.my_character.character_id), + zkillboard.character_url(self.my_character.character_id), + ) + + + def test_zkillboard_corporation_url(self): + self.assertEqual( + evelinks.zkillboard_corporation_url(self.my_character), + zkillboard.corporation_url(self.my_character.corporation_id), + ) + self.assertEqual( + evelinks.zkillboard_corporation_url(self.my_corporation), + zkillboard.corporation_url(self.my_corporation.corporation_id), + ) + self.assertEqual( + evelinks.zkillboard_corporation_url(None), + '' + ) + self.assertEqual( + evelinks.zkillboard_corporation_url(self.my_character.corporation_id), + zkillboard.corporation_url(self.my_character.corporation_id), + ) + + + def test_zkillboard_alliance_url(self): + self.assertEqual( + evelinks.zkillboard_alliance_url(self.my_character), + zkillboard.alliance_url(self.my_character.alliance_id), + ) + self.assertEqual( + evelinks.zkillboard_alliance_url(self.my_character_2), + '', + ) + self.assertEqual( + evelinks.zkillboard_alliance_url(self.my_alliance), + zkillboard.alliance_url(self.my_alliance.alliance_id), + ) + self.assertEqual( + evelinks.zkillboard_alliance_url(None), + '' + ) + self.assertEqual( + evelinks.zkillboard_alliance_url(self.my_character.alliance_id), + zkillboard.alliance_url(self.my_character.alliance_id), + ) + + + def test_zkillboard_region_url(self): + self.assertEqual( + evelinks.zkillboard_region_url(self.my_region_id), + zkillboard.region_url(self.my_region_id), + ) + self.assertEqual( + evelinks.zkillboard_region_url(None), + '' + ) + + + def test_zkillboard_solar_system_url(self): + self.assertEqual( + evelinks.zkillboard_solar_system_url(self.my_solar_system_id), + zkillboard.solar_system_url(self.my_solar_system_id), + ) + self.assertEqual( + evelinks.zkillboard_solar_system_url(None), + '' + ) + + + # image URLs + + def test_character_portrait_url(self): + self.assertEqual( + evelinks.character_portrait_url(123), + EveCharacter.generic_portrait_url(123) + + ), + self.assertEqual( + evelinks.character_portrait_url(123, 128), + EveCharacter.generic_portrait_url(123, 128) + + ) + self.assertEqual( + evelinks.character_portrait_url(123, 99), + '' + ) + self.assertEqual( + evelinks.character_portrait_url(self.my_character), + self.my_character.portrait_url() + ) + self.assertEqual( + evelinks.character_portrait_url(None), + '' + ) + + + def test_corporation_logo_url(self): + self.assertEqual( + evelinks.corporation_logo_url(123), + EveCorporationInfo.generic_logo_url(123) + ), + self.assertEqual( + evelinks.corporation_logo_url(123, 128), + EveCorporationInfo.generic_logo_url(123, 128) + ) + self.assertEqual( + evelinks.corporation_logo_url(123, 99), + '' + ) + self.assertEqual( + evelinks.corporation_logo_url(self.my_corporation), + self.my_corporation.logo_url() + ) + self.assertEqual( + evelinks.corporation_logo_url(self.my_character), + self.my_character.corporation_logo_url() + ) + self.assertEqual( + evelinks.corporation_logo_url(None), + '' + ) + + + def test_alliance_logo_url(self): + self.assertEqual( + evelinks.alliance_logo_url(123), + EveAllianceInfo.generic_logo_url(123) + ), + self.assertEqual( + evelinks.alliance_logo_url(123, 128), + EveAllianceInfo.generic_logo_url(123, 128) + ) + self.assertEqual( + evelinks.alliance_logo_url(123, 99), + '' + ) + self.assertEqual( + evelinks.alliance_logo_url(self.my_alliance), + self.my_alliance.logo_url() + ) + self.assertEqual( + evelinks.alliance_logo_url(self.my_character), + self.my_character.alliance_logo_url() + ) + self.assertEqual( + evelinks.alliance_logo_url(None), + '' + ) + self.assertEqual( + evelinks.alliance_logo_url(self.my_character_2), + '' + ) + diff --git a/allianceauth/eveonline/evelinks/zkillboard.py b/allianceauth/eveonline/evelinks/zkillboard.py new file mode 100644 index 00000000..44187819 --- /dev/null +++ b/allianceauth/eveonline/evelinks/zkillboard.py @@ -0,0 +1,57 @@ +# this module generates profile URLs for zKillboard + +from urllib.parse import urljoin, quote + +from . import * + +BASE_URL = 'https://zkillboard.com' + + +def _build_url(category: str, eve_id: int) -> str: + """return url to profile page for an eve entity""" + + if category == ESI_CATEGORY_ALLIANCE: + partial = 'alliance' + + elif category == ESI_CATEGORY_CORPORATION: + partial = 'corporation' + + elif category == ESI_CATEGORY_CHARACTER: + partial = 'character' + + elif category == ESI_CATEGORY_REGION: + partial = 'region' + + elif category == ESI_CATEGORY_SOLARSYSTEM: + partial = 'system' + + else: + raise NotImplementedError( + "Not implemented yet for category:" + category + ) + + url = urljoin( + BASE_URL, + '{}/{}/'.format(partial, int(eve_id)) + ) + return url + + +def alliance_url(eve_id: int) -> str: + """url for page about given alliance on zKillboard""" + return _build_url(ESI_CATEGORY_ALLIANCE, eve_id) + +def character_url(eve_id: int) -> str: + """url for page about given character on zKillboard""" + return _build_url(ESI_CATEGORY_CHARACTER, eve_id) + +def corporation_url(eve_id: int) -> str: + """url for page about given corporation on zKillboard""" + return _build_url(ESI_CATEGORY_CORPORATION, eve_id) + +def region_url(eve_id: int) -> str: + """url for page about given region on zKillboard""" + return _build_url(ESI_CATEGORY_REGION, eve_id) + +def solar_system_url(eve_id: int) -> str: + return _build_url(ESI_CATEGORY_SOLARSYSTEM, eve_id) \ No newline at end of file diff --git a/allianceauth/eveonline/templatetags/__init__.py b/allianceauth/eveonline/templatetags/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/allianceauth/eveonline/templatetags/evelinks.py b/allianceauth/eveonline/templatetags/evelinks.py new file mode 100644 index 00000000..f19aaddf --- /dev/null +++ b/allianceauth/eveonline/templatetags/evelinks.py @@ -0,0 +1,286 @@ +# This module defines template tags for evelinks URLs and eve image URLs +# +# Many tags will work both with their respective eveonline object +# and their respective eve entity ID +# +# Example: +# character URL on evewho: {{ my_character|evewho_character_url}} +# character URL on evewho: {{ 1456384556|evewho_character_url}} +# +# For more examples see examples.html +# +# To add templatetags for additional providers just add the respective +# template functions and let them call the generic functions + +from django import template + +from ..models import EveCharacter, EveCorporationInfo, EveAllianceInfo +from ..evelinks import evewho, dotlan, zkillboard + +register = template.Library() + +_DEFAULT_IMAGE_SIZE = 32 + + +# generic functions + +def _generic_character_url( + provider: object, + obj_prop: str, + eve_obj: EveCharacter +) -> str: + """returns character URL for given provider and object""" + my_func = getattr(provider, 'character_url') + if isinstance(eve_obj, EveCharacter): + return my_func(getattr(eve_obj, obj_prop)) + + elif eve_obj is None: + return '' + + else: + return my_func(eve_obj) + + +def _generic_corporation_url( + provider: object, + obj_prop: str, + eve_obj: object +) -> str: + """returns corporation URL for given provider and object""" + my_func = getattr(provider, 'corporation_url') + if isinstance(eve_obj, (EveCharacter, EveCorporationInfo)): + return my_func(getattr(eve_obj, obj_prop)) + + elif eve_obj is None: + return '' + + else: + return my_func(eve_obj) + + +def _generic_alliance_url( + provider: object, + obj_prop: str, + eve_obj: object +) -> str: + """returns alliance URL for given provider and object""" + my_func = getattr(provider, 'alliance_url') + + if isinstance(eve_obj, EveCharacter): + if eve_obj.alliance_id: + return my_func(getattr(eve_obj, obj_prop)) + else: + return '' + + elif isinstance(eve_obj, EveAllianceInfo): + return my_func(getattr(eve_obj, obj_prop)) + + elif eve_obj is None: + return '' + + else: + return my_func(eve_obj) + + +def _generic_evelinks_url( + provider: object, + provider_func: str, + eve_obj: object +) -> str: + """returns evelinks URL for given provider, function and object""" + my_func = getattr(provider, provider_func) + if eve_obj is None: + return '' + + else: + return my_func(eve_obj) + + +# evewho + +@register.filter +def evewho_character_url(eve_obj: EveCharacter) -> str: + """generates an evewho URL for the given object + Works with allianceauth.eveonline objects and eve entity IDs + Returns URL or empty string + """ + return _generic_character_url(evewho, 'character_id', eve_obj) + + +@register.filter +def evewho_corporation_url(eve_obj: object) -> str: + """generates an evewho URL for the given object + Works with allianceauth.eveonline objects and eve entity IDs + Returns URL or empty string + """ + return _generic_corporation_url(evewho, 'corporation_id', eve_obj) + + +@register.filter +def evewho_alliance_url(eve_obj: object) -> str: + """generates an evewho URL for the given object + Works with allianceauth.eveonline objects and eve entity IDs + Returns URL or empty string + """ + return _generic_alliance_url(evewho, 'alliance_id', eve_obj) + + +# dotlan + +@register.filter +def dotlan_corporation_url(eve_obj: object) -> str: + """generates a dotlan URL for the given object + Works with allianceauth.eveonline objects and eve entity names + Returns URL or empty string + """ + return _generic_corporation_url(dotlan, 'corporation_name', eve_obj) + + +@register.filter +def dotlan_alliance_url(eve_obj: object) -> str: + """generates a dotlan URL for the given object + Works with allianceauth.eveonline objects and eve entity names + Returns URL or empty string + """ + return _generic_alliance_url(dotlan, 'alliance_name', eve_obj) + + +@register.filter +def dotlan_region_url(eve_obj: object) -> str: + """generates a dotlan URL for the given object + Works with eve entity names + Returns URL or empty string + """ + return _generic_evelinks_url(dotlan, 'region_url', eve_obj) + + +@register.filter +def dotlan_solar_system_url(eve_obj: object) -> str: + """generates a dotlan URL for the given object + Works with eve entity names + Returns URL or empty string + """ + return _generic_evelinks_url(dotlan, 'solar_system_url', eve_obj) + + +#zkillboard + +@register.filter +def zkillboard_character_url(eve_obj: EveCharacter) -> str: + """generates a zkillboard URL for the given object + Works with allianceauth.eveonline objects and eve entity IDs + Returns URL or empty string + """ + return _generic_character_url(zkillboard, 'character_id', eve_obj) + + +@register.filter +def zkillboard_corporation_url(eve_obj: object) -> str: + """generates a zkillboard URL for the given object + Works with allianceauth.eveonline objects and eve entity IDs + Returns URL or empty string + """ + return _generic_corporation_url(zkillboard, 'corporation_id', eve_obj) + + +@register.filter +def zkillboard_alliance_url(eve_obj: object) -> str: + """generates a zkillboard URL for the given object + Works with allianceauth.eveonline objects and eve entity IDs + Returns URL or empty string + """ + return _generic_alliance_url(zkillboard, 'alliance_id', eve_obj) + + +@register.filter +def zkillboard_region_url(eve_obj: object) -> str: + """generates a zkillboard URL for the given object + Works with eve entity IDs + Returns URL or empty string + """ + return _generic_evelinks_url(zkillboard, 'region_url', eve_obj) + + +@register.filter +def zkillboard_solar_system_url(eve_obj: object) -> str: + """generates zkillboard URL for the given object + Works with eve entity IDs + Returns URL or empty string + """ + return _generic_evelinks_url(zkillboard, 'solar_system_url', eve_obj) + + +# image urls + + +@register.filter +def character_portrait_url( + eve_obj: object, + size: int = _DEFAULT_IMAGE_SIZE +) -> str: + """generates an image URL for the given object + Works with EveCharacter objects or character IDs + Returns URL or empty string + """ + if isinstance(eve_obj, EveCharacter): + return eve_obj.portrait_url(size) + + elif eve_obj is None: + return '' + + else: + try: + return EveCharacter.generic_portrait_url(eve_obj, size) + except ValueError: + return '' + + +@register.filter +def corporation_logo_url( + eve_obj: object, + size: int = _DEFAULT_IMAGE_SIZE +) -> str: + """generates image URL for the given object + Works with EveCharacter, EveCorporationInfo objects or corporation IDs + Returns URL or empty string + """ + if isinstance(eve_obj, EveCorporationInfo): + return eve_obj.logo_url(size) + + elif isinstance(eve_obj, EveCharacter): + return eve_obj.corporation_logo_url(size) + + elif eve_obj is None: + return '' + + else: + try: + return EveCorporationInfo.generic_logo_url(eve_obj, size) + except ValueError: + return '' + + +@register.filter +def alliance_logo_url( + eve_obj: object, + size: int = _DEFAULT_IMAGE_SIZE +) -> str: + """generates image URL for the given object + Works with EveCharacter, EveAllianceInfo objects or alliance IDs + Returns URL or empty string + """ + if isinstance(eve_obj, EveAllianceInfo): + return eve_obj.logo_url(size) + + elif isinstance(eve_obj, EveCharacter): + return eve_obj.alliance_logo_url(size) + + elif eve_obj is None: + return '' + + else: + try: + return EveAllianceInfo.generic_logo_url(eve_obj, size) + except ValueError: + return '' + diff --git a/allianceauth/eveonline/templatetags/examples.html b/allianceauth/eveonline/templatetags/examples.html new file mode 100644 index 00000000..61e5d096 --- /dev/null +++ b/allianceauth/eveonline/templatetags/examples.html @@ -0,0 +1,84 @@ + + +{% extends 'allianceauth/base.html' %} +{% load evelinks %} + +{% block page_title %}Evelinks examples{% endblock %} + +{% block content %} + +
+

Evelinks templatetags examples

+
+ +

profile URLs

+ + +
+ +

image URLs

+ +
+ +
+

character from ID:

+

character from character object:

+
+ +
+

corporation from ID:

+

corporation from character object:

+

corporation from corporation object:

+
+ +
+

alliance from ID:

+

alliance from character object:

+

alliance from alliance object:

+
+ +
+ +
+ + +{% endblock %} diff --git a/allianceauth/groupmanagement/templates/groupmanagement/audit.html b/allianceauth/groupmanagement/templates/groupmanagement/audit.html index 8cdad2cd..7010ea47 100644 --- a/allianceauth/groupmanagement/templates/groupmanagement/audit.html +++ b/allianceauth/groupmanagement/templates/groupmanagement/audit.html @@ -8,43 +8,47 @@

{% include 'groupmanagement/menu.html' %} -
-

{{ group }} Audit Log

-

All times displayed are EVE/UTC.

- {% if entries %} -
- - - - - - - - - - - - {% for entry in entries %} - - - - - - - {% if entry.request_type is None %} - - {% else %} - - {% endif %} - - - {% endfor %} - -
{% trans "Date/Time" %}{% trans "Requestor" %}{% trans "Main Character" %}{% trans "Group" %}{% trans "Type" %}{% trans "Action" %}{% trans "Actor" %}
{{ entry.date }}{{ entry.requestor }}{{ entry.req_char }}{{ entry.group }}{{ entry.type_to_str }} Removed{{ entry.action_to_str }}{{ entry.request_actor }}
-
- {% else %} -
{% trans "No entries found for this group." %}
- {% endif %} +
+
+ {{ group }} - {% trans 'Audit Log' %} +
+
+

All times displayed are EVE/UTC.

+ {% if entries %} +
+ + + + + + + + + + + + {% for entry in entries %} + + + + + + + {% if entry.request_type is None %} + + {% else %} + + {% endif %} + + + {% endfor %} + +
{% trans "Date/Time" %}{% trans "Requestor" %}{% trans "Main Character" %}{% trans "Group" %}{% trans "Type" %}{% trans "Action" %}{% trans "Actor" %}
{{ entry.date }}{{ entry.requestor }}{{ entry.req_char }}{{ entry.group }}{{ entry.type_to_str }} Removed{{ entry.action_to_str }}{{ entry.request_actor }}
+
+ {% else %} +
{% trans "No entries found for this group." %}
+ {% endif %} +
{% endblock %} diff --git a/allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html b/allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html index 1b8ab8f7..0874faf2 100644 --- a/allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html +++ b/allianceauth/groupmanagement/templates/groupmanagement/groupmembers.html @@ -1,6 +1,7 @@ {% extends "allianceauth/base.html" %} {% load staticfiles %} {% load i18n %} +{% load evelinks %} {% block page_title %}{% trans "Group Members" %}{% endblock page_title %} {% block extra_css %}{% endblock extra_css %} @@ -9,35 +10,62 @@

{% include 'groupmanagement/menu.html' %} -

{{ group.name }} {% trans 'Members' %}

-
- {% if group.user_set %} - - - - - - - - - {% for member in members %} - - - - - - - - {% endfor %} -
{% trans "User" %}{% trans "Character" %}{% trans "Corp" %}{% trans "Alliance" %}{% trans "Action" %}
{{ member.user.username }}{{ member.main_char.character_name }}{{ member.main_char.corporation_name }}{{ member.main_char.alliance_name }} - - - -
- {% else %} -
{% trans "No group members to list." %}
- {% endif %} + +
+
+ {{ group.name }} - {% trans 'Members' %} +
+
+
+ {% if group.user_set %} + + + + + + + + + + {% for member in members %} + + + + + + + + + {% endfor %} +
{% trans "Leader" %}{% trans "Portrait" %}{% trans "Character" %}{% trans "Corporation" %}{% trans "Alliance" %}{% trans "Action" %}
+ {% if member.is_leader %} + + {% endif %} + + + + + {{ member.main_char.character_name }} + + + + {{ member.main_char.corporation_name }} + + + + {{ member.main_char.alliance_name|default_if_none:"" }} + + + + + +
+ {% else %} +
{% trans "No group members to list." %}
+ {% endif %} +
+
{% endblock content %} diff --git a/allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html b/allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html index 5e47a0be..dd6584cf 100644 --- a/allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html +++ b/allianceauth/groupmanagement/templates/groupmanagement/groupmembership.html @@ -9,48 +9,52 @@

{% include 'groupmanagement/menu.html' %} -
- {% if groups %} -

Groups

- - - - - - - - - {% for group in groups %} - - - - - - - - {% endfor %} -
{% trans "Name" %}{% trans "Description" %}{% trans "Status" %}{% trans "Member Count" %}{% trans "Action" %}
{{ group.name }}{{ group.authgroup.description }} - {% if group.authgroup.hidden %} - {% trans "Hidden" %} - {% elif group.authgroup.open %} - {% trans "Open" %} - {% else %} - {% trans "Requestable" %} - {% endif %} - - {{ group.num_members }} - - - - - - - -
- {% else %} -
{% trans "No groups to list." %}
- {% endif %} +
+
+ Groups +
+
+ {% if groups %} + + + + + + + + + {% for group in groups %} + + + + + + + + {% endfor %} +
{% trans "Name" %}{% trans "Description" %}{% trans "Status" %}{% trans "Member Count" %}{% trans "Action" %}
{{ group.name }}{{ group.authgroup.description }} + {% if group.authgroup.hidden %} + {% trans "Hidden" %} + {% elif group.authgroup.open %} + {% trans "Open" %} + {% else %} + {% trans "Requestable" %} + {% endif %} + + {{ group.num_members }} + + + + + + + +
+ {% else %} +
{% trans "No groups to list." %}
+ {% endif %} +
{% endblock content %} diff --git a/allianceauth/groupmanagement/templates/groupmanagement/index.html b/allianceauth/groupmanagement/templates/groupmanagement/index.html index c8c09d0c..e44fd4f9 100644 --- a/allianceauth/groupmanagement/templates/groupmanagement/index.html +++ b/allianceauth/groupmanagement/templates/groupmanagement/index.html @@ -1,33 +1,65 @@ {% extends "allianceauth/base.html" %} {% load staticfiles %} {% load i18n %} +{% load evelinks %} {% block page_title %}{% trans "Groups Management" %}{% endblock page_title %} -{% block extra_css %}{% endblock extra_css %} +{% block extra_css %} + + +{% endblock extra_css %} {% block content %}

{% include 'groupmanagement/menu.html' %} + +
+
{% if acceptrequests %} - - - - + + + + + + + {% for acceptrequest in acceptrequests %} - + + + +
{% trans "RequestID" %}{% trans "CharacterName" %}{% trans "GroupName" %}{% trans "Action" %}{% trans "#" %}{% trans "Portrait" %}{% trans "Character" %}{% trans "Corporation" %}{% trans "Alliance" %}{% trans "Group" %}
{{ acceptrequest.id }}{{ acceptrequest.main_char.character_name }} + + + + {{ acceptrequest.main_char.character_name }} + + + + {{ acceptrequest.main_char.corporation_name }} + + + + {{ acceptrequest.main_char.alliance_name|default_if_none:"" }} + + {{ acceptrequest.group.name }} @@ -45,20 +77,41 @@ {% endif %} +
{% if leaverequests %} - - - - + + + + + + + {% for leaverequest in leaverequests %} - + + + +
{% trans "RequestID" %}{% trans "CharacterName" %}{% trans "GroupName" %}{% trans "Action" %}{% trans "#" %}{% trans "Portrait" %}{% trans "Character" %}{% trans "Corporation" %}{% trans "Alliance" %}{% trans "Group" %}
{{ leaverequest.id }}{{ leaverequest.main_char.character_name }} + + + + {{ leaverequest.main_char.character_name }} + + + + {{ leaverequest.main_char.corporation_name }} + + + + {{ leaverequest.main_char.alliance_name|default_if_none:"" }} + + {{ leaverequest.group.name }} @@ -76,6 +129,7 @@ {% endif %} + {% endblock content %} diff --git a/allianceauth/groupmanagement/templates/groupmanagement/menu.html b/allianceauth/groupmanagement/templates/groupmanagement/menu.html index db2751b9..96761d96 100644 --- a/allianceauth/groupmanagement/templates/groupmanagement/menu.html +++ b/allianceauth/groupmanagement/templates/groupmanagement/menu.html @@ -3,25 +3,28 @@ {% load navactive %} diff --git a/allianceauth/groupmanagement/views.py b/allianceauth/groupmanagement/views.py index d0d7381d..0cd86dda 100755 --- a/allianceauth/groupmanagement/views.py +++ b/allianceauth/groupmanagement/views.py @@ -96,32 +96,47 @@ def group_membership_audit(request, group_id): @login_required @user_passes_test(GroupManager.can_manage_groups) def group_membership_list(request, group_id): - logger.debug("group_membership_list called by user %s for group id %s" % (request.user, group_id)) + logger.debug( + "group_membership_list called by user %s " + "for group id %s" % (request.user, group_id) + ) group = get_object_or_404(Group, id=group_id) try: # Check its a joinable group i.e. not corp or internal # And the user has permission to manage it - if not GroupManager.check_internal_group(group) or not GroupManager.can_manage_group(request.user, group): - logger.warning("User %s attempted to view the membership of group %s but permission was denied" % - (request.user, group_id)) + if (not GroupManager.check_internal_group(group) + or not GroupManager.can_manage_group(request.user, group) + ): + logger.warning( + "User %s attempted to view the membership of group %s " + "but permission was denied" % (request.user, group_id) + ) raise PermissionDenied except ObjectDoesNotExist: raise Http404("Group does not exist") + group_leaders = group.authgroup.group_leaders.all() members = list() - - for member in group.user_set.select_related('profile').all().order_by('username'): + for member in \ + group.user_set\ + .all()\ + .select_related('profile')\ + .order_by('profile__main_character__character_name'): members.append({ 'user': member, - 'main_char': member.profile.main_character + 'main_char': member.profile.main_character, + 'is_leader': member in group_leaders }) render_items = {'group': group, 'members': members} - return render(request, 'groupmanagement/groupmembers.html', context=render_items) + return render( + request, 'groupmanagement/groupmembers.html', + context=render_items + ) @login_required diff --git a/allianceauth/optimer/templates/optimer/fleetoptable.html b/allianceauth/optimer/templates/optimer/fleetoptable.html index 8db97a74..31543120 100644 --- a/allianceauth/optimer/templates/optimer/fleetoptable.html +++ b/allianceauth/optimer/templates/optimer/fleetoptable.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load evelinks %} {% block content %} @@ -23,7 +24,7 @@ diff --git a/allianceauth/timerboard/templates/timerboard/view.html b/allianceauth/timerboard/templates/timerboard/view.html index 198af430..4dd4c85a 100644 --- a/allianceauth/timerboard/templates/timerboard/view.html +++ b/allianceauth/timerboard/templates/timerboard/view.html @@ -2,6 +2,7 @@ {% load staticfiles %} {% load i18n %} {% get_current_language as LANGUAGE_CODE %} +{% load evelinks %} {% block page_title %}{% trans "Structure Timer Management" %}{% endblock page_title %} {% block extra_css %}{% endblock extra_css %} @@ -61,7 +62,7 @@ {% endif %}
{{ ops.operation_name }} {{ ops.doctrine }} - {{ ops.system }} + {{ ops.system }} {{ ops.start | date:"Y-m-d H:i" }}
{{ timer.system }} {{ timer.planet_moon }} + href="{{ timer.system|dotlan_solar_system_url }}">{{ timer.system }} {{ timer.planet_moon }} {% if timer.structure == "POCO" %} @@ -220,7 +221,7 @@ {% endif %} - {{ timer.system }} {{ timer.planet_moon }} + {{ timer.system }} {{ timer.planet_moon }} {% if timer.structure == "POCO" %} @@ -381,7 +382,7 @@ {% endif %} - {{ timer.system }} {{ timer.planet_moon }} + {{ timer.system }} {{ timer.planet_moon }} {% if timer.structure == "POCO" %}