Exemple #1
0
    async def get_system_factions_history(
            self, system_name: str) -> list[SystemFactionHistory]:
        """Get factions history for a specified system.

        :raises ContentFetchingException: Unable to retrieve the data
        :raises SystemNotFoundException: Unable to retrieve the system
        """
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.get(
                    f"https://www.edsm.net/api-system-v1/factions?systemName={system_name}&showHistory=1"
                )
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        json_content = api_response.json()

        if json_content is None or len(json_content) == 0:
            raise SystemNotFoundException(system_name)

        response = []
        for faction in json_content["factions"]:
            response.append(
                SystemFactionHistory(
                    faction_name=faction["name"],
                    history=self._get_system_faction_history(faction),
                ))

        return response
Exemple #2
0
    async def find_commodity(
        self,
        mode: FindCommodityMode,
        reference_system: str,
        commodity: str,
        min_landing_pad_size: StationLandingPadSize,
        min_quantity: int,
    ) -> list[StationCommodityDetails]:
        """Get stations buying or selling a specific commodity near a reference system.

        Only works for non-rare commodities.
        """
        # First get commodity price
        current_commodity_price = self.get_commodity_prices(commodity)

        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.post(
                    SPANSH_STATIONS_SEARCH_URL,
                    json=self._find_commodity_generate_request_body(
                        mode, reference_system, commodity, min_quantity),
                )
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        return self._map_spansh_stations_to_model(api_response,
                                                  current_commodity_price,
                                                  mode, min_landing_pad_size)
Exemple #3
0
    async def __get_systems_factions_details(
            self, system_name: str) -> list[SystemDetailsFaction]:
        """Get system factions details."""
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.get(
                    f"{self.EDSM_SYSTEM_FACTIONS_URL}?systemName={system_name}"
                )
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        json_content = api_response.json()

        # Check result is not empty
        if json_content is None or len(json_content.get("factions", [])) == 0:
            return []

        factions = []
        for item in json_content["factions"]:
            new_faction = SystemDetailsFaction(
                allegiance=item["allegiance"],
                happiness=item["happiness"],
                influence=item["influence"],
                name=item["name"],
                state=item["state"],
                government=item["government"],
                is_player_faction=item["isPlayer"],
                updated_at=pendulum.from_timestamp(item["lastUpdate"]),
            )
            factions.append(new_faction)
        return factions
Exemple #4
0
    def get_community_goals(self) -> list[CommunityGoal]:
        """Get latest community goals informations."""
        inara_res = _get_community_goals_from_inara()
        if (inara_res.get("header", {}).get("eventStatus", None) != 200 and
                inara_res.get("events", [{}])[0].get("eventStatus") != 200):
            raise ContentFetchingException()

        # Return empty if no CGs running
        if "eventData" not in inara_res["events"][0]:
            return []

        return [
            CommunityGoal(
                contributors=event["contributorsNum"],
                current_tier=event["tierReached"],
                description=event["goalDescriptionText"],
                end_date=pendulum.parse(event["goalExpiry"]),  # type: ignore
                last_update=pendulum.parse(
                    event["lastUpdate"]),  # type: ignore
                objective=event["goalObjectiveText"],
                ongoing=not event["isCompleted"],
                reward=event["goalRewardText"],
                station=event["stationName"],
                system=event["starsystemName"],
                max_tier=event["tierMax"],
                title=event["communitygoalName"],
                id=event["communitygoalGameID"],
            ) for event in inara_res["events"][0]["eventData"]
        ]
Exemple #5
0
 def get_commodities(self) -> list[Commodity]:
     """Get all commodities."""
     try:
         res = _get_commodities_from_eddb()
     except httpx.HTTPError as e:  # type: ignore
         raise ContentFetchingException() from e
     return res
Exemple #6
0
    async def get_articles(self, language: Language) -> list[GalnetArticle]:
        """Get the latest Galnet articles.

        :raises ContentFetchingException: Unable to retrieve the articles
        """
        url = f"{get_frontier_api_url_for_language(language)}/galnet_article?&sort=-published_at&page[offset]=0&page[limit]=12"
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.get(url)
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        articles = api_response.json()

        # Build response
        response_list: list[GalnetArticle] = []

        for item in articles["data"]:
            new_item = GalnetArticle(
                content=item["attributes"]["body"]["value"],
                uri=
                f"https://www.elitedangerous.com/news/galnet/{item['attributes']['field_slug']}",
                title=item["attributes"]["title"],
                published_date=pendulum.parse(
                    item["attributes"]["published_at"]),  # type: ignore
                picture=
                f"{self.BASE_PICTURE_PATH}/{item['attributes']['field_galnet_image']}.png",
            )
            response_list.append(new_item)

        return response_list
Exemple #7
0
    def get_commodities_typeahead(self, input_text: str) -> list[str]:
        """Get commodities names for autocomplete."""
        try:
            commodities = _get_commodities_names_from_spansh()
        except httpx.HTTPError as e:  # type: ignore
            raise ContentFetchingException() from e

        return [
            item for item in commodities
            if item.lower().startswith(input_text.lower())
        ]
Exemple #8
0
    async def get_systems_typeahead(self, input_text: str) -> list[str]:
        """Get systems names for autocomplete.

        :raises ContentFetchingException: Unable to retrieve the data
        """
        url = f"{self.FUELRATS_TYPEAHEAD_URL}?term={input_text}"
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.get(url)
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        return api_response.json()
Exemple #9
0
 def get_commodities_prices(self,
                            filter: Optional[str]) -> list[CommodityPrice]:
     """Get all commodities prices (with an optional filter) ."""
     try:
         res = _get_commodities_prices_from_inara()
     except httpx.HTTPError as e:  # type: ignore
         raise ContentFetchingException() from e
     else:
         if filter:
             return [
                 item for item in res
                 if item.commodity.name.lower().startswith(filter.lower())
             ]
         return res
Exemple #10
0
    def get_commodity_prices(self, commodity_name: str) -> CommodityPrice:
        """Get prices for a specific commodity."""
        try:
            res = _get_commodities_prices_from_inara()
        except httpx.HTTPError as e:  # type: ignore
            raise ContentFetchingException() from e

        matching_commodity = next(
            (price for price in res
             if price.commodity.name.lower() == commodity_name.lower()),
            None,
        )
        if matching_commodity is None:
            raise CommodityNotFoundException(commodity_name)

        return matching_commodity
Exemple #11
0
    async def get_articles(self, language: Language) -> list[NewsArticle]:
        """Get the latest news articles.

        :raises ContentFetchingException: Unable to retrieve the articles
        """
        url = (
            f"{get_frontier_api_url_for_language(language)}/news_article"
            "?include=field_image_entity.field_media_image,field_site"
            "&filter[site][condition][path]=field_site.field_slug"
            "&filter[site][condition][operator]=CONTAINS"
            "&filter[site][condition][value]=elite-dangerous&sort[sort-published][path]=published_at"
            "&sort[sort-published][direction]=DESC&page[offset]=0&page[limit]=12"
        )

        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.get(url)
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        articles = api_response.json()

        # Build response
        response_list: list[NewsArticle] = []

        for item in articles["data"]:

            try:
                picture = _get_picture_url_for_article(articles, item["id"])
            except Exception:
                logger.error(f"Couldn't get picture for article {item['id']}")
                picture = None

            new_item = NewsArticle(
                content=item["attributes"]["body"]["value"],
                uri=f"https://www.elitedangerous.com/news/{item['attributes']['field_slug']}",
                picture=picture,
                title=item["attributes"]["title"],
                published_date=pendulum.parse(item["attributes"]["published_at"]),  # type: ignore
            )
            response_list.append(new_item)

        return response_list
Exemple #12
0
    async def get_station_selling_ship(
        self, reference_system: str, ship_model: ShipModel
    ) -> list[StationSellingShip]:
        """Search for a station selling a specific ship.

        :raises ContentFetchingException: Unable to retrieve the articles
        """
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.post(
                    self.SHIPS_SEARCH_ENDPOINT,
                    json={
                        "filters": {"ships": {"value": [ship_model.values[0]]}},
                        "sort": [{"distance": {"direction": "asc"}}],
                        "size": 15,
                        "page": 0,
                        "reference_system": reference_system,
                    },
                )
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        stations = api_response.json()["results"]

        return [
            StationSellingShip(
                distance_from_reference_system=item["distance"],
                distance_to_arrival=item["distance_to_arrival"],
                max_landing_pad_size=StationLandingPadSize.LARGE
                if item["has_large_pad"]
                else StationLandingPadSize.MEDIUM
                if item["medium_pads"] > 0
                else StationLandingPadSize.SMALL,
                name=item["name"],
                shipyard_updated_at=pendulum.parse(item["shipyard_updated_at"]),  # type: ignore
                system_name=item["system_name"],
                is_planetary=item["is_planetary"],
                is_fleet_carrier=is_fleet_carrier(item["controlling_minor_faction"]),
                is_settlement=is_settlement(item["type"]),
            )
            for item in stations
        ]
Exemple #13
0
    async def _get_best_prices_for_commodity_and_mode(
        self,
        commodity: CommodityPrice,
        mode: FindCommodityMode,
    ) -> list[StationCommodityDetails]:
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.post(
                    SPANSH_STATIONS_SEARCH_URL,
                    json=self.
                    _find_commodity_best_prices_generate_request_body(
                        mode, commodity.commodity.name),
                )
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        return self._map_spansh_stations_to_model(api_response, commodity,
                                                  mode,
                                                  StationLandingPadSize.SMALL)
Exemple #14
0
    async def _get_system(self, system_name: str) -> System:
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.get(
                    f"https://www.edsm.net/api-v1/system?systemName={system_name}&showCoordinates=1&showPermit=1"
                )
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        json_content = api_response.json()

        if json_content is None or len(json_content) == 0:
            raise SystemNotFoundException(system_name)

        return System(
            name=json_content["name"],
            x=json_content["coords"]["x"],
            y=json_content["coords"]["y"],
            z=json_content["coords"]["z"],
            permit_required=json_content["requirePermit"],
        )
Exemple #15
0
    async def get_system_details(self, system_name: str) -> SystemDetails:
        """Get system details.

        :raises ContentFetchingException: Unable to retrieve the data
        :raises SystemNotFoundException: Unable to retrieve the system
        """
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.post(
                    self.SPANSH_SYSTEMS_SEARCH_URL,
                    json={
                        "filters": {
                            "name": {
                                "value": system_name
                            }
                        },
                        "sort": [{
                            "distance": {
                                "direction": "asc"
                            }
                        }],
                        "size": 1,
                        "page": 0,
                    },
                )
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        json_content = api_response.json()

        if json_content is None or len(json_content["results"]) == 0:
            raise SystemNotFoundException(system_name)

        result = json_content["results"][0]

        try:
            factions = await self.__get_systems_factions_details(system_name)
        except ContentFetchingException:
            factions = []

        return SystemDetails(
            allegiance=result.get("allegiance"),
            controlling_faction_state=result.get(
                "controlling_minor_faction_state"),
            controlling_faction=result.get("controlling_minor_faction"),
            government=result.get("government"),
            name=result["name"],
            permit_required=result["needs_permit"],
            population=result.get("population"),
            power_state=result.get("power_state"),
            power=result["power"][0]
            if len(result.get("power", [])) > 0 else None,
            primary_economy=result.get("primary_economy"),
            secondary_economy=result.get("secondary_economy"),
            security=result.get("security"),
            state=result.get("state"),
            x=result["x"],
            y=result["y"],
            z=result["z"],
            factions=factions,
        )
Exemple #16
0
    async def get_system_stations(self, system_name: str) -> list[Station]:
        """Get system stations.

        :raises ContentFetchingException: Unable to retrieve the data
        :raises SystemNotFoundException: Unable to retrieve the system
        """
        async with get_aynsc_httpx_client() as client:
            try:
                api_response = await client.post(
                    self.SPANSH_STATIONS_SEARCH_URL,
                    json={
                        "filters": {
                            "system_name": {
                                "value": system_name
                            }
                        },
                        "sort": [{
                            "distance": {
                                "direction": "asc"
                            }
                        }],
                        "size": 200,
                        "page": 0,
                    },
                )
                api_response.raise_for_status()
            except httpx.HTTPError as e:  # type: ignore
                raise ContentFetchingException() from e

        # We need the system too
        system = await self.get_system_details(system_name)

        # Check that the system has stations
        json_content = api_response.json()
        if json_content is None or len(json_content["results"]) == 0:
            return []

        stations: list[Station] = []
        for item in json_content["results"]:
            station_landing_pad_size = get_station_max_landing_pad_size(item)

            stations.append(
                Station(
                    distance_to_arrival=item["distance_to_arrival"],
                    has_blackmarket=station_has_service(
                        item, SpanshStationService.BLACK_MARKET),
                    has_docking=station_has_service(item,
                                                    SpanshStationService.DOCK),
                    has_market=item.get("has_market", False),
                    has_missions=station_has_service(
                        item, SpanshStationService.MISSIONS),
                    has_outfitting=item.get("has_outfitting", False),
                    has_restock=station_has_service(
                        item, SpanshStationService.RESTOCK),
                    has_refuel=station_has_service(
                        item, SpanshStationService.REFUEL),
                    has_repair=station_has_service(
                        item, SpanshStationService.REPAIR),
                    has_shipyard=item.get("has_shipyard", False),
                    has_universal_cartographics=station_has_service(
                        item, SpanshStationService.UNIVERSAL_CARTOGRAPHICS),
                    is_fleet_carrier=is_fleet_carrier(
                        item["controlling_minor_faction"]),
                    is_planetary=item["is_planetary"],
                    is_settlement=is_settlement(item["type"]),
                    last_market_update=pendulum.parse(
                        item["market_updated_at"])
                    if item.get("market_updated_at") else None,  # type: ignore
                    last_outfitting_update=pendulum.parse(
                        item["outfitting_updated_at"])
                    if item.get("outfitting_updated_at") else
                    None,  # type: ignore
                    last_shipyard_update=pendulum.parse(
                        item["shipyard_updated_at"]) if
                    item.get("shipyard_updated_at") else None,  # type: ignore
                    max_landing_pad_size=station_landing_pad_size,
                    name=item["name"],
                    system_name=item["system_name"],
                    system_permit_required=system.permit_required,
                    type=item["type"],
                ))

        return stations