diff --git a/calefaction/eve/zkill.py b/calefaction/eve/zkill.py index d44c2e9..c9db858 100644 --- a/calefaction/eve/zkill.py +++ b/calefaction/eve/zkill.py @@ -2,6 +2,7 @@ import time +from flask import g import requests from ..exceptions import ZKillboardError @@ -20,6 +21,45 @@ class ZKillboard: self._base_url = "https://zkillboard.com/api" self._last_query = 0 + def _extend_killmail(self, kill): + """Extend a killmail object to match the old ZKill format. + + Requires ESI API calls to fill in entity names. If we can't do them, + we'll just set the names to be empty. + """ + esi = g.eve.esi() + victim = kill["victim"] + + if "character_id" in victim: + char_info = esi.v4.characters(victim["character_id"]).get() + victim["character_name"] = char_info["name"] + else: + victim["character_id"] = 0 + victim["character_name"] = "" + + if "corporation_id" in victim: + corp_info = esi.v3.corporations(victim["corporation_id"]).get() + victim["corporation_name"] = corp_info["corporation_name"] + else: + victim["corporation_id"] = 0 + victim["corporation_name"] = "" + + if "alliance_id" in victim: + alliance_info = esi.v2.alliances(victim["alliance_id"]).get() + victim["alliance_name"] = alliance_info["alliance_name"] + else: + victim["alliance_id"] = 0 + victim["alliance_name"] = "" + + if "faction_id" in victim: + factions = esi.v1.universe.factions.get() + matches = [fac["faction_name"] for fac in factions + if fac["faction_id"] == victim["faction_id"]] + victim["faction_name"] = matches[0] if matches else "" + else: + victim["faction_id"] = 0 + victim["faction_name"] = "" + def query(self, *args): """Make an API query using the given arguments.""" query = "/" + "".join(str(arg) + "/" for arg in args) @@ -47,10 +87,15 @@ class ZKillboard: self._last_query = time.time() return result - def iter_killmails(self, *args): + def iter_killmails(self, *args, extended=False): """Return an iterator over killmails using the given API arguments. Automagically follows pagination as far as possible. (Be careful.) + + If extended is True, we will provide extra information for each kill + (names of entities instead of just IDs), which requires ESI API calls. + This matches the original API format of ZKill before it was, er, + "simplified". """ page = 1 while True: @@ -60,7 +105,11 @@ class ZKillboard: result = self.query(*args) if result: - yield from result + if extended: + for kill in result: + yield self._extend_killmail(kill) + else: + yield from result page += 1 else: break diff --git a/calefaction/modules/campaigns/database.py b/calefaction/modules/campaigns/database.py index b17e974..9db9ae2 100644 --- a/calefaction/modules/campaigns/database.py +++ b/calefaction/modules/campaigns/database.py @@ -94,10 +94,10 @@ class CampaignDB: def add_kill(self, kill): """Insert a killmail into the database.""" try: - datetime.strptime(kill["killTime"], "%Y-%m-%d %H:%M:%S") + datetime.strptime(kill["killmail_time"], "%Y-%m-%d %H:%M:%S") except ValueError: raise RuntimeError("Invalid kill_date=%s for kill_id=%d" % ( - kill["killTime"], kill["killID"])) + kill["killmail_time"], kill["killmail_id"])) query = """INSERT OR REPLACE INTO kill ( kill_id, kill_date, kill_system, kill_victim_shipid, @@ -108,12 +108,13 @@ class CampaignDB: VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""" victim = kill["victim"] args = ( - int(kill["killID"]), kill["killTime"], int(kill["solarSystemID"]), - int(victim["shipTypeID"]), int(victim["characterID"]), - victim["characterName"], int(victim["corporationID"]), - victim["corporationName"], int(victim["allianceID"]), - victim["allianceName"], int(victim["factionID"]), - victim["factionName"], float(kill["zkb"]["totalValue"])) + int(kill["killmail_id"]), kill["killmail_time"], + int(kill["solar_system_id"]), int(victim["ship_type_id"]), + int(victim["character_id"]), victim["character_name"], + int(victim["corporation_id"]), victim["corporation_name"], + int(victim["alliance_id"]), victim["alliance_name"], + int(victim["faction_id"]), victim["faction_name"], + float(kill["zkb"]["totalValue"])) with self._conn as conn: conn.execute(query, args) diff --git a/calefaction/modules/campaigns/update.py b/calefaction/modules/campaigns/update.py index 66e9c73..c98a52a 100644 --- a/calefaction/modules/campaigns/update.py +++ b/calefaction/modules/campaigns/update.py @@ -33,7 +33,7 @@ def _build_filter(qualifiers, arg): def _store_kill(cname, opnames, kill): """Store the given kill and its associations into the database.""" - kid = kill["killID"] + kid = kill["killmail_id"] if g.campaign_db.has_kill(kid): current = g.campaign_db.get_kill_associations(cname, kid) opnames -= set(current) @@ -59,12 +59,16 @@ def _update_killboard_operations(cname, opnames, min_kill_id): "no-attackers", "orderDirection", "desc"] max_kill_id = min_kill_id - for kill in g.eve.zkill.iter_killmails(*args): - kid = kill["killID"] + for kill in g.eve.zkill.iter_killmails(*args, extended=True): + kid = kill["killmail_id"] if min_kill_id > 0 and kid == min_kill_id: + # TODO: This fails if ZKill receives kills out of order. + # Should look ahead for kills within, say, 12 hours of the + # min_kill_id, and extend code below to ignore kills aleady + # included instead of re-adding. break - ktime = kill["killTime"] + ktime = kill["killmail_time"] logger.debug("Evaluating kill date=%s id=%d for campaign=%s " "operations=%s", ktime, kid, cname, ",".join(opnames)) max_kill_id = max(max_kill_id, kid)