Beispiel #1
0
    async def _initialize(self) -> None:
        """Configures initial universe, loads mappers and runs one iteration,
        does not start any periodic callbacks or loops.

        Prereq of daemon() and killmail_oneshot()."""
        self.universes = {}
        self.mappers = {}

        # Path is a custom universe where users can add jumpbridges or other
        # custom connections. If it is in use we create a universe for it and
        # add all custom connections.
        if "path" in self.config and len(self.config["path"]):
            self.universes["_path"] = await Universe.from_empty()

            for path in self.config["path"]:
                state = State()
                setattr(state, path["type"], True)

                left = System(path["from"])
                right = System(path["to"])

                connection = Connection(left, right, state)

                await self.universes["_path"].connect(connection)

        if "mapper" in self.config and len(self.config["mapper"]):
            log.info("initialize: `unchaind` with {} mappers.".format(
                len(self.config["mapper"])))

            for index, mapper in enumerate(self.config["mapper"]):
                mapper.update({"home_system": self.config.get("home_system")})

                transport = await get_transport(mapper["type"]
                                                ).from_config(mapper)

                if transport is None:
                    log.warn("initialize: failed to create %s mapper",
                             mapper["type"])
                else:
                    # The transport has been created, we can now create a name
                    # and universe for this mapper.
                    self.universes[
                        f"_{mapper['type']}_{index}"] = await Universe.from_empty(
                        )
                    self.mappers[f"_{mapper['type']}_{index}"] = get_mapper(
                        mapper["type"])(transport)

            log.info(
                "initialize: %d mappers initialized, starting initial pass.",
                len(self.mappers),
            )

            # Run our initial pass to get all the results without firing their
            # callbacks since we're booting
            await self.periodic_mappers()
Beispiel #2
0
    async def update(self) -> Universe:
        """Update our internal Universe with a new Universe."""

        data = await self.transport.update()

        if self.universe is None:
            self.universe: Universe = await Universe.from_empty()

        universe: Universe = await Universe.from_empty()

        chain = data["chainMap"]

        connections = chain["wormholes"]

        if isinstance(connections, list):
            # For some weird reason when there are no connections siggy changes
            # the type of this to a list instead of a dict
            log.debug("update: connections was a list")
            self.universe = universe
            return universe

        for connection in connections.values():
            state = State()
            state.end_of_life = bool(connection.get("eol", 0))

            await universe.connect(
                Connection(
                    System(connection["from_system_id"]),
                    System(connection["to_system_id"]),
                    state,
                ))

        aliases: Dict[System, str] = {}
        systems = chain["systems"]

        for system in systems.values():
            if (len(system.get("displayName", ""))
                    and system["displayName"] != system["name"]):
                aliases[System(system["systemID"])] = system["displayName"]

        universe.aliases = aliases

        self.universe = universe

        return self.universe
Beispiel #3
0
async def _match_location(value: str, package: Dict[str, Any],
                          universe: Universe) -> bool:
    killmail = package["killmail"]
    solar_system = System(killmail.get("solar_system_id", None))

    if value == "chain":
        return solar_system in universe.systems

    if value == "wspace":
        return bool(re.match(r"J\d{6}", solar_system.name))

    return value.lower() == solar_system.name.lower()
Beispiel #4
0
    async def update(self) -> Universe:
        """Update our internal Universe with a new Universe."""

        data = await self.transport.update()

        if self.universe is None:
            self.universe: Universe = await Universe.from_empty()

        universe: Universe = await Universe.from_empty()

        for connection in data:
            state = State()

            await universe.connect(
                Connection(
                    System(connection["source_solar_system"]["id"]),
                    System(connection["destination_solar_system"]["id"]),
                    state,
                )
            )

        self.universe = universe

        return self.universe
Beispiel #5
0
async def _match_security_status(value: str, package: Dict[str, Any],
                                 universe: Universe) -> bool:
    killmail = package["killmail"]
    solar_system = System(killmail.get("solar_system_id", None))

    value = value.lower()

    if value in ("high", "highsec"):
        return solar_system.truesec >= 0.45
    if value in ("low", "lowsec"):
        return 0.0 < solar_system.truesec < 0.45
    if value in ("null", "nullsec"):
        return solar_system.truesec < 0.0

    log.warning("unknown security status '%s'", value)
    return False
Beispiel #6
0
async def stats_for_killmail(package: Dict[str, Any],
                             universe: Universe) -> Optional[KillmailStats]:

    try:
        victim_ship_typeid: int = int(
            package["killmail"]["victim"]["ship_type_id"])
        solar_system_id: int = int(package["killmail"]["solar_system_id"])

        d = {
            "victim_moniker":
            char_name_with_ticker(package["killmail"]["victim"]),
            "victim_ship":
            esi_util.type_details(victim_ship_typeid),
            "final_blow_moniker":
            char_name_with_ticker(
                next(
                    filter(
                        lambda x: x["final_blow"],
                        package["killmail"]["attackers"],
                    ))),
            "top_damage_moniker":
            char_name_with_ticker(
                max(
                    package["killmail"]["attackers"],
                    key=lambda x: x["damage_done"],
                )),
            "attacker_entities":
            gather(*[
                entity_ticker_for_char(x)
                for x in package["killmail"]["attackers"]
            ]),
            "attacker_ships":
            gather(*[(esi_util.type_details(x["ship_type_id"]))
                     for x in package["killmail"]["attackers"]]),
            "solar_system_name":
            universe.system_name(System(solar_system_id)),
        }

        d = await multi(d)

        d["victim_ship"] = d["victim_ship"]["name"]
        d["attacker_entities_summary"] = _stringify_counter_by_popularity(
            collections.Counter(d["attacker_entities"]))
        d["attacker_ships_summary"] = _stringify_counter_by_popularity(
            collections.Counter(
                map(operator.itemgetter("name"), d["attacker_ships"])))

        d.pop("attacker_entities", None)
        d.pop("attacker_ships", None)

        d["timestamp"] = int(
            dateutil.parser.parse(
                package["killmail"]["killmail_time"]).timestamp())
        d["victim_ship_typeid"] = victim_ship_typeid
        d["kill_id"] = package["killID"]
        d["isk_value"] = package["zkb"]["totalValue"]
        d["solar_system_id"] = solar_system_id

        return KillmailStats(**d)
    except Exception as e:
        log.exception(e)

    return None