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
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)
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
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"] ]
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
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
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()) ]
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()
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
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
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
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 ]
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)
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"], )
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, )
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