Compare commits

..

21 Commits

Author SHA1 Message Date
Col Crunch
98b799d821 Version Bump 2.3.0 2020-01-16 15:28:07 -05:00
Col Crunch
02714956d8 Add CI stage to deploy to pypi on tags. 2020-01-15 23:16:02 -05:00
colcrunch
4d435d58c5 Merge branch 'affiliations' into 'master'
Affiliations for Character updates

See merge request allianceauth/allianceauth!1140
2020-01-16 04:00:58 +00:00
Aaron Kable
1c2fd3be50 Affiliations for Character updates 2020-01-16 04:00:55 +00:00
colcrunch
6222439e21 Merge branch 'fleetup-removal' into 'master'
Fleetup removal

Closes #1179

See merge request allianceauth/allianceauth!1144
2020-01-16 03:54:18 +00:00
colcrunch
46d46ac90b Fleetup removal 2020-01-16 03:54:18 +00:00
colcrunch
a5fe61eb15 Merge branch 'issue-1172' into 'master'
Fix issue #1172: Replace deprecated eve image URLs in apps and services

Closes #1172

See merge request allianceauth/allianceauth!1145
2020-01-16 03:51:16 +00:00
Erik Kalkoken
0bfec36983 Fix issue #1172: Replace deprecated eve image URLs in apps and services 2020-01-16 03:51:16 +00:00
colcrunch
11607ecf24 Merge branch 'tests_eveonline_providers' into 'master'
Add unit tests for eveonline providers and fix coverage counting

See merge request allianceauth/allianceauth!1150
2020-01-16 03:49:16 +00:00
Erik Kalkoken
9970e5535b Add unit tests for eveonline providers and fix coverage counting 2020-01-16 03:49:16 +00:00
Basraah
99492e9c34 Merge branch 'issue-1198' into 'master'
Re-enable automatic testing against all Python versions

Closes #1198

See merge request allianceauth/allianceauth!1149
2020-01-10 06:55:19 +00:00
Erik Kalkoken
1d6ecffb3b Re-enable automatic testing against all Python versions 2020-01-10 06:55:19 +00:00
Basraah
cfb2c55a4b Merge branch 'issue-1177' into 'master'
Fix issue #1177: Add project description and classifiers to PyPI page

Closes #1177

See merge request allianceauth/allianceauth!1143
2019-12-13 02:14:54 +00:00
ErikKalkoken
e24d29f1d3 Fix issue #1177 2019-12-05 13:02:31 +01:00
Basraah
debd6ef2b9 Version bump to v2.2.2 2019-12-05 02:37:22 +00:00
Basraah
58e9c21e4f Merge branch 'issue-1176' into 'master'
Fix issue #1176: Prevent Django 3 installation

Closes #1176

See merge request allianceauth/allianceauth!1142
2019-12-05 02:36:03 +00:00
ErikKalkoken
c7c3083e3e Fix issue #1176: Prevent Django 3 installation 2019-12-04 14:02:03 +01:00
Basraah
63d061e9f2 Merge branch 'bug-1165' into 'master'
add fix and unittest for issue #1165

See merge request allianceauth/allianceauth!1137
2019-09-12 09:53:05 +00:00
ErikKalkoken
1887bdb90a add fix and unittest for issue #1165 2019-09-08 23:09:20 +02:00
Basraah
69addb068a Merge branch 'patch-3' into 'master'
Add discord warning for tasks

See merge request allianceauth/allianceauth!1136
2019-08-30 03:22:49 +00:00
Aaron Kable
a62c3ce0f9 Add discord warning for tasks 2019-08-30 03:22:49 +00:00
44 changed files with 1441 additions and 1624 deletions

View File

@@ -8,6 +8,8 @@ omit =
*/example/*
*/project_template/*
*/bin/*
*/tests/*
*/tests.py
[report]
exclude_lines =

View File

@@ -1,33 +1,36 @@
# Official language image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/python/tags/
stages:
- "test"
- deploy
.job_template: &job_definition
# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache"
# Pip's cache doesn't store the python packages
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
#
# If you want to also cache the installed packages, you have to install
# them in a virtualenv and cache it as well.
cache:
paths:
- .cache/pip
- venv/
before_script:
- python -V # Print out python version for debugging
- pip install virtualenv tox
- virtualenv venv
- source venv/bin/activate
coverage: '/TOTAL.+ ([0-9]{1,3}%)/'
before_script:
- python -V
- pip install wheel tox
py36-dj20:
<<: *job_definition
test-3.5:
image: python:3.5-stretch
script:
- tox -e py35
test-3.6:
image: python:3.6-stretch
script:
- tox -e py36
test-3.7:
image: python:3.7-stretch
script:
- tox -e py37
deploy_production:
stage: deploy
image: python:3.6-stretch
before_script:
- pip install twine
script:
- export TOXENV=py36-dj20
- tox
- python setup.py sdist
- twine upload dist/*
only:
- tags

View File

@@ -1,6 +1,6 @@
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
__version__ = '2.2.1'
__version__ = '2.3.0'
NAME = 'Alliance Auth v%s' % __version__
default_app_config = 'allianceauth.apps.AllianceAuthConfig'

View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def remove_permission(apps, schema_editor):
User = apps.get_model('auth', 'User')
ContentType = apps.get_model('contenttypes', 'ContentType')
Permission = apps.get_model('auth', 'Permission')
ct = ContentType.objects.get_for_model(User)
Permission.objects.filter(codename="view_fleetup", content_type=ct, name="view_fleetup").delete()
class Migration(migrations.Migration):
dependencies = [
('authentication', '0016_ownershiprecord'),
]
operations = [
migrations.RunPython(remove_permission, migrations.RunPython.noop)
]

View File

@@ -20,8 +20,8 @@
<div class="col-lg-4 col-sm-2">
<table class="table">
<tr>
<td class="text-center"><img class="ra-avatar"
src="{{ main.portrait_url_128 }}">
<td class="text-center">
<img class="ra-avatar"src="{{ main.portrait_url_128 }}">
</td>
</tr>
<tr>
@@ -32,8 +32,8 @@
<div class="col-lg-4 col-sm-2">
<table class="table">
<tr>
<td class="text-center"><img class="ra-avatar"
src="https://image.eveonline.com/Corporation/{{ main.corporation_id }}_128.png">
<td class="text-center">
<img class="ra-avatar"src="{{ main.corporation_logo_url_128 }}">
</td>
</tr>
<tr>
@@ -45,8 +45,8 @@
{% if main.alliance_id %}
<table class="table">
<tr>
<td class="text-center"><img class="ra-avatar"
src="https://image.eveonline.com/Alliance/{{ main.alliance_id }}_128.png">
<td class="text-center">
<img class="ra-avatar"src="{{ main.alliance_logo_url_128 }}">
</td>
</tr>
<tr>

View File

@@ -6,7 +6,8 @@ from bravado.exception import HTTPForbidden
from django.db import models
from esi.errors import TokenError
from esi.models import Token
from allianceauth.eveonline.models import EveCorporationInfo, EveCharacter
from allianceauth.eveonline.models import EveCorporationInfo, EveCharacter,\
EveAllianceInfo
from allianceauth.notifications import notify
from allianceauth.corputils.managers import CorpStatsManager
@@ -137,13 +138,13 @@ class CorpStats(models.Model):
return self.token.user == user or self.visible_to(user)
def corp_logo(self, size=128):
return "https://image.eveonline.com/Corporation/%s_%s.png" % (self.corp.corporation_id, size)
return self.corp.logo_url(size)
def alliance_logo(self, size=128):
if self.corp.alliance:
return "https://image.eveonline.com/Alliance/%s_%s.png" % (self.corp.alliance.alliance_id, size)
return self.corp.alliance.logo_url(size)
else:
return "https://image.eveonline.com/Alliance/1_%s.png" % size
return EveAllianceInfo.generic_logo_url(1, size)
class CorpMember(models.Model):
@@ -185,10 +186,16 @@ class CorpMember(models.Model):
return CharacterOwnership.objects.filter(character__character_id=self.character_id).exists()
def portrait_url(self, size=32):
return "https://image.eveonline.com/Character/%s_%s.jpg" % (self.character_id, size)
return EveCharacter.generic_portrait_url(self.character_id, size)
def __getattr__(self, item):
if item.startswith('portrait_url_'):
size = item.strip('portrait_url_')
return self.portrait_url(size)
return self.__getattribute__(item)
@property
def portrait_url_32(self):
return self.portrait_url(32)
@property
def portrait_url_64(self):
return self.portrait_url(64)
@property
def portrait_url_128(self):
return self.portrait_url(128)

View File

@@ -80,7 +80,7 @@
<tr>
<td class="text-center" style="width:5%">
<div class="thumbnail" style="border: 0 none; box-shadow: none; background: transparent;">
<img src="https://image.eveonline.com/Character/{{ alt.character_id }}_32.jpg" class="img-circle">
<img src="{{ alt.portrait_url_32 }}" class="img-circle">
</div>
</td>
<td class="text-center" style="width:30%">{{ alt.character_name }}</td>

View File

@@ -205,13 +205,13 @@ class CorpStatsPropertiesTestCase(TestCase):
AuthUtils.connect_signals()
def test_logos(self):
self.assertEqual(self.corpstats.corp_logo(size=128), 'https://image.eveonline.com/Corporation/2_128.png')
self.assertEqual(self.corpstats.alliance_logo(size=128), 'https://image.eveonline.com/Alliance/1_128.png')
self.assertEqual(self.corpstats.corp_logo(size=128), 'https://images.evetech.net/corporations/2/logo?size=128')
self.assertEqual(self.corpstats.alliance_logo(size=128), 'https://images.evetech.net/alliances/1/logo?size=128')
alliance = EveAllianceInfo.objects.create(alliance_name='test alliance', alliance_id='3', alliance_ticker='TEST', executor_corp_id='2')
self.corp.alliance = alliance
self.corp.save()
self.assertEqual(self.corpstats.alliance_logo(size=128), 'https://image.eveonline.com/Alliance/3_128.png')
self.assertEqual(self.corpstats.alliance_logo(size=128), 'https://images.evetech.net/alliances/3/logo?size=128')
alliance.delete()
@@ -273,5 +273,7 @@ class CorpMemberTestCase(TestCase):
AuthUtils.connect_signals()
def test_portrait_url(self):
self.assertEquals(self.member.portrait_url(size=32), 'https://image.eveonline.com/Character/2_32.jpg')
self.assertEquals(self.member.portrait_url(size=32), 'https://images.evetech.net/characters/2/portrait?size=32')
self.assertEquals(self.member.portrait_url(size=32), self.member.portrait_url_32)
self.assertEquals(self.member.portrait_url(size=64), self.member.portrait_url_64)
self.assertEquals(self.member.portrait_url(size=128), self.member.portrait_url_128)

View File

@@ -7,6 +7,90 @@ from .managers import EveAllianceManager, EveAllianceProviderManager
from . import providers
EVE_IMAGE_SERVER_URL = 'https://images.evetech.net'
def _eve_entity_image_url(
category: str,
id: int,
size: int = 32,
variant: str = None,
tenant: str = None,
) -> str:
"""returns image URL for an Eve Online ID.
Supported categories: `alliance`, `corporation`, `character`
Arguments:
- category: category of the ID
- id: Eve ID of the entity
- size: (optional) render size of the image.must be between 32 (default) and 1024
- variant: (optional) image variant for category. currently not relevant.
- tentant: (optional) Eve Server, either `tranquility`(default) or `singularity`
Returns:
- URL string for the requested image on the Eve image server
Exceptions:
- Throws ValueError on invalid input
"""
# input validations
categories = {
'alliance': {
'endpoint': 'alliances',
'variants': [
'logo'
]
},
'corporation': {
'endpoint': 'corporations',
'variants': [
'logo'
]
},
'character': {
'endpoint': 'characters',
'variants': [
'portrait'
]
}
}
tenants = ['tranquility', 'singularity']
if size < 32 or size > 1024 or (size & (size - 1) != 0):
raise ValueError('Invalid size: {}'.format(size))
if category not in categories:
raise ValueError('Invalid category {}'.format(category))
else:
endpoint = categories[category]['endpoint']
if variant:
if variant not in categories[category]['variants']:
raise ValueError('Invalid variant {} for category {}'.format(
variant,
category
))
else:
variant = categories[category]['variants'][0]
if tenant and tenant not in tenants:
raise ValueError('Invalid tentant {}'.format(tenant))
# compose result URL
result = '{}/{}/{}/{}?size={}'.format(
EVE_IMAGE_SERVER_URL,
endpoint,
id,
variant,
size
)
if tenant:
result += '&tenant={}'.format(tenant)
return result
class EveAllianceInfo(models.Model):
alliance_id = models.CharField(max_length=254, unique=True)
alliance_name = models.CharField(max_length=254, unique=True)
@@ -35,14 +119,34 @@ class EveAllianceInfo(models.Model):
def __str__(self):
return self.alliance_name
def logo_url(self, size=32):
return "https://image.eveonline.com/Alliance/%s_%s.png" % (self.alliance_id, size)
@staticmethod
def generic_logo_url(alliance_id: int, size: int = 32) -> str:
"""image URL for the given alliance ID"""
return _eve_entity_image_url('alliance', alliance_id, size)
def logo_url(self, size:int = 32) -> str:
"""image URL of this alliance"""
return self.generic_logo_url(self.alliance_id, size)
def __getattr__(self, item):
if item.startswith('logo_url_'):
size = item.strip('logo_url_')
return self.logo_url(size)
return self.__getattribute__(item)
@property
def logo_url_32(self) -> str:
"""image URL for this alliance"""
return self.logo_url(32)
@property
def logo_url_64(self) -> str:
"""image URL for this alliance"""
return self.logo_url(64)
@property
def logo_url_128(self) -> str:
"""image URL for this alliance"""
return self.logo_url(128)
@property
def logo_url_256(self) -> str:
"""image URL for this alliance"""
return self.logo_url(256)
class EveCorporationInfo(models.Model):
@@ -69,14 +173,34 @@ class EveCorporationInfo(models.Model):
def __str__(self):
return self.corporation_name
def logo_url(self, size=32):
return "https://image.eveonline.com/Corporation/%s_%s.png" % (self.corporation_id, size)
@staticmethod
def generic_logo_url(corporation_id: int, size: int = 32) -> str:
"""image URL for the given corporation ID"""
return _eve_entity_image_url('corporation', corporation_id, size)
def __getattr__(self, item):
if item.startswith('logo_url_'):
size = item.strip('logo_url_')
return self.logo_url(size)
return self.__getattribute__(item)
def logo_url(self, size:int = 32) -> str:
"""image URL for this corporation"""
return self.generic_logo_url(self.corporation_id, size)
@property
def logo_url_32(self) -> str:
"""image URL for this corporation"""
return self.logo_url(32)
@property
def logo_url_64(self) -> str:
"""image URL for this corporation"""
return self.logo_url(64)
@property
def logo_url_128(self) -> str:
"""image URL for this corporation"""
return self.logo_url(128)
@property
def logo_url_256(self) -> str:
"""image URL for this corporation"""
return self.logo_url(256)
class EveCharacter(models.Model):
@@ -128,11 +252,82 @@ class EveCharacter(models.Model):
def __str__(self):
return self.character_name
def portrait_url(self, size=32):
return "https://image.eveonline.com/Character/%s_%s.jpg" % (self.character_id, size)
@staticmethod
def generic_portrait_url(character_id: int, size: int = 32) -> str:
"""image URL for the given character ID"""
return _eve_entity_image_url('character', character_id, size)
def __getattr__(self, item):
if item.startswith('portrait_url_'):
size = item.strip('portrait_url_')
return self.portrait_url(size)
return self.__getattribute__(item)
def portrait_url(self, size = 32) -> str:
"""image URL for this character"""
return self.generic_portrait_url(self.character_id, size)
@property
def portrait_url_32(self) -> str:
"""image URL for this character"""
return self.portrait_url(32)
@property
def portrait_url_64(self) -> str:
"""image URL for this character"""
return self.portrait_url(64)
@property
def portrait_url_128(self) -> str:
"""image URL for this character"""
return self.portrait_url(128)
@property
def portrait_url_256(self) -> str:
"""image URL for this character"""
return self.portrait_url(256)
def corporation_logo_url(self, size = 32) -> str:
"""image URL for corporation of this character"""
return EveCorporationInfo.generic_logo_url(self.corporation_id, size)
@property
def corporation_logo_url_32(self) -> str:
"""image URL for corporation of this character"""
return self.corporation_logo_url(32)
@property
def corporation_logo_url_64(self) -> str:
"""image URL for corporation of this character"""
return self.corporation_logo_url(64)
@property
def corporation_logo_url_128(self) -> str:
"""image URL for corporation of this character"""
return self.corporation_logo_url(128)
@property
def corporation_logo_url_256(self) -> str:
"""image URL for corporation of this character"""
return self.corporation_logo_url(256)
def alliance_logo_url(self, size = 32) -> str:
"""image URL for alliance of this character or empty string"""
if self.alliance_id:
return EveAllianceInfo.generic_logo_url(self.alliance_id, size)
else:
return ''
@property
def alliance_logo_url_32(self) -> str:
"""image URL for alliance of this character or empty string"""
return self.alliance_logo_url(32)
@property
def alliance_logo_url_64(self) -> str:
"""image URL for alliance of this character or empty string"""
return self.alliance_logo_url(64)
@property
def alliance_logo_url_128(self) -> str:
"""image URL for alliance of this character or empty string"""
return self.alliance_logo_url(128)
@property
def alliance_logo_url_256(self) -> str:
"""image URL for alliance of this character or empty string"""
return self.alliance_logo_url(256)

View File

@@ -12,6 +12,7 @@ get_alliances_alliance_id_corporations
get_corporations_corporation_id
get_characters_character_id
get_universe_types_type_id
post_character_affiliation
"""
@@ -189,11 +190,13 @@ class EveSwaggerProvider(EveProvider):
def get_character(self, character_id):
try:
data = self.client.Character.get_characters_character_id(character_id=character_id).result()
affiliation = self.client.Character.post_characters_affiliation(characters=[character_id]).result()[0]
model = Character(
id=character_id,
name=data['name'],
corp_id=data['corporation_id'],
alliance_id=data['alliance_id'] if 'alliance_id' in data else None,
corp_id=affiliation['corporation_id'],
alliance_id=affiliation['alliance_id'] if 'alliance_id' in affiliation else None,
)
return model
except (HTTPNotFound, HTTPUnprocessableEntity):

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,104 @@
from unittest.mock import Mock, patch
from django.test import TestCase
from ..models import EveCharacter, EveCorporationInfo, EveAllianceInfo
from ..models import EveCharacter, EveCorporationInfo, \
EveAllianceInfo, _eve_entity_image_url
from ..providers import Alliance, Corporation, Character
class EveUniverseImageUrlTestCase(TestCase):
"""unit test for _eve_entity_image_url()"""
def test_sizes(self):
self.assertEqual(
_eve_entity_image_url('character', 42),
'https://images.evetech.net/characters/42/portrait?size=32'
)
self.assertEqual(
_eve_entity_image_url('character', 42, size=32),
'https://images.evetech.net/characters/42/portrait?size=32'
)
self.assertEqual(
_eve_entity_image_url('character', 42, size=64),
'https://images.evetech.net/characters/42/portrait?size=64'
)
self.assertEqual(
_eve_entity_image_url('character', 42, size=128),
'https://images.evetech.net/characters/42/portrait?size=128'
)
self.assertEqual(
_eve_entity_image_url('character', 42, size=256),
'https://images.evetech.net/characters/42/portrait?size=256'
)
self.assertEqual(
_eve_entity_image_url('character', 42, size=512),
'https://images.evetech.net/characters/42/portrait?size=512'
)
self.assertEqual(
_eve_entity_image_url('character', 42, size=1024),
'https://images.evetech.net/characters/42/portrait?size=1024'
)
with self.assertRaises(ValueError):
_eve_entity_image_url('corporation', 42, size=-5)
with self.assertRaises(ValueError):
_eve_entity_image_url('corporation', 42, size=0)
with self.assertRaises(ValueError):
_eve_entity_image_url('corporation', 42, size=31)
with self.assertRaises(ValueError):
_eve_entity_image_url('corporation', 42, size=1025)
with self.assertRaises(ValueError):
_eve_entity_image_url('corporation', 42, size=2048)
def test_variant(self):
self.assertEqual(
_eve_entity_image_url('character', 42, variant='portrait'),
'https://images.evetech.net/characters/42/portrait?size=32'
)
self.assertEqual(
_eve_entity_image_url('alliance', 42, variant='logo'),
'https://images.evetech.net/alliances/42/logo?size=32'
)
with self.assertRaises(ValueError):
_eve_entity_image_url('character', 42, variant='logo')
def test_alliance(self):
self.assertEqual(
_eve_entity_image_url('alliance', 42),
'https://images.evetech.net/alliances/42/logo?size=32'
)
self.assertEqual(
_eve_entity_image_url('corporation', 42),
'https://images.evetech.net/corporations/42/logo?size=32'
)
self.assertEqual(
_eve_entity_image_url('character', 42),
'https://images.evetech.net/characters/42/portrait?size=32'
)
with self.assertRaises(ValueError):
_eve_entity_image_url('station', 42)
def test_tenants(self):
self.assertEqual(
_eve_entity_image_url('character', 42, tenant='tranquility'),
'https://images.evetech.net/characters/42/portrait?size=32&tenant=tranquility'
)
self.assertEqual(
_eve_entity_image_url('character', 42, tenant='singularity'),
'https://images.evetech.net/characters/42/portrait?size=32&tenant=singularity'
)
with self.assertRaises(ValueError):
_eve_entity_image_url('character', 42, tenant='xxx')
class EveCharacterTestCase(TestCase):
def test_corporation_prop(self):
"""
@@ -119,3 +215,410 @@ class EveCharacterTestCase(TestCase):
)
self.assertIsNone(character.alliance)
@patch('allianceauth.eveonline.providers.provider')
def test_update_character(self, mock_provider):
mock_provider.get_corp.return_value = Corporation(
id=2002,
name='Dummy Corp 2',
ticker='DC2',
ceo_id=1001,
members=34,
)
my_character = EveCharacter.objects.create(
character_id='1001',
character_name='Bruce Wayne',
corporation_id='2001',
corporation_name='Dummy Corp 1',
corporation_ticker='DC1',
alliance_id='3001',
alliance_name='Dummy Alliance 1',
)
my_updated_character = Character(
name='Bruce X. Wayne',
corp_id=2002
)
my_character.update_character(my_updated_character)
self.assertEqual(my_character.character_name, 'Bruce X. Wayne')
# todo: add test cases not yet covered, e.g. with alliance
def test_image_url(self):
self.assertEqual(
EveCharacter.generic_portrait_url(42),
_eve_entity_image_url('character', 42)
)
self.assertEqual(
EveCharacter.generic_portrait_url(42, 256),
_eve_entity_image_url('character', 42, 256)
)
def test_portrait_urls(self):
x = EveCharacter(
character_id='42',
character_name='character.name',
corporation_id='123',
corporation_name='corporation.name',
corporation_ticker='ABC',
)
self.assertEqual(
x.portrait_url(),
_eve_entity_image_url('character', 42)
)
self.assertEqual(
x.portrait_url(64),
_eve_entity_image_url('character', 42, size=64)
)
self.assertEqual(
x.portrait_url_32,
_eve_entity_image_url('character', 42, size=32)
)
self.assertEqual(
x.portrait_url_64,
_eve_entity_image_url('character', 42, size=64)
)
self.assertEqual(
x.portrait_url_128,
_eve_entity_image_url('character', 42, size=128)
)
self.assertEqual(
x.portrait_url_256,
_eve_entity_image_url('character', 42, size=256)
)
def test_corporation_logo_urls(self):
x = EveCharacter(
character_id='42',
character_name='character.name',
corporation_id='123',
corporation_name='corporation.name',
corporation_ticker='ABC',
)
self.assertEqual(
x.corporation_logo_url(),
_eve_entity_image_url('corporation', 123)
)
self.assertEqual(
x.corporation_logo_url(256),
_eve_entity_image_url('corporation', 123, size=256)
)
self.assertEqual(
x.corporation_logo_url_32,
_eve_entity_image_url('corporation', 123, size=32)
)
self.assertEqual(
x.corporation_logo_url_64,
_eve_entity_image_url('corporation', 123, size=64)
)
self.assertEqual(
x.corporation_logo_url_128,
_eve_entity_image_url('corporation', 123, size=128)
)
self.assertEqual(
x.corporation_logo_url_256,
_eve_entity_image_url('corporation', 123, size=256)
)
def test_alliance_logo_urls(self):
x = EveCharacter(
character_id='42',
character_name='character.name',
corporation_id='123',
corporation_name='corporation.name',
corporation_ticker='ABC',
)
self.assertEqual(
x.alliance_logo_url(),
''
)
self.assertEqual(
x.alliance_logo_url_32,
''
)
self.assertEqual(
x.alliance_logo_url_64,
''
)
self.assertEqual(
x.alliance_logo_url_128,
''
)
self.assertEqual(
x.alliance_logo_url_256,
''
)
x.alliance_id = 987
self.assertEqual(
x.alliance_logo_url(),
_eve_entity_image_url('alliance', 987)
)
self.assertEqual(
x.alliance_logo_url(128),
_eve_entity_image_url('alliance', 987, size=128)
)
self.assertEqual(
x.alliance_logo_url_32,
_eve_entity_image_url('alliance', 987, size=32)
)
self.assertEqual(
x.alliance_logo_url_64,
_eve_entity_image_url('alliance', 987, size=64)
)
self.assertEqual(
x.alliance_logo_url_128,
_eve_entity_image_url('alliance', 987, size=128)
)
self.assertEqual(
x.alliance_logo_url_256,
_eve_entity_image_url('alliance', 987, size=256)
)
class EveAllianceTestCase(TestCase):
def test_str(self):
my_alliance = EveAllianceInfo(
alliance_id=3001,
alliance_name='Dummy Alliance 1',
alliance_ticker='DA1',
executor_corp_id=2001
)
self.assertEqual(str(my_alliance), 'Dummy Alliance 1')
@patch(
'allianceauth.eveonline.models.EveCorporationInfo.objects.create_corporation'
)
def test_populate_alliance(self, mock_create_corporation):
def create_corp(corp_id):
if corp_id == 2002:
EveCorporationInfo.objects.create(
corporation_id=2002,
corporation_name='Dummy Corporation 2',
corporation_ticker='DC2',
member_count=87,
)
else:
raise ValueError()
mock_EveAllianceProviderManager = Mock()
mock_EveAllianceProviderManager.get_alliance.return_value = \
Alliance(
id=3001,
name='Dummy Alliance 1',
corp_ids=[2001, 2002]
)
mock_create_corporation.side_effect = create_corp
EveCorporationInfo.objects.create(
corporation_id=2001,
corporation_name='Dummy Corporation 1',
corporation_ticker='DC1',
member_count=42,
)
my_alliance = EveAllianceInfo(
alliance_id=3001,
alliance_name='Dummy Alliance 1',
alliance_ticker='DA1',
executor_corp_id=2001
)
my_alliance.provider = mock_EveAllianceProviderManager
my_alliance.save()
my_alliance.populate_alliance()
for corporation in EveCorporationInfo.objects\
.filter(corporation_id__in=[2001, 2002]
):
self.assertEqual(corporation.alliance, my_alliance)
def test_update_alliance_with_object(self):
my_alliance = EveAllianceInfo.objects.create(
alliance_id=3001,
alliance_name='Dummy Alliance 1',
alliance_ticker='DA1',
executor_corp_id=2001
)
updated_alliance = Alliance(
id=3002,
name='Dummy Alliance 2',
corp_ids=[2004],
executor_corp_id=2004
)
my_alliance.update_alliance(updated_alliance)
my_alliance.refresh_from_db()
self.assertEqual(int(my_alliance.executor_corp_id), 2004)
# potential bug
# update_alliance() is only updateting executor_corp_id when object is given
def test_update_alliance_wo_object(self):
mock_EveAllianceProviderManager = Mock()
mock_EveAllianceProviderManager.get_alliance.return_value = \
Alliance(
id=3002,
name='Dummy Alliance 2',
corp_ids=[2004],
executor_corp_id=2004
)
my_alliance = EveAllianceInfo.objects.create(
alliance_id=3001,
alliance_name='Dummy Alliance 1',
alliance_ticker='DA1',
executor_corp_id=2001
)
my_alliance.provider = mock_EveAllianceProviderManager
my_alliance.save()
updated_alliance = Alliance(
name='Dummy Alliance 2',
corp_ids=[2004],
executor_corp_id=2004
)
my_alliance.update_alliance()
my_alliance.refresh_from_db()
self.assertEqual(int(my_alliance.executor_corp_id), 2004)
# potential bug
# update_alliance() is only updateting executor_corp_id nothing else ???
def test_image_url(self):
self.assertEqual(
EveAllianceInfo.generic_logo_url(42),
_eve_entity_image_url('alliance', 42)
)
self.assertEqual(
EveAllianceInfo.generic_logo_url(42, 256),
_eve_entity_image_url('alliance', 42, 256)
)
def test_logo_url(self):
x = EveAllianceInfo(
alliance_id='42',
alliance_name='alliance.name',
alliance_ticker='ABC',
executor_corp_id='123'
)
self.assertEqual(
x.logo_url(),
'https://images.evetech.net/alliances/42/logo?size=32'
)
self.assertEqual(
x.logo_url(64),
'https://images.evetech.net/alliances/42/logo?size=64'
)
self.assertEqual(
x.logo_url_32,
'https://images.evetech.net/alliances/42/logo?size=32'
)
self.assertEqual(
x.logo_url_64,
'https://images.evetech.net/alliances/42/logo?size=64'
)
self.assertEqual(
x.logo_url_128,
'https://images.evetech.net/alliances/42/logo?size=128'
)
self.assertEqual(
x.logo_url_256,
'https://images.evetech.net/alliances/42/logo?size=256'
)
class EveCorporationTestCase(TestCase):
def setUp(self):
my_alliance = EveAllianceInfo.objects.create(
alliance_id=3001,
alliance_name='Dummy Alliance 1',
alliance_ticker='DA1',
executor_corp_id=2001
)
self.my_corp = EveCorporationInfo(
corporation_id=2001,
corporation_name='Dummy Corporation 1',
corporation_ticker='DC1',
member_count=42,
alliance=my_alliance
)
def test_str(self):
self.assertEqual(str(self.my_corp), 'Dummy Corporation 1')
def test_update_corporation_from_object_w_alliance(self):
updated_corp = Corporation(
members=87
)
self.my_corp.update_corporation(updated_corp)
self.assertEqual(self.my_corp.member_count, 87)
# potential bug
# update_corporation updates member_count only
def test_update_corporation_no_object_w_alliance(self):
mock_provider = Mock()
mock_provider.get_corporation.return_value = Corporation(
members=87
)
self.my_corp.provider = mock_provider
self.my_corp.update_corporation()
self.assertEqual(self.my_corp.member_count, 87)
def test_update_corporation_from_object_wo_alliance(self):
my_corp2 = EveCorporationInfo(
corporation_id=2011,
corporation_name='Dummy Corporation 11',
corporation_ticker='DC11',
member_count=6
)
updated_corp = Corporation(
members=8
)
my_corp2.update_corporation(updated_corp)
self.assertEqual(my_corp2.member_count, 8)
self.assertIsNone(my_corp2.alliance)
def test_image_url(self):
self.assertEqual(
EveCorporationInfo.generic_logo_url(42),
_eve_entity_image_url('corporation', 42)
)
self.assertEqual(
EveCorporationInfo.generic_logo_url(42, 256),
_eve_entity_image_url('corporation', 42, 256)
)
def test_logo_url(self):
self.assertEqual(
self.my_corp.logo_url(),
'https://images.evetech.net/corporations/2001/logo?size=32'
)
self.assertEqual(
self.my_corp.logo_url(64),
'https://images.evetech.net/corporations/2001/logo?size=64'
)
self.assertEqual(
self.my_corp.logo_url_32,
'https://images.evetech.net/corporations/2001/logo?size=32'
)
self.assertEqual(
self.my_corp.logo_url_64,
'https://images.evetech.net/corporations/2001/logo?size=64'
)
self.assertEqual(
self.my_corp.logo_url_128,
'https://images.evetech.net/corporations/2001/logo?size=128'
)
self.assertEqual(
self.my_corp.logo_url_256,
'https://images.evetech.net/corporations/2001/logo?size=256'
)

View File

@@ -0,0 +1,545 @@
from unittest.mock import Mock, patch
from bravado.exception import HTTPNotFound, HTTPUnprocessableEntity
from django.test import TestCase
from ..models import EveCharacter, EveCorporationInfo, EveAllianceInfo
from ..providers import ObjectNotFound, Entity, Character, Corporation, \
Alliance, ItemType, EveProvider, EveSwaggerProvider
class TestObjectNotFound(TestCase):
def test_str(self):
x = ObjectNotFound(1001, 'Character')
self.assertEqual(str(x), 'Character with ID 1001 not found.')
class TestEntity(TestCase):
def test_str(self):
x = Entity(1001, 'Bruce Wayne')
self.assertEqual(str(x), 'Bruce Wayne')
# bug - does not return a string
"""
x = Entity(1001)
self.assertEqual(str(x), '')
x = Entity()
self.assertEqual(str(x), '')
"""
def test_repr(self):
x = Entity(1001, 'Bruce Wayne')
self.assertEqual(repr(x), '<Entity (1001): Bruce Wayne>')
x = Entity(1001)
self.assertEqual(repr(x), '<Entity (1001): None>')
x = Entity()
self.assertEqual(repr(x), '<Entity (None): None>')
def test_bool(self):
x = Entity(1001)
self.assertTrue(bool(x))
x = Entity()
self.assertFalse(bool(x))
def test_eq(self):
x1 = Entity(1001)
x2 = Entity(1001)
y = Entity(1002)
z1 = Entity()
z2 = Entity()
self.assertEqual(x1, x2)
self.assertNotEqual(x1, y)
self.assertNotEqual(x1, z1)
self.assertEqual(z1, z2)
# bug: missing _neq_ in Equity to compliment _eq_
class TestCorporation(TestCase):
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_alliance')
def test_alliance_defined(self, mock_provider_get_alliance):
my_alliance = Alliance(
id=3001,
name='Dummy Alliance',
ticker='Dummy',
corp_ids=[2001, 2002, 2003],
executor_corp_id=2001
)
mock_provider_get_alliance.return_value = my_alliance
x = Corporation(alliance_id=3001)
self.assertEqual(
x.alliance,
my_alliance
)
self.assertEqual(
x.alliance,
my_alliance
)
# should fetch alliance once only
self.assertEqual(mock_provider_get_alliance.call_count, 1)
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_alliance')
def test_alliance_not_defined(self, mock_provider_get_alliance):
mock_provider_get_alliance.return_value = None
x = Corporation()
self.assertEqual(
x.alliance,
Entity(None, None)
)
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_character')
def test_ceo(self, mock_provider_get_character):
my_ceo = Character(
id=1001,
name='Bruce Wayne',
corp_id=2001,
alliance_id=3001
)
mock_provider_get_character.return_value = my_ceo
# fetch from provider if not defined
x = Corporation()
self.assertEqual(
x.ceo,
my_ceo
)
# return existing if defined
mock_provider_get_character.return_value = None
self.assertEqual(
x.ceo,
my_ceo
)
self.assertEqual(mock_provider_get_character.call_count, 1)
# bug in ceo(): will try to fetch character even if ceo_id is None
class TestAlliance(TestCase):
def setUp(self):
self.my_alliance = Alliance(
id=3001,
name='Dummy Alliance',
ticker='Dummy',
corp_ids=[2001, 2002, 2003],
executor_corp_id=2001
)
@staticmethod
def _get_corp(corp_id):
corps = {
2001: Corporation(
id=2001,
name='Dummy Corp 1',
alliance_id=3001
),
2002: Corporation(
id=2002,
name='Dummy Corp 2',
alliance_id=3001
),
2003: Corporation(
id=2003,
name='Dummy Corp 3',
alliance_id=3001
),
}
if corp_id:
return corps[int(corp_id)]
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_corp')
def test_corp(self, mock_provider_get_corp):
mock_provider_get_corp.side_effect = TestAlliance._get_corp
# should fetch corp if not in the object
self.assertEqual(
self.my_alliance.corp(2001),
TestAlliance._get_corp(2001)
)
# should fetch corp if not in the object
self.assertEqual(
self.my_alliance.corp(2002),
TestAlliance._get_corp(2002)
)
# should return from the object if its there
self.assertEqual(
self.my_alliance.corp(2001),
TestAlliance._get_corp(2001)
)
# should return from the object if its there
self.assertEqual(
self.my_alliance.corp(2002),
TestAlliance._get_corp(2002)
)
# should be called once by used corp only
self.assertEqual(mock_provider_get_corp.call_count, 2)
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_corp')
def test_corps(self, mock_provider_get_corp):
mock_provider_get_corp.side_effect = TestAlliance._get_corp
self.assertEqual(
self.my_alliance.corps,
[
TestAlliance._get_corp(2001),
TestAlliance._get_corp(2002),
TestAlliance._get_corp(2003),
]
)
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_corp')
def test_executor_corp(self, mock_provider_get_corp):
mock_provider_get_corp.side_effect = TestAlliance._get_corp
self.assertEqual(
self.my_alliance.executor_corp,
TestAlliance._get_corp(2001),
)
x = Alliance()
self.assertEqual(
x.executor_corp,
Entity(None, None),
)
class TestCharacter(TestCase):
def setUp(self):
self.my_character = Character(
id=1001,
name='Bruce Wayne',
corp_id=2001,
alliance_id=3001
)
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_corp')
def test_corp(self, mock_provider_get_corp):
my_corp = Corporation(
id=2001,
name='Dummy Corp 1'
)
mock_provider_get_corp.return_value = my_corp
self.assertEqual(self.my_character.corp, my_corp)
self.assertEqual(self.my_character.corp, my_corp)
# should call the provider one time only
self.assertEqual(mock_provider_get_corp.call_count, 1)
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_alliance')
@patch('allianceauth.eveonline.providers.EveSwaggerProvider.get_corp')
def test_alliance_has_one(
self,
mock_provider_get_corp,
mock_provider_get_alliance,
):
my_corp = Corporation(
id=2001,
name='Dummy Corp 1',
alliance_id=3001
)
mock_provider_get_corp.return_value = my_corp
my_alliance = Alliance(
id=3001,
name='Dummy Alliance 1',
executor_corp_id=2001,
corp_ids=[2001, 2002]
)
mock_provider_get_alliance.return_value = my_alliance
self.assertEqual(self.my_character.alliance, my_alliance)
self.assertEqual(self.my_character.alliance, my_alliance)
# should call the provider one time only
self.assertEqual(mock_provider_get_corp.call_count, 1)
self.assertEqual(mock_provider_get_alliance.call_count, 1)
def test_alliance_has_none(self):
self.my_character.alliance_id = None
self.assertEqual(self.my_character.alliance, Entity(None, None))
class TestItemType(TestCase):
def test_init(self):
x = ItemType(id=99, name='Dummy Item')
self.assertIsInstance(x, ItemType)
class TestEveProvider(TestCase):
def setUp(self):
self.my_provider = EveProvider()
def test_get_alliance(self):
with self.assertRaises(NotImplementedError):
self.my_provider.get_alliance(3001)
def test_get_corp(self):
with self.assertRaises(NotImplementedError):
self.my_provider.get_corp(2001)
def test_get_character(self):
with self.assertRaises(NotImplementedError):
self.my_provider.get_character(1001)
# bug: should be calling NotImplementedError() not NotImplemented
"""
def test_get_itemtype(self):
with self.assertRaises(NotImplementedError):
self.my_provider.get_itemtype(4001)
"""
class TestEveSwaggerProvider(TestCase):
@staticmethod
def esi_get_alliances_alliance_id(alliance_id):
alliances = {
3001: {
'name': 'Dummy Alliance 1',
'ticker': 'DA1',
'executor_corporation_id': 2001
},
3002: {
'name': 'Dummy Alliance 2',
'ticker': 'DA2'
}
}
mock_result = Mock()
if alliance_id in alliances:
mock_result.result.return_value = alliances[alliance_id]
return mock_result
else:
raise HTTPNotFound(Mock())
@staticmethod
def esi_get_alliances_alliance_id_corporations(alliance_id):
alliances = {
3001: [2001, 2002, 2003],
3002: [2004, 2005]
}
mock_result = Mock()
if alliance_id in alliances:
mock_result.result.return_value = alliances[alliance_id]
return mock_result
else:
raise HTTPNotFound(Mock())
@staticmethod
def esi_get_corporations_corporation_id(corporation_id):
corporations = {
2001: {
'name': 'Dummy Corp 1',
'ticker': 'DC1',
'ceo_id': 1001,
'member_count': 42,
'alliance_id': 3001
},
2002: {
'name': 'Dummy Corp 2',
'ticker': 'DC2',
'ceo_id': 1011,
'member_count': 5
}
}
mock_result = Mock()
if corporation_id in corporations:
mock_result.result.return_value = corporations[corporation_id]
return mock_result
else:
raise HTTPNotFound(Mock())
@staticmethod
def esi_get_characters_character_id(character_id):
characters = {
1001: {
'name': 'Bruce Wayne',
'corporation_id': 2001,
'alliance_id': 3001
},
1002: {
'name': 'Peter Parker',
'corporation_id': 2101
}
}
mock_result = Mock()
if character_id in characters:
mock_result.result.return_value = characters[character_id]
return mock_result
else:
raise HTTPNotFound(Mock())
@staticmethod
def esi_post_characters_affiliation(characters):
character_data = {
1001: {
'corporation_id': 2001,
'alliance_id': 3001
},
1002: {
'corporation_id': 2101
}
}
mock_result = Mock()
if isinstance(characters, list):
characters_result = list()
for character_id in characters:
if character_id in character_data:
characters_result.append(character_data[character_id])
else:
raise HTTPNotFound(Mock())
mock_result.result.return_value = characters_result
return mock_result
else:
raise TypeError()
@staticmethod
def esi_get_universe_types_type_id(type_id):
types = {
4001: {
'name': 'Dummy Type 1'
},
4002: {
'name': 'Dummy Type 2'
}
}
mock_result = Mock()
if type_id in types:
mock_result.result.return_value = types[type_id]
return mock_result
else:
raise HTTPNotFound(Mock())
@patch('allianceauth.eveonline.providers.esi_client_factory')
def test_str(self, mock_esi_client_factory):
my_provider = EveSwaggerProvider()
self.assertEqual(str(my_provider), 'esi')
@patch('allianceauth.eveonline.providers.esi_client_factory')
def test_get_alliance(self, mock_esi_client_factory):
mock_esi_client_factory.return_value\
.Alliance.get_alliances_alliance_id \
= TestEveSwaggerProvider.esi_get_alliances_alliance_id
mock_esi_client_factory.return_value\
.Alliance.get_alliances_alliance_id_corporations \
= TestEveSwaggerProvider.esi_get_alliances_alliance_id_corporations
my_provider = EveSwaggerProvider()
# fully defined alliance
my_alliance = my_provider.get_alliance(3001)
self.assertEqual(my_alliance.id, 3001)
self.assertEqual(my_alliance.name, 'Dummy Alliance 1')
self.assertEqual(my_alliance.ticker, 'DA1')
self.assertListEqual(my_alliance.corp_ids, [2001, 2002, 2003])
self.assertEqual(my_alliance.executor_corp_id, 2001)
# alliance missing executor_corporation_id
my_alliance = my_provider.get_alliance(3002)
self.assertEqual(my_alliance.id, 3002)
self.assertEqual(my_alliance.executor_corp_id, None)
# alliance not found
with self.assertRaises(ObjectNotFound):
my_provider.get_alliance(3999)
@patch('allianceauth.eveonline.providers.esi_client_factory')
def test_get_corp(self, mock_esi_client_factory):
mock_esi_client_factory.return_value\
.Corporation.get_corporations_corporation_id \
= TestEveSwaggerProvider.esi_get_corporations_corporation_id
my_provider = EveSwaggerProvider()
# corporation with alliance
my_corp = my_provider.get_corp(2001)
self.assertEqual(my_corp.id, 2001)
self.assertEqual(my_corp.name, 'Dummy Corp 1')
self.assertEqual(my_corp.ticker, 'DC1')
self.assertEqual(my_corp.ceo_id, 1001)
self.assertEqual(my_corp.members, 42)
self.assertEqual(my_corp.alliance_id, 3001)
# corporation wo/ alliance
my_corp = my_provider.get_corp(2002)
self.assertEqual(my_corp.id, 2002)
self.assertEqual(my_corp.alliance_id, None)
# corporation not found
with self.assertRaises(ObjectNotFound):
my_provider.get_corp(2999)
@patch('allianceauth.eveonline.providers.esi_client_factory')
def test_get_character(self, mock_esi_client_factory):
mock_esi_client_factory.return_value\
.Character.get_characters_character_id \
= TestEveSwaggerProvider.esi_get_characters_character_id
mock_esi_client_factory.return_value\
.Character.post_characters_affiliation \
= TestEveSwaggerProvider.esi_post_characters_affiliation
my_provider = EveSwaggerProvider()
# character with alliance
my_character = my_provider.get_character(1001)
self.assertEqual(my_character.id, 1001)
self.assertEqual(my_character.name, 'Bruce Wayne')
self.assertEqual(my_character.corp_id, 2001)
self.assertEqual(my_character.alliance_id, 3001)
# character wo/ alliance
my_character = my_provider.get_character(1002)
self.assertEqual(my_character.id, 1002)
self.assertEqual(my_character.alliance_id, None)
# character not found
with self.assertRaises(ObjectNotFound):
my_provider.get_character(1999)
@patch('allianceauth.eveonline.providers.esi_client_factory')
def test_get_itemtype(self, mock_esi_client_factory):
mock_esi_client_factory.return_value\
.Universe.get_universe_types_type_id \
= TestEveSwaggerProvider.esi_get_universe_types_type_id
my_provider = EveSwaggerProvider()
# type exists
my_type = my_provider.get_itemtype(4001)
self.assertEqual(my_type.id, 4001)
self.assertEqual(my_type.name, 'Dummy Type 1')
# type not found
with self.assertRaises(ObjectNotFound):
my_provider.get_itemtype(4999)

View File

@@ -12,7 +12,7 @@
<div class="panel-heading">{{ character_name }}</div>
<div class="panel-body">
<div class="col-lg-2 col-sm-2">
<img class="ra-avatar img-responsive" src="https://image.eveonline.com/Character/{{ character_id }}_128.jpg">
<img class="ra-avatar img-responsive" src="{{ character_portrait_url }}">
</div>
<div class="col-lg-10 col-sm-2">
<div class="alert alert-danger" role="alert">{% trans "Character not registered!" %}</div>

View File

@@ -29,7 +29,7 @@
{% for memberStat in fatStats %}
<tr>
<td>
<img src="https://image.eveonline.com/Character/{{ memberStat.mainchid }}_32.jpg" class="ra-avatar img-responsive">
<img src="{{ memberStat.mainchar.portrait_url_32 }}" class="ra-avatar img-responsive">
</td>
<td class="text-center">{{ memberStat.mainchar.character_name }}</td>
<td class="text-center">{{ memberStat.n_chars }}</td>

View File

@@ -30,7 +30,7 @@
{% for corpStat in fatStats %}
<tr>
<td>
<img src="https://image.eveonline.com/Corporation/{{ corpStat.corp.corporation_id }}_32.png" class="ra-avatar img-responsive">
<img src="{{ corpStat.corp.logo_url_32 }}" class="ra-avatar img-responsive">
</td>
<td class="text-center"><a href="{% url 'fatlink:statistics_corp' corpStat.corp.corporation_id %}">[{{ corpStat.corp.corporation_ticker }}]</td>
<td class="text-center">{{ corpStat.corp.corporation_name }}</td>

View File

@@ -287,8 +287,13 @@ def click_fatlink_view(request, token, fat_hash=None):
err_messages.append(message[0])
messages.error(request, ' '.join(err_messages))
else:
context = {'character_id': token.character_id,
'character_name': token.character_name}
context = {
'character_id': token.character_id,
'character_name': token.character_name,
'character_portrait_url': EveCharacter.generic_portrait_url(
token.character_id, 128
),
}
return render(request, 'fleetactivitytracking/characternotexisting.html', context=context)
else:
messages.error(request, _('FAT link has expired.'))

View File

@@ -1 +0,0 @@
default_app_config = 'allianceauth.fleetup.apps.FleetupConfig'

View File

@@ -1,6 +0,0 @@
from django.apps import AppConfig
class FleetupConfig(AppConfig):
name = 'allianceauth.fleetup'
label = 'fleetup'

View File

@@ -1,27 +0,0 @@
from allianceauth.services.hooks import MenuItemHook, UrlHook
from allianceauth import hooks
from . import urls
class FleetUpMenu(MenuItemHook):
def __init__(self):
MenuItemHook.__init__(self, 'Fleet-Up',
'fa fa-arrow-up fa-fw',
'fleetup:view',
navactive=['fleetup:'])
def render(self, request):
if request.user.has_perm('auth.view_fleetup'):
return MenuItemHook.render(self, request)
return ''
@hooks.register('menu_item_hook')
def register_menu():
return FleetUpMenu()
@hooks.register('url_hook')
def register_url():
return UrlHook(urls, 'fleetup', r'^fleetup/')

View File

@@ -1,189 +0,0 @@
from django.conf import settings
from django.core.cache import cache
from django.utils import timezone
from datetime import datetime
import logging
import requests
import hashlib
logger = logging.getLogger(__name__)
class FleetUpManager:
APP_KEY = settings.FLEETUP_APP_KEY
USER_ID = settings.FLEETUP_USER_ID
API_ID = settings.FLEETUP_API_ID
GROUP_ID = settings.FLEETUP_GROUP_ID
BASE_URL = "http://api.fleet-up.com/Api.svc/{}/{}/{}".format(APP_KEY, USER_ID, API_ID)
TZ = timezone.utc
def __init__(self):
pass
@classmethod
def _request_cache_key(cls, url):
h = hashlib.sha1()
h.update(url.encode('utf-8'))
return 'FLEETUP_ENDPOINT_' + h.hexdigest()
@classmethod
def _cache_until_seconds(cls, cache_until_json):
# Format comes in like "/Date(1493896236163)/"
try:
epoch_ms = int(cache_until_json[6:-2])
cache_delta = datetime.fromtimestamp(epoch_ms/1000) - datetime.now()
cache_delta_seconds = cache_delta.total_seconds()
if cache_delta_seconds < 0:
return 0
elif cache_delta_seconds > 3600:
return 3600
else:
return cache_delta_seconds
except TypeError:
logger.debug("Couldn't convert CachedUntil time, defaulting to 600 seconds")
return 600
@classmethod
def get_endpoint(cls, url):
try:
cache_key = cls._request_cache_key(url)
cached = cache.get(cache_key)
if cached:
return cached
r = requests.get(url)
r.raise_for_status()
json = r.json()
if json['Success']:
cache.set(cache_key, json, cls._cache_until_seconds(json['CachedUntilUTC']))
return json
except requests.exceptions.ConnectionError:
logger.warning("Can't connect to Fleet-Up API, is it offline?!")
except requests.HTTPError:
logger.exception("Error accessing Fleetup API")
return None
@classmethod
def get_fleetup_members(cls):
url = "{}/GroupCharacters/{}".format(cls.BASE_URL, cls.GROUP_ID)
try:
fmembers = cls.get_endpoint(url)
if not fmembers:
return None
return {row["UserId"]: {"user_id": row["UserId"],
"char_name": row["EveCharName"],
"char_id": row["EveCharId"],
"corporation": row["Corporation"]} for row in fmembers["Data"]}
except (ValueError, UnicodeDecodeError, TypeError):
logger.debug("No fleetup members retrieved.")
return {}
@classmethod
def get_fleetup_operations(cls):
url = "{}/Operations/{}".format(cls.BASE_URL, cls.GROUP_ID)
foperations = cls.get_endpoint(url)
if foperations is None:
return None
return {row["StartString"]: {"subject": row["Subject"],
"start": timezone.make_aware(
datetime.strptime(row["StartString"], "%Y-%m-%d %H:%M:%S"), cls.TZ),
"end": timezone.make_aware(
datetime.strptime(row["EndString"], "%Y-%m-%d %H:%M:%S"), cls.TZ),
"operation_id": row["OperationId"],
"location": row["Location"],
"location_info": row["LocationInfo"],
"details": row["Details"],
"url": row["Url"],
"doctrine": row["Doctrines"],
"organizer": row["Organizer"]} for row in foperations["Data"]}
@classmethod
def get_fleetup_timers(cls):
url = "{}/Timers/{}".format(cls.BASE_URL, cls.GROUP_ID)
ftimers = cls.get_endpoint(url)
if not ftimers:
return None
return {row["ExpiresString"]: {"solarsystem": row["SolarSystem"],
"planet": row["Planet"],
"moon": row["Moon"],
"owner": row["Owner"],
"type": row["Type"],
"timer_type": row["TimerType"],
"expires": timezone.make_aware(
datetime.strptime(row["ExpiresString"], "%Y-%m-%d %H:%M:%S"), cls.TZ),
"notes": row["Notes"]} for row in ftimers["Data"]}
@classmethod
def get_fleetup_doctrines(cls):
url = "{}/Doctrines/{}".format(cls.BASE_URL, cls.GROUP_ID)
fdoctrines = cls.get_endpoint(url)
if not fdoctrines:
return None
return {"fleetup_doctrines": fdoctrines["Data"]}
@classmethod
def get_fleetup_doctrine(cls, doctrinenumber):
url = "{}/DoctrineFittings/{}".format(cls.BASE_URL, doctrinenumber)
fdoctrine = cls.get_endpoint(url)
if not fdoctrine:
return None
return {"fitting_doctrine": fdoctrine}
@classmethod
def get_fleetup_fittings(cls):
url = "{}/Fittings/{}".format(cls.BASE_URL, cls.GROUP_ID)
ffittings = cls.get_endpoint(url)
if not ffittings:
return None
return {row["FittingId"]: {"fitting_id": row["FittingId"],
"name": row["Name"],
"icon_id": row["EveTypeId"],
"hull": row["HullType"],
"shiptype": row["ShipType"],
"estimated": row["EstPrice"],
"faction": row["Faction"],
"categories": row["Categories"],
"last_update":
timezone.make_aware(
datetime.strptime(row["LastUpdatedString"], "%Y-%m-%d %H:%M:%S"), cls.TZ)}
for row in ffittings["Data"]}
@classmethod
def get_fleetup_fitting(cls, fittingnumber):
url = "{}/Fitting/{}".format(cls.BASE_URL, fittingnumber)
try:
ffitting = cls.get_endpoint(url)
if not ffitting:
return None
return {"fitting_data": ffitting["Data"]}
except KeyError:
logger.warning("Failed to retrieve fleetup fitting number %s" % fittingnumber)
return {"fitting_data": {}}
@classmethod
def get_fleetup_doctrineid(cls, fittingnumber):
url = "{}/Fitting/{}".format(cls.BASE_URL, fittingnumber)
try:
fdoctrineid = cls.get_endpoint(url)
if not fdoctrineid:
return None
return fdoctrineid['Data']['Doctrines'][0]['DoctrineId']
except (KeyError, IndexError):
logger.debug("Fleetup fitting number %s not in a doctrine." % fittingnumber)
return {}
@classmethod
def get_fleetup_fitting_eft(cls, fittingnumber):
url = "{}/Fitting/{}/eft".format(cls.BASE_URL, fittingnumber)
try:
ffittingeft = cls.get_endpoint(url)
if not ffittingeft:
return None
return {"fitting_eft": ffittingeft["Data"]["FittingData"]}
except KeyError:
logger.warning("Fleetup fitting eft not found for fitting number %s" % fittingnumber)
return {"fitting_eft": {}}

View File

@@ -1,48 +0,0 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% load staticfiles %}
{% load i18n %}
{% block page_title %}Characters - FleetUp{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
{% if perms.auth.corp_stats %}
{% include "fleetup/menu.html" %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans "Characters registered on Fleet-Up.com" %}</h3>
</div>
<div class="panel-body">
<div class="col-lg-6">
<div class="table-responsive">
<table class="table table-condensed table-hover table-striped">
<tr>
<th class="col-md-1"></th>
<th class="col-md-1">{% trans "Character" %}</th>
<th class="col-md-1">{% trans "Corporation" %}</th>
<th class="col-md-1">Fleet-Up(id)</th>
</tr>
{% for char_name, user_id in member_list %}
<tr>
<td>
<img src="https://imageserver.eveonline.com/Character/{{ user_id.char_id }}_32.jpg" class="img-circle">
</td>
<td>
<p>{{ user_id.char_name }}</p>
</td>
<td>
<p>{{ user_id.corporation }}</p>
</td>
<td>
<p>{{ user_id.user_id }}</p>
</td>
{% endfor %}
</table>
</div>
</div>
</div>
</div>
{% endif %}
</div>
{% endblock content %}

View File

@@ -1,67 +0,0 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% load staticfiles %}
{% load i18n %}
{% block page_title %}Doctrine - FleetUp{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
{% include "fleetup/menu.html" %}
<div>
{% for a, j in doctrine.items %}
{% regroup j.Data|dictsort:"Role" by Role as role_list %}
{% for Role in role_list %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><b>{{ Role.grouper }}</b></h3>
</div>
<div class="panel-body">
<table class="table table-condensed table-hover table-striped">
<tr>
<th class="col-md-1"></th>
<th class="col-md-1">{% trans "Name" %}</th>
<th class="col-md-1">{% trans "Role" %}</th>
<th class="col-md-1">{% trans "Hull type" %}</th>
<th class="col-md-1">{% trans "Ship type" %}</th>
<th class="col-md-1">{% trans "Estimated ISK" %}</th>
<th class="col-md-2">{% trans "Categories" %}</th>
</tr>
{% for item in Role.list %}
<tr>
<td>
<a href="{% url 'fleetup:fitting' item.FittingId %}"><img src="https://image.eveonline.com/InventoryType/{{ item.EveTypeId }}_32.png"></a>
</td>
<td>
{{ item.Name }}
</td>
<td>
{{ item.Role }}
</td>
<td>
{{ item.HullType }}
</td>
<td>
{{ item.ShipType }}
</td>
<td>
{% load humanize %}{{ item.EstPrice|intword }}
</td>
<td>
{% for categories in item.Categories %}
{{ categories }},
{% endfor %}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endblock content %}

View File

@@ -1,62 +0,0 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% load staticfiles %}
{% load i18n %}
{% block page_title %}Doctrines - FleetUp{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
{% include "fleetup/menu.html" %}
<div>
{% if doctrines_list %}
{% for a, j in doctrines_list.items %}
{% regroup j|dictsort:"FolderName" by FolderName as folder_list %}
{% for FolderName in folder_list %}
<div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><b>{{ FolderName.grouper }}</b></h3>
</div>
<div class="panel-body">
<table class="table table-condensed table-hover table-striped">
<tr>
<th class="col-lg-1"></th>
<th class="col-lg-4">{% trans "Name" %}</th>
<th class="col-lg-3">{% trans "Doctrine" %}</th>
<th class="col-lg-4">{% trans "Last updated" %}</th>
<!--<th class="col-lg-1">Owner</th>
<th class="col-lg-2">Note</th>-->
</tr>
{% for item in FolderName.list %}
<tr>
<td>
<a href="{% url 'fleetup:doctrine' item.DoctrineId %}"><img src="https://image.eveonline.com/InventoryType/{{ item.IconId }}_32.png"></a>
</td>
<td>
{{ item.Name }}
</td>
<td>
<a href="{% url 'fleetup:doctrine' item.DoctrineId %}" class="btn btn-info btn-sm">{{ item.FolderName }}</a>
</td>
<td>
{{ item.LastUpdatedString }}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
{% else %}
<h3>{% trans "There seems to be no Doctrines in here at the moment!" %}</h3>
{% endif %}
</div>
</div>
{% endblock content %}

View File

@@ -1,131 +0,0 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% load staticfiles %}
{% load i18n %}
{% block page_title %}{% trans "Doctrine - FleetUp" %}{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
{% include "fleetup/menu.html" %}
<div class="tab-content row">
<div id="fit" class="tab-pane fade in active">
<div class="col-lg-4">
{% for x, y in fitting_data.items %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans "This fit is part of a doctrine" %}</h3>
</div>
<div class="panel-body">
{% for doctrin in y.Doctrines %}
<div class="clearfix">
<h4>{{ doctrin.Name }}</h4>
<div class="col-lg-12">
<p>{% trans "Role in doctrine:" %} {{ doctrin.Role }}</p>
</div>
<div class="col-lg-4">
<p>{% trans "Priority:" %}</p>
</div>
<div class="col-lg-8">
<div class="progress">
<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="{{ doctrin.Priority }}" aria-valuemin="0" aria-valuemax="5" style="width: {% widthratio doctrin.Priority 5 100 %}%;">
{{ doctrin.Priority }}/5
</div>
</div>
</div>
<div class="pull-right">
<a class="btn btn-primary" href="{% url 'fleetup:doctrine' doctrin.DoctrineId %}">{% trans "See doctrine" %}</a>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans "Fit categories" %}</h3>
</div>
<div class="panel-body">
{% for category in y.Categories %}
<span class="label label-success">{{ category }}</span>
{% endfor %}
</div>
</div>
{% endfor %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans "All fits in this Doctrine" %}</h3>
</div>
<div class="panel-body">
<div class="list-group">
{% for arbit, orbit in doctrines_list.items %}
{% for fitting in orbit.Data %}
<a href="{% url 'fleetup:fitting' fitting.FittingId %}" class="list-group-item">
<h4 class="list-group-item-heading">{{ fitting.Name }}<span class="pull-right"><img src="https://image.eveonline.com/InventoryType/{{ fitting.EveTypeId }}_32.png" class="img-circle"></span></h4>
<p class="list-group-item-heading">{{ fitting.Role }} - {{ fitting.ShipType }}</p>
</a>
{% endfor %}
{% endfor %}
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="panel panel-default">
<div class="panel-heading">
{% for a, j in fitting_data.items %}
<h3 class="panel-title">{{ j.Name }}</h3>
</div>
<div class="panel-body">
<div class="col-lg-3">
<img src="https://image.eveonline.com/InventoryType/{{ j.EveTypeId }}_64.png" class="img-responsive">
</div>
<div class="col-lg-9">
<p>{% trans "Hull:" %} <b>{{ j.HullType }}</b></p>
<p>{% trans "Ship:" %} <b>{{ j.ShipType }}</b></p>
{% load humanize %}
<p>{% trans "Estimated price:" %} <b>{{ j.EstPrice|intword }} ISK</b></p>
</div>
{% regroup j.FittingData by Slot as fitting_list %}
<table class="table table-condensed table-hover">
<tr>
<th class="col-lg-1"></th>
<th class="col-lg-11"></th>
</tr>
{% for Slot in fitting_list %}
<tr class="info">
<td></td><td><b>{{ Slot.grouper }}</b></td>
</tr>
{% for item in Slot.list %}
<tr>
<td><img src="https://image.eveonline.com/InventoryType/{{ item.TypeId }}_32.png" class="img-responsive"></td>
<td> {{ item.Quantity }}x {{ item.TypeName }}</td>
</tr>
{% endfor %}
{% endfor %}
</table>
</div>
{% endfor %}
</div>
</div>
<div class="col-lg-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans "EFT/Export" %}</h3>
</div>
<div class="panel-body">
{% for data in fitting_eft.items %}
{% autoescape off %}
<textarea class="form-control" rows="25" spellcheck="false" onclick="this.focus();this.select()" readonly>{{ fitting_eft.fitting_eft }}</textarea>
{% endautoescape %}
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}

View File

@@ -1,55 +0,0 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% load staticfiles %}
{% load i18n %}
{% block page_title %}Fittings - FleetUp{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
{% include "fleetup/menu.html" %}
<div class="panel">
{% if fitting_list %}
<table class="table table-condensed table-hover table-striped">
<tr>
<th class="col-md-1"></th>
<th class="col-md-1">{% trans "Name" %}</th>
<th class="col-md-1">{% trans "Hull" %}</th>
<th class="col-md-1">{% trans "Ship type" %}</th>
<th class="col-md-1">{% trans "Estimated ISK" %}</th>
<th class="col-md-2">{% trans "Categories" %}</th>
</tr>
{% for id, fittings in fitting_list %}
<tr>
<td>
<a href="{% url 'fleetup:fitting' fittings.fitting_id %}"><img src="https://image.eveonline.com/InventoryType/{{ fittings.icon_id }}_32.png"></a>
</td>
<td>
{{ fittings.name }}
</td>
<td>
{{ fittings.hull }}
</td>
<td>
{{ fittings.shiptype }}
</td>
<td>
{% load humanize %}{{ fittings.estimated|intword }}
</td>
<td>
{% for categories in fittings.categories %}
{{ categories }},
{% endfor %}
</td>
</tr>
{% endfor %}
</table>
{% else %}
<h3>{% trans "There seems to be no Fittings in here at the moment!" %}</h3>
{% endif %}
</div>
</div>
{% endblock content %}

View File

@@ -1,254 +0,0 @@
{% extends "allianceauth/base.html" %}
{% load bootstrap %}
{% load staticfiles %}
{% load i18n %}
{% block page_title %}FleetUp{% endblock page_title %}
{% block content %}
<div class="col-lg-12">
{% include "fleetup/menu.html" %}
<div>
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#operations">{% trans "Operations" %}</a></li>
<li><a data-toggle="tab" href="#timers">{% trans "Timers" %}</a></li>
</ul>
<div class="tab-content row">
<div id="operations" class="tab-pane fade in active">
<div class="col-lg-8">
{% if operations_list %}
{% for subject, start in operations_list %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><b>{{ start.subject }}</b></h3>
</div>
<div class="panel-body">
<table class="table table-condensed">
<tr>
<th class="col-md-6">{% trans "Start" %}</th>
<th class="col-md-6">{% trans "End" %}</th>
</tr>
<tr>
<td class="col-md-6">{{ start.start|date:"l d M H:i" }} <span class="label label-success">{% trans "Eve Time" %}</span></td>
<td class="col-md-6">{{ start.end|date:"l d M H:i" }} <span class="label label-success">{% trans "Eve Time" %}</span></td>
</tr>
<tr>
<td class="col-md-6">
<span id="localtime{{ start.operation_id }}"></span>&nbsp;<span class='label label-success'>Local time</span><br>
<div id="countdown{{ start.operation_id }}"></div>
</td>
<td class="col-md-6"></td>
</tr>
</table>
{{ start.details|linebreaks }}
<table class="table table-condensed table-striped">
<tr>
<th class="col-md-4">{% trans "Location" %}</th>
<th class="col-md-4">{% trans "Doctrine" %}</th>
<th class="col-md-2">{% trans "Organizer" %}</th>
<th class="col-md-2">{% trans "URL" %}</th>
</tr>
<tr>
<td>
{{ start.location }} - {{ start.location_info }} <a href="http://evemaps.dotlan.net/system/{{ start.location }}" target="_blank" class="label label-success">Dotlan</a>
</td>
<td>
{% if start.doctrine %}
{% for doctrine in start.doctrine %}
<a href="{% url 'fleetup:doctrine' doctrine.Id %}" class="label label-success">{{ doctrine.Name }}</a>
{% endfor %}
{% else %}
<span class="label label-danger">{% trans "TBA" %}</span>
{% endif %}
</td>
<td>
{{ start.organizer }}
</td>
<td>
{% ifequal start.url "" %}
<div class="label label-danger">{% trans "No link" %}</div>
{% else %}
<a href="{{ start.url }}" target="_blank" class="label label-success">{% trans "External link" %}</a>
{% endifequal %}
</td>
</tr>
</table>
</div>
</div>
{% endfor %}
{% else %}
<h3>{% trans "There seems to be no Operations in the near future." %}</h3>
{% endif %}
</div>
<div class="col-lg-4">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">{% trans "Current Eve Time:" %}</h2>
</div>
<div class="panel-body">
<div id="current-time"></div>
</div>
</div>
{% if timers_list %}
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">{% trans "Timers" %}</h2>
</div>
<div class="panel-body">
<table class="table table-condensed table-hover table-striped">
{% for notes, type in timers_list %}
<tr>
<td>
{{ type.solarsystem }}
</td>
<td>
{{ type.expires|date:"l d M H:i" }}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endif %}
</div>
</div>
<div id="timers" class="tab-pane fade in">
<div class="col-lg-12">
{% if timers_list %}
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">{% trans "Timers" %}</h2>
</div>
<div class="panel-body">
<div class="col-lg-12">
<table class="table table-condensed table-hover table-striped">
<tr>
<th class="col-lg-1">{% trans "Type" %}</th>
<th class="col-lg-1">{% trans "Structure" %}</th>
<th class="col-lg-2">{% trans "Location" %}</th>
<th class="col-lg-2">{% trans "Expires(EVE-time)" %}</th>
<th class="col-lg-1">{% trans "Owner" %}</th>
<th class="col-lg-2">{% trans "Note" %}</th>
</tr>
{% for notes, type in timers_list %}
<tr>
<td>
{% ifequal type.type "Final" %}
<span class="label label-danger">
{{ type.type }}</span>{% else %}{{ type.type }}{% endifequal %}
</td>
<td>
{{ type.timer_type }}
</td>
<td>
{{ type.solarsystem }} - Planet:{{ type.planet }} Moon:{{ type.moon }}
</td>
<td>
{{ type.expires|date:"l d M H:i" }}
</td>
<td>
{{ type.owner }}
</td>
<td>
{{ type.notes }}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
{% else %}
<h3>{% trans "There seems to be no Timers in the near future." %}</h3>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% include 'bundles/moment-js.html' with locale=True %}
<script src="{% static 'js/timers.js' %}"></script>
<script type="text/javascript">
// Data
var timers = [
{% for start, op in operations_list %}
{
'id': {{ op.operation_id }},
'start': moment("{{ op.start | date:"c" }}"),
'end': moment("{{ op.end | date:"c" }}"),
'expired': false
},
{% endfor %}
]
</script>
<script type="text/javascript">
timedUpdate();
setAllLocalTimes();
// Start timed updates
setInterval(timedUpdate, 1000);
function timedUpdate() {
updateClock();
updateAllTimers();
}
function updateAllTimers () {
var l = timers.length;
for (var i=0; i < l; ++i) {
if (timers[i].expired) continue;
updateTimer(timers[i]);
}
}
/**
* Update a timer
* @param timer Timer information
* @param timer.start Date of the timer
* @param timer.id Id number of the timer
* @param timer.expired
*/
function updateTimer(timer) {
if (timer.start.isAfter(Date.now())) {
var duration = moment.duration(timer.start - moment(), 'milliseconds');
document.getElementById("countdown" + timer.id).innerHTML = getDurationString(duration);
} else {
timer.expired = true;
document.getElementById("countdown" + timer.id).innerHTML = "";
}
}
/**
* Set all local time fields
*/
function setAllLocalTimes() {
var l = timers.length;
for (var i=0; i < l; ++i) {
setLocalTime(timers[i]);
}
}
/**
* Set the local time info for the timer
* @param timer Timer information
* @param timer.start Date of the timer
* @param timer.id Id number of the timer
*/
function setLocalTime(timer) {
document.getElementById("localtime" + timer.id).innerHTML = timer.start.format("ddd @ LT");
}
function updateClock() {
document.getElementById("current-time").innerHTML = "<b>" + moment.utc().format('ddd, ll HH:mm:ss z') + "</b>";
}
</script>
{% endblock content %}

View File

@@ -1,26 +0,0 @@
{% load i18n %}
{% load navactive %}
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">{% trans "Toggle navigation" %}</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Fleet-Up</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="{% navactive request 'fleetup:view' %}"><a href="{% url 'fleetup:view' %}">{% trans "Ops and Timers" %}</a></li>
<li class="{% navactive request 'fleetup:doctrines fleetup:doctrine' %}"><a href="{% url 'fleetup:doctrines' %}">{% trans "Doctrines" %}</a></li>
<li class="{% navactive request 'fleetup:fittings fleetup:fitting' %}"><a href="{% url 'fleetup:fittings' %}">{% trans "Fittings" %}</a></li>
{% if perms.auth.corp_stats %}
<li class="{% navactive request 'fleetup:characters' %}"><a href="{% url 'fleetup:characters' %}">{% trans "Characters" %}</a></li>
{% endif %}
</ul>
</div>
</div>
</nav>

View File

@@ -1,503 +0,0 @@
from unittest import mock
import requests_mock
import json
import datetime
from django.test import TestCase
from django.utils.timezone import make_aware, utc
from allianceauth.fleetup.managers import FleetUpManager
class FleetupManagerTestCase(TestCase):
def setUp(self):
pass
def test__request_cache_key(self):
cache_key = FleetUpManager._request_cache_key('testurl')
self.assertEqual('FLEETUP_ENDPOINT_a39562b6ef5b858220be13d2adb61d3f10cf8d61',
cache_key)
@mock.patch('allianceauth.fleetup.managers.cache')
@requests_mock.Mocker()
def test_get_endpoint(self, cache, m):
url = "http://example.com/test/endpoint/"
json_data = {'data': "123456", 'CachedUntilUTC': '/Date(1493896236163)/', 'Success': True}
m.register_uri('GET', url,
text=json.dumps(json_data))
cache.get.return_value = None # No cached value
# Act
result = FleetUpManager.get_endpoint(url)
# Assert
self.assertTrue(cache.get.called)
self.assertTrue(cache.set.called)
args, kwargs = cache.set.call_args
self.assertDictEqual(json_data, args[1])
self.assertDictEqual(json_data, result)
@mock.patch('allianceauth.fleetup.managers.cache')
@requests_mock.Mocker()
def test_get_endpoint_error(self, cache, m):
url = "http://example.com/test/endpoint/"
json_data = {'data': [], 'Success': False}
m.register_uri('GET', url,
text=json.dumps(json_data),
status_code=400)
cache.get.return_value = None # No cached value
# Act
result = FleetUpManager.get_endpoint(url)
# Assert
self.assertTrue(cache.get.called)
self.assertFalse(cache.set.called)
self.assertIsNone(result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_members(self, get_endpoint):
get_endpoint.return_value = {"Data": [
{
'UserId': 1234,
'EveCharName': 'test_name',
'EveCharId': 5678,
'Corporation': 'test_corporation',
}
]}
# Act
result = FleetUpManager.get_fleetup_members()
# Asset
self.assertTrue(get_endpoint.called)
args, kwargs = get_endpoint.call_args
self.assertEqual(args[0],
FleetUpManager.BASE_URL + '/GroupCharacters/' +
FleetUpManager.GROUP_ID)
expected_result = {
1234: {
'user_id': 1234,
'char_name': 'test_name',
'char_id': 5678,
'corporation': 'test_corporation',
}
}
self.assertDictEqual(expected_result, result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_members()
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': []}
# Act
result = FleetUpManager.get_fleetup_members()
# Assert
self.assertDictEqual({}, result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_operations(self, get_endpoint):
get_endpoint.return_value = {"Data": [
{
'Subject': 'test_operation',
'StartString': '2017-05-06 11:11:11',
'EndString': '2017-05-06 12:12:12',
'OperationId': 1234,
'Location': 'Jita',
'LocationInfo': '4-4',
'Details': 'This is a test operation',
'Url': 'http://example.com/1234',
'Doctrines': 'Foxcats',
'Organizer': 'Example FC'
}
]}
# Act
result = FleetUpManager.get_fleetup_operations()
self.maxDiff = None
# Asset
self.assertTrue(get_endpoint.called)
args, kwargs = get_endpoint.call_args
self.assertEqual(args[0],
FleetUpManager.BASE_URL + '/Operations/' +
FleetUpManager.GROUP_ID)
expected_result = {
'2017-05-06 11:11:11': {
'subject': 'test_operation',
'start': make_aware(datetime.datetime(2017, 5, 6, 11, 11, 11), utc),
'end': make_aware(datetime.datetime(2017, 5, 6, 12, 12, 12), utc),
'operation_id': 1234,
'location': 'Jita',
'location_info': '4-4',
'details': 'This is a test operation',
'url': 'http://example.com/1234',
'doctrine': 'Foxcats',
'organizer': 'Example FC'
}
}
self.assertDictEqual(expected_result, result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_operations()
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': []}
# Act
result = FleetUpManager.get_fleetup_operations()
# Assert
self.assertDictEqual({}, result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_timers(self, get_endpoint):
get_endpoint.return_value = {"Data": [
{
'ExpiresString': '2017-05-06 11:11:11',
'SolarSystem': 'Jita',
'Planet': '4',
'Moon': '4',
'Owner': 'Caldari Navy',
'Type': 'Caldari Station',
'TimerType': 'Armor',
'Notes': 'Burn Jita?'
}
]}
# Act
result = FleetUpManager.get_fleetup_timers()
# Asset
self.assertTrue(get_endpoint.called)
args, kwargs = get_endpoint.call_args
self.assertEqual(args[0],
FleetUpManager.BASE_URL + '/Timers/' +
FleetUpManager.GROUP_ID)
expected_result = {
'2017-05-06 11:11:11': {
'expires': make_aware(datetime.datetime(2017, 5, 6, 11, 11, 11), utc),
'solarsystem': 'Jita',
'planet': '4',
'moon': '4',
'owner': 'Caldari Navy',
'type': 'Caldari Station',
'timer_type': 'Armor',
'notes': 'Burn Jita?'
}
}
self.assertDictEqual(expected_result, result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_timers()
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': []}
# Act
result = FleetUpManager.get_fleetup_timers()
# Assert
self.assertDictEqual({}, result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_doctrines(self, get_endpoint):
get_endpoint.return_value = {"Data": [
{
'TestData': True
}
]}
# Act
result = FleetUpManager.get_fleetup_doctrines()
# Asset
self.assertTrue(get_endpoint.called)
args, kwargs = get_endpoint.call_args
self.assertEqual(args[0],
FleetUpManager.BASE_URL + '/Doctrines/' +
FleetUpManager.GROUP_ID)
expected_result = {
'fleetup_doctrines': [{
'TestData': True
}]
}
self.assertDictEqual(expected_result, result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_doctrines()
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': []}
# Act
result = FleetUpManager.get_fleetup_doctrines()
# Assert
self.assertDictEqual({"fleetup_doctrines": []}, result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_doctrine(self, get_endpoint):
get_endpoint.return_value = {"Data": [
{
'TestData': True
}
]}
# Act
result = FleetUpManager.get_fleetup_doctrine(1234)
# Asset
self.assertTrue(get_endpoint.called)
args, kwargs = get_endpoint.call_args
self.assertEqual(args[0],
FleetUpManager.BASE_URL + '/DoctrineFittings/1234')
expected_result = {
'fitting_doctrine': {'Data': [{
'TestData': True
}]}
}
self.assertDictEqual(expected_result, result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_doctrine(1234)
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': []}
# Act
result = FleetUpManager.get_fleetup_doctrine(1234)
# Assert
self.assertDictEqual({"fitting_doctrine": {'Data': []}}, result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_fittings(self, get_endpoint):
get_endpoint.return_value = {"Data": [
{
'FittingId': 1234,
'Name': 'Foxcat',
'EveTypeId': 17726,
'HullType': 'Battleship',
'ShipType': 'Apocalypse Navy Issue',
'EstPrice': 500000000,
'Faction': 'Amarr',
'Categories': ["Armor", "Laser"],
'LastUpdatedString': '2017-05-06 11:11:11',
}
]}
# Act
result = FleetUpManager.get_fleetup_fittings()
# Asset
self.assertTrue(get_endpoint.called)
expected_result = {
1234: {
'fitting_id': 1234,
'name': 'Foxcat',
'icon_id': 17726,
'hull': 'Battleship',
'shiptype': 'Apocalypse Navy Issue',
'estimated': 500000000,
'faction': 'Amarr',
'categories': ["Armor", "Laser"],
'last_update': make_aware(datetime.datetime(2017, 5, 6, 11, 11, 11), utc)
}
}
self.assertDictEqual(expected_result, result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_fittings()
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': []}
# Act
result = FleetUpManager.get_fleetup_fittings()
# Assert
self.assertDictEqual({}, result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_fitting(self, get_endpoint):
get_endpoint.return_value = {"Data":
{
'FittingData': [{}]
}
}
# Act
result = FleetUpManager.get_fleetup_fitting(1234)
# Asset
self.assertTrue(get_endpoint.called)
args, kwargs = get_endpoint.call_args
self.assertEqual(args[0], FleetUpManager.BASE_URL + '/Fitting/1234')
expected_result = {
'fitting_data': {
'FittingData': [{}]
}
}
self.assertDictEqual(expected_result, result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_fitting(1234)
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': {}}
# Act
result = FleetUpManager.get_fleetup_fitting(1234)
# Assert
self.assertDictEqual({"fitting_data": {}}, result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_doctrineid(self, get_endpoint):
get_endpoint.return_value = {
"Data": {
'Doctrines': [{'DoctrineId': 4567}]
}
}
# Act
result = FleetUpManager.get_fleetup_doctrineid(1234)
# Asset
self.assertTrue(get_endpoint.called)
args, kwargs = get_endpoint.call_args
self.assertEqual(args[0], FleetUpManager.BASE_URL + '/Fitting/1234')
self.assertEqual(4567, result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_doctrineid(1234)
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': {}}
# Act
result = FleetUpManager.get_fleetup_doctrineid(1234)
# Assert
self.assertDictEqual({}, result)
@mock.patch('allianceauth.fleetup.managers.FleetUpManager.get_endpoint')
def test_get_fleetup_fitting_eft(self, get_endpoint):
get_endpoint.return_value = {
"Data": {
'FittingData': '[Apocalypse Navy Issue, Foxcat]'
}
}
# Act
result = FleetUpManager.get_fleetup_fitting_eft(1234)
# Asset
self.assertTrue(get_endpoint.called)
args, kwargs = get_endpoint.call_args
self.assertEqual(args[0], FleetUpManager.BASE_URL + '/Fitting/1234/eft')
self.assertDictEqual({"fitting_eft": '[Apocalypse Navy Issue, Foxcat]'},
result)
# Test None response
# Arrange
get_endpoint.return_value = None
# Act
result = FleetUpManager.get_fleetup_fitting_eft(1234)
# Assert
self.assertIsNone(result)
# Test Empty response
# Arrange
get_endpoint.return_value = {'Data': {}}
# Act
result = FleetUpManager.get_fleetup_fitting_eft(1234)
# Assert
self.assertDictEqual({"fitting_eft": {}}, result)

View File

@@ -1,14 +0,0 @@
from django.conf.urls import url
from . import views
app_name = 'fleetup'
urlpatterns = [
url(r'^$', views.fleetup_view, name='view'),
url(r'^fittings/$', views.fleetup_fittings, name='fittings'),
url(r'^fittings/(?P<fittingnumber>[0-9]+)/$', views.fleetup_fitting, name='fitting'),
url(r'^doctrines/$', views.fleetup_doctrines, name='doctrines'),
url(r'^characters/$', views.fleetup_characters, name='characters'),
url(r'^doctrines/(?P<doctrinenumber>[0-9]+)/$', views.fleetup_doctrine, name='doctrine'),
]

View File

@@ -1,112 +0,0 @@
import datetime
import logging
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required
from django.shortcuts import render
from django.template.defaulttags import register
from django.utils.translation import ugettext_lazy as _
from .managers import FleetUpManager
logger = logging.getLogger(__name__)
@register.filter
def get_item(dictionary, key):
return dictionary.get(key)
@login_required
@permission_required('auth.view_fleetup')
def fleetup_view(request):
logger.debug("fleetup_view called by user %s" % request.user)
operations_list = FleetUpManager.get_fleetup_operations()
if operations_list is None:
messages.add_message(request, messages.ERROR, _("Failed to get operations list, contact your administrator"))
operations_list = {}
timers_list = FleetUpManager.get_fleetup_timers()
if timers_list is None:
messages.add_message(request, messages.ERROR, _("Failed to get timers list, contact your administrator"))
timers_list = {}
now = datetime.datetime.now().strftime('%H:%M:%S')
context = {"timers_list": sorted(timers_list.items()),
"operations_list": sorted(operations_list.items()),
"now": now}
return render(request, 'fleetup/index.html', context=context)
@login_required
@permission_required('auth.human_resources')
@permission_required('auth.view_fleetup')
def fleetup_characters(request):
logger.debug("fleetup_characters called by user %s" % request.user)
member_list = FleetUpManager.get_fleetup_members()
if member_list is None:
messages.add_message(request, messages.ERROR, _("Failed to get member list, contact your administrator"))
member_list = {}
context = {"member_list": sorted(member_list.items())}
return render(request, 'fleetup/characters.html', context=context)
@login_required
@permission_required('auth.view_fleetup')
def fleetup_fittings(request):
logger.debug("fleetup_fittings called by user %s" % request.user)
fitting_list = FleetUpManager.get_fleetup_fittings()
if fitting_list is None:
messages.add_message(request, messages.ERROR, _("Failed to get fitting list, contact your administrator"))
fitting_list = {}
context = {"fitting_list": sorted(fitting_list.items())}
return render(request, 'fleetup/fittingsview.html', context=context)
@login_required
@permission_required('auth.view_fleetup')
def fleetup_fitting(request, fittingnumber):
logger.debug("fleetup_fitting called by user %s" % request.user)
fitting_eft = FleetUpManager.get_fleetup_fitting_eft(fittingnumber)
fitting_data = FleetUpManager.get_fleetup_fitting(fittingnumber)
doctrinenumber = FleetUpManager.get_fleetup_doctrineid(fittingnumber)
doctrines_list = FleetUpManager.get_fleetup_doctrine(doctrinenumber)
if fitting_eft is None or fitting_data is None or doctrinenumber is None:
messages.add_message(request, messages.ERROR, _("There was an error getting some of the data for this fitting. "
"Contact your administrator"))
context = {"fitting_eft": fitting_eft,
"fitting_data": fitting_data,
"doctrines_list": doctrines_list}
return render(request, 'fleetup/fitting.html', context=context)
@login_required
@permission_required('auth.view_fleetup')
def fleetup_doctrines(request):
logger.debug("fleetup_doctrines called by user %s" % request.user)
doctrines_list = FleetUpManager.get_fleetup_doctrines()
if doctrines_list is None:
messages.add_message(request, messages.ERROR, _("Failed to get doctrines list, contact your administrator"))
context = {"doctrines_list": doctrines_list}
return render(request, 'fleetup/doctrinesview.html', context=context)
@login_required
@permission_required('auth.view_fleetup')
def fleetup_doctrine(request, doctrinenumber):
logger.debug("fleetup_doctrine called by user %s" % request.user)
doctrine = FleetUpManager.get_fleetup_doctrine(doctrinenumber)
if doctrine is None:
messages.add_message(request, messages.ERROR, _("Failed to get doctine, contact your administrator"))
context = {"doctrine": doctrine}
return render(request, 'fleetup/doctrine.html', context=context)

View File

@@ -50,7 +50,7 @@
<tr>
<td class="text-center">
<img class="ra-avatar img-responsive img-circle"
src="https://image.eveonline.com/Character/{{ char.character_id }}_32.jpg">
src="{{ char.portrait_url_32 }}">
</td>
<td class="text-center">{{ char.character_name }}</td>
<td class="text-center">{{ char.corporation_name }}</td>

View File

@@ -12,7 +12,6 @@ from hashlib import md5
logger = logging.getLogger(__name__)
DISCORD_URL = "https://discordapp.com/api"
EVE_IMAGE_SERVER = "https://image.eveonline.com"
AUTH_URL = "https://discordapp.com/api/oauth2/authorize"
TOKEN_URL = "https://discordapp.com/api/oauth2/token"

View File

@@ -83,7 +83,7 @@ def discourse_sso(request):
}
if main_char:
params['avatar_url'] = 'https://image.eveonline.com/Character/%s_256.jpg' % main_char.character_id
params['avatar_url'] = main_char.portrait_url(256)
return_payload = base64.encodestring(urlencode(params).encode('utf-8'))
h = hmac.new(key, return_payload, digestmod=hashlib.sha256)

View File

@@ -6,6 +6,7 @@ from datetime import datetime
from passlib.apps import phpbb3_context
from django.db import connections
from allianceauth.eveonline.models import EveCharacter
import logging
@@ -58,7 +59,7 @@ class Phpbb3Manager:
@staticmethod
def __add_avatar(username, characterid):
logger.debug("Adding EVE character id %s portrait as phpbb avater for user %s" % (characterid, username))
avatar_url = "https://image.eveonline.com/Character/" + characterid + "_64.jpg"
avatar_url = EveCharacter.generic_portrait_url(characterid, 64)
cursor = connections['phpbb3'].cursor()
userid = Phpbb3Manager.__get_user_id(username)
cursor.execute(Phpbb3Manager.SQL_ADD_USER_AVATAR, [avatar_url, userid])

View File

@@ -8,6 +8,7 @@ import re
from django.db import connections
from django.conf import settings
from allianceauth.eveonline.models import EveCharacter
logger = logging.getLogger(__name__)
@@ -101,8 +102,8 @@ class SmfManager:
@classmethod
def add_avatar(cls, member_name, characterid):
logger.debug("Adding EVE character id %s portrait as smf avatar for user %s" % (characterid, member_name))
avatar_url = "https://image.eveonline.com/Character/" + characterid + "_64.jpg"
logger.debug("Adding EVE character id %s portrait as smf avatar for user %s" % (characterid, member_name))
avatar_url = EveCharacter.generic_portrait_url(characterid, 64)
cursor = connections['smf'].cursor()
id_member = cls.get_user_id(member_name)
cursor.execute(cls.SQL_ADD_USER_AVATAR, [avatar_url, id_member])

View File

@@ -199,7 +199,7 @@ class Teamspeak3Manager:
'tokendescription': username_clean,
'tokencustomset': "ident=sso_uid value=%s" % username_clean})
except TeamspeakError as e:
logger.error("Failed to add teamspeak user %s: %s" % (username, str(e)))
logger.error("Failed to add teamspeak user %s: %s" % (username_clean, str(e)))
return "",""
try:

View File

@@ -12,6 +12,10 @@ from .models import Teamspeak3User, AuthTS, TSgroup, StateGroup
from .tasks import Teamspeak3Tasks
from .signals import m2m_changed_authts_group, post_save_authts, post_delete_authts
from .manager import Teamspeak3Manager
from .util.ts3 import TeamspeakError
from allianceauth.authentication.models import State
MODULE_PATH = 'allianceauth.services.modules.teamspeak3'
DEFAULT_AUTH_GROUP = 'Member'
@@ -290,3 +294,31 @@ class Teamspeak3SignalsTestCase(TestCase):
self.member.profile.save()
self.assertTrue(update_groups.called)
class Teamspeak3ManagerTestCase(TestCase):
@staticmethod
def my_side_effect(*args, **kwargs):
raise TeamspeakError(1)
@mock.patch.object(Teamspeak3Manager, '_group_list')
@mock.patch.object(Teamspeak3Manager, '_group_id_by_name')
def test_add_user_exception(self, _group_id_by_name, _group_list):
"""test 1st exception occuring in add_user()"""
# set mocks in Teamspeak3Manager class
_group_list.return_value = ['Member', 'Guest']
_group_id_by_name.return_value = 99
manager = Teamspeak3Manager()
server = mock.MagicMock()
server._connected.return_value = True
server.send_command = mock.Mock(side_effect=Teamspeak3ManagerTestCase.my_side_effect)
manager._server = server
# create test data
user = User.objects.create_user("dummy")
user.profile.state = State.objects.filter(name="Member").first()
# perform test
manager.add_user(user, "Dummy User")

View File

@@ -1,18 +0,0 @@
# Fleetup
## Installation
Add `'allianceauth.fleetup',` to your auth project's `INSTALLED_APPS` list.
Additional settings are required. Append the following settings to the end of your auth project's settings file and fill them out.
FLEETUP_APP_KEY = '' # The app key from http://fleet-up.com/Api/MyApps
FLEETUP_USER_ID = '' # The user id from http://fleet-up.com/Api/MyKeys
FLEETUP_API_ID = '' # The API id from http://fleet-up.com/Api/MyKeys
FLEETUP_GROUP_ID = '' # The id of the group you want to pull data from, see http://fleet-up.com/Api/Endpoints#groups_mygroupmemberships
Once filled out restart Gunicorn and Celery.
## Permissions
The Fleetup module is only visible to users with the `auth | user | view_fleeup` permission.

View File

@@ -6,6 +6,11 @@ Discord is very popular amongst ad-hoc small groups and larger organizations see
## Setup
```eval_rst
.. warning::
Do not run the `discord.update_*` periodic tasks on a regular schedule, doing so can cause your discord service to stop syncing completely.
```
### Prepare Your Settings File
In your auth project's settings file, do the following:
- Add `'allianceauth.services.modules.discord',` to your `INSTALLED_APPS` list

View File

@@ -1,7 +1,12 @@
# -*- coding: utf-8 -*-
import os
from setuptools import setup
import allianceauth
this_directory = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
install_requires = [
'mysqlclient',
'dnspython',
@@ -16,7 +21,7 @@ install_requires = [
'celery>=4.0.2,<4.3.0',
'celery_once',
'django>=2.0',
'django>=2.0,<3.0',
'django-bootstrap-form',
'django-registration==2.4',
'django-sortedm2m',
@@ -43,6 +48,8 @@ setup(
author='Alliance Auth',
author_email='adarnof@gmail.com',
description='An auth system for EVE Online to help in-game organizations manage online service access.',
long_description=long_description,
long_description_content_type='text/markdown',
install_requires=install_requires,
extras_require={
'testing': testing_extras,
@@ -58,4 +65,16 @@ setup(
[console_scripts]
allianceauth=allianceauth.bin.allianceauth:main
""",
classifiers=[
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 2.2',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)

View File

@@ -24,7 +24,6 @@ INSTALLED_APPS += [
'allianceauth.optimer',
'allianceauth.corputils',
'allianceauth.fleetactivitytracking',
'allianceauth.fleetup',
'allianceauth.permissions_tool',
'allianceauth.services.modules.mumble',
'allianceauth.services.modules.discord',
@@ -174,19 +173,6 @@ SEAT_XTOKEN = 'tokentokentoken'
######################################
SMF_URL = ''
######################################
# Fleet-Up Configuration
######################################
# FLEETUP_APP_KEY - The app key from http://fleet-up.com/Api/MyApps
# FLEETUP_USER_ID - The user id from http://fleet-up.com/Api/MyKeys
# FLEETUP_API_ID - The API id from http://fleet-up.com/Api/MyKeys
# FLEETUP_GROUP_ID - The id of the group you want to pull data from, see http://fleet-up.com/Api/Endpoints#groups_mygroupmemberships
######################################
FLEETUP_APP_KEY = ''
FLEETUP_USER_ID = ''
FLEETUP_API_ID = ''
FLEETUP_GROUP_ID = ''
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.MD5PasswordHasher',
]

15
tox.ini
View File

@@ -1,19 +1,18 @@
[tox]
skipsdist = True
usedevelop = True
envlist = py{34,35,36,37}-dj{111,20}
skipsdist = true
usedevelop = true
envlist = py{35,36,37}-dj{2X}
[testenv]
setenv =
DJANGO_SETTINGS_MODULE = settings
basepython =
py34: python3.4
basepython =
py35: python3.5
py36: python3.6
py37: python3.7
deps=
dj111: Django>=1.11.1,<2.0
dj20: Django>=2.0
deps=
coverage
dj2X: Django>=2.0,<3.0
py37: https://github.com/yaml/pyyaml/zipball/master#egg=pyyaml
py37: https://github.com/celery/kombu/zipball/master#egg=kombu
install_command = pip install -e ".[testing]" -U {opts} {packages}