diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 7f3385a8..00ab907e 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -899,14 +899,19 @@ class AppWindow(object): elif auto_update and not monitor.state['OnFoot'] and not data['commander'].get('docked'): # auto update is only when just docked + logger.warning(f"{auto_update!r} and not {monitor.state['OnFoot']!r} and " + f"not {data['commander'].get('docked')!r}") raise companion.ServerLagging() elif data['lastSystem']['name'] != monitor.system: # CAPI system must match last journal one + logger.warning(f"{data['lastSystem']['name']!r} != {monitor.system!r}") raise companion.ServerLagging() elif data['lastStarport']['name'] != monitor.station: if monitor.state['OnFoot'] and monitor.station: + logger.warning(f"({data['lastStarport']['name']!r} != {monitor.station!r}) AND " + f"{monitor.state['OnFoot']!r} and {monitor.station!r}") raise companion.ServerLagging() else: @@ -914,18 +919,32 @@ class AppWindow(object): if data['commander']['docked']: last_station = data['lastStarport']['name'] + if monitor.station is None: + # Likely (re-)Embarked on ship docked at an EDO settlement. + # Both Disembark and Embark have `"Onstation": false` in Journal. + # So there's nothing to tell us which settlement we're (still, + # or now, if we came here in Apex and then recalled ship) docked at. + logger.debug("monitor.station is None - so EDO settlement?") + raise companion.NoMonitorStation() + if last_station != monitor.station: # CAPI lastStarport must match + logger.warning(f"({data['lastStarport']['name']!r} != {monitor.station!r}) AND " + f"{last_station!r} != {monitor.station!r}") raise companion.ServerLagging() self.holdofftime = querytime + companion.holdoff elif not monitor.state['OnFoot'] and data['ship']['id'] != monitor.state['ShipID']: # CAPI ship must match + logger.warning(f"not {monitor.state['OnFoot']!r} and " + f"{data['ship']['id']!r} != {monitor.state['ShipID']!r}") raise companion.ServerLagging() elif not monitor.state['OnFoot'] and data['ship']['name'].lower() != monitor.state['ShipType']: # CAPI ship type must match + logger.warning(f"not {monitor.state['OnFoot']!r} and " + f"{data['ship']['name'].lower()!r} != {monitor.state['ShipType']!r}") raise companion.ServerLagging() else: diff --git a/L10n/en.template b/L10n/en.template index ba11bb93..39e1346c 100644 --- a/L10n/en.template +++ b/L10n/en.template @@ -4,34 +4,37 @@ /* companion.py: Frontier CAPI didn't respond; In files: companion.py:171; */ "Error: Frontier CAPI didn't respond" = "Error: Frontier CAPI didn't respond"; -/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:189; */ +/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:190; */ "Error: Frontier server is lagging" = "Error: Frontier server is lagging"; -/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:199; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:205; */ +"Docked but unknown station: EDO Settlement?" = "Docked but unknown station: EDO Settlement?"; + +/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:214; */ "Error: Invalid Credentials" = "Error: Invalid Credentials"; -/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:215; */ +/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:230; */ "Error: Wrong Cmdr" = "Error: Wrong Cmdr"; -/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:326; companion.py:407; */ +/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:341; companion.py:422; */ "Error" = "Error"; -/* companion.py: Frontier auth, no 'usr' section in returned data; companion.py: Frontier auth, no 'customer_id' in 'usr' section in returned data; In files: companion.py:365; companion.py:370; */ +/* companion.py: Frontier auth, no 'usr' section in returned data; companion.py: Frontier auth, no 'customer_id' in 'usr' section in returned data; In files: companion.py:380; companion.py:385; */ "Error: Couldn't check token customer_id" = "Error: Couldn't check token customer_id"; -/* companion.py: Frontier auth customer_id doesn't match game session FID; In files: companion.py:376; */ +/* companion.py: Frontier auth customer_id doesn't match game session FID; In files: companion.py:391; */ "Error: customer_id doesn't match!" = "Error: customer_id doesn't match!"; -/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:398; */ +/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:413; */ "Error: unable to get token" = "Error: unable to get token"; -/* companion.py: Frontier CAPI data retrieval failed; In files: companion.py:560; */ +/* companion.py: Frontier CAPI data retrieval failed; In files: companion.py:575; */ "Frontier CAPI query failure" = "Frontier CAPI query failure"; -/* companion.py: Frontier CAPI data retrieval failed with 5XX code; In files: companion.py:576; */ +/* companion.py: Frontier CAPI data retrieval failed with 5XX code; In files: companion.py:591; */ "Frontier CAPI server error" = "Frontier CAPI server error"; -/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:424; EDMarketConnector.py:718; EDMarketConnector.py:1283; */ +/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:424; EDMarketConnector.py:718; EDMarketConnector.py:1302; */ "Update" = "Update"; /* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:507; prefs.py:843; */ @@ -46,10 +49,10 @@ /* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:712; edsm.py:219; stats.py:50; theme.py:227; */ "Cmdr" = "Cmdr"; -/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:714; EDMarketConnector.py:1053; */ +/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:714; EDMarketConnector.py:1072; */ "Role" = "Role"; -/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:714; EDMarketConnector.py:1063; EDMarketConnector.py:1086; stats.py:363; */ +/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:714; EDMarketConnector.py:1082; EDMarketConnector.py:1105; stats.py:363; */ "Ship" = "Ship"; /* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:715; */ @@ -61,7 +64,7 @@ /* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:717; prefs.py:623; prefs.py:738; stats.py:366; */ "Station" = "Station"; -/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:720; EDMarketConnector.py:735; EDMarketConnector.py:738; EDMarketConnector.py:1772; */ +/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:720; EDMarketConnector.py:735; EDMarketConnector.py:738; EDMarketConnector.py:1791; */ "File" = "File"; /* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:721; EDMarketConnector.py:736; EDMarketConnector.py:739; */ @@ -76,7 +79,7 @@ /* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:724; EDMarketConnector.py:737; EDMarketConnector.py:740; */ "Help" = "Help"; -/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:727; EDMarketConnector.py:753; EDMarketConnector.py:1328; */ +/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:727; EDMarketConnector.py:753; EDMarketConnector.py:1347; */ "About {APP}" = "About {APP}"; /* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:729; EDMarketConnector.py:752; */ @@ -91,10 +94,10 @@ /* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:732; EDMarketConnector.py:750; */ "Privacy Policy" = "Privacy Policy"; -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:733; EDMarketConnector.py:751; EDMarketConnector.py:1362; */ +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:733; EDMarketConnector.py:751; EDMarketConnector.py:1381; */ "Release Notes" = "Release Notes"; -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:745; EDMarketConnector.py:1773; prefs.py:254; */ +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:745; EDMarketConnector.py:1792; prefs.py:254; */ "Settings" = "Settings"; /* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:746; */ @@ -109,7 +112,7 @@ /* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:762; */ "Logging in..." = "Logging in..."; -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:778; EDMarketConnector.py:1196; */ +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:778; EDMarketConnector.py:1215; */ "Authentication successful" = "Authentication successful"; /* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:809; */ @@ -121,7 +124,7 @@ /* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:822; */ "Station doesn't have a market!" = "Station doesn't have a market!"; -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI to save to file; stats.py: Fetching data from Frontier CAPI in order to display on File > Status; In files: EDMarketConnector.py:867; EDMarketConnector.py:1409; stats.py:279; */ +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI to save to file; stats.py: Fetching data from Frontier CAPI in order to display on File > Status; In files: EDMarketConnector.py:867; EDMarketConnector.py:1428; stats.py:279; */ "Fetching data..." = "Fetching data..."; /* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:880; */ @@ -136,34 +139,34 @@ /* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:894; stats.py:312; */ "What are you flying?!" = "What are you flying?!"; -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1007; */ +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1026; */ "Last updated at %H:%M:%S" = "Last updated at %H:%M:%S"; -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1033; */ +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1052; */ "Fighter" = "Fighter"; -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1034; */ +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1053; */ "Gunner" = "Gunner"; -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1035; */ +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1054; */ "Helm" = "Helm"; -/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1279; */ +/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1298; */ "cooldown {SS}s" = "cooldown {SS}s"; -/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1388; prefs.py:304; */ +/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1407; prefs.py:304; */ "OK" = "OK"; -/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1470; */ +/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1489; */ "Shutting down..." = "Shutting down..."; -/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:1761:1767; */ +/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:1780:1786; */ "One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name."; -/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:1771; prefs.py:953; */ +/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:1790; prefs.py:953; */ "Plugins" = "Plugins"; -/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:1782; */ +/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:1801; */ "EDMC: Plugins Without Python 3.x Support" = "EDMC: Plugins Without Python 3.x Support"; /* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ diff --git a/companion.py b/companion.py index c6c179c6..0efae6aa 100644 --- a/companion.py +++ b/companion.py @@ -176,7 +176,8 @@ class ServerConnectionError(ServerError): class ServerLagging(Exception): - """Exception Class for CAPI Server lagging. + """ + Exception Class for CAPI Server lagging. Raised when Companion API server is returning old data, e.g. when the servers are too busy. @@ -189,6 +190,22 @@ class ServerLagging(Exception): self.args = (_('Error: Frontier server is lagging'),) +class NoMonitorStation(Exception): + """ + Exception Class for being docked, but not knowing where in monitor. + + Raised when CAPI says we're docked but we forgot where we were at an EDO + Settlement, Disembarked, re-Embarked and then user hit 'Update'. + As of 4.0.0.401 both Disembark and Embark say `"Onstation": false`. + """ + + def __init__(self, *args) -> None: + self.args = args + if not args: + # LANG: Commander is docked at an EDO settlement, got out and back in, we forgot the station + self.args = (_("Docked but unknown station: EDO Settlement?"),) + + class CredentialsError(Exception): """Exception Class for CAPI Credentials error.""" @@ -409,7 +426,7 @@ class Auth(object): @staticmethod def invalidate(cmdr: Optional[str]) -> None: """Invalidate Refresh Token for specified Commander.""" - to_set = None + to_set: Optional[list] = None if cmdr is None: logger.info('Frontier CAPI Auth: Invalidating ALL tokens!') cmdrs = config.get_list('cmdrs', default=[]) @@ -671,6 +688,8 @@ class Session(object): if services.get('commodities'): marketdata = self.query(URL_MARKET) if last_starport_name != marketdata['name'] or last_starport_id != int(marketdata['id']): + logger.warning(f"{last_starport_name!r} != {marketdata['name']!r}" + f" or {last_starport_id!r} != {int(marketdata['id'])!r}") raise ServerLagging() else: @@ -679,6 +698,8 @@ class Session(object): if services.get('outfitting') or services.get('shipyard'): shipdata = self.query(URL_SHIPYARD) if last_starport_name != shipdata['name'] or last_starport_id != int(shipdata['id']): + logger.warning(f"{last_starport_name!r} != {shipdata['name']!r} or " + f"{last_starport_id!r} != {int(shipdata['id'])!r}") raise ServerLagging() else: