From 8a1210f23596306ceb032a25b53028e49e03f3ab Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Wed, 21 Apr 2010 13:31:22 +0100 Subject: [PATCH] Corporate Management stage 1 This changeset adds a couple of new features to the API, it pulls in all characters on a corp basis, if a director's API key is available, and updates last login/logoff date/times for each corp member. --- cronjobs.txt | 1 + eve_api/api_puller/corp_management.py | 73 +++++++++++++++++++++++++++ eve_api/cron.py | 28 +++++++++- eve_api/evolutions/__init__.py | 2 +- eve_api/evolutions/director-update.py | 7 +++ eve_api/evolutions/login-locations.py | 9 ++++ eve_api/models/api_player.py | 14 ++++- 7 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 eve_api/api_puller/corp_management.py create mode 100644 eve_api/evolutions/director-update.py create mode 100644 eve_api/evolutions/login-locations.py diff --git a/cronjobs.txt b/cronjobs.txt index 2ac7cbd..1b320e9 100644 --- a/cronjobs.txt +++ b/cronjobs.txt @@ -5,3 +5,4 @@ ROOT=/home/matalok/auth/auth */5 * * * * $ROOT/run-cron.py eve_api.cron UpdateAPIs > $ROOT/logs/eveapi-update.log 2>&1 @hourly $ROOT/run-cron.py sso.cron RemoveInvalidUsers > $ROOT/logs/auth-update.log 2>&1 @daily $ROOT/run-cron.py registration.cron RemoveExpiredProfiles > /dev/null 2>&1 +@daily $ROOT/run-cron.py eve_api.cron CorpManagementUpdate > $ROOT/logs/corpman-update.log 2>&1 diff --git a/eve_api/api_puller/corp_management.py b/eve_api/api_puller/corp_management.py new file mode 100644 index 0000000..3513788 --- /dev/null +++ b/eve_api/api_puller/corp_management.py @@ -0,0 +1,73 @@ +""" +This module abstracts the pulling of account data from the EVE API. +""" +from xml.dom import minidom +from datetime import datetime + +from datetime import datetime +from django.conf import settings +from eve_proxy.models import CachedDocument +from eve_api.app_defines import * +from eve_api.api_exceptions import APIAuthException, APINoUserIDException +from eve_api.models import EVEAccount, EVEPlayerCharacter, EVEPlayerCorporation + + +def pull_corp_members(api_key, user_id, character_id): + """ + This function pulls all corporation members from the EVE API using a director's + API key. It'll add as much information as it can about the character. + """ + + # grab and decode /corp/MemberTracking.xml.aspx + auth_params = {'userID': user_id, 'apiKey': api_key, 'characterID': character_id } + char_doc = CachedDocument.objects.api_query('/corp/MemberTracking.xml.aspx', + params=auth_params, + no_cache=False) + + dom = minidom.parseString(char_doc.body) + if dom.getElementsByTagName('error'): + return + nodes = dom.getElementsByTagName('result')[0].childNodes + + values = {} + for node in nodes: + if node.nodeType == 1: + node.normalize() + if len(node.childNodes) == 1: + values[node.tagName] = node.childNodes[0].nodeValue + else: + nv = {} + if node.tagName == "rowset": + rset = [] + for nd in node.childNodes: + if nd.nodeType == 1: + d = {} + for e in nd.attributes.keys(): + d[e] = nd.attributes[e].value + rset.append(d) + values[node.attributes['name'].value] = rset + else: + for nd in node.childNodes: + if nd.nodeType == 1: + nv[nd.tagName] = nd.childNodes[0].nodeValue + values[node.tagName] = nv + + + # corpID from director + corp = EVEPlayerCharacter.objects.get(id=character_id).corporation + set = values['members'] + + for character in set: + + pchar, created = EVEPlayerCharacter.objects.get_or_create(id=character['characterID']) + + if created: + pchar.name = character['name'] + pchar.corporation = corp + pchar.last_login = character['logonDateTime'] + pchar.last_logoff = character['logoffDateTime'] + pchar.current_location_id = int(character['locationID']) + + pchar.save() + + diff --git a/eve_api/cron.py b/eve_api/cron.py index 44e429d..b9738a6 100644 --- a/eve_api/cron.py +++ b/eve_api/cron.py @@ -1,8 +1,9 @@ import logging import datetime -from eve_api.models.api_player import EVEAccount, EVEPlayerCorporation +from eve_api.models.api_player import EVEAccount, EVEPlayerCorporation, EVEPlayerCharacter import eve_api.api_puller.accounts +from eve_api.api_puller.corp_management import pull_corp_members from eve_api.api_exceptions import APIAuthException, APINoUserIDException class UpdateAPIs(): @@ -43,3 +44,28 @@ class UpdateAPIs(): except: self._logger.error('Error updating %s' % corp) continue + +class CorpManagementUpdate(): + """ + Pulls character information from corp directors marked in the DB + """ + + settings = { 'update_corp': False } + + last_update_delay = 86400 + batches = 50 + + @property + def _logger(self): + if not hasattr(self, '__logger'): + self.__logger = logging.getLogger(__name__) + return self.__logger + + def job(self): + directors = EVEPlayerCharacter.objects.filter(director_update=True) + + for director in directors: + self._logger.info("Updating: %s / %s" % (director, director.corporation)) + #api = director.eveaccount + api = EVEAccount.objects.get(characters__in=[director]) + pull_corp_members(api.api_key, api.api_user_id, director.id) diff --git a/eve_api/evolutions/__init__.py b/eve_api/evolutions/__init__.py index 788a555..4b9c9d6 100644 --- a/eve_api/evolutions/__init__.py +++ b/eve_api/evolutions/__init__.py @@ -1 +1 @@ -SEQUENCE = ['applications-field', 'total-sp'] +SEQUENCE = ['applications-field', 'total-sp', 'login-locations', 'director-update'] diff --git a/eve_api/evolutions/director-update.py b/eve_api/evolutions/director-update.py new file mode 100644 index 0000000..3fd1e7f --- /dev/null +++ b/eve_api/evolutions/director-update.py @@ -0,0 +1,7 @@ +from django_evolution.mutations import * +from django.db import models + +MUTATIONS = [ + AddField('EVEPlayerCharacter', 'applications', models.BooleanField, initial=False) +] + diff --git a/eve_api/evolutions/login-locations.py b/eve_api/evolutions/login-locations.py new file mode 100644 index 0000000..5f1d4b7 --- /dev/null +++ b/eve_api/evolutions/login-locations.py @@ -0,0 +1,9 @@ +from django_evolution.mutations import * +from django.db import models + +MUTATIONS = [ + AddField('EVEPlayerCharacter', 'current_location_id', models.IntegerField, null=True), + AddField('EVEPlayerCharacter', 'last_login', models.DateTimeField, null=True), + AddField('EVEPlayerCharacter', 'last_logoff', models.DateTimeField, null=True) +] + diff --git a/eve_api/models/api_player.py b/eve_api/models/api_player.py index 3f62788..b97a098 100644 --- a/eve_api/models/api_player.py +++ b/eve_api/models/api_player.py @@ -67,14 +67,26 @@ class EVEPlayerCharacter(EVEAPIModel): race = models.IntegerField(blank=True, null=True, choices=API_RACES_CHOICES) gender = models.IntegerField(blank=True, null=True, choices=API_GENDER_CHOICES) balance = models.FloatField("Account Balance", blank=True, null=True) + attrib_intelligence = models.IntegerField("Intelligence", blank=True, null=True) attrib_memory = models.IntegerField("Memory", blank=True, null=True) attrib_charisma = models.IntegerField("Charisma", blank=True, null=True) attrib_perception = models.IntegerField("Perception", blank=True, null=True) attrib_willpower = models.IntegerField("Willpower", blank=True, null=True) - total_sp = models.IntegerField("Total SP", blank=True, null=True) + + current_location_id = models.IntegerField("Current Location ID", blank=True, null=True) + last_login = models.DateTimeField(blank=True, null=True, + verbose_name="Last Login Date/Time", + help_text="The last time this character logged into EVE") + last_logoff = models.DateTimeField(blank=True, null=True, + verbose_name="Last Logoff Date/Time", + help_text="The last time this character logged off EVE") + + director_update = models.BooleanField(blank=False, default=False, + verbose_name="Director Update", + help_text="This character is a Director of the associated corporation and should be used for updates") objects = EVEPlayerCharacterManager()