Beispiel #1
0
 def clear_character_cache(self, e):
     conn, cur = db.connect_persistent_db()
     query_statement = '''DELETE FROM characters'''
     cur.execute(query_statement)
     conn.commit()
     conn.close()
     statusmsg.push_status("Cleared character cache")
Beispiel #2
0
def get_affil_names(conn, cur):
    # use select distinct to get corp and alliance ids and reslove them
    alliance_ids = cur.execute('''SELECT DISTINCT alliance_id FROM characters
        WHERE alliance_id IS NOT 0''').fetchall()
    corp_ids = cur.execute(
        "SELECT DISTINCT corp_id FROM characters WHERE corp_id IS NOT 0"
    ).fetchall()

    ids = alliance_ids + corp_ids
    ids = json.dumps(tuple([r[0] for r in ids]))

    statusmsg.push_status(
        "Obtaining corporation and alliance names and zKillboard data...")
    try:
        names = apis.post_req_ccp("universe/names/", ids)
    except:
        Logger.info("Failed request corporation and alliance names.",
                    exc_info=True)
        raise Exception

    alliances, corporations = (), ()
    for r in names:
        if r["category"] == "alliance":
            alliances = alliances + ((r["id"], r["name"]), )
        elif r["category"] == "corporation":
            corporations = corporations + ((r["id"], r["name"]), )
    if alliances:
        query_string = ('''INSERT INTO alliances (id, name) VALUES (?, ?)''')
        db.write_many_to_db(conn, cur, query_string, alliances)
    if corporations:
        query_string = (
            '''INSERT INTO corporations (id, name) VALUES (?, ?)''')
        db.write_many_to_db(conn, cur, query_string, corporations)
Beispiel #3
0
def analyze_chars(char_names):
    start_time = time.time()
    wx.CallAfter(app.PySpy.list.DeleteAllItems)
    try:
        outlist = analyze.main(char_names)
        duration = round(time.time() - start_time, 1)
        reportstats.ReportStats(outlist, duration).start()
        if outlist is not None:
            wx.CallAfter(app.PySpy.updateList, outlist, duration)
        else:
            statusmsg.push_status(
                "No valid character names found. Please try again...")
    except Exception:
        Logger.error("Failed to collect character information. Clipboard "
                     "content was: " + str(char_names),
                     exc_info=True)
Beispiel #4
0
def watch_clpbd():
    valid = False
    recent_value = None
    while True:
        clipboard = pyperclip.paste()
        if clipboard != recent_value:
            char_names = clipboard.splitlines()
            for name in char_names:
                valid = check_name_validity(name)
                if valid is False:
                    break
            if valid:
                statusmsg.push_status("Clipboard change detected...")
                recent_value = clipboard
                analyze_chars(clipboard.splitlines())
        time.sleep(0.5)  # Short sleep between loops to reduce CPU load
Beispiel #5
0
def get_char_ids(conn, cur, char_names):
    char_names = json.dumps(
        char_names[0:config.MAX_NAMES])  # apis max char is 1000
    statusmsg.push_status("Resolving character names to IDs...")
    try:
        characters = apis.post_req_ccp("universe/ids/", char_names)
        characters = characters['characters']
    except:
        return 0
    records = ()
    for r in characters:
        records = records + ((r["id"], r["name"]), )
    query_string = (
        '''INSERT INTO characters (char_id, char_name) VALUES (?, ?)''')
    records_added = db.write_many_to_db(conn, cur, query_string, records)
    return records_added
Beispiel #6
0
    def updateList(self, outlist, duration=None):
        # If updateList() gets called before outlist has been provided, do nothing
        if outlist is None:
            return
        self.options.Set("outlist", outlist)
        hl_blops = self.options.Get("HlBlops", True)
        self.list.DeleteAllItems()
        for r in outlist:

            # Schema depending on output_list() in analyze.py
            id = r[0]
            faction_id = r[1]
            name = r[2]
            corp = r[3]
            alliance = str(r[4]) + " (" + str(
                r[6]) + ")" if r[4] is not None else "-"
            faction = r[5] if r[5] is not None else "-"
            week_kills = r[7]
            zkill = str(r[8]) + " - " + str(r[9]) + " - " + str(
                r[10]) if r[8] is not None else "n.a."
            out = [
                id, faction_id, name, corp, alliance, faction, week_kills,
                zkill
            ]

            # Check if character belongs to a faction that should be ignored
            if faction_id != 0:
                if config.IGNORED_FACTIONS == 2 and faction_id % 2 == 0:
                    continue
                if config.IGNORED_FACTIONS == 1 and faction_id % 2 != 0:
                    continue

            self.list.Append(out)

            if hl_blops and r[7] is not None and (
                    r[9] > 0
                    or r[10] > 0):  # Highlight BLOPS killer & HIC pilots.
                self.list.SetItemBackgroundColour(self.list.ItemCount - 1,
                                                  wx.Colour(255, 189, 90))
        if duration is not None:
            statusmsg.push_status(
                str(len(outlist)) + " characters analysed in " +
                str(duration) +
                " seconds. Double click character to go to zKillboard.")
Beispiel #7
0
def post_req_ccp(esi_path, json_data):
    url = "https://esi.evetech.net/latest/" + esi_path + \
        "?datasource=tranquility"
    try:
        r = requests.post(url, json_data)
    except requests.exceptions.ConnectionError:
        Logger.info("No network connection.", exc_info=True)
        statusmsg.push_status(
            "NETWORK ERROR: Check your internet connection and firewall settings."
        )
        time.sleep(5)
        return "network_error"
    if r.status_code != 200:
        server_msg = json.loads(r.text)["error"]
        Logger.info("CCP Servers at (" + esi_path + ") returned error code: " +
                    str(r.status_code) + ", saying: " + server_msg,
                    exc_info=True)
        statusmsg.push_status("CCP SERVER ERROR: " + str(r.status_code) +
                              " (" + server_msg + ")")
        return "server_error"
    return r.json()
Beispiel #8
0
    def run(self):
        url = "http://pyspy.pythonanywhere.com/add_record/"
        headers = {
            "Accept-Encoding":
            "gzip",
            "User-Agent":
            "PySpy, Author: White Russsian, https://github.com/WhiteRusssian/PySpy"
        }
        payload = {
            "uuid": self._uuid,
            "version": self._version,
            "platform": self._platform,
            "chars": self._chars,
            "duration": self._duration,
            "sh_faction": self._sh_faction,
            "hl_blops": self._hl_blops,
            "ig_factions": self._ig_factions,
            "gui_alpha": self._gui_alpha
        }

        try:
            r = requests.get(url, headers=headers, params=payload)
        except requests.exceptions.ConnectionError:
            Logger.info("No network connection.", exc_info=True)
            statusmsg.push_status(
                '''NETWORK ERROR: Check your internet connection
                and firewall settings.''')
            time.sleep(5)
            return

        if r.status_code != 200:
            status_code = r.status_code
            reason = r.reason
            Logger.info(
                "Could not upload usage statistics. Server message: '" +
                reason + "'. Code: " + str(status_code) + " [URL: " + r.url +
                "]",
                exc_info=True)
        return
Beispiel #9
0
def get_char_affiliations(conn, cur):
    char_ids = cur.execute("SELECT char_id FROM characters").fetchall()
    char_ids = json.dumps(tuple([r[0] for r in char_ids]))
    statusmsg.push_status("Retrieving character affiliation IDs...")
    try:
        affiliations = apis.post_req_ccp("characters/affiliation/", char_ids)
    except:
        Logger.info("Failed to obtain character affiliations.", exc_info=True)
        raise Exception

    records = ()
    for r in affiliations:
        corp_id = r["corporation_id"]
        alliance_id = r["alliance_id"] if "alliance_id" in r else 0
        faction_id = r["faction_id"] if "faction_id" in r else 0
        char_id = r["character_id"]
        records = records + ((corp_id, alliance_id, faction_id, char_id), )

    query_string = (
        '''UPDATE characters SET corp_id=?, alliance_id=?, faction_id=?
        WHERE char_id=?''')
    db.write_many_to_db(conn, cur, query_string, records)
Beispiel #10
0
def analyze_chars(char_names):
    conn_mem, cur_mem = db.connect_memory_db()
    conn_dsk, cur_dsk = db.connect_persistent_db()
    start_time = time.time()
    wx.CallAfter(app.PySpy.grid.ClearGrid)
    try:
        outlist = analyze.main(char_names, conn_mem, cur_mem, conn_dsk,
                               cur_dsk)
        duration = round(time.time() - start_time, 1)
        reportstats.ReportStats(outlist, duration).start()
        if outlist is not None:
            # Need to use keyword args as sortOutlist can also get called
            # by event handler which would pass event object as first argument.
            wx.CallAfter(app.PySpy.sortOutlist,
                         outlist=outlist,
                         duration=duration)
        else:
            statusmsg.push_status(
                "No valid character names found. Please try again...")
    except Exception:
        Logger.error("Failed to collect character information. Clipboard "
                     "content was: " + str(char_names),
                     exc_info=True)
Beispiel #11
0
def post_proprietary_db(character_ids):
    '''
    Query PySpy's proprietary kill database for the character ids
    provided as a list or tuple of integers. Returns a JSON containing
    one line per character id.

    :param `character_ids`: List or tuple of character ids as integers.
    :return: JSON dictionary containing certain statistics for each id.
    '''
    url = "http://pyspy.pythonanywhere.com" + "/character_intel/" + "v1/"
    headers = {
        "Accept-Encoding": "gzip",
        "User-Agent": "PySpy, Author: White Russsian, https://github.com/WhiteRusssian/PySpy"
        }
    # Character_ids is a list of tuples, which needs to be converted to dict
    # with list as value.
    character_ids = {"character_ids": character_ids}
    try:
        r = requests.post(url, headers=headers, json=character_ids)
    except requests.exceptions.ConnectionError:
        Logger.info("No network connection.", exc_info=True)
        statusmsg.push_status(
            "NETWORK ERROR: Check your internet connection and firewall settings."
            )
        time.sleep(5)
        return "network_error"
    if r.status_code != 200:
        server_msg = json.loads(r.text)["error"]
        Logger.info(
            "PySpy server returned error code: " +
            str(r.status_code) + ", saying: " + server_msg, exc_info=True
            )
        statusmsg.push_status(
            "PYSPY SERVER ERROR: " + str(r.status_code) + " (" + server_msg + ")"
            )
        return "server_error"
    return r.json()
Beispiel #12
0
    def run(self):
        url = ("https://zkillboard.com/api/stats/characterID/" +
               str(self._char_id) + "/")
        headers = {
            "Accept-Encoding":
            "gzip",
            "User-Agent":
            "PySpy, Author: White Russsian, https://github.com/WhiteRusssian/PySpy"
        }
        try:
            r = requests.get(url, headers=headers)
        except requests.exceptions.ConnectionError:
            Logger.info("No network connection.", exc_info=True)
            statusmsg.push_status(
                '''NETWORK ERROR: Check your internet connection
                and firewall settings.''')
            time.sleep(5)
            return "network error"
        if r.status_code != 200:
            server_msg = json.loads(r.text)["error"]
            Logger.info("zKillboard server returned error for character ID " +
                        str(self._char_id) + ". Error code: " +
                        str(r.status_code),
                        exc_info=True)
            statusmsg.push_status("ZKILL SERVER ERROR: " + str(r.status_code) +
                                  " (" + server_msg + ")")
            return "server error"
        try:
            r = r.json()
        except AttributeError:
            kills = 0
            blops_kills = 0
            hic_losses = 0
            self._queue.put([kills, blops_kills, self._char_id])
            return
        try:
            # Number of total kills of this toon.
            kills = r["shipsDestroyed"]
        except KeyError:
            kills = 0

        try:
            # Number of BLOPS killed by this toon.
            blops_kills = r["groups"]["898"]["shipsDestroyed"]
        except KeyError:
            blops_kills = 0

        try:
            # Number of HICs lost by this toon.
            hic_losses = r["groups"]["894"]["shipsLost"]
        except KeyError:
            hic_losses = 0

        try:
            # Kills over past 7 days
            week_kills = r["activepvp"]["kills"]["count"]
        except KeyError:
            week_kills = 0

        self._queue.put(
            [kills, blops_kills, hic_losses, week_kills, self._char_id])
        return
Beispiel #13
0
    def updateList(self, outlist, duration=None):
        '''
        `updateList()` takes the output of `output_list()` in `analyze.py` (via
        `sortOutlist()`) or a copy thereof stored in self.option, and uses it
        to populate the grid widget. Before it does so, it checks each
        item in outlist against a list of ignored characters, corporations
        and alliances. Finally, it highlights certain characters and
        updates the statusbar message.

        :param `outlist`: A list of rows with character data.

        :param `duration`: Time in seconds taken to query all relevant
        databases for each character.
        '''
        # If updateList() gets called before outlist has been provided, do nothing
        if outlist is None:
            return
        # Clean up grid
        if self.grid.GetNumberRows() > 0:
            self.grid.DeleteRows(numRows=self.grid.GetNumberRows())
        self.grid.AppendRows(len(outlist))
        # Add any NPSI fleet related characters to ignored_list
        npsi_list = self.options.Get("NPSIList", default=[])
        ignored_list = self.options.Get("ignoredList", default=[])
        highlighted_list = self.options.Get("highlightedList", default=[])
        hl_blops = self.options.Get("HlBlops", True)
        hl_hic = self.options.Get("HlHic", True)
        hl_cyno = self.options.Get("HlCyno", True)
        hl_list = self.options.Get("HlList", True)
        hl_cyno_prob = config.CYNO_HL_PERCENTAGE
        ignore_count = 0
        rowidx = 0
        for r in outlist:

            ignore = False
            for rec in ignored_list:
                if r[0] == rec[0] or r[3] == rec[0] or r[5] == rec[0]:
                    ignore = True
            for rec in npsi_list:
                if r[0] == rec[0]:
                    ignore = True
            if ignore:
                self.grid.HideRow(rowidx)
                ignore_count += 1

            # Schema depending on output_list() in analyze.py
            id = r[0]  # Hidden, used for zKillboard link
            faction_id = r[1]  # Hidden, used for faction ignoring
            name = r[2]
            corp_id = r[3]
            corp_name = r[4]
            alliance_id = r[5]
            alliance_name = r[6]
            faction = r[7] if r[7] is not None else "-"
            allies = "{:,}".format(int(r[8]))

            # Add number of allies to alliance name
            if alliance_name is not None:
                alliance_name = alliance_name + " (" + allies + ")"
            else:
                alliance_name = "-"

            # zKillboard data is "n.a." unless available
            week_kills = kills = blops_kills = hic_losses = "n.a."
            losses = solo_ratio = sec_status = "n.a."

            if r[13] is not None:
                week_kills = "{:,}".format(int(r[9])) if int(r[9]) > 0 else "-"
                kills = "{:,}".format(int(r[10]))
                blops_kills = "{:,}".format(int(
                    r[11])) if int(r[11]) > 0 else "-"
                hic_losses = "{:,}".format(int(
                    r[12])) if int(r[12]) > 0 else "-"
                losses = "{:,}".format(int(r[13]))
                solo_ratio = "{:.0%}".format(float(r[14]))
                sec_status = "{:.1f}".format(float(r[15]))

            # PySpy proprietary data is "n.a." unless available
            last_loss = last_kill = covert_ship = normal_ship = "n.a."
            avg_attackers = covert_prob = normal_prob = abyssal_losses = "n.a."
            cov_prob_float = norm_prob_float = 0
            if r[16] is not None:

                if int(r[16]) > 0:
                    last_loss = str(
                        (datetime.date.today() - datetime.datetime.strptime(
                            str(r[16]), '%Y%m%d').date()).days) + "d"
                else:
                    last_loss = "n.a."

                if int(r[17]) > 0:
                    last_kill = str(
                        (datetime.date.today() - datetime.datetime.strptime(
                            str(r[17]), '%Y%m%d').date()).days) + "d"
                else:
                    last_kill = "n.a."

                avg_attackers = "{:.1f}".format(float(r[18]))
                cov_prob_float = r[19]
                covert_prob = "{:.0%}".format(
                    cov_prob_float) if cov_prob_float > 0 else "-"
                norm_prob_float = r[20]
                normal_prob = "{:.0%}".format(
                    norm_prob_float) if norm_prob_float > 0 else "-"
                covert_ship = r[21]
                normal_ship = r[22]
                abyssal_losses = r[23] if int(r[23]) > 0 else "-"

            out = [
                id, "-", faction_id, name, sec_status, corp_id, corp_name,
                alliance_id, alliance_name, faction, kills, losses, week_kills,
                solo_ratio, blops_kills, hic_losses, last_loss, last_kill,
                avg_attackers, covert_prob, normal_prob, covert_ship,
                normal_ship, abyssal_losses
            ]

            # Check if character belongs to a faction that should be ignored
            if faction_id != 0:
                if config.IGNORED_FACTIONS == 2 and faction_id % 2 == 0:
                    self.grid.HideRow(rowidx)
                if config.IGNORED_FACTIONS == 1 and faction_id % 2 != 0:
                    self.grid.HideRow(rowidx)
            colidx = 0

            if hl_blops and r[9] is not None and r[
                    11] > 0:  # Add BLOPS to Warning Column
                out[1] = self.appendString(out[1], "BLOPS")
            if hl_hic and r[9] is not None and r[12] > 0:
                out[1] = self.appendString(out[1],
                                           "HIC")  # Add HIC to Warning Column
            if hl_cyno and (cov_prob_float >= hl_cyno_prob or norm_prob_float
                            >= hl_cyno_prob):  # Add CYNO to Warnin Column
                out[1] = self.appendString(out[1], "CYNO")

            # Cell text formatting
            for value in out:
                color = False
                self.grid.SetCellValue(rowidx, colidx, str(value))
                #self.grid.SetCellAlignment(self.columns[colidx][2], rowidx, colidx)
                if hl_blops and r[
                        9] is not None and r[11] > 0:  # Highlight BLOPS chars
                    self.grid.SetCellTextColour(rowidx, colidx,
                                                self.hl1_colour)
                    color = True
                if hl_hic and r[
                        9] is not None and r[12] > 0:  # Highlight HIC chars
                    self.grid.SetCellTextColour(rowidx, colidx,
                                                self.hl1_colour)
                    color = True
                if hl_cyno and (cov_prob_float >= hl_cyno_prob
                                or norm_prob_float >= hl_cyno_prob
                                ):  # Highlight CYNO chars
                    self.grid.SetCellTextColour(rowidx, colidx,
                                                self.hl2_colour)
                    color = True

                for entry in highlighted_list:  # Highlight chars from highlight list
                    if hl_list and (entry[1] == out[3] or entry[1] == out[6]
                                    or entry[1] == out[8][:-4]):
                        self.grid.SetCellTextColour(rowidx, colidx,
                                                    self.hl3_colour)
                        color = True

                if not color:
                    self.grid.SetCellTextColour(rowidx, colidx,
                                                self.txt_colour)
                colidx += 1
            rowidx += 1

        if duration is not None:
            statusmsg.push_status(
                str(len(outlist) - ignore_count) +
                " characters analysed, in " + str(duration) + " seconds (" +
                str(ignore_count) + " ignored). Double click " +
                "character to go to zKillboard.")
        else:
            statusmsg.push_status(
                str(len(outlist) - ignore_count) + " characters analysed (" +
                str(ignore_count) +
                " ignored). Double click character to go " + " to zKillboard.")