mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-12 22:10:16 +02:00
EVE Swagger Interface
Closes #591 Conflicts: authentication/views.py eveonline/views.py stock/templates/public/characternotexisting.html
This commit is contained in:
commit
71c1054328
@ -61,8 +61,9 @@ INSTALLED_APPS = [
|
|||||||
'corputils',
|
'corputils',
|
||||||
'fleetactivitytracking',
|
'fleetactivitytracking',
|
||||||
'notifications',
|
'notifications',
|
||||||
'eve_sso',
|
'esi',
|
||||||
'geelweb.django.navhelper',
|
'geelweb.django.navhelper',
|
||||||
|
'bootstrap_pagination',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
@ -238,9 +239,9 @@ FORUM_URL = os.environ.get('AA_FORUM_URL', '')
|
|||||||
# Callback URL should be http://mydomain.com/sso/callback
|
# Callback URL should be http://mydomain.com/sso/callback
|
||||||
# Leave callback blank to hide SSO button on login page
|
# Leave callback blank to hide SSO button on login page
|
||||||
###################
|
###################
|
||||||
EVE_SSO_CLIENT_ID = os.environ.get('AA_EVE_SSO_CLIENT_ID', '')
|
ESI_SSO_CLIENT_ID = os.environ.get('AA_EVE_SSO_CLIENT_ID', '')
|
||||||
EVE_SSO_CLIENT_SECRET = os.environ.get('AA_EVE_SSO_CLIENT_SECRET', '')
|
ESI_SSO_CLIENT_SECRET = os.environ.get('AA_EVE_SSO_CLIENT_SECRET', '')
|
||||||
EVE_SSO_CALLBACK_URL = os.environ.get('AA_EVE_SSO_CALLBACK_URL', '')
|
ESI_SSO_CALLBACK_URL = os.environ.get('AA_EVE_SSO_CALLBACK_URL', '')
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
# Default Group Settings
|
# Default Group Settings
|
||||||
@ -356,6 +357,19 @@ REJECT_OLD_APIS = 'True' == os.environ.get('AA_REJECT_OLD_APIS', 'False')
|
|||||||
REJECT_OLD_APIS_MARGIN = os.environ.get('AA_REJECT_OLD_APIS_MARGIN', 50)
|
REJECT_OLD_APIS_MARGIN = os.environ.get('AA_REJECT_OLD_APIS_MARGIN', 50)
|
||||||
API_SSO_VALIDATION = 'True' == os.environ.get('AA_API_SSO_VALIDATION', 'False')
|
API_SSO_VALIDATION = 'True' == os.environ.get('AA_API_SSO_VALIDATION', 'False')
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# EVE Provider Settings
|
||||||
|
#######################
|
||||||
|
# EVEONLINE_CHARACTER_PROVIDER - Name of default data source for getting eve character data
|
||||||
|
# EVEONLINE_CORP_PROVIDER - Name of default data source for getting eve corporation data
|
||||||
|
# EVEONLINE_ALLIANCE_PROVIDER - Name of default data source for getting eve alliance data
|
||||||
|
#
|
||||||
|
# Available soruces are 'esi' and 'xml'
|
||||||
|
#######################
|
||||||
|
EVEONLINE_CHARACTER_PROVIDER = os.environ.get('AA_EVEONLINE_CHARACTER_PROVIDER', 'esi')
|
||||||
|
EVEONLINE_CORP_PROVIDER = os.environ.get('AA_EVEONLINE_CORP_PROVIDER', 'esi')
|
||||||
|
EVEONLINE_ALLIANCE_PROVIDER = os.environ.get('AA_EVEONLINE_ALLIANCE_PROVIDER', 'esi')
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
# Alliance Market
|
# Alliance Market
|
||||||
#####################
|
#####################
|
||||||
|
@ -10,13 +10,13 @@ import services.views
|
|||||||
import groupmanagement.views
|
import groupmanagement.views
|
||||||
import optimer.views
|
import optimer.views
|
||||||
import timerboard.views
|
import timerboard.views
|
||||||
import corputils.views
|
|
||||||
import fleetactivitytracking.views
|
import fleetactivitytracking.views
|
||||||
import fleetup.views
|
import fleetup.views
|
||||||
import srp.views
|
import srp.views
|
||||||
import notifications.views
|
import notifications.views
|
||||||
import hrapplications.views
|
import hrapplications.views
|
||||||
import eve_sso.urls
|
import corputils.urls
|
||||||
|
import esi.urls
|
||||||
|
|
||||||
# Functional/Untranslated URL's
|
# Functional/Untranslated URL's
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@ -27,9 +27,12 @@ urlpatterns = [
|
|||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
|
|
||||||
# SSO
|
# SSO
|
||||||
url (r'^sso/', include(eve_sso.urls, namespace='eve_sso')),
|
url(r'^sso/', include(esi.urls, namespace='esi')),
|
||||||
url(r'^sso/login$', authentication.views.sso_login, name='auth_sso_login'),
|
url(r'^sso/login$', authentication.views.sso_login, name='auth_sso_login'),
|
||||||
|
|
||||||
|
# Corputils
|
||||||
|
url(r'^corpstats/', include(corputils.urls, namespace='corputils')),
|
||||||
|
|
||||||
# Index
|
# Index
|
||||||
url(_(r'^$'), authentication.views.index_view, name='auth_index'),
|
url(_(r'^$'), authentication.views.index_view, name='auth_index'),
|
||||||
|
|
||||||
@ -144,14 +147,6 @@ urlpatterns = [
|
|||||||
# User viewed/translated URLS
|
# User viewed/translated URLS
|
||||||
urlpatterns += i18n_patterns(
|
urlpatterns += i18n_patterns(
|
||||||
|
|
||||||
# corputils
|
|
||||||
url(r'^corputils/$', corputils.views.corp_member_view, name='auth_corputils'),
|
|
||||||
url(r'^corputils/(?P<corpid>[0-9]+)/$', corputils.views.corp_member_view, name='auth_corputils_corp_view'),
|
|
||||||
url(r'^corputils/(?P<corpid>[0-9]+)/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$', corputils.views.corp_member_view,
|
|
||||||
name='auth_corputils_month'),
|
|
||||||
url(r'^corputils/search/$', corputils.views.corputils_search, name="auth_corputils_search"),
|
|
||||||
url(r'^corputils/search/(?P<corpid>[0-9]+)/$', corputils.views.corputils_search, name='auth_corputils_search_corp'),
|
|
||||||
|
|
||||||
# Fleetup
|
# Fleetup
|
||||||
url(r'^fleetup/$', fleetup.views.fleetup_view, name='auth_fleetup_view'),
|
url(r'^fleetup/$', fleetup.views.fleetup_view, name='auth_fleetup_view'),
|
||||||
url(r'^fleetup/fittings/$', fleetup.views.fleetup_fittings, name='auth_fleetup_fittings'),
|
url(r'^fleetup/fittings/$', fleetup.views.fleetup_fittings, name='auth_fleetup_fittings'),
|
||||||
@ -249,12 +244,6 @@ urlpatterns += i18n_patterns(
|
|||||||
# Teamspeak Urls
|
# Teamspeak Urls
|
||||||
url(r'verify_teamspeak3/$', services.views.verify_teamspeak3, name='auth_verify_teamspeak3'),
|
url(r'verify_teamspeak3/$', services.views.verify_teamspeak3, name='auth_verify_teamspeak3'),
|
||||||
|
|
||||||
# corputils
|
|
||||||
url(_(r'^corputils/$'), corputils.views.corp_member_view, name='auth_corputils'),
|
|
||||||
url(_(r'^corputils/(?P<corpid>[0-9]+)/$'), corputils.views.corp_member_view, name='auth_corputils_corp_view'),
|
|
||||||
url(_(r'^corputils/search/$'), corputils.views.corputils_search, name="auth_corputils_search"),
|
|
||||||
url(_(r'^corputils/search/(?P<corpid>[0-9]+)/$'), corputils.views.corputils_search, name='auth_corputils_search_corp'),
|
|
||||||
|
|
||||||
# Timer URLS
|
# Timer URLS
|
||||||
url(_(r'^timers/$'), timerboard.views.timer_view, name='auth_timer_view'),
|
url(_(r'^timers/$'), timerboard.views.timer_view, name='auth_timer_view'),
|
||||||
url(_(r'^add_timer/$'), timerboard.views.add_timer_view, name='auth_add_timer_view'),
|
url(_(r'^add_timer/$'), timerboard.views.add_timer_view, name='auth_add_timer_view'),
|
||||||
|
@ -19,5 +19,5 @@ def states(request):
|
|||||||
|
|
||||||
def sso(request):
|
def sso(request):
|
||||||
return {
|
return {
|
||||||
'EVE_SSO_CALLBACK_URL': settings.EVE_SSO_CALLBACK_URL,
|
'EVE_SSO_CALLBACK_URL': settings.ESI_SSO_CALLBACK_URL,
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ from authentication.models import AuthServicesInfo
|
|||||||
from authentication.forms import LoginForm, RegistrationForm
|
from authentication.forms import LoginForm, RegistrationForm
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from eve_sso.decorators import token_required
|
from esi.decorators import token_required
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -95,13 +95,14 @@ def help_view(request):
|
|||||||
|
|
||||||
|
|
||||||
@token_required(new=True)
|
@token_required(new=True)
|
||||||
def sso_login(request, tokens=[]):
|
def sso_login(request, token):
|
||||||
token = tokens[0]
|
|
||||||
try:
|
try:
|
||||||
char = EveCharacter.objects.get(character_id=token.character_id)
|
char = EveCharacter.objects.get(character_id=token.character_id)
|
||||||
if char.user:
|
if char.user:
|
||||||
if char.user.is_active:
|
if char.user.is_active:
|
||||||
login(request, char.user)
|
login(request, char.user)
|
||||||
|
token.user = char.user
|
||||||
|
token.save()
|
||||||
return redirect('auth_dashboard')
|
return redirect('auth_dashboard')
|
||||||
else:
|
else:
|
||||||
messages.error(request, 'Your account has been disabled.')
|
messages.error(request, 'Your account has been disabled.')
|
||||||
|
@ -1 +1,5 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
from corputils.models import CorpStats
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
admin.site.register(CorpStats)
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
from django import forms
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
class CorputilsSearchForm(forms.Form):
|
|
||||||
search_string = forms.CharField(max_length=254, required=True, label="",
|
|
||||||
widget=forms.TextInput(attrs={'placeholder': _('Search characters...')}))
|
|
42
corputils/managers.py
Normal file
42
corputils/managers.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
from django.db import models
|
||||||
|
from authentication.models import AuthServicesInfo
|
||||||
|
from eveonline.models import EveCharacter
|
||||||
|
|
||||||
|
|
||||||
|
class CorpStatsQuerySet(models.QuerySet):
|
||||||
|
def visible_to(self, user):
|
||||||
|
# superusers get all visible
|
||||||
|
if user.is_superuser:
|
||||||
|
return self
|
||||||
|
|
||||||
|
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
|
||||||
|
try:
|
||||||
|
char = EveCharacter.objects.get(character_id=auth.main_char_id)
|
||||||
|
# build all accepted queries
|
||||||
|
queries = []
|
||||||
|
if user.has_perm('corputils.view_corp_corpstats'):
|
||||||
|
queries.append(models.Q(corp__corporation_id=char.corporation_id))
|
||||||
|
if user.has_perm('corputils.view_alliance_corpstats'):
|
||||||
|
queries.append(models.Q(corp__alliance__alliance_id=char.alliance_id))
|
||||||
|
if user.has_perm('corputils.view_blue_corpstats'):
|
||||||
|
queries.append(models.Q(corp__is_blue=True))
|
||||||
|
|
||||||
|
# filter based on queries
|
||||||
|
if queries:
|
||||||
|
query = queries.pop()
|
||||||
|
for q in queries:
|
||||||
|
query |= q
|
||||||
|
return self.filter(query)
|
||||||
|
else:
|
||||||
|
# not allowed to see any
|
||||||
|
return self.none()
|
||||||
|
except EveCharacter.DoesNotExist:
|
||||||
|
return self.none()
|
||||||
|
|
||||||
|
|
||||||
|
class CorpStatsManager(models.Manager):
|
||||||
|
def get_queryset(self):
|
||||||
|
return CorpStatsQuerySet(self.model, using=self._db)
|
||||||
|
|
||||||
|
def visible_to(self, user):
|
||||||
|
return self.get_queryset().visible_to(user)
|
35
corputils/migrations/0001_initial.py
Normal file
35
corputils/migrations/0001_initial.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.1 on 2016-12-14 21:36
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('esi', '0002_scopes_20161208'),
|
||||||
|
('eveonline', '0004_eveapikeypair_sso_verified'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CorpStats',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('last_update', models.DateTimeField(auto_now=True)),
|
||||||
|
('_members', models.TextField(default='{}')),
|
||||||
|
('corp', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCorporationInfo')),
|
||||||
|
('token', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='esi.Token')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'default_permissions': ('add', 'change', 'remove', 'view_corp', 'view_alliance', 'view_blue'),
|
||||||
|
'verbose_name': 'corp stats',
|
||||||
|
'verbose_name_plural': 'corp stats',
|
||||||
|
'permissions': (('corp_apis', 'Can view API keys of members of their corporation.'), ('alliance_apis', 'Can view API keys of members of their alliance.'), ('blue_apis', 'Can view API keys of members of blue corporations.')),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
125
corputils/migrations/0002_migrate_permissions.py
Normal file
125
corputils/migrations/0002_migrate_permissions.py
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.1 on 2016-12-14 21:48
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
PERMISSIONS = {
|
||||||
|
'user': [
|
||||||
|
'corp_apis',
|
||||||
|
'alliance_apis',
|
||||||
|
],
|
||||||
|
'corpstats': {
|
||||||
|
'corp_apis': 'Can view API keys of members of their corporation.',
|
||||||
|
'alliance_apis': 'Can view API keys of members of their alliance.',
|
||||||
|
'blue_apis': 'Can view API keys of members of blue corporations.',
|
||||||
|
'view_corp_corpstats': 'Can view_corp corpstats',
|
||||||
|
'view_alliance_corpstats': 'Can view_alliance corpstats',
|
||||||
|
'view_blue_corpstats': 'Can view_blue corpstats',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def user_permissions_dict(apps):
|
||||||
|
Permission = apps.get_model('auth', 'Permission')
|
||||||
|
ContentType = apps.get_model('contenttypes', 'ContentType')
|
||||||
|
User = apps.get_model('auth', 'User')
|
||||||
|
CorpStats = apps.get_model('corputils', 'CorpStats')
|
||||||
|
|
||||||
|
user_ct = ContentType.objects.get_for_model(User)
|
||||||
|
corpstats_ct = ContentType.objects.get_for_model(CorpStats)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'user': {x: Permission.objects.get_or_create(name=x, codename=x, content_type=user_ct)[0] for x in PERMISSIONS['user']},
|
||||||
|
'corpstats': {x: Permission.objects.get_or_create(codename=x, content_type=corpstats_ct)[0] for x, y in PERMISSIONS['corpstats'].items()},
|
||||||
|
}
|
||||||
|
|
||||||
|
def users_with_permission(apps, perm):
|
||||||
|
User = apps.get_model('auth', 'User')
|
||||||
|
return User.objects.filter(user_permissions=perm.pk)
|
||||||
|
|
||||||
|
def groups_with_permission(apps, perm):
|
||||||
|
Group = apps.get_model('auth', 'Group')
|
||||||
|
return Group.objects.filter(permissions=perm.pk)
|
||||||
|
|
||||||
|
def forward(apps, schema_editor):
|
||||||
|
perm_dict = user_permissions_dict(apps)
|
||||||
|
|
||||||
|
corp_users = users_with_permission(apps, perm_dict['user']['corp_apis'])
|
||||||
|
for u in corp_users:
|
||||||
|
u.user_permissions.add(perm_dict['corpstats']['corp_apis'].pk)
|
||||||
|
u.user_permissions.add(perm_dict['corpstats']['view_corp_corpstats'].pk)
|
||||||
|
|
||||||
|
alliance_users = users_with_permission(apps, perm_dict['user']['alliance_apis'])
|
||||||
|
for u in alliance_users:
|
||||||
|
u.user_permissions.add(perm_dict['corpstats']['alliance_apis'].pk)
|
||||||
|
u.user_permissions.add(perm_dict['corpstats']['view_alliance_corpstats'].pk)
|
||||||
|
|
||||||
|
corp_groups = groups_with_permission(apps, perm_dict['user']['corp_apis'])
|
||||||
|
for g in corp_groups:
|
||||||
|
g.permissions.add(perm_dict['corpstats']['corp_apis'].pk)
|
||||||
|
g.permissions.add(perm_dict['corpstats']['view_corp_corpstats'].pk)
|
||||||
|
|
||||||
|
alliance_groups = groups_with_permission(apps, perm_dict['user']['alliance_apis'])
|
||||||
|
for g in alliance_groups:
|
||||||
|
g.permissions.add(perm_dict['corpstats']['alliance_apis'].pk)
|
||||||
|
g.permissions.add(perm_dict['corpstats']['view_alliance_corpstats'].pk)
|
||||||
|
|
||||||
|
for name, perm in perm_dict['user'].items():
|
||||||
|
perm.delete()
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor):
|
||||||
|
perm_dict = user_permissions_dict(apps)
|
||||||
|
|
||||||
|
corp_users = users_with_permission(apps, perm_dict['corpstats']['view_corp_corpstats'])
|
||||||
|
corp_api_users = users_with_permission(apps, perm_dict['corpstats']['corp_apis'])
|
||||||
|
corp_us = corp_users | corp_api_users
|
||||||
|
for u in corp_us.distinct():
|
||||||
|
u.user_permissions.add(perm_dict['user']['corp_apis'].pk)
|
||||||
|
for u in corp_users:
|
||||||
|
u.user_permissions.remove(perm_dict['corpstats']['view_corp_corpstats'].pk)
|
||||||
|
for u in corp_api_users:
|
||||||
|
u.user_permissions.remove(perm_dict['corpstats']['corp_apis'].pk)
|
||||||
|
|
||||||
|
|
||||||
|
alliance_users = users_with_permission(apps, perm_dict['corpstats']['view_alliance_corpstats'])
|
||||||
|
alliance_api_users = users_with_permission(apps, perm_dict['corpstats']['alliance_apis'])
|
||||||
|
alliance_us = alliance_users | alliance_api_users
|
||||||
|
for u in alliance_us.distinct():
|
||||||
|
u.user_permissions.add(perm_dict['user']['alliance_apis'].pk)
|
||||||
|
for u in alliance_users:
|
||||||
|
u.user_permissions.remove(perm_dict['corpstats']['view_alliance_corpstats'].pk)
|
||||||
|
for u in alliance_api_users:
|
||||||
|
u.user_permissions.remove(perm_dict['corpstats']['alliance_apis'].pk)
|
||||||
|
|
||||||
|
corp_groups = groups_with_permission(apps, perm_dict['corpstats']['view_corp_corpstats'])
|
||||||
|
corp_api_groups = groups_with_permission(apps, perm_dict['corpstats']['corp_apis'])
|
||||||
|
corp_gs = corp_groups | corp_api_groups
|
||||||
|
for g in corp_groups.distinct():
|
||||||
|
g.permissions.add(perm_dict['user']['corp_apis'].pk)
|
||||||
|
for g in corp_groups:
|
||||||
|
g.permissions.remove(perm_dict['corpstats']['view_corp_corpstats'].pk)
|
||||||
|
for g in corp_api_groups:
|
||||||
|
g.permissions.remove(perm_dict['corpstats']['corp_apis'].pk)
|
||||||
|
|
||||||
|
alliance_groups = groups_with_permission(apps, perm_dict['corpstats']['view_alliance_corpstats'])
|
||||||
|
alliance_api_groups = groups_with_permission(apps, perm_dict['corpstats']['alliance_apis'])
|
||||||
|
alliance_gs = alliance_groups | alliance_api_groups
|
||||||
|
for g in alliance_gs.distinct():
|
||||||
|
g.permissions.add(perm_dict['user']['alliance_apis'].pk)
|
||||||
|
for g in alliance_groups:
|
||||||
|
g.permissions.remove(perm_dict['corpstats']['view_alliance_corpstats'].pk)
|
||||||
|
for g in alliance_api_groups:
|
||||||
|
g.permissions.remove(perm_dict['corpstats']['alliance_apis'].pk)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('corputils', '0001_initial'),
|
||||||
|
('authentication', '0005_delete_perms'),
|
||||||
|
('auth', '0008_alter_user_username_max_length'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(forward, reverse),
|
||||||
|
]
|
0
corputils/migrations/__init__.py
Normal file
0
corputils/migrations/__init__.py
Normal file
@ -1 +1,174 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
from django.utils.encoding import python_2_unicode_compatible
|
||||||
|
from django.db import models
|
||||||
|
from eveonline.models import EveCorporationInfo, EveCharacter, EveApiKeyPair
|
||||||
|
from esi.models import Token
|
||||||
|
from esi.errors import TokenError
|
||||||
|
from notifications import notify
|
||||||
|
from authentication.models import AuthServicesInfo
|
||||||
|
from bravado.exception import HTTPForbidden
|
||||||
|
from corputils.managers import CorpStatsManager
|
||||||
|
from operator import attrgetter
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class CorpStats(models.Model):
|
||||||
|
token = models.ForeignKey(Token, on_delete=models.CASCADE)
|
||||||
|
corp = models.OneToOneField(EveCorporationInfo)
|
||||||
|
last_update = models.DateTimeField(auto_now=True)
|
||||||
|
_members = models.TextField(default='{}')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
permissions = (
|
||||||
|
('corp_apis', 'Can view API keys of members of their corporation.'),
|
||||||
|
('alliance_apis', 'Can view API keys of members of their alliance.'),
|
||||||
|
('blue_apis', 'Can view API keys of members of blue corporations.'),
|
||||||
|
)
|
||||||
|
default_permissions = (
|
||||||
|
'add',
|
||||||
|
'change',
|
||||||
|
'remove',
|
||||||
|
'view_corp',
|
||||||
|
'view_alliance',
|
||||||
|
'view_blue',
|
||||||
|
)
|
||||||
|
verbose_name = "corp stats"
|
||||||
|
verbose_name_plural = "corp stats"
|
||||||
|
|
||||||
|
objects = CorpStatsManager()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s for %s" % (self.__class__.__name__, self.corp)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
try:
|
||||||
|
c = self.token.get_esi_client()
|
||||||
|
assert c.Character.get_characters_character_id(character_id=self.token.character_id).result()['corporation_id'] == int(self.corp.corporation_id)
|
||||||
|
members = c.Corporation.get_corporations_corporation_id_members(corporation_id=self.corp.corporation_id).result()
|
||||||
|
member_ids = [m['character_id'] for m in members]
|
||||||
|
member_names = c.Character.get_characters_names(character_ids=member_ids).result()
|
||||||
|
member_list = {m['character_id']:m['character_name'] for m in member_names}
|
||||||
|
self.members = member_list
|
||||||
|
self.save()
|
||||||
|
except TokenError as e:
|
||||||
|
logger.warning("%s failed to update: %s" % (self, e))
|
||||||
|
if self.token.user:
|
||||||
|
notify(self.token.user, "%s failed to update with your ESI token." % self, message="Your token has expired or is no longer valid. Please add a new one to create a new CorpStats.", level="error")
|
||||||
|
self.delete()
|
||||||
|
except HTTPForbidden as e:
|
||||||
|
logger.warning("%s failed to update: %s" % (self, e))
|
||||||
|
if self.token.user:
|
||||||
|
notify(self.token.user, "%s failed to update with your ESI token." % self, message="%s: %s" % (e.status_code, e.message), level="error")
|
||||||
|
self.delete()
|
||||||
|
except AssertionError:
|
||||||
|
logger.warning("%s token character no longer in corp." % self)
|
||||||
|
if self.token.user:
|
||||||
|
notify(self.token.user, "%s cannot update with your ESI token." % self, message="%s cannot update with your ESI token as you have left corp." % self, level="error")
|
||||||
|
self.delete()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def members(self):
|
||||||
|
return json.loads(self._members)
|
||||||
|
|
||||||
|
@members.setter
|
||||||
|
def members(self, dict):
|
||||||
|
self._members = json.dumps(dict)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def member_ids(self):
|
||||||
|
return [id for id, name in self.members.items()]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def member_names(self):
|
||||||
|
return [name for id, name in self.members.items()]
|
||||||
|
|
||||||
|
def show_apis(self, user):
|
||||||
|
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
|
||||||
|
if auth.main_char_id:
|
||||||
|
try:
|
||||||
|
char = EveCharacter.objects.get(character_id=auth.main_char_id)
|
||||||
|
if char.corporation_id == self.corp.corporation_id and user.has_perm('corputils.corp_apis'):
|
||||||
|
return True
|
||||||
|
if self.corp.alliance and char.alliance_id == self.corp.alliance.alliance_id and user.has_perm('corputils.alliance_apis'):
|
||||||
|
return True
|
||||||
|
if user.has_perm('corputils.blue_apis') and self.corp.is_blue:
|
||||||
|
return True
|
||||||
|
except EveCharacter.DoesNotExist:
|
||||||
|
pass
|
||||||
|
return user.is_superuser
|
||||||
|
|
||||||
|
def entered_apis(self):
|
||||||
|
return EveCharacter.objects.filter(character_id__in=self.member_ids).exclude(api_id__isnull=True).count()
|
||||||
|
|
||||||
|
def member_count(self):
|
||||||
|
return len(self.members)
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class MemberObject(object):
|
||||||
|
def __init__(self, character_id, character_name, show_apis=False):
|
||||||
|
self.character_id = character_id
|
||||||
|
self.character_name = character_name
|
||||||
|
try:
|
||||||
|
char = EveCharacter.objects.get(character_id=character_id)
|
||||||
|
auth = AuthServicesInfo.objects.get(user=char.user)
|
||||||
|
try:
|
||||||
|
self.main = EveCharacter.objects.get(character_id=auth.main_char_id)
|
||||||
|
except EveCharacter.DoesNotExist:
|
||||||
|
self.main = None
|
||||||
|
api = EveApiKeyPair.objects.get(api_id=char.api_id)
|
||||||
|
self.registered = True
|
||||||
|
if show_apis:
|
||||||
|
self.api = api
|
||||||
|
else:
|
||||||
|
self.api = None
|
||||||
|
except (EveCharacter.DoesNotExist, AuthServicesInfo.DoesNotExist):
|
||||||
|
self.main = None
|
||||||
|
self.api = None
|
||||||
|
self.registered = False
|
||||||
|
except EveApiKeyPair.DoesNotExist:
|
||||||
|
self.api = None
|
||||||
|
self.registered = False
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
def get_member_objects(self, user):
|
||||||
|
show_apis = self.show_apis(user)
|
||||||
|
return sorted([CorpStats.MemberObject(id, name, show_apis=show_apis) for id, name in self.members.items()], key=attrgetter('character_name'))
|
||||||
|
|
||||||
|
def can_update(self, user):
|
||||||
|
return user.is_superuser or user == self.token.user
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class ViewModel(object):
|
||||||
|
def __init__(self, corpstats, user):
|
||||||
|
self.corp = corpstats.corp
|
||||||
|
self.members = corpstats.get_member_objects(user)
|
||||||
|
self.can_update = corpstats.can_update(user)
|
||||||
|
self.total_members = len(self.members)
|
||||||
|
self.registered_members = corpstats.entered_apis()
|
||||||
|
self.show_apis = corpstats.show_apis(user)
|
||||||
|
self.last_updated = corpstats.last_update
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.corp)
|
||||||
|
|
||||||
|
def corp_logo(self, size=128):
|
||||||
|
return "https://image.eveonline.com/Corporation/%s_%s.png" % (self.corp.corporation_id, 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)
|
||||||
|
else:
|
||||||
|
return "https://image.eveonline.com/Alliance/1_%s.png" % size
|
||||||
|
|
||||||
|
def get_view_model(self, user):
|
||||||
|
return CorpStats.ViewModel(self, user)
|
||||||
|
39
corputils/templates/corputils/base.html
Normal file
39
corputils/templates/corputils/base.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{% extends 'public/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Corporation Member Data" %}{% endblock %}
|
||||||
|
{% block page_title %}{% trans "Corporation Member Data" %}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<h1 class="page-header text-center">{% trans "Corporation Member Data" %}</h1>
|
||||||
|
<div class="col-lg-10 col-lg-offset-1 container">
|
||||||
|
<nav class="navbar navbar-default">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Corporations<span class="caret"></span></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
{% for corpstat in available %}
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'corputils:view_corp' corpstat.corp.corporation_id %}">{{ corpstat.corp.corporation_name }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% if perms.corputils.add_corpstats %}
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'corputils:add' %}">Add</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<form class="navbar-form navbar-right" role="search" action="{% url 'corputils:search' %}" method="GET">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="search_string" placeholder="{% if search_string %}{{ search_string }}{% else %}Search characters...{% endif %}">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
{% block member_data %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
92
corputils/templates/corputils/corpstats.html
Normal file
92
corputils/templates/corputils/corpstats.html
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
{% extends 'corputils/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load humanize %}
|
||||||
|
{% load bootstrap_pagination %}
|
||||||
|
{% block member_data %}
|
||||||
|
{% if corpstats %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12 text-center">
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<td class="text-center col-lg-6 {% if corpstats.corp.alliance %}{% else %}col-lg-offset-3{% endif %}"><img class="ra-avatar" src="{{ corpstats.corp_logo }}"></td>
|
||||||
|
{% if corpstats.corp.alliance %}
|
||||||
|
<td class="text-center col-lg-6"><img class="ra-avatar" src="{{ corpstats.alliance_logo }}"></td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-center"><h4>{{ corpstats.corp.corporation_name }}</h4></td>
|
||||||
|
{% if corpstats.corp.alliance %}
|
||||||
|
<td class="text-center"><h4>{{ corpstats.corp.alliance.alliance_name }}</h4></td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<b>{% trans "API Index:" %}</b>
|
||||||
|
<div class="progress">
|
||||||
|
<div class="progress-bar" role="progressbar" aria-valuenow="{{ corpstats.registered_members }}" aria-valuemin="0" aria-valuemax="{{ corpstats.total_members }}" style="width: {% widthratio corpstats.registered_members corpstats.total_members 100 %}%;">
|
||||||
|
{{ corpstats.registered_members }}/{{ corpstats.total_members }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading clearfix">
|
||||||
|
<div class="panel-title pull-left">
|
||||||
|
<h4>Members</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-title pull-right">
|
||||||
|
Last update: {{ corpstats.last_updated|naturaltime }}
|
||||||
|
{% if corpstats.can_update %}
|
||||||
|
<a class="btn btn-success" type="button" href="{% url 'corputils:update' corpstats.corp.corporation_id %}" title="Update Now">
|
||||||
|
<span class="glyphicon glyphicon-refresh"></span>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="text-center">
|
||||||
|
{% bootstrap_paginate members range=10 %}
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th class="text-center">Character</th>
|
||||||
|
{% if corpstats.show_apis %}
|
||||||
|
<th class="text-center">API</th>
|
||||||
|
{% endif %}
|
||||||
|
<th class="text-center">zKillboard</th>
|
||||||
|
<th class="text-center">Main Character</th>
|
||||||
|
<th class="text-center">Main Corporation</th>
|
||||||
|
<th class="text-center">Main Alliance</th>
|
||||||
|
</tr>
|
||||||
|
{% for member in members %}
|
||||||
|
<tr {% if not member.registered %}class="danger"{% endif %}>
|
||||||
|
<td><img src="{{ member.portrait_url }}" class="img-circle"></td>
|
||||||
|
<td class="text-center">{{ member.character_name }}</td>
|
||||||
|
{% if corpstats.show_apis %}
|
||||||
|
{% if member.api %}
|
||||||
|
<td class="text-center"><a href="{{ JACK_KNIFE_URL }}?usid={{ member.api.api_id }}&apik={{ member.api.api_key }}" target="_blank" class="label label-primary">{{ member.api.api_id }}</td>
|
||||||
|
{% else %}
|
||||||
|
<td></td>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
<td class="text-center"><a href="https://zkillboard.com/character/{{ member.character_id }}/" class="label label-danger" target="_blank">{% trans "Killboard" %}</a></td>
|
||||||
|
<td class="text-center">{{ member.main.character_name }}</td>
|
||||||
|
<td class="text-center">{{ member.main.corporation_name }}</td>
|
||||||
|
<td class="text-center">{{ member.main.alliance_name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
43
corputils/templates/corputils/search.html
Normal file
43
corputils/templates/corputils/search.html
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{% extends "corputils/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap_pagination %}
|
||||||
|
{% block member_data %}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading clearfix">
|
||||||
|
<div class="panel-title pull-left">Search Results</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="text-center">
|
||||||
|
{% bootstrap_paginate results range=10 %}
|
||||||
|
</div>
|
||||||
|
<table class="table table-hover">
|
||||||
|
<tr>
|
||||||
|
<th class="text-center"></th>
|
||||||
|
<th class="text-center">Character</th>
|
||||||
|
<th class="text-center">Corporation</th>
|
||||||
|
<th class="text-center">API</th>
|
||||||
|
<th class="text-center">zKillboard</th>
|
||||||
|
<th class="text-center">Main Character</th>
|
||||||
|
<th class="text-center">Main Corporation</th>
|
||||||
|
<th class="text-center">Main Alliance</th>
|
||||||
|
</tr>
|
||||||
|
{% for result in results %}
|
||||||
|
<tr {% if not result.1.registered %}class="danger"{% endif %}>
|
||||||
|
<td class="text-center"><img src="{{ result.1.portrait_url }}" class="img-circle"></td>
|
||||||
|
<td class="text-center">{{ result.1.character_name }}</td>
|
||||||
|
<td class="text-center">{{ result.0.corp.corporation_name }}</td>
|
||||||
|
{% if result.1.api %}
|
||||||
|
<td class="text-center"><a href="{{ JACK_KNIFE_URL }}?usid={{ result.1.api.api_id }}&apik={{ result.1.api.api_key }}" target="_blank" class="label label-primary">{{ result.1.api.api_id }}</td>
|
||||||
|
{% else %}
|
||||||
|
<td></td>
|
||||||
|
{% endif %}
|
||||||
|
<td class="text-center"><a href="https://zkillboard.com/character/{{ result.1.character_id }}/" class="label label-danger" target="_blank">{% trans "Killboard" %}</a></td>
|
||||||
|
<td class="text-center">{{ result.1.main.character_name }}</td>
|
||||||
|
<td class="text-center">{{ result.1.main.corporation_name }}</td>
|
||||||
|
<td class="text-center">{{ result.1.main.alliance_name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
11
corputils/urls.py
Normal file
11
corputils/urls.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from django.conf.urls import url
|
||||||
|
import corputils.views
|
||||||
|
|
||||||
|
app_name='corputils'
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^$', corputils.views.corpstats_view, name='view'),
|
||||||
|
url(r'^add/$', corputils.views.corpstats_add, name='add'),
|
||||||
|
url(r'^(?P<corp_id>(\d)*)/$', corputils.views.corpstats_view, name='view_corp'),
|
||||||
|
url(r'^(?P<corp_id>(\d)+)/update/$', corputils.views.corpstats_update, name='update'),
|
||||||
|
url(r'^search/$', corputils.views.corpstats_search, name='search'),
|
||||||
|
]
|
@ -1,325 +1,124 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.db import IntegrityError
|
||||||
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||||
|
from django.conf import settings
|
||||||
|
from eveonline.models import EveCharacter, EveCorporationInfo
|
||||||
|
from corputils.models import CorpStats
|
||||||
|
from esi.decorators import token_required
|
||||||
|
|
||||||
from collections import namedtuple
|
MEMBERS_PER_PAGE = int(getattr(settings, 'CORPSTATS_MEMBERS_PER_PAGE', 20))
|
||||||
|
|
||||||
from authentication.models import AuthServicesInfo
|
def get_page(model_list, page_num):
|
||||||
from services.managers.eve_api_manager import EveApiManager
|
p = Paginator(model_list, MEMBERS_PER_PAGE)
|
||||||
from services.managers.evewho_manager import EveWhoManager
|
try:
|
||||||
from eveonline.models import EveCorporationInfo
|
members = p.page(page_num)
|
||||||
from eveonline.models import EveAllianceInfo
|
except PageNotAnInteger:
|
||||||
from eveonline.models import EveCharacter
|
members = p.page(1)
|
||||||
from eveonline.models import EveApiKeyPair
|
except EmptyPage:
|
||||||
from fleetactivitytracking.models import Fat
|
members = p.page(p.num_pages)
|
||||||
from corputils.forms import CorputilsSearchForm
|
return members
|
||||||
from evelink.api import APIError
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class Player(object):
|
|
||||||
def __init__(self, main, user, maincorp, maincorpid, altlist, apilist, n_fats):
|
|
||||||
self.main = main
|
|
||||||
self.user = user
|
|
||||||
self.maincorp = maincorp
|
|
||||||
self.maincorpid = maincorpid
|
|
||||||
self.altlist = altlist
|
|
||||||
self.apilist = apilist
|
|
||||||
self.n_fats = n_fats
|
|
||||||
|
|
||||||
|
|
||||||
def first_day_of_next_month(year, month):
|
|
||||||
if month == 12:
|
|
||||||
return datetime.datetime(year + 1, 1, 1)
|
|
||||||
else:
|
|
||||||
return datetime.datetime(year, month + 1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
def first_day_of_previous_month(year, month):
|
|
||||||
if month == 1:
|
|
||||||
return datetime.datetime(year - 1, 12, 1)
|
|
||||||
else:
|
|
||||||
return datetime.datetime(year, month - 1, 1)
|
|
||||||
|
|
||||||
|
def access_corpstats_test(user):
|
||||||
|
return user.has_perm('corputils.view_corp_corpstats') or user.has_perm('corputils.view_alliance_corpstats') or user.has_perm('corputils.view_blue_corpstats')
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def corp_member_view(request, corpid=None, year=datetime.date.today().year, month=datetime.date.today().month):
|
@user_passes_test(access_corpstats_test)
|
||||||
year = int(year)
|
@permission_required('corputils.add_corpstats')
|
||||||
month = int(month)
|
@token_required(scopes='esi-corporations.read_corporation_membership.v1')
|
||||||
start_of_month = datetime.datetime(year, month, 1)
|
def corpstats_add(request, token):
|
||||||
start_of_next_month = first_day_of_next_month(year, month)
|
|
||||||
start_of_previous_month = first_day_of_previous_month(year, month)
|
|
||||||
logger.debug("corp_member_view called by user %s" % request.user)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user_main = EveCharacter.objects.get(
|
if EveCharacter.objects.filter(character_id=token.character_id).exists():
|
||||||
character_id=AuthServicesInfo.objects.get_or_create(user=request.user)[0].main_char_id)
|
corp_id = EveCharacter.objects.get(character_id=token.character_id).corporation_id
|
||||||
user_corp_id = user_main.corporation_id
|
|
||||||
except (ValueError, EveCharacter.DoesNotExist):
|
|
||||||
user_corp_id = settings.CORP_ID
|
|
||||||
|
|
||||||
if not settings.IS_CORP:
|
|
||||||
alliance = EveAllianceInfo.objects.get(alliance_id=settings.ALLIANCE_ID)
|
|
||||||
alliancecorps = EveCorporationInfo.objects.filter(alliance=alliance)
|
|
||||||
membercorplist = [(int(membercorp.corporation_id), str(membercorp.corporation_name)) for membercorp in
|
|
||||||
alliancecorps]
|
|
||||||
membercorplist.sort(key=lambda tup: tup[1])
|
|
||||||
membercorp_id_list = [int(membercorp.corporation_id) for membercorp in alliancecorps]
|
|
||||||
|
|
||||||
bluecorps = EveCorporationInfo.objects.filter(is_blue=True)
|
|
||||||
bluecorplist = [(int(bluecorp.corporation_id), str(bluecorp.corporation_name)) for bluecorp in bluecorps]
|
|
||||||
bluecorplist.sort(key=lambda tup: tup[1])
|
|
||||||
bluecorp_id_list = [int(bluecorp.corporation_id) for bluecorp in bluecorps]
|
|
||||||
|
|
||||||
if not (user_corp_id in membercorp_id_list or user_corp_id not in bluecorp_id_list):
|
|
||||||
user_corp_id = None
|
|
||||||
|
|
||||||
if not corpid:
|
|
||||||
if settings.IS_CORP:
|
|
||||||
corpid = settings.CORP_ID
|
|
||||||
elif user_corp_id:
|
|
||||||
corpid = user_corp_id
|
|
||||||
else:
|
else:
|
||||||
corpid = membercorplist[0][0]
|
corp_id = token.get_esi_client().Character.get_characters_character_id(character_id=token.character_id).result()['corporation_id']
|
||||||
|
corp = EveCorporationInfo.objects.get(corporation_id=corp_id)
|
||||||
corp = EveCorporationInfo.objects.get(corporation_id=corpid)
|
cs = CorpStats.objects.create(token=token, corp=corp)
|
||||||
if request.user.has_perm('auth.alliance_apis') or (request.user.has_perm('auth.corp_apis') and user_corp_id == corpid):
|
cs.update()
|
||||||
logger.debug("Retreiving and sending API-information")
|
assert cs.pk # ensure update was succesful
|
||||||
|
if CorpStats.objects.filter(pk=cs.pk).visible_to(request.user).exists():
|
||||||
if settings.IS_CORP:
|
return redirect('corputils:view_corp', corp_id=corp.corporation_id)
|
||||||
try:
|
except EveCorporationInfo.DoesNotExist:
|
||||||
member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE)
|
messages.error(request, 'Unrecognized corporation. Please ensure it is a member of the alliance or a blue.')
|
||||||
except APIError:
|
except IntegrityError:
|
||||||
logger.debug("Corp API does not have membertracking scope, using EveWho data instead.")
|
messages.error(request, 'Selected corp already has a statistics module.')
|
||||||
member_list = EveWhoManager.get_corporation_members(corpid)
|
except AssertionError:
|
||||||
else:
|
messages.error(request, 'Failed to gather corporation statistics with selected token.')
|
||||||
member_list = EveWhoManager.get_corporation_members(corpid)
|
return redirect('corputils:view')
|
||||||
|
|
||||||
characters_with_api = {}
|
|
||||||
characters_without_api = {}
|
|
||||||
|
|
||||||
num_registered_characters = 0
|
|
||||||
for char_id, member_data in member_list.items():
|
|
||||||
try:
|
|
||||||
char = EveCharacter.objects.get(character_id=char_id)
|
|
||||||
char_owner = char.user
|
|
||||||
try:
|
|
||||||
if not char_owner:
|
|
||||||
raise AttributeError("Character has no assigned user.")
|
|
||||||
mainid = int(AuthServicesInfo.objects.get_or_create(user=char_owner)[0].main_char_id)
|
|
||||||
mainchar = EveCharacter.objects.get(character_id=mainid)
|
|
||||||
mainname = mainchar.character_name
|
|
||||||
maincorp = mainchar.corporation_name
|
|
||||||
maincorpid = mainchar.corporation_id
|
|
||||||
api_pair = EveApiKeyPair.objects.get(api_id=char.api_id)
|
|
||||||
except (ValueError, EveCharacter.DoesNotExist, EveApiKeyPair.DoesNotExist):
|
|
||||||
logger.debug("No main character seem to be set for character %s" % char.character_name)
|
|
||||||
mainname = "User: " + char_owner.username
|
|
||||||
mainchar = char
|
|
||||||
maincorp = "Not set."
|
|
||||||
maincorpid = None
|
|
||||||
api_pair = None
|
|
||||||
except AttributeError:
|
|
||||||
logger.debug("No associated user for character %s" % char.character_name)
|
|
||||||
mainname = None
|
|
||||||
mainchar = char
|
|
||||||
maincorp = None
|
|
||||||
maincorpid = None
|
|
||||||
try:
|
|
||||||
api_pair = EveApiKeyPair.objects.get(api_id=char.api_id)
|
|
||||||
except EveApiKeyPair.DoesNotExist:
|
|
||||||
api_pair = None
|
|
||||||
num_registered_characters += 1
|
|
||||||
characters_with_api.setdefault(mainname, Player(main=mainchar,
|
|
||||||
user=char_owner,
|
|
||||||
maincorp=maincorp,
|
|
||||||
maincorpid=maincorpid,
|
|
||||||
altlist=[],
|
|
||||||
apilist=[],
|
|
||||||
n_fats=0)
|
|
||||||
).altlist.append(char)
|
|
||||||
if api_pair:
|
|
||||||
characters_with_api[mainname].apilist.append(api_pair)
|
|
||||||
|
|
||||||
except EveCharacter.DoesNotExist:
|
|
||||||
characters_without_api.update({member_data["name"]: member_data["id"]})
|
|
||||||
|
|
||||||
for char in EveCharacter.objects.filter(corporation_id=corpid):
|
|
||||||
if not int(char.character_id) in member_list:
|
|
||||||
logger.debug("Character '%s' does not exist in EveWho dump." % char.character_name)
|
|
||||||
char_owner = char.user
|
|
||||||
try:
|
|
||||||
if not char_owner:
|
|
||||||
raise AttributeError("Character has no assigned user.")
|
|
||||||
mainid = int(AuthServicesInfo.objects.get_or_create(user=char_owner)[0].main_char_id)
|
|
||||||
mainchar = EveCharacter.objects.get(character_id=mainid)
|
|
||||||
mainname = mainchar.character_name
|
|
||||||
maincorp = mainchar.corporation_name
|
|
||||||
maincorpid = mainchar.corporation_id
|
|
||||||
api_pair = EveApiKeyPair.objects.get(api_id=char.api_id)
|
|
||||||
except (ValueError, EveCharacter.DoesNotExist, EveApiKeyPair.DoesNotExist):
|
|
||||||
logger.debug("No main character seem to be set for character %s" % char.character_name)
|
|
||||||
mainname = "User: " + char_owner.username
|
|
||||||
mainchar = char
|
|
||||||
maincorp = "Not set."
|
|
||||||
maincorpid = None
|
|
||||||
api_pair = None
|
|
||||||
except AttributeError:
|
|
||||||
logger.debug("No associated user for character %s" % char.character_name)
|
|
||||||
mainname = None
|
|
||||||
mainchar = char
|
|
||||||
maincorp = None
|
|
||||||
maincorpid = None
|
|
||||||
try:
|
|
||||||
api_pair = EveApiKeyPair.objects.get(api_id=char.api_id)
|
|
||||||
except EveApiKeyPair.DoesNotExist:
|
|
||||||
api_pair = None
|
|
||||||
num_registered_characters += 1
|
|
||||||
characters_with_api.setdefault(mainname, Player(main=mainchar,
|
|
||||||
user=char_owner,
|
|
||||||
maincorp=maincorp,
|
|
||||||
maincorpid=maincorpid,
|
|
||||||
altlist=[],
|
|
||||||
apilist=[],
|
|
||||||
n_fats=0)
|
|
||||||
).altlist.append(char)
|
|
||||||
if api_pair:
|
|
||||||
characters_with_api[mainname].apilist.append(api_pair)
|
|
||||||
|
|
||||||
n_unacounted = corp.member_count - (num_registered_characters + len(characters_without_api))
|
|
||||||
|
|
||||||
for mainname, player in characters_with_api.items():
|
|
||||||
fats_this_month = Fat.objects.filter(user=player.user).filter(
|
|
||||||
fatlink__fatdatetime__gte=start_of_month).filter(fatlink__fatdatetime__lt=start_of_next_month)
|
|
||||||
characters_with_api[mainname].n_fats = len(fats_this_month)
|
|
||||||
|
|
||||||
if start_of_next_month > datetime.datetime.now():
|
|
||||||
start_of_next_month = None
|
|
||||||
|
|
||||||
if not settings.IS_CORP:
|
|
||||||
context = {"membercorplist": membercorplist,
|
|
||||||
"corp": corp,
|
|
||||||
"characters_with_api": sorted(characters_with_api.items()),
|
|
||||||
'n_registered': num_registered_characters,
|
|
||||||
'n_unacounted': n_unacounted,
|
|
||||||
"characters_without_api": sorted(characters_without_api.items()),
|
|
||||||
"search_form": CorputilsSearchForm()}
|
|
||||||
else:
|
|
||||||
logger.debug("corp_member_view running in corportation mode")
|
|
||||||
context = {"corp": corp,
|
|
||||||
"characters_with_api": sorted(characters_with_api.items()),
|
|
||||||
'n_registered': num_registered_characters,
|
|
||||||
'n_unacounted': n_unacounted,
|
|
||||||
"characters_without_api": sorted(characters_without_api.items()),
|
|
||||||
"search_form": CorputilsSearchForm()}
|
|
||||||
|
|
||||||
context["next_month"] = start_of_next_month
|
|
||||||
context["previous_month"] = start_of_previous_month
|
|
||||||
context["this_month"] = start_of_month
|
|
||||||
|
|
||||||
return render(request, 'registered/corputils.html', context=context)
|
|
||||||
else:
|
|
||||||
logger.warn('User %s (%s) not authorized to view corp stats for corp id %s' % (request.user, user_corp_id, corpid))
|
|
||||||
return redirect("auth_dashboard")
|
|
||||||
|
|
||||||
|
|
||||||
def can_see_api(user, character):
|
|
||||||
if user.has_perm('auth.alliance_apis'):
|
|
||||||
return True
|
|
||||||
try:
|
|
||||||
user_main = EveCharacter.objects.get(
|
|
||||||
character_id=AuthServicesInfo.objects.get_or_create(user=user)[0].main_char_id)
|
|
||||||
if user.has_perm('auth.corp_apis') and user_main.corporation_id == character.corporation_id:
|
|
||||||
return True
|
|
||||||
except EveCharacter.DoesNotExist:
|
|
||||||
return False
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def corputils_search(request, corpid=settings.CORP_ID):
|
@user_passes_test(access_corpstats_test)
|
||||||
logger.debug("corputils_search called by user %s" % request.user)
|
def corpstats_view(request, corp_id=None):
|
||||||
|
corpstats = None
|
||||||
|
show_apis = False
|
||||||
|
|
||||||
corp = EveCorporationInfo.objects.get(corporation_id=corpid)
|
# get requested model
|
||||||
|
if corp_id:
|
||||||
|
corp = get_object_or_404(EveCorporationInfo, corporation_id=corp_id)
|
||||||
|
corpstats = get_object_or_404(CorpStats, corp=corp)
|
||||||
|
|
||||||
authorized = False
|
# get available models
|
||||||
try:
|
available = CorpStats.objects.visible_to(request.user)
|
||||||
user_main = EveCharacter.objects.get(
|
|
||||||
character_id=AuthServicesInfo.objects.get_or_create(user=request.user)[0].main_char_id)
|
|
||||||
if request.user.has_perm('auth.alliance_apis') or (
|
|
||||||
request.user.has_perm('auth.corp_apis') and (user_main.corporation_id == corpid)):
|
|
||||||
logger.debug("Retreiving and sending API-information")
|
|
||||||
authorized = True
|
|
||||||
except (ValueError, EveCharacter.DoesNotExist):
|
|
||||||
if request.user.has_perm('auth.alliance_apis'):
|
|
||||||
logger.debug("Retrieving and sending API-information")
|
|
||||||
authorized = True
|
|
||||||
|
|
||||||
if authorized:
|
# ensure we can see the requested model
|
||||||
if request.method == 'POST':
|
if corpstats and not corpstats in available:
|
||||||
form = CorputilsSearchForm(request.POST)
|
raise PermissionDenied('You do not have permission to view the selected corporation statistics module.')
|
||||||
logger.debug("Request type POST contains form valid: %s" % form.is_valid())
|
|
||||||
if form.is_valid():
|
|
||||||
# Really dumb search and only checks character name
|
|
||||||
# This can be improved but it does the job for now
|
|
||||||
searchstring = form.cleaned_data['search_string']
|
|
||||||
logger.debug("Searching for player with character name %s for user %s" % (searchstring, request.user))
|
|
||||||
|
|
||||||
member_list = {}
|
# get default model if none requested
|
||||||
if settings.IS_CORP:
|
if not corp_id and available.count() == 1:
|
||||||
member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE)
|
corpstats = available[0]
|
||||||
if not member_list:
|
|
||||||
logger.debug('Unable to fetch members from API. Pulling from EveWho')
|
|
||||||
member_list = EveWhoManager.get_corporation_members(corpid)
|
|
||||||
|
|
||||||
SearchResult = namedtuple('SearchResult',
|
context = {
|
||||||
['name', 'id', 'main', 'api_registered', 'character', 'apiinfo'])
|
'available': available,
|
||||||
|
}
|
||||||
|
|
||||||
searchresults = []
|
# paginate
|
||||||
for memberid, member_data in member_list.items():
|
members = []
|
||||||
if searchstring.lower() in member_data["name"].lower():
|
if corpstats:
|
||||||
try:
|
page = request.GET.get('page', 1)
|
||||||
char = EveCharacter.objects.get(character_name=member_data["name"])
|
members = get_page(corpstats.get_member_objects(request.user), page)
|
||||||
user = char.user
|
|
||||||
mainid = int(AuthServicesInfo.objects.get_or_create(user=user)[0].main_char_id)
|
if corpstats:
|
||||||
main = EveCharacter.objects.get(character_id=mainid)
|
context.update({
|
||||||
if can_see_api(request.user, char):
|
'corpstats': corpstats.get_view_model(request.user),
|
||||||
api_registered = True
|
'members': members,
|
||||||
apiinfo = EveApiKeyPair.objects.get(api_id=char.api_id)
|
})
|
||||||
|
|
||||||
|
return render(request, 'corputils/corpstats.html', context=context)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_passes_test(access_corpstats_test)
|
||||||
|
def corpstats_update(request, corp_id):
|
||||||
|
corp = get_object_or_404(EveCorporationInfo, corporation_id=corp_id)
|
||||||
|
corpstats = get_object_or_404(CorpStats, corp=corp)
|
||||||
|
if corpstats.can_update(request.user):
|
||||||
|
corpstats.update()
|
||||||
else:
|
else:
|
||||||
api_registered = False
|
raise PermissionDenied('You do not have permission to update member data for the selected corporation statistics module.')
|
||||||
apiinfo = None
|
return redirect('corputils:view_corp', corp_id=corp.corporation_id)
|
||||||
except EveCharacter.DoesNotExist:
|
|
||||||
api_registered = False
|
|
||||||
char = None
|
|
||||||
main = ""
|
|
||||||
apiinfo = None
|
|
||||||
|
|
||||||
searchresults.append(SearchResult(name=member_data["name"], id=memberid, main=main,
|
@login_required
|
||||||
api_registered=api_registered,
|
@user_passes_test(access_corpstats_test)
|
||||||
character=char, apiinfo=apiinfo))
|
def corpstats_search(request):
|
||||||
|
results = []
|
||||||
logger.info("Found %s members for user %s matching search string %s" % (
|
search_string = request.GET.get('search_string', None)
|
||||||
len(searchresults), request.user, searchstring))
|
if search_string:
|
||||||
|
has_similar = CorpStats.objects.filter(_members__icontains=search_string).visible_to(request.user)
|
||||||
context = {'corp': corp, 'results': searchresults, 'search_form': CorputilsSearchForm(),
|
for corpstats in has_similar:
|
||||||
"year": datetime.datetime.now().year, "month": datetime.datetime.now().month}
|
similar = [(member_id, corpstats.members[member_id]) for member_id in corpstats.members if search_string.lower() in corpstats.members[member_id].lower()]
|
||||||
|
for s in similar:
|
||||||
return render(request, 'registered/corputilssearchview.html',
|
results.append((corpstats, CorpStats.MemberObject(s[0], s[1], show_apis=corpstats.show_apis(request.user))))
|
||||||
context=context)
|
page = request.GET.get('page', 1)
|
||||||
else:
|
results = sorted(results, key=lambda x: x[1].character_name)
|
||||||
logger.debug("Form invalid - returning for user %s to retry." % request.user)
|
results_page = get_page(results, page)
|
||||||
context = {'corp': corp, 'members': None, 'search_form': CorputilsSearchForm()}
|
context = {
|
||||||
return render(request, 'registered/corputilssearchview.html', context=context)
|
'available': CorpStats.objects.visible_to(request.user),
|
||||||
|
'results': results_page,
|
||||||
else:
|
'search_string': search_string,
|
||||||
logger.debug("Returning empty search form for user %s" % request.user)
|
}
|
||||||
return redirect("auth_corputils")
|
return render(request, 'corputils/search.html', context=context)
|
||||||
else:
|
return redirect('corputils:view')
|
||||||
logger.warn('User %s not authorized to view corp stats for corp ID %s' % (request.user, corpid))
|
|
||||||
return redirect("auth_dashboard")
|
|
||||||
|
@ -3,71 +3,48 @@ from eveonline.models import EveCharacter
|
|||||||
from eveonline.models import EveApiKeyPair
|
from eveonline.models import EveApiKeyPair
|
||||||
from eveonline.models import EveAllianceInfo
|
from eveonline.models import EveAllianceInfo
|
||||||
from eveonline.models import EveCorporationInfo
|
from eveonline.models import EveCorporationInfo
|
||||||
|
from eveonline.providers import eve_adapter_factory, EveXmlProvider
|
||||||
from services.managers.eve_api_manager import EveApiManager
|
from services.managers.eve_api_manager import EveApiManager
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
adapter = eve_adapter_factory()
|
||||||
|
|
||||||
class EveManager:
|
class EveManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_character(character_id, character_name, corporation_id,
|
def create_character(id, user, api_id):
|
||||||
corporation_name, corporation_ticker, alliance_id,
|
return EveManager.create_character_obj(adapter.get_character(id), user, api_id)
|
||||||
alliance_name, user, api_id):
|
|
||||||
logger.debug("Creating model for character %s id %s" % (character_name, character_id))
|
|
||||||
if not EveCharacter.objects.filter(character_id=character_id).exists():
|
|
||||||
eve_char = EveCharacter()
|
|
||||||
eve_char.character_id = character_id
|
|
||||||
eve_char.character_name = character_name
|
|
||||||
eve_char.corporation_id = corporation_id
|
|
||||||
eve_char.corporation_name = corporation_name
|
|
||||||
eve_char.corporation_ticker = corporation_ticker
|
|
||||||
eve_char.alliance_id = alliance_id
|
|
||||||
eve_char.alliance_name = alliance_name
|
|
||||||
eve_char.user = user
|
|
||||||
eve_char.api_id = api_id
|
|
||||||
eve_char.save()
|
|
||||||
logger.info("Created new character model %s for user %s" % (eve_char, user))
|
|
||||||
else:
|
|
||||||
logger.warn("Attempting to create existing character model with id %s" % character_id)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_characters_from_list(chars, user, api_id):
|
def create_character_obj(character, user, api_id):
|
||||||
logger.debug("Creating characters from batch: %s" % chars.result)
|
EveCharacter.objects.create(
|
||||||
for char in chars.result:
|
character_id = character.id,
|
||||||
if not EveManager.check_if_character_exist(chars.result[char]['name']):
|
character_name = character.name,
|
||||||
EveManager.create_character(chars.result[char]['id'],
|
corporation_id = character.corp.id,
|
||||||
chars.result[char]['name'],
|
corporation_name = character.corp.name,
|
||||||
chars.result[char]['corp']['id'],
|
alliance_id = character.alliance.id,
|
||||||
chars.result[char]['corp']['name'],
|
alliance_name = character.alliance.name,
|
||||||
EveApiManager.get_corporation_ticker_from_id(
|
user = user,
|
||||||
chars.result[char]['corp']['id']),
|
api_id = api_id,
|
||||||
chars.result[char]['alliance']['id'],
|
)
|
||||||
chars.result[char]['alliance']['name'],
|
|
||||||
user, api_id)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_characters_from_list(chars):
|
def update_character(id):
|
||||||
logger.debug("Updating characters from list: %s" % chars.result)
|
return EveManager.update_character_obj(adapter.get_character(id))
|
||||||
for char in chars.result:
|
|
||||||
if EveManager.check_if_character_exist(chars.result[char]['name']):
|
@staticmethod
|
||||||
eve_char = EveManager.get_character_by_character_name(chars.result[char]['name'])
|
def update_character_obj(char):
|
||||||
logger.debug("Got existing character model %s" % eve_char)
|
model = EveCharacter.objects.get(character_id=char.id)
|
||||||
eve_char.corporation_id = chars.result[char]['corp']['id']
|
model.character_name = char.name
|
||||||
eve_char.corporation_name = chars.result[char]['corp']['name']
|
model.corporation_id = char.corp.id
|
||||||
eve_char.corporation_ticker = EveApiManager.get_corporation_ticker_from_id(
|
model.corporation_name = char.corp.name
|
||||||
chars.result[char]['corp']['id'])
|
model.alliance_id = char.alliance.id
|
||||||
eve_char.alliance_id = chars.result[char]['alliance']['id']
|
model.alliance_name = char.alliance.name
|
||||||
eve_char.alliance_name = chars.result[char]['alliance']['name']
|
model.save()
|
||||||
eve_char.save()
|
|
||||||
logger.info("Updated character model %s" % eve_char)
|
|
||||||
else:
|
|
||||||
logger.warn(
|
|
||||||
"Attempting to update non-existing character model with name %s" % chars.result[char]['name'])
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_api_keypair(api_id, api_key, user_id):
|
def create_api_keypair(api_id, api_key, user_id):
|
||||||
@ -83,64 +60,80 @@ class EveManager:
|
|||||||
logger.warn("Attempting to create existing api keypair with id %s" % api_id)
|
logger.warn("Attempting to create existing api keypair with id %s" % api_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_alliance_info(alliance_id, alliance_name, alliance_ticker, alliance_executor_corp_id,
|
def create_alliance(id, is_blue=False):
|
||||||
alliance_member_count, is_blue):
|
return EveManager.create_alliance_obj(adapter.get_alliance(id), is_blue=is_blue)
|
||||||
logger.debug("Creating alliance info for alliance %s id %s" % (alliance_name, alliance_id))
|
|
||||||
if not EveManager.check_if_alliance_exists_by_id(alliance_id):
|
|
||||||
alliance_info = EveAllianceInfo()
|
|
||||||
alliance_info.alliance_id = alliance_id
|
|
||||||
alliance_info.alliance_name = alliance_name
|
|
||||||
alliance_info.alliance_ticker = alliance_ticker
|
|
||||||
alliance_info.executor_corp_id = alliance_executor_corp_id
|
|
||||||
alliance_info.member_count = alliance_member_count
|
|
||||||
alliance_info.is_blue = is_blue
|
|
||||||
alliance_info.save()
|
|
||||||
logger.info("Created alliance model for %s" % alliance_info)
|
|
||||||
else:
|
|
||||||
logger.warn("Attempting to create existing alliance model with id %s" % alliance_id)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_alliance_info(alliance_id, alliance_executor_corp_id, alliance_member_count, is_blue):
|
def create_alliance_obj(alliance, is_blue=False):
|
||||||
logger.debug("Updating alliance model with id %s" % alliance_id)
|
EveAllianceInfo.objects.create(
|
||||||
if EveManager.check_if_alliance_exists_by_id(alliance_id):
|
alliance_id = alliance.id,
|
||||||
alliance_info = EveAllianceInfo.objects.get(alliance_id=alliance_id)
|
alliance_name = alliance.name,
|
||||||
alliance_info.executor_corp_id = alliance_executor_corp_id
|
alliance_ticker = alliance.ticker,
|
||||||
alliance_info.member_count = alliance_member_count
|
executor_corp_id = alliance.executor_corp_id,
|
||||||
alliance_info.is_blue = is_blue
|
is_blue = is_blue,
|
||||||
alliance_info.save()
|
)
|
||||||
logger.debug("Updated alliance model %s" % alliance_info)
|
|
||||||
else:
|
|
||||||
logger.warn("Attempting to update non-existing alliance model with id %s" % alliance_id)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_corporation_info(corp_id, corp_name, corp_ticker, corp_member_count, is_blue, alliance):
|
def update_alliance(id, is_blue=None):
|
||||||
logger.debug("Creating corp info for corp %s id %s" % (corp_name, corp_id))
|
return EveManager.update_alliance_obj(adapter.get_alliance(id), is_blue=is_blue)
|
||||||
if not EveManager.check_if_corporation_exists_by_id(corp_id):
|
|
||||||
corp_info = EveCorporationInfo()
|
|
||||||
corp_info.corporation_id = corp_id
|
|
||||||
corp_info.corporation_name = corp_name
|
|
||||||
corp_info.corporation_ticker = corp_ticker
|
|
||||||
corp_info.member_count = corp_member_count
|
|
||||||
corp_info.is_blue = is_blue
|
|
||||||
if alliance:
|
|
||||||
corp_info.alliance = alliance
|
|
||||||
corp_info.save()
|
|
||||||
logger.info("Created corp model for %s" % corp_info)
|
|
||||||
else:
|
|
||||||
logger.warn("Attempting to create existing corp model with id %s" % corp_id)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_corporation_info(corp_id, corp_member_count, alliance, is_blue):
|
def update_alliance_obj(alliance, is_blue=None):
|
||||||
logger.debug("Updating corp model with id %s" % corp_id)
|
model = EveAllianceInfo.objects.get(alliance_id=alliance.id)
|
||||||
if EveManager.check_if_corporation_exists_by_id(corp_id):
|
model.executor_corp_id = alliance.executor_corp_id
|
||||||
corp_info = EveCorporationInfo.objects.get(corporation_id=corp_id)
|
model.is_blue = model.is_blue if is_blue == None else is_blue
|
||||||
corp_info.member_count = corp_member_count
|
model.save()
|
||||||
corp_info.alliance = alliance
|
|
||||||
corp_info.is_blue = is_blue
|
@staticmethod
|
||||||
corp_info.save()
|
def populate_alliance(id):
|
||||||
logger.debug("Updated corp model %s" % corp_info)
|
alliance_model = EveAllianceInfo.objects.get(alliance_id=id)
|
||||||
else:
|
alliance = adapter.get_alliance(id)
|
||||||
logger.warn("Attempting to update non-existant corp model with id %s" % corp_id)
|
for corp_id in alliance.corp_ids:
|
||||||
|
if not EveCorporationInfo.objects.filter(corporation_id=corp_id).exists():
|
||||||
|
EveManager.create_corporation(corp_id, is_blue=alliance_model.is_blue)
|
||||||
|
EveCorporationInfo.objects.filter(corporation_id__in=alliance.corp_ids).update(alliance=alliance_model)
|
||||||
|
EveCorporationInfo.objects.filter(alliance=alliance_model).exclude(corporation_id__in=alliance.corp_ids).update(alliance=None)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_corporation(id, is_blue=False):
|
||||||
|
return EveManager.create_corporation_obj(adapter.get_corp(id), is_blue=is_blue)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_corporation_obj(corp, is_blue=False):
|
||||||
|
try:
|
||||||
|
alliance = EveAllianceInfo.objects.get(alliance_id=corp.alliance_id)
|
||||||
|
except EveAllianceInfo.DoesNotExist:
|
||||||
|
alliance = None
|
||||||
|
EveCorporationInfo.objects.create(
|
||||||
|
corporation_id = corp.id,
|
||||||
|
corporation_name = corp.name,
|
||||||
|
corporation_ticker = corp.ticker,
|
||||||
|
member_count = corp.members,
|
||||||
|
alliance = alliance,
|
||||||
|
is_blue = is_blue,
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_corporation(id, is_blue=None):
|
||||||
|
return EveManager.update_corporation_obj(adapter.get_corp(id), is_blue=is_blue)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_corporation_obj(corp, is_blue=None):
|
||||||
|
model = EveCorporationInfo.objects.get(corporation_id=corp.id)
|
||||||
|
model.member_count = corp.members
|
||||||
|
try:
|
||||||
|
model.alliance = EveAllianceInfo.objects.get(alliance_id=corp.alliance_id)
|
||||||
|
except EveAllianceInfo.DoesNotExist:
|
||||||
|
model.alliance = None
|
||||||
|
model.is_blue = model.is_blue if is_blue == None else is_blue
|
||||||
|
model.save()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_characters_from_api(api):
|
||||||
|
char_result = EveApiManager.get_characters_from_api(api.api_id, api.api_key).result
|
||||||
|
provider = EveXmlProvider(adapter=adapter)
|
||||||
|
return [provider._build_character(result) for id, result in char_result.items()]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_api_key_pairs(user):
|
def get_api_key_pairs(user):
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.1 on 2016-12-16 23:22
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('eveonline', '0004_eveapikeypair_sso_verified'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='eveallianceinfo',
|
||||||
|
name='member_count',
|
||||||
|
),
|
||||||
|
]
|
@ -38,7 +38,6 @@ class EveAllianceInfo(models.Model):
|
|||||||
alliance_ticker = models.CharField(max_length=254)
|
alliance_ticker = models.CharField(max_length=254)
|
||||||
executor_corp_id = models.CharField(max_length=254)
|
executor_corp_id = models.CharField(max_length=254)
|
||||||
is_blue = models.BooleanField(default=False)
|
is_blue = models.BooleanField(default=False)
|
||||||
member_count = models.IntegerField()
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.alliance_name
|
return self.alliance_name
|
||||||
|
279
eveonline/providers.py
Normal file
279
eveonline/providers.py
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
from django.utils.encoding import python_2_unicode_compatible
|
||||||
|
from esi.clients import esi_client_factory
|
||||||
|
from django.conf import settings
|
||||||
|
from bravado.exception import HTTPNotFound, HTTPUnprocessableEntity
|
||||||
|
import evelink
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class ObjectNotFound(Exception):
|
||||||
|
def __init__(self, id, type):
|
||||||
|
self.id = id
|
||||||
|
self.type = type
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s with ID %s not found.' % (self.type, self.id)
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class Entity(object):
|
||||||
|
def __init__(self, id, name):
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<{} ({}): {}>".format(self.__class__.__name__, self.id, self.name)
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return bool(self.id)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.id == other.id
|
||||||
|
|
||||||
|
|
||||||
|
class Corporation(Entity):
|
||||||
|
def __init__(self, provider, id, name, ticker, ceo_id, members, alliance_id):
|
||||||
|
super(Corporation, self).__init__(id, name)
|
||||||
|
self.provider = provider
|
||||||
|
self.ticker = ticker
|
||||||
|
self.ceo_id = ceo_id
|
||||||
|
self.members = members
|
||||||
|
self.alliance_id = alliance_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alliance(self):
|
||||||
|
if self.alliance_id:
|
||||||
|
return self.provider.get_alliance(self.alliance_id)
|
||||||
|
return Entity(None, None)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ceo(self):
|
||||||
|
return self.provider.get_character(self.ceo_id)
|
||||||
|
|
||||||
|
|
||||||
|
class Alliance(Entity):
|
||||||
|
def __init__(self, provider, id, name, ticker, corp_ids, executor_corp_id):
|
||||||
|
super(Alliance, self).__init__(id, name)
|
||||||
|
self.provider = provider
|
||||||
|
self.ticker = ticker
|
||||||
|
self.corp_ids = corp_ids
|
||||||
|
self.executor_corp_id = executor_corp_id
|
||||||
|
|
||||||
|
def corp(self, id):
|
||||||
|
assert id in self.corp_ids
|
||||||
|
return self.provider.get_corp(id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def corps(self):
|
||||||
|
return sorted([self.corp(id) for id in self.corp_ids], key=lambda x: x.name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def executor_corp(self):
|
||||||
|
return self.provider.get_corp(self.executor_corp_id)
|
||||||
|
|
||||||
|
|
||||||
|
class Character(Entity):
|
||||||
|
def __init__(self, provider, id, name, corp_id, alliance_id):
|
||||||
|
super(Character, self).__init__(id, name)
|
||||||
|
self.provider = provider
|
||||||
|
self.corp_id = corp_id
|
||||||
|
self.alliance_id = alliance_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def corp(self):
|
||||||
|
return self.provider.get_corp(self.corp_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alliance(self):
|
||||||
|
if self.alliance_id:
|
||||||
|
return self.provider.get_alliance(self.alliance_id)
|
||||||
|
return Entity(None, None)
|
||||||
|
|
||||||
|
|
||||||
|
class EveProvider:
|
||||||
|
def get_alliance(self, alliance_id):
|
||||||
|
"""
|
||||||
|
:return: an Alliance object for the given ID
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_corp(self, corp_id):
|
||||||
|
"""
|
||||||
|
:return: a Corporation object for the given ID
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_character(self, corp_id):
|
||||||
|
"""
|
||||||
|
:return: a Character object for the given ID
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class EveSwaggerProvider(EveProvider):
|
||||||
|
def __init__(self, token=None, adapter=None):
|
||||||
|
self.client = esi_client_factory(token=token)
|
||||||
|
self.adapter = adapter or self
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'esi'
|
||||||
|
|
||||||
|
def get_alliance(self, id):
|
||||||
|
try:
|
||||||
|
data = self.client.Alliance.get_alliances_alliance_id(alliance_id=id).result()
|
||||||
|
corps = self.client.Alliance.get_alliances_alliance_id_corporations(alliance_id=id).result()
|
||||||
|
model = Alliance(
|
||||||
|
self.adapter,
|
||||||
|
id,
|
||||||
|
data['alliance_name'],
|
||||||
|
data['ticker'],
|
||||||
|
corps,
|
||||||
|
data['executor_corp'],
|
||||||
|
)
|
||||||
|
return model
|
||||||
|
except HTTPNotFound:
|
||||||
|
raise ObjectNotFound(id, 'alliance')
|
||||||
|
|
||||||
|
def get_corp(self, id):
|
||||||
|
try:
|
||||||
|
data = self.client.Corporation.get_corporations_corporation_id(corporation_id=id).result()
|
||||||
|
model = Corporation(
|
||||||
|
self.adapter,
|
||||||
|
id,
|
||||||
|
data['corporation_name'],
|
||||||
|
data['ticker'],
|
||||||
|
data['ceo_id'],
|
||||||
|
data['member_count'],
|
||||||
|
data['alliance_id'] if 'alliance_id' in data else None,
|
||||||
|
)
|
||||||
|
return model
|
||||||
|
except HTTPNotFound:
|
||||||
|
raise ObjectNotFound(id, 'corporation')
|
||||||
|
|
||||||
|
def get_character(self, id):
|
||||||
|
try:
|
||||||
|
data = self.client.Character.get_characters_character_id(character_id=id).result()
|
||||||
|
alliance_id = self.adapter.get_corp(data['corporation_id']).alliance_id
|
||||||
|
model = Character(
|
||||||
|
self.adapter,
|
||||||
|
id,
|
||||||
|
data['name'],
|
||||||
|
data['corporation_id'],
|
||||||
|
alliance_id,
|
||||||
|
)
|
||||||
|
return model
|
||||||
|
except (HTTPNotFound, HTTPUnprocessableEntity):
|
||||||
|
raise ObjectNotFound(id, 'character')
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
|
class EveXmlProvider(EveProvider):
|
||||||
|
def __init__(self, api_key=None, adapter=None):
|
||||||
|
"""
|
||||||
|
:param api_key: eveonline.EveApiKeyPair
|
||||||
|
"""
|
||||||
|
self.api = evelink.api.API(api_key=(api_key.api_id, api_key.api_key)) if api_key else evelink.api.API()
|
||||||
|
self.adapter = adapter or self
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'xml'
|
||||||
|
|
||||||
|
def get_alliance(self, id):
|
||||||
|
api = evelink.eve.EVE(api=self.api)
|
||||||
|
alliances = api.alliances().result
|
||||||
|
try:
|
||||||
|
results = alliances[int(id)]
|
||||||
|
except KeyError:
|
||||||
|
raise ObjectNotFound(id, 'alliance')
|
||||||
|
model = Alliance(
|
||||||
|
self.adapter,
|
||||||
|
id,
|
||||||
|
results['name'],
|
||||||
|
results['ticker'],
|
||||||
|
results['member_corps'],
|
||||||
|
results['executor_id'],
|
||||||
|
)
|
||||||
|
return model
|
||||||
|
|
||||||
|
def get_corp(self, id):
|
||||||
|
api = evelink.corp.Corp(api=self.api)
|
||||||
|
try:
|
||||||
|
corpinfo = api.corporation_sheet(corp_id=int(id)).result
|
||||||
|
except evelink.api.APIError as e:
|
||||||
|
if int(e.code) == 523:
|
||||||
|
raise ObjectNotFound(id, 'corporation')
|
||||||
|
raise e
|
||||||
|
model = Corporation(
|
||||||
|
self.adapter,
|
||||||
|
id,
|
||||||
|
corpinfo['name'],
|
||||||
|
corpinfo['ceo']['id'],
|
||||||
|
corpinfo['members']['current'],
|
||||||
|
corpinfo['ticker'],
|
||||||
|
corpinfo['alliance']['id'] if corpinfo['alliance'] else None,
|
||||||
|
)
|
||||||
|
return model
|
||||||
|
|
||||||
|
def _build_character(self, result):
|
||||||
|
return Character(
|
||||||
|
self.adapter,
|
||||||
|
result['id'],
|
||||||
|
result['name'],
|
||||||
|
result['corp']['id'],
|
||||||
|
result['alliance']['id'],
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_character(self, id):
|
||||||
|
api = evelink.eve.EVE(api=self.api)
|
||||||
|
try:
|
||||||
|
charinfo = api.character_info_from_id(id).result
|
||||||
|
except evelink.api.APIError as e:
|
||||||
|
if int(e.code) == 105:
|
||||||
|
raise ObjectNotFound(id, 'character')
|
||||||
|
raise e
|
||||||
|
return self._build_character(charinfo)
|
||||||
|
|
||||||
|
|
||||||
|
class EveAdapter(EveProvider):
|
||||||
|
"""
|
||||||
|
Redirects queries to appropriate data source.
|
||||||
|
"""
|
||||||
|
def __init__(self, char_provider, corp_provider, alliance_provider):
|
||||||
|
self.char_provider = char_provider
|
||||||
|
self.corp_provider = corp_provider
|
||||||
|
self.alliance_provider = alliance_provider
|
||||||
|
self.char_provider.adapter = self
|
||||||
|
self.corp_provider.adapter = self
|
||||||
|
self.alliance_provider.adapter = self
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<{} (char:{}, corp:{}, alliance:{})>".format(self.__class__.__name__, str(self.char_provider), str(self.corp_provider), str(self.alliance_provider))
|
||||||
|
|
||||||
|
def get_character(self, id):
|
||||||
|
return self.char_provider.get_character(id)
|
||||||
|
|
||||||
|
def get_corp(self, id):
|
||||||
|
return self.corp_provider.get_corp(id)
|
||||||
|
|
||||||
|
def get_alliance(self, id):
|
||||||
|
return self.alliance_provider.get_alliance(id)
|
||||||
|
|
||||||
|
|
||||||
|
def eve_adapter_factory(character_source=settings.EVEONLINE_CHARACTER_PROVIDER, corp_source=settings.EVEONLINE_CORP_PROVIDER, alliance_source=settings.EVEONLINE_ALLIANCE_PROVIDER, api_key=None, token=None):
|
||||||
|
sources = [character_source, corp_source, alliance_source]
|
||||||
|
providers = []
|
||||||
|
|
||||||
|
xml = EveXmlProvider(api_key=api_key)
|
||||||
|
esi = EveSwaggerProvider(token=token)
|
||||||
|
|
||||||
|
for source in sources:
|
||||||
|
if source == 'xml':
|
||||||
|
providers.append(xml)
|
||||||
|
elif source == 'esi':
|
||||||
|
providers.append(esi)
|
||||||
|
else:
|
||||||
|
raise ValueError('Unrecognized data source "%s"' % source)
|
||||||
|
return EveAdapter(providers[0], providers[1], providers[2])
|
@ -12,6 +12,7 @@ from services.managers.eve_api_manager import EveApiManager
|
|||||||
from eveonline.models import EveCharacter
|
from eveonline.models import EveCharacter
|
||||||
from eveonline.models import EveCorporationInfo
|
from eveonline.models import EveCorporationInfo
|
||||||
from eveonline.models import EveAllianceInfo
|
from eveonline.models import EveAllianceInfo
|
||||||
|
from eveonline.providers import eve_adapter_factory
|
||||||
from authentication.tasks import set_state
|
from authentication.tasks import set_state
|
||||||
import logging
|
import logging
|
||||||
import evelink
|
import evelink
|
||||||
@ -26,21 +27,16 @@ def refresh_api(api):
|
|||||||
try:
|
try:
|
||||||
EveApiManager.validate_api(api.api_id, api.api_key, api.user)
|
EveApiManager.validate_api(api.api_id, api.api_key, api.user)
|
||||||
# Update characters
|
# Update characters
|
||||||
characters = EveApiManager.get_characters_from_api(api.api_id, api.api_key)
|
characters = EveManager.get_characters_from_api(api)
|
||||||
EveManager.update_characters_from_list(characters)
|
for c in characters:
|
||||||
new_character = False
|
try:
|
||||||
for char in characters.result:
|
EveManager.update_character_obj(c)
|
||||||
# Ensure we have a model for all characters on key
|
except EveCharacter.DoesNotExist:
|
||||||
if not EveManager.check_if_character_exist(characters.result[char]['name']):
|
logger.debug("API key %s has a new character on the account: %s" % (api.api_id, c))
|
||||||
logger.debug(
|
EveManager.create_character_obj(c, api.user, api.api_id)
|
||||||
"API key %s has a new character on the account: %s" % (api.api_id, characters.result[char]['name']))
|
|
||||||
new_character = True
|
|
||||||
if new_character:
|
|
||||||
logger.debug("Creating new character %s from api key %s" % (characters.result[char]['name'], api.api_id))
|
|
||||||
EveManager.create_characters_from_list(characters, api.user, api.api_id)
|
|
||||||
current_chars = EveCharacter.objects.filter(api_id=api.api_id)
|
current_chars = EveCharacter.objects.filter(api_id=api.api_id)
|
||||||
for c in current_chars:
|
for c in current_chars:
|
||||||
if not int(c.character_id) in characters.result:
|
if not int(c.character_id) in [c.id for c in characters]:
|
||||||
logger.info("Character %s no longer found on API ID %s" % (c, api.api_id))
|
logger.info("Character %s no longer found on API ID %s" % (c, api.api_id))
|
||||||
c.delete()
|
c.delete()
|
||||||
except evelink.api.APIError as e:
|
except evelink.api.APIError as e:
|
||||||
@ -105,65 +101,14 @@ def run_api_refresh():
|
|||||||
refresh_user_apis.delay(u)
|
refresh_user_apis.delay(u)
|
||||||
|
|
||||||
|
|
||||||
def populate_alliance(id, blue=False):
|
@task
|
||||||
logger.debug("Populating alliance model with id %s blue %s" % (id, blue))
|
def update_corp(id):
|
||||||
alliance_info = EveApiManager.get_alliance_information(id)
|
EveManager.update_corporation(id)
|
||||||
|
|
||||||
if not alliance_info:
|
|
||||||
raise ValueError("Supplied alliance id %s is invalid" % id)
|
|
||||||
|
|
||||||
if not EveAllianceInfo.objects.filter(alliance_id=id).exists():
|
|
||||||
EveManager.create_alliance_info(alliance_info['id'], alliance_info['name'], alliance_info['ticker'],
|
|
||||||
alliance_info['executor_id'], alliance_info['member_count'], blue)
|
|
||||||
alliance = EveAllianceInfo.objects.get(alliance_id=id)
|
|
||||||
for member_corp in alliance_info['member_corps']:
|
|
||||||
if EveCorporationInfo.objects.filter(corporation_id=member_corp).exists():
|
|
||||||
corp = EveCorporationInfo.objects.get(corporation_id=member_corp)
|
|
||||||
if corp.alliance != alliance:
|
|
||||||
corp.alliance = alliance
|
|
||||||
corp.save()
|
|
||||||
else:
|
|
||||||
logger.info("Creating new alliance member corp id %s" % member_corp)
|
|
||||||
corpinfo = EveApiManager.get_corporation_information(member_corp)
|
|
||||||
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
|
|
||||||
corpinfo['members']['current'], blue, alliance)
|
|
||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
def update_alliance(id):
|
def update_alliance(id):
|
||||||
alliance = EveAllianceInfo.objects.get(alliance_id=id)
|
EveManager.update_alliance(id)
|
||||||
corps = EveCorporationInfo.objects.filter(alliance=alliance)
|
EveManager.populate_alliance(id)
|
||||||
logger.debug("Updating alliance %s with %s member corps" % (alliance, len(corps)))
|
|
||||||
allianceinfo = EveApiManager.get_alliance_information(alliance.alliance_id)
|
|
||||||
if allianceinfo:
|
|
||||||
EveManager.update_alliance_info(allianceinfo['id'], allianceinfo['executor_id'],
|
|
||||||
allianceinfo['member_count'], alliance.is_blue)
|
|
||||||
for corp in corps:
|
|
||||||
if corp.corporation_id in allianceinfo['member_corps'] is False:
|
|
||||||
logger.info("Corp %s no longer in alliance %s" % (corp, alliance))
|
|
||||||
corp.alliance = None
|
|
||||||
corp.save()
|
|
||||||
populate_alliance(alliance.alliance_id, blue=alliance.is_blue)
|
|
||||||
elif EveApiManager.check_if_alliance_exists(alliance.alliance_id) is False:
|
|
||||||
logger.info("Alliance %s has closed. Deleting model" % alliance)
|
|
||||||
alliance.delete()
|
|
||||||
|
|
||||||
|
|
||||||
@task
|
|
||||||
def update_corp(id):
|
|
||||||
corp = EveCorporationInfo.objects.get(corporation_id=id)
|
|
||||||
logger.debug("Updating corp %s" % corp)
|
|
||||||
corpinfo = EveApiManager.get_corporation_information(corp.corporation_id)
|
|
||||||
if corpinfo:
|
|
||||||
alliance = None
|
|
||||||
if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists():
|
|
||||||
alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id'])
|
|
||||||
EveManager.update_corporation_info(corpinfo['id'], corpinfo['members']['current'], alliance, corp.is_blue)
|
|
||||||
elif EveApiManager.check_if_corp_exists(corp.corporation_id) is False:
|
|
||||||
logger.info("Corp %s has closed. Deleting model" % corp)
|
|
||||||
corp.delete()
|
|
||||||
|
|
||||||
# Run Every 2 hours
|
|
||||||
|
|
||||||
|
|
||||||
@periodic_task(run_every=crontab(minute=0, hour="*/2"))
|
@periodic_task(run_every=crontab(minute=0, hour="*/2"))
|
||||||
@ -172,71 +117,26 @@ def run_corp_update():
|
|||||||
logger.warn("Aborted updating corp and alliance models: API server unreachable")
|
logger.warn("Aborted updating corp and alliance models: API server unreachable")
|
||||||
return
|
return
|
||||||
standing_level = 'alliance'
|
standing_level = 'alliance'
|
||||||
try:
|
|
||||||
# get corp info for owning corp if required
|
|
||||||
ownercorpinfo = {}
|
|
||||||
if settings.IS_CORP:
|
|
||||||
standing_level = 'corp'
|
|
||||||
logger.debug("Getting information for owning corp with id %s" % settings.CORP_ID)
|
|
||||||
ownercorpinfo = EveApiManager.get_corporation_information(settings.CORP_ID)
|
|
||||||
if not ownercorpinfo:
|
|
||||||
logger.error("Failed to retrieve corp info for owning corp id %s - bad corp id?" % settings.CORP_ID)
|
|
||||||
return
|
|
||||||
|
|
||||||
# check if we need to update an alliance model
|
|
||||||
alliance_id = ''
|
|
||||||
if ownercorpinfo and ownercorpinfo['alliance']['id']:
|
|
||||||
alliance_id = ownercorpinfo['alliance']['id']
|
|
||||||
elif settings.IS_CORP is False:
|
|
||||||
alliance_id = settings.ALLIANCE_ID
|
alliance_id = settings.ALLIANCE_ID
|
||||||
|
|
||||||
|
# get corp info for owning corp if required
|
||||||
|
if settings.IS_CORP:
|
||||||
|
standing_level = 'corp'
|
||||||
|
if EveCorporationInfo.objects.filter(corporation_id=settings.CORP_ID).exists():
|
||||||
|
update_corp(settings.CORP_ID)
|
||||||
|
else:
|
||||||
|
EveManager.create_corporation(settings.CORP_ID)
|
||||||
|
|
||||||
|
alliance_id = eve_adapter_factory().get_corp(settings.CORP_ID).alliance_id
|
||||||
|
|
||||||
# get and create alliance info for owning alliance if required
|
# get and create alliance info for owning alliance if required
|
||||||
alliance = None
|
|
||||||
if alliance_id:
|
if alliance_id:
|
||||||
logger.debug("Getting information for owning alliance with id %s" % alliance_id)
|
if EveAllianceInfo.objects.filter(alliance_id=alliance_id).exists():
|
||||||
ownerallianceinfo = EveApiManager.get_alliance_information(alliance_id)
|
|
||||||
if not ownerallianceinfo:
|
|
||||||
logger.error("Failed to retrieve corp info for owning alliance id %s - bad alliance id?" % alliance_id)
|
|
||||||
return
|
|
||||||
if EveAllianceInfo.objects.filter(alliance_id=ownerallianceinfo['id']).exists():
|
|
||||||
logger.debug("Updating existing owner alliance model with id %s" % alliance_id)
|
logger.debug("Updating existing owner alliance model with id %s" % alliance_id)
|
||||||
EveManager.update_alliance_info(ownerallianceinfo['id'], ownerallianceinfo['executor_id'],
|
update_alliance(alliance_id)
|
||||||
ownerallianceinfo['member_count'], False)
|
|
||||||
else:
|
else:
|
||||||
populate_alliance(alliance_id)
|
EveManager.create_alliance(id)
|
||||||
alliance = EveAllianceInfo.objects.get(alliance_id=alliance_id)
|
EveManager.populate_alliance(id)
|
||||||
|
|
||||||
# create corp info for owning corp if required
|
|
||||||
if ownercorpinfo:
|
|
||||||
if EveCorporationInfo.objects.filter(corporation_id=ownercorpinfo['id']).exists():
|
|
||||||
logger.debug("Updating existing owner corp model with id %s" % ownercorpinfo['id'])
|
|
||||||
EveManager.update_corporation_info(ownercorpinfo['id'], ownercorpinfo['members']['current'], alliance,
|
|
||||||
False)
|
|
||||||
else:
|
|
||||||
logger.info("Creating model for owning corp with id %s" % ownercorpinfo['id'])
|
|
||||||
EveManager.create_corporation_info(ownercorpinfo['id'], ownercorpinfo['name'], ownercorpinfo['ticker'],
|
|
||||||
ownercorpinfo['members']['current'], False, alliance)
|
|
||||||
|
|
||||||
# validate and create corp models for member corps of owning alliance
|
|
||||||
if alliance:
|
|
||||||
current_corps = EveCorporationInfo.objects.filter(alliance=alliance)
|
|
||||||
for corp in current_corps:
|
|
||||||
if corp.corporation_id in ownerallianceinfo['member_corps'] is False:
|
|
||||||
logger.info("Corp %s is no longer in owning alliance %s - updating model." % (corp, alliance))
|
|
||||||
corp.alliance = None
|
|
||||||
corp.save()
|
|
||||||
for member_corp in ownerallianceinfo['member_corps']:
|
|
||||||
if EveCorporationInfo.objects.filter(corporation_id=member_corp).exists():
|
|
||||||
corp = EveCorporationInfo.objects.get(corporation_id=member_corp)
|
|
||||||
if corp.alliance == alliance is not True:
|
|
||||||
logger.info("Associating corp %s with owning alliance %s" % (corp, alliance))
|
|
||||||
corp.alliance = alliance
|
|
||||||
corp.save()
|
|
||||||
else:
|
|
||||||
corpinfo = EveApiManager.get_corporation_information(member_corp)
|
|
||||||
logger.info("Creating model for owning alliance member corp with id %s" % corpinfo['id'])
|
|
||||||
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
|
|
||||||
corpinfo['members']['current'], False, alliance)
|
|
||||||
|
|
||||||
# update existing corp models
|
# update existing corp models
|
||||||
for corp in EveCorporationInfo.objects.all():
|
for corp in EveCorporationInfo.objects.all():
|
||||||
@ -246,6 +146,7 @@ def run_corp_update():
|
|||||||
for alliance in EveAllianceInfo.objects.all():
|
for alliance in EveAllianceInfo.objects.all():
|
||||||
update_alliance.delay(alliance.alliance_id)
|
update_alliance.delay(alliance.alliance_id)
|
||||||
|
|
||||||
|
try:
|
||||||
# create standings
|
# create standings
|
||||||
standings = EveApiManager.get_corp_standings()
|
standings = EveApiManager.get_corp_standings()
|
||||||
if standings:
|
if standings:
|
||||||
@ -262,7 +163,7 @@ def run_corp_update():
|
|||||||
alliance.is_blue = True
|
alliance.is_blue = True
|
||||||
alliance.save()
|
alliance.save()
|
||||||
else:
|
else:
|
||||||
populate_alliance(standing, blue=True)
|
EveManager.create_alliance(standing, blue=True)
|
||||||
elif EveApiManager.check_if_id_is_corp(standing):
|
elif EveApiManager.check_if_id_is_corp(standing):
|
||||||
logger.debug("Standing %s is a corp" % standing)
|
logger.debug("Standing %s is a corp" % standing)
|
||||||
if EveCorporationInfo.objects.filter(corporation_id=standing).exists():
|
if EveCorporationInfo.objects.filter(corporation_id=standing).exists():
|
||||||
@ -273,13 +174,7 @@ def run_corp_update():
|
|||||||
corp.save()
|
corp.save()
|
||||||
else:
|
else:
|
||||||
logger.info("Creating model for blue corp with id %s" % standing)
|
logger.info("Creating model for blue corp with id %s" % standing)
|
||||||
corpinfo = EveApiManager.get_corporation_information(standing)
|
EveManager.create_corporation(standing, blue=True)
|
||||||
corp_alliance = None
|
|
||||||
if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists():
|
|
||||||
logger.debug("New corp model for standing %s has existing alliance model" % standing)
|
|
||||||
corp_alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id'])
|
|
||||||
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
|
|
||||||
corpinfo['members']['current'], True, corp_alliance)
|
|
||||||
|
|
||||||
# update alliance standings
|
# update alliance standings
|
||||||
for alliance in EveAllianceInfo.objects.filter(is_blue=True):
|
for alliance in EveAllianceInfo.objects.filter(is_blue=True):
|
||||||
@ -310,6 +205,8 @@ def run_corp_update():
|
|||||||
logger.info("Corp %s is no longer blue" % corp)
|
logger.info("Corp %s is no longer blue" % corp)
|
||||||
corp.is_blue = False
|
corp.is_blue = False
|
||||||
corp.save()
|
corp.save()
|
||||||
|
except evelink.api.APIError as e:
|
||||||
|
logger.error("Model update failed with error code %s" % e.code)
|
||||||
|
|
||||||
# delete unnecessary alliance models
|
# delete unnecessary alliance models
|
||||||
for alliance in EveAllianceInfo.objects.filter(is_blue=False):
|
for alliance in EveAllianceInfo.objects.filter(is_blue=False):
|
||||||
@ -348,5 +245,3 @@ def run_corp_update():
|
|||||||
corp.delete()
|
corp.delete()
|
||||||
else:
|
else:
|
||||||
logger.debug("Corp %s is owning corp" % corp)
|
logger.debug("Corp %s is owning corp" % corp)
|
||||||
except evelink.api.APIError as e:
|
|
||||||
logger.error("Model update failed with error code %s" % e.code)
|
|
||||||
|
@ -12,7 +12,7 @@ from authentication.models import AuthServicesInfo
|
|||||||
from authentication.tasks import set_state
|
from authentication.tasks import set_state
|
||||||
from eveonline.tasks import refresh_api
|
from eveonline.tasks import refresh_api
|
||||||
|
|
||||||
from eve_sso.decorators import token_required
|
from esi.decorators import token_required
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -46,9 +46,8 @@ def add_api_key(request):
|
|||||||
api_key.save()
|
api_key.save()
|
||||||
owner = request.user
|
owner = request.user
|
||||||
# Grab characters associated with the key pair
|
# Grab characters associated with the key pair
|
||||||
characters = EveApiManager.get_characters_from_api(form.cleaned_data['api_id'],
|
characters = EveManager.get_characters_from_api(api_key)
|
||||||
form.cleaned_data['api_key'])
|
[EveManager.create_character_obj(c, owner, api_key.api_id) for c in characters if not EveCharacter.objects.filter(character_id=c.id).exists()]
|
||||||
EveManager.create_characters_from_list(characters, owner, form.cleaned_data['api_id'])
|
|
||||||
logger.info("Successfully processed api add form for user %s" % request.user)
|
logger.info("Successfully processed api add form for user %s" % request.user)
|
||||||
if not settings.API_SSO_VALIDATION:
|
if not settings.API_SSO_VALIDATION:
|
||||||
messages.success(request, 'Added API key %s to your account.' % form.cleaned_data['api_id'])
|
messages.success(request, 'Added API key %s to your account.' % form.cleaned_data['api_id'])
|
||||||
@ -70,7 +69,7 @@ def add_api_key(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@token_required(new=True)
|
@token_required(new=True)
|
||||||
def api_sso_validate(request, tokens, api_id):
|
def api_sso_validate(request, token, api_id):
|
||||||
logger.debug('api_sso_validate called by user %s for api %s' % (request.user, api_id))
|
logger.debug('api_sso_validate called by user %s for api %s' % (request.user, api_id))
|
||||||
api = get_object_or_404(EveApiKeyPair, api_id=api_id)
|
api = get_object_or_404(EveApiKeyPair, api_id=api_id)
|
||||||
if api.user and api.user != request.user:
|
if api.user and api.user != request.user:
|
||||||
@ -81,7 +80,6 @@ def api_sso_validate(request, tokens, api_id):
|
|||||||
logger.debug('API %s has already been verified.' % api_id)
|
logger.debug('API %s has already been verified.' % api_id)
|
||||||
messages.info(request, 'API %s has already been verified' % api_id)
|
messages.info(request, 'API %s has already been verified' % api_id)
|
||||||
return redirect('auth_dashboard')
|
return redirect('auth_dashboard')
|
||||||
token = tokens[0]
|
|
||||||
logger.debug('API %s has not been verified. Checking if token for %s matches.' % (api_id, token.character_name))
|
logger.debug('API %s has not been verified. Checking if token for %s matches.' % (api_id, token.character_name))
|
||||||
characters = EveApiManager.get_characters_from_api(api.api_id, api.api_key).result
|
characters = EveApiManager.get_characters_from_api(api.api_id, api.api_key).result
|
||||||
if token.character_id in characters:
|
if token.character_id in characters:
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
{% extends 'public/base.html' %}
|
||||||
|
{% block title %}Fleet Participation{% endblock %}
|
||||||
|
{% block page_title %}Fleet Participation{% endblock %}
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<h1 class="page-header text-center">Character not found!</h1>
|
||||||
|
<div class="col-lg-12 container" id="example">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<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">
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-10 col-sm-2">
|
||||||
|
<div class="alert alert-danger" role="alert">Character not registered!</div>
|
||||||
|
This character is not part of any registered API-key. You must go to <a href=" {% url 'auth_api_key_management' %}">API key management</a> and add an API with the character on before being able to click fleet attendance links.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,63 @@
|
|||||||
|
{% extends "public/base.html" %}
|
||||||
|
{% load bootstrap %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap_pagination %}
|
||||||
|
{% block title %}Alliance Auth{% endblock %}
|
||||||
|
{% block page_title %}{% trans "Fatlink view" %}{% endblock page_title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<h1 class="page-header text-center">{% blocktrans %}Edit fatlink "{{ fatlink }}"{% endblocktrans %}
|
||||||
|
<div class="text-right">
|
||||||
|
<form>
|
||||||
|
<button type="submit" onclick="return confirm('Are you sure?')" class="btn btn-danger" name="deletefat" value="True">
|
||||||
|
{% trans "Delete fat" %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</h1>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">{% trans "Registered characters" %}</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="text-center">
|
||||||
|
{% bootstrap_paginate registered_fats range=10 %}
|
||||||
|
</div>
|
||||||
|
<table class="table table-responsive table-hover">
|
||||||
|
<tr>
|
||||||
|
<th class="text-center">{% trans "User" %}</th>
|
||||||
|
<th class="text-center">{% trans "Character" %}</th>
|
||||||
|
<th class="text-center">{% trans "System" %}</th>
|
||||||
|
<th class="text-center">{% trans "Ship" %}</th>
|
||||||
|
<th class="text-center">{% trans "Eve Time" %}</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
{% for fat in registered_fats %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-center">{{ fat.user }}</td>
|
||||||
|
<td class="text-center">{{ fat.character.character_name }}</td>
|
||||||
|
{% if fat.station != "No Station" %}
|
||||||
|
<td class="text-center">Docked in {{ fat.system }}</td>
|
||||||
|
{% else %}
|
||||||
|
<td class="text-center">{{ fat.system }}</td>
|
||||||
|
{% endif %}
|
||||||
|
<td class="text-center">{{ fat.shiptype }}</td>
|
||||||
|
<td class="text-center">{{ fat.fatlink.fatdatetime }}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<form>
|
||||||
|
<button type="submit" class="btn btn-warning" name="removechar" value="{{ fat.character.character_id }}">
|
||||||
|
<span class="glyphicon glyphicon-remove"></span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/static/js/dateformat.js"></script>
|
||||||
|
|
||||||
|
{% endblock content %}
|
@ -6,16 +6,17 @@ from django.contrib.auth.decorators import login_required
|
|||||||
from django.contrib.auth.decorators import permission_required
|
from django.contrib.auth.decorators import permission_required
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||||
from eveonline.models import EveCharacter
|
from eveonline.models import EveCharacter
|
||||||
from eveonline.models import EveCorporationInfo
|
from eveonline.models import EveCorporationInfo
|
||||||
from eveonline.managers import EveManager
|
from eveonline.managers import EveManager
|
||||||
from fleetactivitytracking.forms import FatlinkForm
|
from fleetactivitytracking.forms import FatlinkForm
|
||||||
from fleetactivitytracking.models import Fatlink, Fat
|
from fleetactivitytracking.models import Fatlink, Fat
|
||||||
|
|
||||||
from slugify import slugify
|
from esi.decorators import token_required
|
||||||
|
|
||||||
from collections import OrderedDict
|
from slugify import slugify
|
||||||
|
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
@ -25,15 +26,27 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
FATS_PER_PAGE = int(getattr(settings, 'FATS_PER_PAGE', 20))
|
||||||
|
|
||||||
|
def get_page(model_list, page_num):
|
||||||
|
p = Paginator(model_list, FATS_PER_PAGE)
|
||||||
|
try:
|
||||||
|
fats = p.page(page_num)
|
||||||
|
except PageNotAnInteger:
|
||||||
|
fatss = p.page(1)
|
||||||
|
except EmptyPage:
|
||||||
|
fatss = p.page(p.num_pages)
|
||||||
|
return fats
|
||||||
|
|
||||||
|
|
||||||
class CorpStat(object):
|
class CorpStat(object):
|
||||||
def __init__(self, corp_id, corp=None, blue=False):
|
def __init__(self, corp_id, start_of_month, start_of_next_month, corp=None):
|
||||||
if corp:
|
if corp:
|
||||||
self.corp = corp
|
self.corp = corp
|
||||||
else:
|
else:
|
||||||
self.corp = EveCorporationInfo.objects.get(corporation_id=corp_id)
|
self.corp = EveCorporationInfo.objects.get(corporation_id=corp_id)
|
||||||
self.n_fats = 0
|
self.n_fats = Fat.objects.filter(character__corporation_id=self.corp.corporation_id).filter(fatlink__fatdatetime__gte=start_of_month).filter(fatlink__fatdatetime__lte=start_of_next_month).count()
|
||||||
self.blue = blue
|
self.blue = self.corp.is_blue
|
||||||
|
|
||||||
def avg_fat(self):
|
def avg_fat(self):
|
||||||
return "%.2f" % (float(self.n_fats) / float(self.corp.member_count))
|
return "%.2f" % (float(self.n_fats) / float(self.corp.member_count))
|
||||||
@ -69,7 +82,7 @@ def fatlink_view(request):
|
|||||||
else:
|
else:
|
||||||
context = {'user': user, 'fats': latest_fats}
|
context = {'user': user, 'fats': latest_fats}
|
||||||
|
|
||||||
return render(request, 'registered/fatlinkview.html', context=context)
|
return render(request, 'fleetactivitytracking/fatlinkview.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@ -81,37 +94,38 @@ def fatlink_statistics_view(request, year=datetime.date.today().year, month=date
|
|||||||
start_of_next_month = first_day_of_next_month(year, month)
|
start_of_next_month = first_day_of_next_month(year, month)
|
||||||
start_of_previous_month = first_day_of_previous_month(year, month)
|
start_of_previous_month = first_day_of_previous_month(year, month)
|
||||||
|
|
||||||
fatStats = OrderedDict()
|
fat_stats = {}
|
||||||
|
|
||||||
|
|
||||||
|
# get FAT stats for member corps
|
||||||
if settings.IS_CORP:
|
if settings.IS_CORP:
|
||||||
fatStats[settings.CORP_NAME] = CorpStat(settings.CORP_ID)
|
fat_stats[settings.CORP_ID] = CorpStat(settings.CORP_ID, start_of_month, start_of_next_month)
|
||||||
else:
|
else:
|
||||||
alliance_corps = EveCorporationInfo.objects.filter(alliance__alliance_id=settings.ALLIANCE_ID)
|
alliance_corps = EveCorporationInfo.objects.filter(alliance__alliance_id=settings.ALLIANCE_ID)
|
||||||
for corp in alliance_corps:
|
for corp in alliance_corps:
|
||||||
fatStats[corp.corporation_name] = CorpStat(corp.corporation_id, corp=corp)
|
fat_stats[corp.corporation_id] = CorpStat(corp.corporation_id, start_of_month, start_of_next_month)
|
||||||
|
|
||||||
fatlinks_in_span = Fatlink.objects.filter(fatdatetime__gte=start_of_month).filter(
|
# get FAT stats for corps not in alliance
|
||||||
fatdatetime__lt=start_of_next_month)
|
fats_in_span = Fat.objects.filter(fatlink__fatdatetime__gte=start_of_month).filter(
|
||||||
|
fatlink__fatdatetime__lt=start_of_next_month).exclude(character__corporation_id__in=fat_stats)
|
||||||
|
|
||||||
for fatlink in fatlinks_in_span:
|
for fat in fats_in_span:
|
||||||
fats_in_fatlink = Fat.objects.filter(fatlink=fatlink)
|
if not fat.character.corporation_id in fat_stats:
|
||||||
for fat in fats_in_fatlink:
|
fat_stats[fat.character.corporation_id] = CorpStat(fat.character.corporation_id, start_of_month, start_of_next_month)
|
||||||
fatStats.setdefault(fat.character.corporation_name,
|
|
||||||
CorpStat(fat.character.corporation_id, blue=True)
|
|
||||||
).n_fats += 1
|
|
||||||
|
|
||||||
fatStatsList = [fatStat for corp_name, fatStat in fatStats.items()]
|
# collect and sort stats
|
||||||
fatStatsList.sort(key=lambda stat: stat.corp.corporation_name)
|
stat_list = [fat_stats[x] for x in fat_stats]
|
||||||
fatStatsList.sort(key=lambda stat: (stat.n_fats, stat.n_fats / stat.corp.member_count), reverse=True)
|
stat_list.sort(key=lambda stat: stat.corp.corporation_name)
|
||||||
|
stat_list.sort(key=lambda stat: (stat.n_fats, stat.n_fats / stat.corp.member_count), reverse=True)
|
||||||
|
|
||||||
if datetime.datetime.now() > start_of_next_month:
|
if datetime.datetime.now() > start_of_next_month:
|
||||||
context = {'fatStats': fatStatsList, 'month': start_of_month.strftime("%B"), 'year': year,
|
context = {'fatStats': stat_list, 'month': start_of_month.strftime("%B"), 'year': year,
|
||||||
'previous_month': start_of_previous_month, 'next_month': start_of_next_month}
|
'previous_month': start_of_previous_month, 'next_month': start_of_next_month}
|
||||||
else:
|
else:
|
||||||
context = {'fatStats': fatStatsList, 'month': start_of_month.strftime("%B"), 'year': year,
|
context = {'fatStats': stat_list, 'month': start_of_month.strftime("%B"), 'year': year,
|
||||||
'previous_month': start_of_previous_month}
|
'previous_month': start_of_previous_month}
|
||||||
|
|
||||||
return render(request, 'registered/fatlinkstatisticsview.html', context=context)
|
return render(request, 'fleetactivitytracking/fatlinkstatisticsview.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@ -139,7 +153,7 @@ def fatlink_personal_statistics_view(request, year=datetime.date.today().year, m
|
|||||||
else:
|
else:
|
||||||
context = {'user': user, 'monthlystats': monthlystats, 'year': year, 'previous_year': year - 1}
|
context = {'user': user, 'monthlystats': monthlystats, 'year': year, 'previous_year': year - 1}
|
||||||
|
|
||||||
return render(request, 'registered/fatlinkpersonalstatisticsview.html', context=context)
|
return render(request, 'fleetactivitytracking/fatlinkpersonalstatisticsview.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@ -173,55 +187,58 @@ def fatlink_monthly_personal_statistics_view(request, year, month, char_id=None)
|
|||||||
context["created_fats"] = created_fats
|
context["created_fats"] = created_fats
|
||||||
context["n_created_fats"] = len(created_fats)
|
context["n_created_fats"] = len(created_fats)
|
||||||
|
|
||||||
return render(request, 'registered/fatlinkpersonalmonthlystatisticsview.html', context=context)
|
return render(request, 'fleetactivitytracking/fatlinkpersonalmonthlystatisticsview.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def click_fatlink_view(request, hash, fatname):
|
@token_required(scopes=['esi-location.read_location.v1', 'esi-location.read_ship_type.v1', 'esi-universe.read_structures.v1'])
|
||||||
# Take IG-header data and register the fatlink if not existing already.
|
def click_fatlink_view(request, token, hash, fatname):
|
||||||
# use obj, created = Fat.objects.get_or_create()
|
|
||||||
# onload="CCPEVE.requestTrust('http://www.mywebsite.com')"
|
|
||||||
|
|
||||||
if 'HTTP_EVE_TRUSTED' in request.META and request.META['HTTP_EVE_TRUSTED'] == "Yes":
|
|
||||||
# Retrieve the latest fatlink using the hash.
|
|
||||||
try:
|
try:
|
||||||
fatlink = Fatlink.objects.filter(hash=hash)[0]
|
fatlink = Fatlink.objects.filter(hash=hash)[0]
|
||||||
|
|
||||||
if (timezone.now() - fatlink.fatdatetime) < datetime.timedelta(seconds=(fatlink.duration * 60)):
|
if (timezone.now() - fatlink.fatdatetime) < datetime.timedelta(seconds=(fatlink.duration * 60)):
|
||||||
|
|
||||||
character = EveManager.get_character_by_id(request.META['HTTP_EVE_CHARID'])
|
character = EveManager.get_character_by_id(token.character_id)
|
||||||
|
|
||||||
if character:
|
if character:
|
||||||
fat = Fat()
|
# get data
|
||||||
fat.system = request.META['HTTP_EVE_SOLARSYSTEMNAME']
|
c = token.get_esi_client()
|
||||||
if 'HTTP_EVE_STATIONNAME' in request.META:
|
location = c.Location.get_characters_character_id_location(character_id=token.character_id).result()
|
||||||
fat.station = request.META['HTTP_EVE_STATIONNAME']
|
ship = c.Location.get_characters_character_id_ship(character_id=token.character_id).result()
|
||||||
|
location['solar_system_name'] = c.Universe.get_universe_systems_system_id(system_id=location['solar_system_id']).result()['solar_system_name']
|
||||||
|
if location['structure_id']:
|
||||||
|
location['station_name'] = c.Universe.get_universe_structures_structure_id(structure_id=location['structure_id']).result()['name']
|
||||||
|
elif location['station_id']:
|
||||||
|
location['station_name'] = c.Universe.get_universe_stations_station_id(station_id=location['station_id']).result()['station_name']
|
||||||
else:
|
else:
|
||||||
fat.station = "No Station"
|
location['station_name'] = "No Station"
|
||||||
fat.shiptype = request.META['HTTP_EVE_SHIPTYPENAME']
|
ship['ship_type_name'] = c.Universe.get_universe_types_type_id(type_id=ship['ship_type_id']).result()['type_name']
|
||||||
|
|
||||||
|
fat = Fat()
|
||||||
|
fat.system = location['solar_system_name']
|
||||||
|
fat.station = location['station_name']
|
||||||
|
fat.shiptype = ship['ship_type_name']
|
||||||
fat.fatlink = fatlink
|
fat.fatlink = fatlink
|
||||||
fat.character = character
|
fat.character = character
|
||||||
fat.user = character.user
|
fat.user = character.user
|
||||||
try:
|
try:
|
||||||
fat.full_clean()
|
fat.full_clean()
|
||||||
fat.save()
|
fat.save()
|
||||||
context = {'trusted': True, 'registered': True}
|
messages.success(request, 'Fleet participation registered.')
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
messages = []
|
err_messages = []
|
||||||
for errorname, message in e.message_dict.items():
|
for errorname, message in e.message_dict.items():
|
||||||
messages.append(message[0].decode())
|
err_messages.append(message[0].decode())
|
||||||
context = {'trusted': True, 'errormessages': messages}
|
messages.error(request, ' '.join(err_messages))
|
||||||
else:
|
else:
|
||||||
context = {'character_id': request.META['HTTP_EVE_CHARID'],
|
context = {'character_id': token.character_id,
|
||||||
'character_name': request.META['HTTP_EVE_CHARNAME']}
|
'character_name': token.character_name}
|
||||||
return render(request, 'public/characternotexisting.html', context=context)
|
return render(request, 'fleetactivitytracking/characternotexisting.html', context=context)
|
||||||
else:
|
else:
|
||||||
context = {'trusted': True, 'expired': True}
|
messages.error(request, 'FAT link has expired.')
|
||||||
except ObjectDoesNotExist:
|
except (ObjectDoesNotExist, KeyError):
|
||||||
context = {'trusted': True}
|
messages.error(request, 'Invalid FAT link.')
|
||||||
else:
|
return redirect('auth_fatlink_view')
|
||||||
context = {'trusted': False, 'fatname': fatname}
|
|
||||||
return render(request, 'public/clickfatlinkview.html', context=context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@ -250,7 +267,7 @@ def create_fatlink_view(request):
|
|||||||
for errorname, message in e.message_dict.items():
|
for errorname, message in e.message_dict.items():
|
||||||
messages.append(message[0].decode())
|
messages.append(message[0].decode())
|
||||||
context = {'form': form, 'errormessages': messages}
|
context = {'form': form, 'errormessages': messages}
|
||||||
return render(request, 'registered/fatlinkformatter.html', context=context)
|
return render(request, 'fleetactivitytracking/fatlinkformatter.html', context=context)
|
||||||
else:
|
else:
|
||||||
form = FatlinkForm()
|
form = FatlinkForm()
|
||||||
context = {'form': form, 'badrequest': True}
|
context = {'form': form, 'badrequest': True}
|
||||||
@ -263,7 +280,7 @@ def create_fatlink_view(request):
|
|||||||
|
|
||||||
context = {'form': form}
|
context = {'form': form}
|
||||||
|
|
||||||
return render(request, 'registered/fatlinkformatter.html', context=context)
|
return render(request, 'fleetactivitytracking/fatlinkformatter.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@ -271,24 +288,26 @@ def create_fatlink_view(request):
|
|||||||
def modify_fatlink_view(request, hash=""):
|
def modify_fatlink_view(request, hash=""):
|
||||||
logger.debug("modify_fatlink_view called by user %s" % request.user)
|
logger.debug("modify_fatlink_view called by user %s" % request.user)
|
||||||
if not hash:
|
if not hash:
|
||||||
return redirect('/fat/')
|
return redirect('auth_fatlink_view')
|
||||||
|
|
||||||
fatlink = Fatlink.objects.filter(hash=hash)[0]
|
fatlink = Fatlink.objects.filter(hash=hash)[0]
|
||||||
|
|
||||||
if request.GET.get('removechar'):
|
if request.GET.get('removechar', None):
|
||||||
character_id = request.GET.get('removechar')
|
character_id = request.GET.get('removechar')
|
||||||
character = EveCharacter.objects.get(character_id=character_id)
|
character = EveCharacter.objects.get(character_id=character_id)
|
||||||
logger.debug("Removing character %s from fleetactivitytracking %s" % (character.character_name, fatlink.name))
|
logger.debug("Removing character %s from fleetactivitytracking %s" % (character.character_name, fatlink.name))
|
||||||
|
|
||||||
Fat.objects.filter(fatlink=fatlink).filter(character=character).delete()
|
Fat.objects.filter(fatlink=fatlink).filter(character=character).delete()
|
||||||
|
|
||||||
if request.GET.get('deletefat'):
|
if request.GET.get('deletefat', None):
|
||||||
logger.debug("Removing fleetactivitytracking %s" % fatlink.name)
|
logger.debug("Removing fleetactivitytracking %s" % fatlink.name)
|
||||||
fatlink.delete()
|
fatlink.delete()
|
||||||
return redirect('/fat/')
|
return redirect('auth_fatlink_view')
|
||||||
|
|
||||||
registered_fats = Fat.objects.filter(fatlink=fatlink).order_by('character')
|
registered_fats = Fat.objects.filter(fatlink=fatlink).order_by('character__character_name')
|
||||||
|
|
||||||
context = {'fatlink': fatlink, 'registered_fats': registered_fats}
|
fat_page = get_page(registered_fats, request.GET.get('page', 1))
|
||||||
|
|
||||||
return render(request, 'registered/fatlinkmodify.html', context=context)
|
context = {'fatlink': fatlink, 'registered_fats': fat_page}
|
||||||
|
|
||||||
|
return render(request, 'fleetactivitytracking/fatlinkmodify.html', context=context)
|
||||||
|
@ -15,6 +15,7 @@ redis
|
|||||||
django>=1.10,<2.0
|
django>=1.10,<2.0
|
||||||
django-bootstrap-form
|
django-bootstrap-form
|
||||||
django-navhelper
|
django-navhelper
|
||||||
|
django-bootstrap-pagination
|
||||||
|
|
||||||
# awating release for fix to celery/django-celery#447
|
# awating release for fix to celery/django-celery#447
|
||||||
# django-celery
|
# django-celery
|
||||||
@ -23,4 +24,4 @@ git+https://github.com/celery/django-celery
|
|||||||
git+git://github.com/nikdoof/python-ts3.git
|
git+git://github.com/nikdoof/python-ts3.git
|
||||||
git+https://github.com/pyghassen/openfire-restapi
|
git+https://github.com/pyghassen/openfire-restapi
|
||||||
|
|
||||||
git+https://github.com/adarnof/adarnauth-eve-sso
|
git+https://github.com/adarnof/adarnauth-esi
|
||||||
|
@ -319,7 +319,6 @@ class EveApiManager:
|
|||||||
def validate_api(api_id, api_key, user):
|
def validate_api(api_id, api_key, user):
|
||||||
try:
|
try:
|
||||||
info = EveApiManager.get_api_info(api_id, api_key).result
|
info = EveApiManager.get_api_info(api_id, api_key).result
|
||||||
chars = EveApiManager.get_characters_from_api(api_id, api_key).result
|
|
||||||
except evelink.api.APIError as e:
|
except evelink.api.APIError as e:
|
||||||
if int(e.code) == 222:
|
if int(e.code) == 222:
|
||||||
raise EveApiManager.ApiInvalidError(api_id)
|
raise EveApiManager.ApiInvalidError(api_id)
|
||||||
@ -329,6 +328,7 @@ class EveApiManager:
|
|||||||
auth, c = AuthServicesInfo.objects.get_or_create(user=user)
|
auth, c = AuthServicesInfo.objects.get_or_create(user=user)
|
||||||
states = [auth.state]
|
states = [auth.state]
|
||||||
from authentication.tasks import determine_membership_by_character # circular import issue
|
from authentication.tasks import determine_membership_by_character # circular import issue
|
||||||
|
chars = info['characters']
|
||||||
for char in chars:
|
for char in chars:
|
||||||
evechar = EveCharacter()
|
evechar = EveCharacter()
|
||||||
evechar.character_name = chars[char]['name']
|
evechar.character_name = chars[char]['name']
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
import requests
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
class EveWhoManager:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_corporation_members(corpid):
|
|
||||||
url = "http://evewho.com/api.php?type=corplist&id=%s" % corpid
|
|
||||||
jsondata = requests.get(url).content
|
|
||||||
data = json.loads(jsondata.decode())
|
|
||||||
|
|
||||||
members = {}
|
|
||||||
page_count = 0
|
|
||||||
while len(data["characters"]):
|
|
||||||
for row in data["characters"]:
|
|
||||||
members[int(row["character_id"])] = {"name": row["name"], "id": int(row["character_id"])}
|
|
||||||
page_count += 1
|
|
||||||
jsondata = requests.get(url + "&page=%i" % page_count).content
|
|
||||||
data = json.loads(jsondata.decode())
|
|
||||||
|
|
||||||
return members
|
|
@ -12,7 +12,7 @@
|
|||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="author" content="">
|
<meta name="author" content="">
|
||||||
|
|
||||||
<title>{% block title %}Empty title{% endblock title %}</title>
|
<title>{% block title %}Alliance Auth{% endblock title %}</title>
|
||||||
|
|
||||||
<!-- Bootstrap Core CSS -->
|
<!-- Bootstrap Core CSS -->
|
||||||
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
|
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
|
||||||
@ -145,9 +145,9 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if perms.auth.corp_apis or perms.auth.alliance_apis %}
|
{% if perms.corputils.view_corp_corpstats or perms.corputils.view_alliance_corpstats or perms.corputils.view_blue_corpstats %}
|
||||||
<li>
|
<li>
|
||||||
<a class="{% navactive request 'auth_corputils auth_corputils_search auth_corputils_corp_view auth_corputils_month' %}" href="{% url 'auth_corputils' %}">
|
<a class="{% navactive request 'corputils:view corputils:search' %}" href="{% url 'corputils:view' %}">
|
||||||
<i class="fa fa-share-alt fa-fw grayiconecolor"></i>{% trans " Corporation Stats" %}
|
<i class="fa fa-share-alt fa-fw grayiconecolor"></i>{% trans " Corporation Stats" %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
{% load staticfiles %}
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>Fleet participation</title>
|
|
||||||
|
|
||||||
<!-- Bootstrap Core CSS -->
|
|
||||||
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
|
|
||||||
<!-- Custom Fonts -->
|
|
||||||
<link href="{% static 'css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
|
|
||||||
<link href="{% static 'css/sb-admin-2.css' %}" rel="stylesheet">
|
|
||||||
{% block extra_css %}{% endblock extra_css %}
|
|
||||||
<style>
|
|
||||||
.grayiconecolor {
|
|
||||||
color: #505050;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body onload=CCPEVE.requestTrust('{{ DOMAIN }}')>
|
|
||||||
<div id="wrapper">
|
|
||||||
<!-- Navigation -->
|
|
||||||
|
|
||||||
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
|
|
||||||
|
|
||||||
<div class="navbar-header ">
|
|
||||||
<a class="navbar-brand " href="/dashboard/">
|
|
||||||
<div class="fa fa-cog fa-spin"></div>
|
|
||||||
{% if IS_CORP %}
|
|
||||||
{{ CORP_NAME }}
|
|
||||||
{% else %}
|
|
||||||
{{ ALLIANCE_NAME }}
|
|
||||||
{% endif %}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- /.navbar-header -->
|
|
||||||
|
|
||||||
<ul class="nav navbar-top-links navbar-right">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<li><a href="{% url 'auth_logout_user' %}">Logout</a></li>
|
|
||||||
{% else %}
|
|
||||||
<li><a href="{% url 'auth_login_user' %}">Login</a></li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
<!-- /.navbar-static-side -->
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<h1 class="page-header text-center">Character not found!</h1>
|
|
||||||
<div class="col-lg-12 container" id="example">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<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">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-10 col-sm-2">
|
|
||||||
<div class="alert alert-danger" role="alert">Character not registered!</div>
|
|
||||||
This character is not part of any registered API-key. You must go to <a href=" {% url 'auth_dashboard' %}">API key management</a> and add an API with the character on before being able to click fleet attendance links.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="{% static 'js/jquery.min.js' %}"></script>
|
|
||||||
<script src="{% static 'js/jquery.datetimepicker.js' %}"></script>
|
|
||||||
<script src="{% static 'js/bootstrap.min.js' %}"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,96 +0,0 @@
|
|||||||
{% load staticfiles %}
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>Fleet participation</title>
|
|
||||||
|
|
||||||
<!-- Bootstrap Core CSS -->
|
|
||||||
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
|
|
||||||
<!-- Custom Fonts -->
|
|
||||||
<link href="{% static 'css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
|
|
||||||
<link href="{% static 'css/sb-admin-2.css' %}" rel="stylesheet">
|
|
||||||
{% block extra_css %}{% endblock extra_css %}
|
|
||||||
<style>
|
|
||||||
.grayiconecolor {
|
|
||||||
color: #505050;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body onload=CCPEVE.requestTrust('{{ DOMAIN }}')>
|
|
||||||
<div id="wrapper">
|
|
||||||
<!-- Navigation -->
|
|
||||||
|
|
||||||
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
|
|
||||||
|
|
||||||
<div class="navbar-header ">
|
|
||||||
<a class="navbar-brand " href="/dashboard/">
|
|
||||||
<div class="fa fa-cog fa-spin"></div>
|
|
||||||
{% if IS_CORP %}
|
|
||||||
{{ CORP_NAME }}
|
|
||||||
{% else %}
|
|
||||||
{{ ALLIANCE_NAME }}
|
|
||||||
{% endif %}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- /.navbar-header -->
|
|
||||||
|
|
||||||
<ul class="nav navbar-top-links navbar-right">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<li><a href="{% url 'auth_logout_user' %}">Logout</a></li>
|
|
||||||
{% else %}
|
|
||||||
<li><a href="{% url 'auth_login_user' %}">Login</a></li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
<!-- /.navbar-static-side -->
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="col-lg-12">
|
|
||||||
{% if registered %}<h1 class="page-header text-center">Fleet registered!</h1> {% elif expired%}<h1 class="page-header text-center">This link has expired.</h1> {% elif errormessages%}<h1 class="page-header text-center">Something horrible happened. Shoot your FC!</h1>{% else %}<h1 class="page-header text-center">Invalid link.</h1>{% endif %}
|
|
||||||
<div class="col-lg-12 container" id="example">
|
|
||||||
{% for message in errormessages %}
|
|
||||||
<div class="alert alert-danger" role="alert">{{ message }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% if trusted %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">Fleet stats</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="col-lg-2 col-sm-2">
|
|
||||||
<img class="ra-avatar img-responsive" src="https://image.eveonline.com/{% if IS_CORP %}Corporation/{{ CORPORATION_ID }}{% else %}Alliance/{{ ALLIANCE_ID }}{% endif %}_128.png">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-7 col-sm-2">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<div class="alert alert-danger" role="alert">This page requires trust to operate.</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="{% static 'js/jquery.min.js' %}"></script>
|
|
||||||
<script src="{% static 'js/jquery.datetimepicker.js' %}"></script>
|
|
||||||
<script src="{% static 'js/bootstrap.min.js' %}"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,229 +0,0 @@
|
|||||||
{% extends "public/base.html" %}
|
|
||||||
{% load bootstrap %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block title %}Alliance Auth{% endblock %}
|
|
||||||
{% block page_title %}{% trans "Corporation Member Tracking" %}{% endblock page_title %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<h1 class="page-header text-center">{% trans "Corporation Member Data" %}</h1>
|
|
||||||
<div class="col-lg-12 container" id="example">
|
|
||||||
{% if corp %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">{% trans "Corporation" %}</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="col-lg-5 col-sm-2">
|
|
||||||
<img class="ra-avatar img-responsive" src="https://image.eveonline.com/Corporation/{{ corp.corporation_id }}_128.png">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-7 col-sm-2">
|
|
||||||
<h4 class="">{{ corp.corporation_name }}</h4>
|
|
||||||
|
|
||||||
<p>{% trans "Ticker:" %} {{ corp.corporation_ticker }}</p>
|
|
||||||
|
|
||||||
<p>{% trans "Member count:" %} {{ corp.member_count }}</p>
|
|
||||||
|
|
||||||
<p>{% trans "Player count:" %} {{characters_with_api|length}}</p>
|
|
||||||
|
|
||||||
<p>{% trans "Unregistered characters:" %} {{characters_without_api|length|add:n_unacounted}}</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 col-sm-5">
|
|
||||||
<b>{% trans "API Index:" %}</b>
|
|
||||||
<div class="progress">
|
|
||||||
<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="{{ n_registered }}" aria-valuemin="0" aria-valuemax="{{ corp.member_count }}" style="width: {% widthratio characters_with_api|length corp.member_count 100 %}%;">
|
|
||||||
{{n_registered}}/{{ corp.member_count }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav class="navbar navbar-default">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<ul class="nav navbar-nav navbar-wide">
|
|
||||||
{% if membercorplist and perms.auth.alliance_apis %}
|
|
||||||
<li class="dropdown">
|
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{% trans "Alliance corporations" %} <span class="caret"></span></a>
|
|
||||||
<ul class="dropdown-menu scrollable">
|
|
||||||
{% for membercorpid, membercorpname in membercorplist %}
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'auth_corputils_corp_view' membercorpid %}">{{ membercorpname }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
<li style="float: right">
|
|
||||||
<p class="navbar-form">
|
|
||||||
Statistics for:
|
|
||||||
<a href="{% url 'auth_corputils_month' corp.corporation_id previous_month|date:"Y" previous_month|date:"m" %}">
|
|
||||||
<i class="fa fa-arrow-circle-left fa-fw grayiconecolor"></i>
|
|
||||||
</a>
|
|
||||||
{{ this_month|date:"M" }}, {{ this_month|date:"Y" }}
|
|
||||||
{% if next_month %}
|
|
||||||
<a href="{% url 'auth_corputils_month' corp.corporation_id next_month|date:"Y" next_month|date:"m" %}" >
|
|
||||||
<i class="fa fa-arrow-circle-right fa-fw grayiconecolor"></i>
|
|
||||||
</a>
|
|
||||||
<a href="{% url 'auth_corputils' %}" >
|
|
||||||
<i class="fa fa-angle-double-right fa-fw grayiconecolor"></i>
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li style="float: right">
|
|
||||||
<p class="navbar-btn">
|
|
||||||
<a href="https://zkillboard.com/corporation/{{ corp.corporation_id }}/" class="btn btn-default" target="_blank">{{ corp.corporation_name }} {% trans "Killboard" %}</a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li style="float: right">
|
|
||||||
<form class="navbar-form navbar-left" role="search" action={% url 'auth_corputils_search' %}{{ corp.corporation_id }}/ method="POST">
|
|
||||||
<div class="form-group">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ search_form.as_table }}
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-default" type="submit">{% trans "Search" %}</button>
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
<li class="active"><a data-toggle="tab" href="#gotapi">{% blocktrans %}Registered Main Characters{% endblocktrans %} <b>({{characters_with_api|length}})</b></a></li>
|
|
||||||
<li><a data-toggle="tab" href="#noapi">{% blocktrans %}Characters without API{% endblocktrans %} <b>({{characters_without_api|length|add:n_unacounted}})</b></a></li>
|
|
||||||
</ul>
|
|
||||||
<div class="tab-content">
|
|
||||||
<div id="gotapi" class="tab-pane fade in active">
|
|
||||||
{% if characters_with_api %}
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-condensed table-hover table-striped">
|
|
||||||
<tr>
|
|
||||||
<th class="col-md-1"></th>
|
|
||||||
<th class="col-md-2">{% trans "Main character" %}</th>
|
|
||||||
<th class="col-md-2">{% trans "Main corporation" %}</th>
|
|
||||||
<th class="col-md-2">{% trans "Character list" %}</th>
|
|
||||||
<th class="col-md-1">{% trans "Fats" %}</th>
|
|
||||||
{% if perms.auth.fleetactivitytracking_statistics %}
|
|
||||||
<th class="col-md-3">{% trans "Killboard" %}</th>
|
|
||||||
<th class="col-md-2">{% trans "Fleet statistics" %}</th>
|
|
||||||
{% else %}
|
|
||||||
<th class="col-md-3">{% trans "Killboard" %}</th>
|
|
||||||
{% endif %}
|
|
||||||
<th class="col-md-2">{% trans "API JackKnife" %}</th>
|
|
||||||
</tr>
|
|
||||||
{% for maincharname, player in characters_with_api %}
|
|
||||||
<tr >
|
|
||||||
<td>
|
|
||||||
<img src="http://image.eveonline.com/Character/{{ player.main.character_id }}_32.jpg" class="img-circle">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<p>{{ maincharname }}</p>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if not corp.corporation_name == player.maincorp%}
|
|
||||||
<span class="label label-danger">
|
|
||||||
{{ player.maincorp }}
|
|
||||||
</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="label label-success">
|
|
||||||
{{ player.maincorp }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% for char in player.altlist %}
|
|
||||||
<p>{{ char.character_name }}</p>
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ player.n_fats }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% for char in player.altlist %}
|
|
||||||
<p><a href="https://zkillboard.com/character/{{ char.character_id }}/" class="label label-danger" target="_blank">{% trans "Killboard" %}</a></p>
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
|
||||||
{% if perms.auth.fleetactivitytracking %}
|
|
||||||
<td>
|
|
||||||
<a href="{% url 'auth_fatlink_view_user_statistics_month' player.main.character_id this_month|date:"Y" this_month|date:"m" %}">
|
|
||||||
<button type="button" class="btn btn-primary">Statistics
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
<td>
|
|
||||||
{% for apiinfo in player.apilist %}
|
|
||||||
<p>
|
|
||||||
<a href="{{ JACK_KNIFE_URL }}?usid={{ apiinfo.api_id }}&apik={{ apiinfo.api_key }}" target="_blank" class="btn btn-primary">
|
|
||||||
{% trans "API JackKnife" %}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="alert alert-danger" role="alert">
|
|
||||||
<h3>{% blocktrans %}Seems there are no characters in {{ corp.corporation_name }} tied to a registered API!{% endblocktrans %}</h3>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div id="noapi" class="tab-pane fade">
|
|
||||||
{% if characters_without_api %}
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
{% if 0 < n_unacounted %}
|
|
||||||
<div class="alert alert-danger" role="alert">
|
|
||||||
<h3>{% blocktrans %}There are atleast {{ n_unacounted }} characters not accounted for in EveWho.{% endblocktrans %}</h3>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<table class="table table-condensed table-hover table-striped">
|
|
||||||
<tr>
|
|
||||||
<th class="col-md-1"></th>
|
|
||||||
<th class="col-md-2">{% trans "Character" %}</th>
|
|
||||||
<th class="col-md-5">{% trans "Killboard" %}</th>
|
|
||||||
</tr>
|
|
||||||
{% for character_name, character_id in characters_without_api %}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<img src="http://image.eveonline.com/Character/{{ character_id }}_32.jpg" class="img-circle">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<p>{{ character_name }}</p>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="https://zkillboard.com/character/{{ character_id }}/" class="label label-danger" target="_blank">{% trans "Killboard" %}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="alert alert-success" role="alert">
|
|
||||||
<h3>{% blocktrans %}Good job! Every character in {{ corp.corporation_name }} seem to be tied to an API!{% endblocktrans %}</h3>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="col-md-4 col-md-offset-4">
|
|
||||||
<div class="row">
|
|
||||||
<div class="alert alert-danger text-center" role="alert">{% trans "No corporation model found. Contact your admin." %}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock content %}
|
|
@ -1,93 +0,0 @@
|
|||||||
{% extends "public/base.html" %}
|
|
||||||
{% load bootstrap %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block title %}Alliance Auth{% endblock %}
|
|
||||||
|
|
||||||
{% block page_title %}{% trans "Corporation Member Tracking" %}{% endblock page_title %}
|
|
||||||
{% block extra_css %}{% endblock extra_css %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<h1 class="page-header text-center">{% trans "Member Search Results" %}</h1>
|
|
||||||
<h2 class="text-center"><a href="{% url 'auth_corputils_corp_view' corp.corporation_id %}">{{ corp.corporation_name }}</a></h2>
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<nav class="navbar navbar-default">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<ul class="nav navbar-nav navbar-wide">
|
|
||||||
<li style="float: right">
|
|
||||||
<form class="navbar-form navbar-right" role="search" action="{% url 'auth_corputils_search_corp' corp.corporation_id %}" method="POST">
|
|
||||||
<div class="form-group">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ search_form|bootstrap }}
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-default" type="submit">{% trans "Search" %}</button>
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<div class="panel-body">
|
|
||||||
<table class="table table-condensed table-hover table-striped">
|
|
||||||
<tr>
|
|
||||||
<th class="col-md-1"></th>
|
|
||||||
<th class="col-md-2">{% trans "Character" %}</th>
|
|
||||||
<th class="col-md-2">{% trans "Main character" %}</th>
|
|
||||||
{% if perms.auth.fleetactivitytracking%}
|
|
||||||
<th class="col-md-5">{% trans "Killboard" %}</th>
|
|
||||||
<th class="col-md-2">{% trans "Fleet statistics" %}</th>
|
|
||||||
{% else %}
|
|
||||||
<th class="col-md-5">{% trans "Killboard" %}</th>
|
|
||||||
{% endif %}
|
|
||||||
<th class="col-md-2">{% trans "API JackKnife" %}</th>
|
|
||||||
</tr>
|
|
||||||
{% for result in results %}
|
|
||||||
<tr >
|
|
||||||
<td>
|
|
||||||
<img src="http://image.eveonline.com/Character/{{ result.id }}_32.jpg" class="img-circle">
|
|
||||||
</td>
|
|
||||||
<td>{{ result.name }}</td>
|
|
||||||
<td>
|
|
||||||
{% if result.api_registered%}
|
|
||||||
{{ result.main.character_name }}
|
|
||||||
{% else %}
|
|
||||||
<span class="label label-danger">{% trans "No API registered!" %}</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<p><a href="https://zkillboard.com/character/{{ result.char.character_id }}/" class="label label-danger" target="_blank">{% trans "Killboard" %}</a></p>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{% if perms.auth.fleetactivitytracking %}
|
|
||||||
{% if result.main %}
|
|
||||||
<td>
|
|
||||||
<a href="{% url 'auth_fatlink_view_user_statistics_month' result.main.character_id year month%}">
|
|
||||||
<button type="button" class="btn btn-primary">Statistics
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
{% else %}
|
|
||||||
<td></td>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<td>
|
|
||||||
{% if result.api_registered %}
|
|
||||||
<a href="{{ JACK_KNIFE_URL }}?usid={{ result.apiinfo.api_id }}&apik={{ result.apiinfo.api_key }}"
|
|
||||||
target="_blank">
|
|
||||||
<button type="button" class="btn btn-primary">{% trans "API JackKnife" %}
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock content %}
|
|
@ -1,55 +0,0 @@
|
|||||||
{% extends "public/base.html" %}
|
|
||||||
{% load bootstrap %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block title %}Alliance Auth{% endblock %}
|
|
||||||
{% block page_title %}{% trans "Fatlink view" %}{% endblock page_title %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<h1 class="page-header text-center">{% blocktrans %}Edit fatlink "{{ fatlink.name }}"{% endblocktrans %}
|
|
||||||
<div class="text-right">
|
|
||||||
<form>
|
|
||||||
<button type="submit" onclick="return confirm('Are you sure?')" class="btn btn-danger" name="deletefat" value="True">
|
|
||||||
{% trans "Delete fat" %}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</h1>
|
|
||||||
<h4><b>{% trans "Registered characters" %}</b></h4>
|
|
||||||
<table class="table table-responsive table-bordered">
|
|
||||||
<tr>
|
|
||||||
<th class="text-center">{% trans "User" %}</th>
|
|
||||||
<th class="text-center">{% trans "Character" %}</th>
|
|
||||||
<th class="text-center">{% trans "System" %}</th>
|
|
||||||
<th class="text-center">{% trans "Ship" %}</th>
|
|
||||||
<th class="text-center">{% trans "Eve Time" %}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
{% for fat in registered_fats %}
|
|
||||||
<tr>
|
|
||||||
<td class="text-center">{{ fat.user }}</td>
|
|
||||||
<td class="text-center">{{ fat.character.character_name }}</td>
|
|
||||||
{% if fat.station != "No Station" %}
|
|
||||||
<td class="text-center">Docked in {{ fat.system }}</td>
|
|
||||||
{% else %}
|
|
||||||
<td class="text-center">{{ fat.system }}</td>
|
|
||||||
{% endif %}
|
|
||||||
<td class="text-center">{{ fat.shiptype }}</td>
|
|
||||||
<td class="text-center">{{ fat.fatlink.fatdatetime }}</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<form>
|
|
||||||
<button type="submit" class="btn btn-warning" name="removechar" value="{{ fat.character.character_id }}"><span
|
|
||||||
class="glyphicon glyphicon-remove"></span></button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script src="/static/js/dateformat.js"></script>
|
|
||||||
|
|
||||||
{% endblock content %}
|
|
Loading…
x
Reference in New Issue
Block a user