def _populate_characters(account, characters_node_children): """ Iterate through an account's character list and create/update the appropriate ApiPlayerCharacter objects. """ ApiPlayerCorporation = get_api_model_class("apiplayercorporation") ApiPlayerCharacter = get_api_model_class("apiplayercharacter") for node in characters_node_children: try: # Get this first, as it's safe. corporation_id = node.get('corporationID') corp, created = ApiPlayerCorporation.objects.get_or_create(id=corporation_id) # Do this last, since the things we retrieved above are used # on the ApiPlayerCharacter object's fields. character_id = node.get('characterID') pchar, created = ApiPlayerCharacter.objects.get_or_create(id=character_id) name = node.get('name') # Save these for last to keep the save count low. pchar.name = name pchar.corporation = corp # This also saves the model. pchar.set_api_last_updated() account.characters.add(pchar) except AttributeError: # This must be a Text node, ignore it. continue
def __transfer_divisions(tree, corp): """ Transfer corporate divisions and wallet divisions. """ ApiPlayerCorporationDivision = get_api_model_class("apiplayercorporationdivision") ApiPlayerCorporationWalletDivision = get_api_model_class("apiplayercorporationwalletdivision") rowsets = tree.findall('result/rowset') for rowset in rowsets: rowset_name = rowset.get('name') for row in rowset.getchildren(): account_key = row.get('accountKey') if rowset_name == 'divisions': division, created = ApiPlayerCorporationDivision.objects.get_or_create( account_key=account_key, corporation=corp) elif rowset_name =='walletDivisions': division, created = ApiPlayerCorporationWalletDivision.objects.get_or_create( account_key=account_key, corporation=corp) else: # This shouldn't happen unless CCP adds a new rowset type # and we don't support it yet. continue division.name = row.get('description') division.save()
def update_alliance_corporations(**kwargs): """ Imports all of the corps that are in all of the known alliances. WARNING: THIS WILL TAKE A _LONG_ TIME AND MUST BE RAN AFTER eve_db.api_puller.alliances.__start_full_import() OR YOU WON'T GET ALL OF THE CORPS (or any at all). """ ApiPlayerAlliance = get_api_model_class('ApiPlayerAlliance') ApiPlayerCorporation = get_api_model_class('ApiPlayerCorporation') alliances = ApiPlayerAlliance.objects.all() # These two variables are used to track progress. alliance_count = alliances.count() # Use this as a progress indicator. current_alliance_num = 1 for alliance in alliances: # Keep the user informed as to the progress. print "Alliance %d of %d..." % (current_alliance_num, alliance_count) # A list of the alliance's member corps. member_corps = alliance.apiplayercorporation_set.all() # We're getting the list of corps to update from alliance memberships. for corp in member_corps: print "Querying", corp.id corp = ApiPlayerCorporation.api.update_from_api(corp, **kwargs) print "DONE: %s" % corp # Increment progress counter. current_alliance_num += 1
def query_character_journal(character_or_id, account_key=1000, before_ref_id=None, **kwargs): """ This function queries a character's journal and creates/updates ApiJournalTransaction objects found therein. """ try: # If the user has provided an int, this will fail. id = character_or_id.id # User has provided a corp object, use that instead of looking one up. character = character_or_id except AttributeError: # User provided an int, no corp object provided. id = character_or_id character = None # This raises a ApiAccount.DoesNotExist if there is no match. account = character.get_account() # Assemble GET keys. query_params = {'userID': account.api_user_id, 'apiKey': account.api_key, 'characterID': character.id, 'accountKey': account_key} if before_ref_id: # This allows for walking journal transactions backwards. # http://wiki.eve-id.net/APIv2_Char_JournalEntries_XML query_params['beforeRefID'] = before_ref_id # Retrieve the XML for the query from the API or the cache. corp_doc = CachedDocument.objects.api_query('/char/WalletJournal.xml.aspx', params=query_params, **kwargs) # Parse the XML response. tree = ElementTree.fromstring(corp_doc.body) # List of <row> elements, each being a transaction. transactions = tree.find('result/rowset').getchildren() # The following calls get around circular imports. ApiJournalTransaction = get_api_model_class('ApiJournalTransaction') ApiJournalRefType = get_api_model_class('ApiJournalRefType') ApiPlayerCorporation = get_api_model_class('ApiPlayerCorporation') for transaction in transactions: # Hand off importing logic. __import_transaction(transaction, ApiJournalTransaction, ApiJournalRefType, ApiPlayerCorporation)
def __import_transaction(elem, ApiJournalTransaction, ApiJournalRefType, ApiPlayerCorporation): """ Given an ElementTree Element, parse it for Journal transaction data and import it to the DB. """ ref_id = elem.get('refID') ref_type_id = elem.get('refTypeID') transaction, created = ApiJournalTransaction.objects.get_or_create(id=ref_id) transaction.transaction_time = parse_api_datetime(elem.get('date')) ref_type, created = ApiJournalRefType.objects.get_or_create(id=ref_type_id) transaction.ref_type = ref_type transaction.owner_name1 = elem.get('ownerName1') transaction.owner_name2 = elem.get('ownerName2') transaction.arg_name = elem.get('argName1') transaction.arg_id = elem.get('argID1') transaction.amount = elem.get('amount') transaction.balance = elem.get('balance') transaction.reason = elem.get('reason') # For things like bounties, taxes get paid to the player's corp. tax_amount = elem.get('taxAmount') if tax_amount: transaction.tax_amount = tax_amount tax_receiver_id = elem.get('taxReceiverID') if tax_receiver_id: tax_receiver, created = ApiPlayerCorporation.objects.get_or_create(id=tax_receiver_id) transaction.tax_receiver = tax_receiver # Get around circular dependencies. ApiPlayerCharacter = get_api_model_class('ApiPlayerCharacter') ApiPlayerCorporation = get_api_model_class('ApiPlayerCorporation') # Resolve the generic relationships by the ownerID* values. transaction.owner1 = __resolve_generic_relation(elem.get('ownerID1'), transaction.owner_name1, ApiPlayerCharacter, ApiPlayerCorporation) transaction.owner2 = __resolve_generic_relation(elem.get('ownerID2'), transaction.owner_name2, ApiPlayerCharacter, ApiPlayerCorporation) # This also saves changes. transaction.set_api_last_updated()
def __transfer_ceo(tree, corp): """ Transfers the CEO data. """ ApiPlayerCharacter = get_api_model_class("apiplayercharacter") ceo_id = int(tree.find('result/ceoID').text) ceo, created = ApiPlayerCharacter.objects.get_or_create(id=ceo_id) corp.ceo_character = ceo if not ceo.name: # Fill in the CEO's name if it's missing from their ApiPlayer object. ceo.name = ceo_id = tree.find('result/ceoName').text ceo.save()
def __transfer_alliance(tree, corp): """ Transfers alliance data (if applicable). """ alliance_id = int(tree.find('result/allianceID').text) if alliance_id != 0: ApiPlayerAlliance = get_api_model_class("apiplayeralliance") alliance, created = ApiPlayerAlliance.objects.get_or_create(id=alliance_id) corp.alliance = alliance if not alliance.name: # Alliance name is missing from the ApiPlayerAlliance object. # Set it and save it. alliance.name = ceo_id = tree.find('result/allianceName').text alliance.save()
def query_type_list(**kwargs): """ This function is called to update the reference type list objects. """ type_doc = CachedDocument.objects.api_query('/eve/RefTypes.xml.aspx ', **kwargs) tree = ElementTree.fromstring(type_doc.body) type_rowset = tree.find('result/rowset').getchildren() for type_node in type_rowset: type_id = int(type_node.get('refTypeID')) ApiJournalRefType = get_api_model_class('ApiJournalRefType') reftype, created = ApiJournalRefType.objects.get_or_create(id=type_id) reftype.name = type_node.get('refTypeName') reftype.save()
def __remove_invalid_corp_alliance_memberships(): """ Compares UPDATED_CORPS list to the full list of player corporations. If the corporation was not updated from being found in one of the alliance data sets, it has no alliance affiliation and needs to be set to no alliance if it is not already a None value. """ ApiPlayerCorporation = get_api_model_class('apiplayercorporation') all_corps = ApiPlayerCorporation.objects.all() # This is not terribly efficient, but it will do for a background process. for corp in all_corps: """ If the corp is not in the UPDATED_CORP list that was built from alliance memberCorporations rowsets, then it does not belong to an alliance and should be un-allianced if it currently is. """ if corp.id not in UPDATED_CORPS and corp.alliance != None: corp.alliance = None corp.save()
def query_server_status(**kwargs): """ Populates and returns an ApiServer object. """ server_doc = CachedDocument.objects.api_query('/server/ServerStatus.xml.aspx', **kwargs) tree = ElementTree.fromstring(server_doc.body) server_open = tree.find('result/serverOpen').text online_players = tree.find('result/onlinePlayers').text ApiServer = get_api_model_class('apiserver') server, created = ApiServer.objects.get_or_create(id=1) server.server_open = server_open == 'True' server.online_players = online_players server.save() return server
def query_character_list(api_key, user_id, account_obj=None, **kwargs): """ Imports an account from the API into the ApiAccount model. Optional kwargs account_obj: (ApiAccount) Update the following account object instead of querying for one. This is used to update ApiAccount objects in place. """ auth_params = {'userID': user_id, 'apiKey': api_key} account_doc = CachedDocument.objects.api_query('/account/Characters.xml.aspx', params=auth_params, **kwargs) tree = ElementTree.fromstring(account_doc.body) characters_node_children = tree.find('result/rowset').getchildren() if account_obj == None: # User did not specify an ApiAccount object to use. Query and get or # create one with a matching user_id. ApiAccount = get_api_model_class("apiaccount") # Create or retrieve the account last to make sure everything # before here is good to go. try: account = ApiAccount.objects.get(id=user_id) except ApiAccount.DoesNotExist: account = ApiAccount(id=user_id) else: # User specified an ApiAccount object to use. account = account_obj account.api_key = api_key account.api_user_id = user_id account.api_last_updated = datetime.now() account.api_status = API_STATUS_OK account.save() # Iterate through the characters on this account and create/update the # appropriate ApiPlayerCharacter models. _populate_characters(account, characters_node_children) # Finally, return the latest version of the ApiAccount. return account
def query_alliance_list(**kwargs): """ This method runs a full import of all known alliances. This may take a few minutes and should be ran regularly if you are maintaining a full corp list of all EVE corps as well. """ alliance_doc = CachedDocument.objects.api_query('/eve/AllianceList.xml.aspx', **kwargs) tree = ElementTree.fromstring(alliance_doc.body) alliance_rowset = tree.find('result/rowset').getchildren() # We now have a list of <row> tags representing each alliance. print "Updating alliance and member corporation data..." for alliance_node in alliance_rowset: try: # If this fails, this is a Text node and should be ignored. alliance_id = int(alliance_node.get('allianceID')) except AttributeError: # This is probably a Text node, ignore it. continue """ Search for an existing ApiPlayerAlliance object with the given alliance ID. Create one if it doesn't exist, retrieve the existing object if it's already there. """ ApiPlayerAlliance = get_api_model_class('apiplayeralliance') alliance, created = ApiPlayerAlliance.objects.get_or_create(id=alliance_id) alliance.id = alliance_id alliance.name = alliance_node.get('name') alliance.ticker = alliance_node.get('shortName') alliance.member_count = alliance_node.get('memberCount') alliance.date_founded = datetime.strptime(alliance_node.get('startDate'), '%Y-%m-%d %H:%M:%S') alliance.save() # Update member corp alliance attributes. __update_corp_from_alliance_node(alliance_node, alliance) # Alliances and member corps updated. # Removing corps alliance memberships that are no longer valid... __remove_invalid_corp_alliance_memberships()
def query_corporation_sheet(corp_or_id, query_character=None, **kwargs): """ Returns a corp's data sheet from the EVE API in the form of an ElementTree Element. corp_or_id: (ApiPlayerCorporation or int) A player corporation object to update, or an int matching a corporation's ID number. query_character: (ApiPlayerCharacter) To get detailed data about a corp, provide a character that is a member of said corp. """ try: # If the user has provided an int, this will fail. id = corp_or_id.id # User has provided a corp object, use that instead of looking one up. corp = corp_or_id except AttributeError: # User provided an int, no corp object provided. id = corp_or_id corp = None query_params = {} if query_character: # Character provided, provide their credentials. account = query_character.get_account() query_params['userID'] = account.api_user_id query_params['apiKey'] = account.api_key query_params['characterID'] = query_character.id else: # Outsider is looking for details on a corp. query_params['corporationID'] = id ApiPlayerCorporation = get_api_model_class("apiplayercorporation") try: corp_doc = CachedDocument.objects.api_query('/corp/CorporationSheet.xml.aspx', params=query_params, **kwargs) except APIQueryErrorException, exc: if exc.code == 523: # The specified corp doesn't exist. raise ApiPlayerCorporation.DoesNotExist('No such corporation with ID: %s' % id) # Was some other error, re-raise it. raise
def __update_corp_from_alliance_node(alliance_node, alliance): """ Updates a corp's alliance membership from an alliance <row> element. """ member_corp_nodelist = alliance_node.find('rowset').getchildren() for node in member_corp_nodelist: corp_row_node = None try: # If this fails, this is a Text node and should be ignored. corporation_id = int(node.get('corporationID')) except AttributeError: # This is probably a Text node, ignore it. continue ApiPlayerCorporation = get_api_model_class('apiplayercorporation') corp, created = ApiPlayerCorporation.objects.get_or_create(id=corporation_id) corp.id = corporation_id corp.alliance = alliance corp.alliance_join_date = datetime.strptime(alliance_node.get('startDate'), '%Y-%m-%d %H:%M:%S') corp.save() # Store the corp in the updated corps list for later checks. UPDATED_CORPS.append(corp.id)