From b40d3b889f91957bec4534243038839fcbaf3cdb Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 1 Dec 2022 15:30:46 +0000 Subject: [PATCH] CAPI: Use `CAPI-Live-` game_version for market & shipyard --- EDMarketConnector.py | 1 + companion.py | 75 ++++++++++++++++++++++++++++++-------------- plugins/eddn.py | 36 ++++++++++++++++++--- 3 files changed, 84 insertions(+), 28 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 36d7215c..ef97b3a2 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1172,6 +1172,7 @@ class AppWindow(object): monitor.state['Loan'] = capi_response.capi_data['commander'].get('debt', 0) # stuff we can do when not docked + # TODO: Use plug.notify_capi_legacy if Legacy host err = plug.notify_newdata(capi_response.capi_data, monitor.is_beta) self.status['text'] = err and err or '' if err: diff --git a/companion.py b/companion.py index 352e7fb0..4aff101a 100644 --- a/companion.py +++ b/companion.py @@ -66,24 +66,29 @@ class CAPIData(UserDict): def __init__( self, - data: Union[str, Dict[str, Any], 'CAPIData', None] = None, source_endpoint: str = None + data: Union[str, Dict[str, Any], 'CAPIData', None] = None, + source_host: str = None, + source_endpoint: str = None ) -> None: if data is None: super().__init__() + elif isinstance(data, str): super().__init__(json.loads(data)) + else: super().__init__(data) self.original_data = self.data.copy() # Just in case + self.source_host = source_host self.source_endpoint = source_endpoint if source_endpoint is None: return if source_endpoint == Session.FRONTIER_CAPI_PATH_SHIPYARD and self.data.get('lastStarport'): - # All the other endpoints may or may not have a lastStarport, but definitely wont have valid data + # All the other endpoints may or may not have a lastStarport, but definitely won't have valid data # for this check, which means it'll just make noise for no reason while we're working on other things self.check_modules_ships() @@ -557,7 +562,8 @@ class EDMCCAPIRequest(EDMCCAPIReturn): REQUEST_WORKER_SHUTDOWN = '__EDMC_WORKER_SHUTDOWN' def __init__( - self, endpoint: str, query_time: int, + self, capi_host: str, endpoint: str, + query_time: int, tk_response_event: Optional[str] = None, play_sound: bool = False, auto_update: bool = False ): @@ -565,6 +571,7 @@ class EDMCCAPIRequest(EDMCCAPIReturn): query_time=query_time, tk_response_event=tk_response_event, play_sound=play_sound, auto_update=auto_update ) + self.capi_host: str = capi_host # The CAPI host to use. self.endpoint: str = endpoint # The CAPI query to perform. @@ -606,7 +613,6 @@ class Session(object): def __init__(self) -> None: self.state = Session.STATE_INIT - self.server: Optional[str] = None self.credentials: Optional[Dict[str, Any]] = None self.requests_session: Optional[requests.Session] = None self.auth: Optional[Auth] = None @@ -744,17 +750,20 @@ class Session(object): logger.debug('CAPI worker thread starting') def capi_single_query( - capi_endpoint: str, timeout: int = capi_default_requests_timeout + capi_host: str, + capi_endpoint: str, + timeout: int = capi_default_requests_timeout ) -> CAPIData: """ Perform a *single* CAPI endpoint query within the thread worker. + :param capi_host: CAPI host to query. :param capi_endpoint: An actual Frontier CAPI endpoint to query. :param timeout: requests query timeout to use. :return: The resulting CAPI data, of type CAPIData. """ capi_data: CAPIData - if not monitor.is_live_galaxy(): + if capi_host == SERVER_LEGACY: logger.warning("Dropping CAPI request because this is the Legacy galaxy") return capi_data @@ -768,7 +777,7 @@ class Session(object): # This is one-shot conf_module.capi_debug_access_token = None - r = self.requests_session.get(self.server + capi_endpoint, timeout=timeout) # type: ignore + r = self.requests_session.get(capi_host + capi_endpoint, timeout=timeout) # type: ignore logger.trace_if('capi.worker', '... got result...') r.raise_for_status() # Typically 403 "Forbidden" on token expiry @@ -776,7 +785,7 @@ class Session(object): # r.status_code = 401 # raise requests.HTTPError capi_json = r.json() - capi_data = CAPIData(capi_json, capi_endpoint) + capi_data = CAPIData(capi_json, capi_host, capi_endpoint) self.capi_raw_data.record_endpoint( capi_endpoint, r.content.decode(encoding='utf-8'), datetime.datetime.utcnow() @@ -822,7 +831,9 @@ class Session(object): return capi_data - def capi_station_queries(timeout: int = capi_default_requests_timeout) -> CAPIData: # noqa: CCR001 + def capi_station_queries( # noqa: CCR001 + capi_host: str, timeout: int = capi_default_requests_timeout + ) -> CAPIData: """ Perform all 'station' queries for the caller. @@ -835,7 +846,7 @@ class Session(object): :param timeout: requests timeout to use. :return: CAPIData instance with what we retrieved. """ - station_data = capi_single_query(self.FRONTIER_CAPI_PATH_PROFILE, timeout=timeout) + station_data = capi_single_query(capi_host, self.FRONTIER_CAPI_PATH_PROFILE, timeout=timeout) if not station_data['commander'].get('docked') and not monitor.state['OnFoot']: return station_data @@ -876,7 +887,7 @@ class Session(object): last_starport_id = int(last_starport.get('id')) if services.get('commodities'): - market_data = capi_single_query(self.FRONTIER_CAPI_PATH_MARKET, timeout=timeout) + market_data = capi_single_query(capi_host, self.FRONTIER_CAPI_PATH_MARKET, timeout=timeout) if last_starport_id != int(market_data['id']): logger.warning(f"{last_starport_id!r} != {int(market_data['id'])!r}") raise ServerLagging() @@ -886,7 +897,7 @@ class Session(object): station_data['lastStarport'].update(market_data) if services.get('outfitting') or services.get('shipyard'): - shipyard_data = capi_single_query(self.FRONTIER_CAPI_PATH_SHIPYARD, timeout=timeout) + shipyard_data = capi_single_query(capi_host, self.FRONTIER_CAPI_PATH_SHIPYARD, timeout=timeout) if last_starport_id != int(shipyard_data['id']): logger.warning(f"{last_starport_id!r} != {int(shipyard_data['id'])!r}") raise ServerLagging() @@ -913,10 +924,10 @@ class Session(object): capi_data: CAPIData try: if query.endpoint == self._CAPI_PATH_STATION: - capi_data = capi_station_queries() + capi_data = capi_station_queries(query.capi_host) else: - capi_data = capi_single_query(self.FRONTIER_CAPI_PATH_PROFILE) + capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE) except Exception as e: self.capi_response_queue.put( @@ -951,6 +962,7 @@ class Session(object): """Ask the CAPI query thread to finish.""" self.capi_request_queue.put( EDMCCAPIRequest( + capi_host='', endpoint=EDMCCAPIRequest.REQUEST_WORKER_SHUTDOWN, query_time=int(time.time()) ) @@ -968,22 +980,15 @@ class Session(object): :param play_sound: Whether the app should play a sound on error. :param auto_update: Whether this request was triggered automatically. """ - if self.credentials is not None and self.credentials['beta']: - self.server = SERVER_BETA - - elif monitor.is_live_galaxy(): - self.server = SERVER_LIVE - - else: - logger.warning("Dropping CAPI request because this is the Legacy galaxy, which is not yet supported") - # self.server = SERVER_LEGACY - self.server = None + capi_host = self.capi_host_for_galaxy() + if not capi_host: return # Ask the thread worker to perform all three queries logger.trace_if('capi.worker', 'Enqueueing request') self.capi_request_queue.put( EDMCCAPIRequest( + capi_host=capi_host, endpoint=self._CAPI_PATH_STATION, tk_response_event=tk_response_event, query_time=query_time, @@ -1064,6 +1069,28 @@ class Session(object): indent=2, sort_keys=True, separators=(',', ': ')).encode('utf-8')) + + def capi_host_for_galaxy(self) -> str: + """ + Determine the correct CAPI host. + + This is based on the current state of beta and game galaxy. + + :return: The required CAPI host. + """ + if self.credentials is None: + # Can't tell if beta or not + return '' + + if self.credentials['beta']: + return SERVER_BETA + + if monitor.is_live_galaxy(): + return SERVER_LIVE + + # return SERVER_LEGACY # Not Yet + logger.warning("Dropping CAPI request because this is the Legacy galaxy, which is not yet supported") + return "" ###################################################################### diff --git a/plugins/eddn.py b/plugins/eddn.py index 5af9b6e6..8499eb62 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -41,6 +41,7 @@ from typing import Tuple, Union import requests +import companion import edmc_data import killswitch import myNotebook as nb # noqa: N813 @@ -610,7 +611,7 @@ class EDDN: logger.debug('Done.') - def export_commodities(self, data: Mapping[str, Any], is_beta: bool) -> None: # noqa: CCR001 + def export_commodities(self, data: CAPIData, is_beta: bool) -> None: # noqa: CCR001 """ Update EDDN with the commodities on the current (lastStarport) station. @@ -675,10 +676,19 @@ class EDDN: if 'prohibited' in data['lastStarport']: message['prohibited'] = sorted(x for x in (data['lastStarport']['prohibited'] or {}).values()) + if data.source_host == companion.SERVER_LIVE: + gv = 'CAPI-Live-market' + + elif data.source_host == companion.SERVER_LEGACY: + gv = 'CAPI-Legacy-market' + + else: + gv = 'CAPI-market' + self.send_message(data['commander']['name'], { '$schemaRef': f'https://eddn.edcd.io/schemas/commodity/3{"/test" if is_beta else ""}', 'message': message, - 'header': self.standard_header(game_version='CAPI-market', game_build=''), + 'header': self.standard_header(game_version=gv, game_build=''), }) this.commodities = commodities @@ -761,6 +771,15 @@ class EDDN: # Don't send empty modules list - schema won't allow it if outfitting and this.outfitting != (horizons, outfitting): + if data.source_host == companion.SERVER_LIVE: + gv = 'CAPI-Live-shipyard' + + elif data.source_host == companion.SERVER_LEGACY: + gv = 'CAPI-Legacy-shipyard' + + else: + gv = 'CAPI-shipyard' + self.send_message(data['commander']['name'], { '$schemaRef': f'https://eddn.edcd.io/schemas/outfitting/2{"/test" if is_beta else ""}', 'message': OrderedDict([ @@ -772,7 +791,7 @@ class EDDN: ('modules', outfitting), ('odyssey', this.odyssey), ]), - 'header': self.standard_header(game_version='CAPI-shipyard', game_build=''), + 'header': self.standard_header(game_version=gv, game_build=''), }) this.outfitting = (horizons, outfitting) @@ -806,6 +825,15 @@ class EDDN: ) # Don't send empty ships list - shipyard data is only guaranteed present if user has visited the shipyard. if shipyard and this.shipyard != (horizons, shipyard): + if data.source_host == companion.SERVER_LIVE: + gv = 'CAPI-Live-shipyard' + + elif data.source_host == companion.SERVER_LEGACY: + gv = 'CAPI-Legacy-shipyard' + + else: + gv = 'CAPI-shipyard' + self.send_message(data['commander']['name'], { '$schemaRef': f'https://eddn.edcd.io/schemas/shipyard/2{"/test" if is_beta else ""}', 'message': OrderedDict([ @@ -817,7 +845,7 @@ class EDDN: ('ships', shipyard), ('odyssey', this.odyssey), ]), - 'header': self.standard_header(game_version='CAPI-shipyard', game_build=''), + 'header': self.standard_header(game_version=gv, game_build=''), }) this.shipyard = (horizons, shipyard)