import re
from html.parser import HTMLParser
import requests
OWNER_HREF = re.compile(r"/(?:corporation|alliance)/(\d+)/?")
class ZkillError(Exception):
"""
Marks a problem encountered when interfacing with Zkillboard's API.
"""
class RelatedParser(HTMLParser):
"""
Reads kill IDs and teams from Zkillboard's related kills page.
"""
def __init__(self):
super().__init__()
self._team = 0
self._kills = set()
self._current = None
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag == "table" and attrs.get("id", "").lower() == "killlist":
self._team += 1
if tag == "tr" and attrs.get("class", "").lower() == "killlistrow" and self._team > 0:
self._flush()
killid = attrs.get("killid", "")
self._current = (killid, self._team, None)
if tag == "a" and self._team > 0 and self._current:
match = OWNER_HREF.match(attrs.get("href", ""))
if match:
self._current = (*self._current[:2], match.group(1))
self._flush()
def _flush(self):
if self._current and all(self._current):
self._kills.add(self._current)
self._current = None
@property
def kills(self):
"""
Returns all kills found by the parser along with their team and the ID of the victim.
"""
self._flush()
return self._kills
def hash(kill_id):
"""
Looks up and returns the hash associated with *kill_id* using Zkillboard's API.
"""
response = requests.get("https://zkillboard.com/api/killID/{}/".format(kill_id))
response.raise_for_status()
data = response.json()
if len(data) == 0:
raise ZkillError("Could not find hash", kill_id)
if len(data) > 1:
raise ZkillError("Too many hashes found", kill_id)
return data[0]['zkb']['hash']
def parse_battle_report(url):
"""
Builds a basic snapshot containing all killmails from the battle report at *url*.
"""
response = requests.get(url)
response.raise_for_status()
page = response.text
related = RelatedParser()
related.feed(page)
killmails = []
teams = (set(), set())
for kill, team, victim in related.kills:
killmails.append({'killmail_id': int(kill)})
destination = teams[team - 1]
destination.add(int(victim))
return {'killmails': killmails, 'teams': list(map(list, teams))}