def Music(cls, system, cmdr, timestamp, client): if cls.state == 2: debug("Hyperdiction Detected") cls.show() x, y, z = Systems.edsmGetSystem(system) dx, dy, dz = Systems.edsmGetSystem(cls.target_system) canonn.emitter.post( "https://europe-west1-canonn-api-236217.cloudfunctions.net/postHDDetected", { "cmdr": cmdr, "system": system, "timestamp": timestamp, "x": x, "y": y, "z": z, "destination": cls.target_system, "dx": dx, "dy": dy, "dz": dz, "client": client }) plug.show_error("Hyperdiction: Exit to main menu") else: debug("FSDJUMP resetting state back") cls.hide() cls.state == 0
def worker(): while True: item = this.queue.get() if not item: return # Closing else: (url, data, callback) = item retrying = 0 while retrying < 3: try: r = this.session.post(url, data=data, timeout=_TIMEOUT) r.raise_for_status() reply = r.json() (msgnum, msg) = reply['msgnum'], reply['msg'] if callback: callback(reply) elif msgnum // 100 != 1: # 1xx = OK, 2xx = fatal error plug.show_error(_('Error: EDSM {MSG}').format(MSG=msg)) break except: retrying += 1 else: if callback: callback(None) else: plug.show_error(_("Error: Can't connect to EDSM"))
def find_overlay_binary() -> Path: our_directory = Path(__file__).resolve().parent overlay_binary = our_directory / "overlay" if not overlay_binary.exists(): plug.show_error("edmcoverlay2 unable to find overlay binary") raise RuntimeError("edmcoverlay2 unable to find overlay binary") return overlay_binary
def edsm_notify_system(reply): if not reply: this.system['image'] = this._IMG_ERROR plug.show_error(_("Error: Can't connect to EDSM")) elif reply['msgnum'] // 100 not in (1,4): this.system['image'] = this._IMG_ERROR plug.show_error(_('Error: EDSM {MSG}').format(MSG=reply['msg'])) elif reply.get('systemCreated'): this.system['image'] = this._IMG_NEW else: this.system['image'] = this._IMG_KNOWN
def edsm_notify_system(reply): if not reply: this.system['image'] = this._IMG_ERROR plug.show_error(_("Error: Can't connect to EDSM")) elif reply['msgnum'] // 100 not in (1, 4): this.system['image'] = this._IMG_ERROR plug.show_error(_('Error: EDSM {MSG}').format(MSG=reply['msg'])) elif reply.get('systemCreated'): this.system['image'] = this._IMG_NEW else: this.system['image'] = this._IMG_KNOWN
def post_traffic(system, entry): debug("posting traffic {} ".format(system)) try: emitter.post( "https://europe-west1-canonn-api-236217.cloudfunctions.net/postTraffic", { "system": system, "timestamp": entry.get("timestamp") }) except: plug.show_error("Failed to post traffic") debug("Failed to post traffic for {}".format(system))
def openLocalDatabase(self): try: self.localDbConnection = sqlite3.connect( os.path.join(self.pluginDir, "cache.sqlite")) self.localDbCursor = self.localDbConnection.cursor() except Exception as e: if __debug__: print("Local cache database could not be opened") plug.show_error( "EDSM-RSE: Local cache database could not be opened") sys.stderr.write( "EDSM-RSE: Local cache database could not be opened\n")
def open_local_database(self): try: self.local_db_connection = sqlite3.connect(os.path.join( self.plugin_dir, "cache.sqlite"), timeout=10) self.local_db_cursor = self.local_db_connection.cursor() except Exception as e: error_message = "Local cache database could not be opened" logger.exception(error_message) plug.show_error( plug.show_error( f"{RseData.PLUGIN_NAME}-{RseData.VERSION}: {error_message}" ))
def update_status(event=None): reply = this.lastlookup # Message numbers: 1xx = OK, 2xx = fatal error, 3xx = error (but not generated in practice), 4xx = ignorable errors if not reply: this.system['image'] = this._IMG_ERROR plug.show_error(_("Error: Can't connect to EDSM")) elif reply['msgnum'] // 100 not in (1, 4): this.system['image'] = this._IMG_ERROR plug.show_error(_('Error: EDSM {MSG}').format(MSG=reply['msg'])) elif reply.get('systemCreated'): this.system['image'] = this._IMG_NEW else: this.system['image'] = this._IMG_KNOWN
def openDatabase(self): try: self.conn = psycopg2.connect( host="cyberlord.de", port=5432, dbname="edmc_rse_db", user="******", password="******", application_name="EDSM-RSE {}".format(VERSION), connect_timeout=10) self.c = self.conn.cursor() except Exception as e: plug.show_error("EDSM-RSE: Database could not be opened") sys.stderr.write("EDSM-RSE: Database could not be opened\n")
def edsm_notify_system(reply: Mapping[str, Any]) -> None: """Update the image next to the system link.""" if not reply: this.system_link['image'] = this._IMG_ERROR plug.show_error(_("Error: Can't connect to EDSM")) elif reply['msgnum'] // 100 not in (1, 4): this.system_link['image'] = this._IMG_ERROR plug.show_error(_('Error: EDSM {MSG}').format(MSG=reply['msg'])) elif reply.get('systemCreated'): this.system_link['image'] = this._IMG_NEW else: this.system_link['image'] = this._IMG_KNOWN
def openRemoteDatabase(self): try: self.remoteDbConnection = psycopg2.connect( host="cyberlord.de", port=5432, dbname="edmc_rse_db", user="******", password="******", application_name="EDSM-RSE {}".format(RseData.VERSION), connect_timeout=10) self.remoteDbCursor = self.remoteDbConnection.cursor() except Exception as e: if __debug__: print("Remote database could not be opened") plug.show_error("EDSM-RSE: Remote database could not be opened") sys.stderr.write("EDSM-RSE: Remote database could not be opened\n")
def send_data(url: str, data: Mapping[str, Any]) -> bool: """ Write a set of events to the inara API. :param url: the target URL to post to :param data: the data to POST :return: success state """ r = this.session.post(url, data=json.dumps(data, separators=(',', ':')), timeout=_TIMEOUT) r.raise_for_status() reply = r.json() status = reply['header']['eventStatus'] if status // 100 != 2: # 2xx == OK (maybe with warnings) # Log fatal errors logger.warning(f'Inara\t{status} {reply["header"].get("eventStatusText", "")}') logger.debug(f'JSON data:\n{json.dumps(data, indent=2, separators = (",", ": "))}') plug.show_error(_('Error: Inara {MSG}').format(MSG=reply['header'].get('eventStatusText', status))) else: # Log individual errors and warnings for data_event, reply_event in zip(data['events'], reply['events']): if reply_event['eventStatus'] != 200: logger.warning(f'Inara\t{status} {reply_event.get("eventStatusText", "")}') logger.debug(f'JSON data:\n{json.dumps(data_event)}') if reply_event['eventStatus'] // 100 != 2: plug.show_error(_('Error: Inara {MSG}').format( MSG=f'{data_event["eventName"]},' f'{reply_event.get("eventStatusText", reply_event["eventStatus"])}' )) if data_event['eventName'] in ( 'addCommanderTravelCarrierJump', 'addCommanderTravelDock', 'addCommanderTravelFSDJump', 'setCommanderTravelLocation' ): this.lastlocation = reply_event.get('eventData', {}) # calls update_location in main thread this.system_link.event_generate('<<InaraLocation>>', when="tail") elif data_event['eventName'] in ['addCommanderShip', 'setCommanderShip']: this.lastship = reply_event.get('eventData', {}) # calls update_ship in main thread this.system_link.event_generate('<<InaraShip>>', when="tail") return True # regardless of errors above, we DID manage to send it, therefore inform our caller as such
def shipyard_url(loadout, is_beta, data=None): # Ignore supplied loadout (except for validation) until Coriolis updates to 3.0. Use cAPI instead. if not data: try: data = companion.session.profile() except Exception as e: if __debug__: print_exc() plug.show_error(str(e)) return if not data.get('commander', {}).get('name'): plug.show_error(_("Who are you?!")) # Shouldn't happen elif ( not data.get('lastSystem', {}).get('name') or (data['commander'].get('docked') and not data.get('lastStarport', {}).get('name'))): # Only care if docked plug.show_error(_("Where are you?!")) # Shouldn't happen elif not data.get('ship', {}).get('name') or not data.get( 'ship', {}).get('modules'): plug.show_error(_("What are you flying?!")) # Shouldn't happen elif (loadout.get('ShipID') is not None and data['ship']['id'] != loadout['ShipID']) or ( loadout.get('Ship') and data['ship']['name'].lower() != loadout['Ship']): plug.show_error( _('Error: Frontier server is lagging') ) # Raised when Companion API server is returning old data, e.g. when the servers are too busy else: string = json.dumps(companion.ship(data), ensure_ascii=False, sort_keys=True, separators=(',', ':')).encode( 'utf-8') # most compact representation out = StringIO.StringIO() with gzip.GzipFile(fileobj=out, mode='w') as f: f.write(string) return (is_beta and 'https://beta.coriolis.edcd.io/import?data=' or 'https://coriolis.edcd.io/import?data=' ) + base64.urlsafe_b64encode(out.getvalue()).replace( '=', '%3D')
def initialize(self): # initialize local cache self.open_local_database() if self.is_local_database_accessible(): self.local_db_cursor.execute( """CREATE TABLE IF NOT EXISTS `CachedSystems` ( `id64` INTEGER, `expirationDate` REAL NOT NULL, `cacheType` INTEGER NOT NULL, PRIMARY KEY(`id64`));""") self.local_db_connection.commit() self.remove_expired_systems_from_caches(handle_db_connection=False) # read cached systems self.local_db_cursor.execute( "SELECT id64, cacheType FROM CachedSystems") for row in self.local_db_cursor.fetchall(): id64, cacheType = row self.get_cached_set(cacheType).add(id64) self.close_local_database() # initialize dictionaries if len(self.projects_dict) == 0: response = self._query_rse_api( "https://cyberlord.de/rse/projects.py") if not response: errorMessage = "Could not get information about projects." logger.error(errorMessage) plug.show_error("{plugin_name}-{version}: {msg}".format( plugin_name=RseData.PLUGIN_NAME, version=RseData.VERSION, msg=errorMessage)) else: for _row in response: rseProject = RseProject(_row["id"], _row["action_text"], _row["project_name"], _row["explanation"], _row["enabled"]) self.projects_dict[rseProject.project_id] = rseProject
def installer(self): # need to add some defensive code around this tag_name = self.latest.get("tag_name") debug("Installing {}".format(tag_name)) new_plugin_dir = os.path.join(os.path.dirname(Release.plugin_dir), "EDMC-Canonn-{}".format(tag_name)) debug("Checking for pre-existence") if os.path.isdir(new_plugin_dir): error("Download already exists: {}".format(new_plugin_dir)) plug.show_error("Canonn upgrade failed") return False try: debug("Downloading new version") download = requests.get( "https://github.com/canonn-science/EDMC-Canonn/archive/{}.zip". format(tag_name), stream=True) try: z = zipfile.ZipFile(BytesIO(download.content)) z.extractall(os.path.dirname(Release.plugin_dir)) except: z = zipfile.ZipFile(StringIO.StringIO(download.content)) z.extractall(os.path.dirname(Release.plugin_dir)) except: error("Download failed: {}".format(new_plugin_dir)) plug.show_error("Canonn upgrade failed") return False # If we got this far then we have a new plugin so any failures and we will need to delete it debug("disable the current plugin") try: os.rename(Release.plugin_dir, "{}.disabled".format(Release.plugin_dir)) debug("Renamed {} to {}".format( Release.plugin_dir, "{}.disabled".format(Release.plugin_dir))) except: error("Upgrade failed reverting: {}".format(new_plugin_dir)) plug.show_error("Canonn upgrade failed") shutil.rmtree(new_plugin_dir) return False if self.rmbackup.get() == 1: config.set('Canonn:RemoveBackup', "{}.disabled".format(Release.plugin_dir)) debug("Upgrade complete") Release.plugin_dir = new_plugin_dir self.installed = True return True
def worker(): while True: item = this.queue.get() if not item: return # Closing else: (url, data, callback) = item retrying = 0 while retrying < 3: try: r = this.session.post(url, data=json.dumps(data, separators=(',', ':')), timeout=_TIMEOUT) r.raise_for_status() reply = r.json() status = reply['header']['eventStatus'] if callback: callback(reply) elif status // 100 != 2: # 2xx == OK (maybe with warnings) # Log fatal errors print 'Inara\t%s %s' % (reply['header']['eventStatus'], reply['header'].get( 'eventStatusText', '')) print json.dumps(data, indent=2, separators=(',', ': ')) plug.show_error( _('Error: Inara {MSG}').format(MSG=reply['header'].get( 'eventStatusText', status))) else: # Log individual errors and warnings for data_event, reply_event in zip(data['events'], reply['events']): if reply_event['eventStatus'] != 200: print 'Inara\t%s %s\t%s' % ( reply_event['eventStatus'], reply_event.get('eventStatusText', ''), json.dumps(data_event, separators=(',', ': '))) if reply_event['eventStatus'] // 100 != 2: plug.show_error( _('Error: Inara {MSG}').format( MSG='%s, %s' % (data_event['eventName'], reply_event.get( 'eventStatusText', reply_event['eventStatus'])))) break except: if __debug__: print_exc() retrying += 1 else: if callback: callback(None) else: plug.show_error(_("Error: Can't connect to Inara"))
def worker(): while True: item = this.queue.get() if not item: return # Closing else: (url, data, callback) = item retrying = 0 while retrying < 3: try: r = this.session.post(url, data=json.dumps(data, separators = (',', ':')), timeout=_TIMEOUT) r.raise_for_status() reply = r.json() status = reply['header']['eventStatus'] if callback: callback(reply) elif status // 100 != 2: # 2xx == OK (maybe with warnings) # Log fatal errors print 'Inara\t%s %s' % (reply['header']['eventStatus'], reply['header'].get('eventStatusText', '')) print json.dumps(data, indent=2, separators = (',', ': ')) plug.show_error(_('Error: Inara {MSG}').format(MSG = reply['header'].get('eventStatusText', status))) else: # Log individual errors and warnings for data_event, reply_event in zip(data['events'], reply['events']): if reply_event['eventStatus'] != 200: print 'Inara\t%s %s\t%s' % (reply_event['eventStatus'], reply_event.get('eventStatusText', ''), json.dumps(data_event)) if reply_event['eventStatus'] // 100 != 2: plug.show_error(_('Error: Inara {MSG}').format(MSG = '%s, %s' % (data_event['eventName'], reply_event.get('eventStatusText', reply_event['eventStatus'])))) if data_event['eventName'] in ['addCommanderTravelDock', 'addCommanderTravelFSDJump', 'setCommanderTravelLocation']: eventData = reply_event.get('eventData', {}) this.system = eventData.get('starsystemInaraURL') if config.get('system_provider') == 'Inara': this.system_link['url'] = this.system # Override standard URL function this.station = eventData.get('stationInaraURL') if config.get('station_provider') == 'Inara': this.station_link['url'] = this.station or this.system # Override standard URL function break except: if __debug__: print_exc() retrying += 1 else: if callback: callback(None) else: plug.show_error(_("Error: Can't connect to Inara"))
def null_callback(reply): if not reply: plug.show_error(_("Error: Can't connect to EDSM"))
def worker(): pending = [] # Unsent events closing = False while True: item = this.queue.get() if item: (cmdr, entry) = item else: closing = True # Try to send any unsent events before we close retrying = 0 while retrying < 3: try: if item and entry['event'] not in this.discardedEvents: pending.append(entry) # Get list of events to discard if not this.discardedEvents: r = this.session.get( 'https://www.edsm.net/api-journal-v1/discard', timeout=_TIMEOUT) r.raise_for_status() this.discardedEvents = set(r.json()) this.discardedEvents.discard( 'Docked' ) # should_send() assumes that we send 'Docked' events assert this.discardedEvents # wouldn't expect this to be empty pending = [ x for x in pending if x['event'] not in this.discardedEvents ] # Filter out unwanted events if should_send(pending): (username, apikey) = credentials(cmdr) data = { 'commanderName': username.encode('utf-8'), 'apiKey': apikey, 'fromSoftware': applongname, 'fromSoftwareVersion': appversion, 'message': json.dumps(pending, ensure_ascii=False).encode('utf-8'), } r = this.session.post( 'https://www.edsm.net/api-journal-v1', data=data, timeout=_TIMEOUT) r.raise_for_status() reply = r.json() (msgnum, msg) = reply['msgnum'], reply['msg'] # 1xx = OK, 2xx = fatal error, 3&4xx not generated at top-level, 5xx = error but events saved for later processing if msgnum // 100 == 2: print('EDSM\t%s %s\t%s' % (msgnum, msg, json.dumps(pending, separators=(',', ': ')))) plug.show_error(_('Error: EDSM {MSG}').format(MSG=msg)) else: for e, r in zip(pending, reply['events']): if not closing and e['event'] in [ 'StartUp', 'Location', 'FSDJump' ]: # Update main window's system status this.lastlookup = r this.system.event_generate( '<<EDSMStatus>>', when="tail" ) # calls update_status in main thread elif r['msgnum'] // 100 != 1: print('EDSM\t%s %s\t%s' % (r['msgnum'], r['msg'], json.dumps(e, separators=(',', ': ')))) pending = [] break except: if __debug__: print_exc() retrying += 1 else: plug.show_error(_("Error: Can't connect to EDSM")) if closing: return
def worker(): pending = [] # Unsent events closing = False while True: item = this.queue.get() if item: (cmdr, entry) = item else: closing = True # Try to send any unsent events before we close retrying = 0 while retrying < 3: try: if item and entry['event'] not in this.discardedEvents: pending.append(entry) # Get list of events to discard if not this.discardedEvents: r = this.session.get('https://www.edsm.net/api-journal-v1/discard', timeout=_TIMEOUT) r.raise_for_status() this.discardedEvents = set(r.json()) this.discardedEvents.discard('Docked') # should_send() assumes that we send 'Docked' events assert this.discardedEvents # wouldn't expect this to be empty pending = [x for x in pending if x['event'] not in this.discardedEvents] # Filter out unwanted events if should_send(pending): (username, apikey) = credentials(cmdr) data = { 'commanderName': username.encode('utf-8'), 'apiKey': apikey, 'fromSoftware': applongname, 'fromSoftwareVersion': appversion, 'message': json.dumps(pending, ensure_ascii=False).encode('utf-8'), } r = this.session.post('https://www.edsm.net/api-journal-v1', data=data, timeout=_TIMEOUT) r.raise_for_status() reply = r.json() (msgnum, msg) = reply['msgnum'], reply['msg'] # 1xx = OK, 2xx = fatal error, 3&4xx not generated at top-level, 5xx = error but events saved for later processing if msgnum // 100 == 2: print('EDSM\t%s %s\t%s' % (msgnum, msg, json.dumps(pending, separators = (',', ': ')))) plug.show_error(_('Error: EDSM {MSG}').format(MSG=msg)) else: for e, r in zip(pending, reply['events']): if not closing and e['event'] in ['StartUp', 'Location', 'FSDJump']: # Update main window's system status this.lastlookup = r this.system.event_generate('<<EDSMStatus>>', when="tail") # calls update_status in main thread elif r['msgnum'] // 100 != 1: print('EDSM\t%s %s\t%s' % (r['msgnum'], r['msg'], json.dumps(e, separators = (',', ': ')))) pending = [] break except: if __debug__: print_exc() retrying += 1 else: plug.show_error(_("Error: Can't connect to EDSM")) if closing: return
def worker(): while True: item = this.queue.get() if not item: return # Closing else: (url, data, callback) = item retrying = 0 while retrying < 3: try: r = this.session.post(url, headers=API_HEADERS, data=json.dumps(data, separators=(',', ':')), timeout=_TIMEOUT) r.raise_for_status() reply = r.json() status = reply['header']['eventStatus'] if callback: callback(reply) elif status // 100 != 2: # 2xx == OK (maybe with warnings) # Log fatal errors print( ('SFR\t%s %s' % (reply['header']['eventStatus'], reply['header'].get( 'eventStatusText', '')))) print((json.dumps(data, indent=2, separators=(',', ': ')))) plug.show_error( _('Error: SFR {MSG}').format(MSG=reply['header'].get( 'eventStatusText', status))) this.status["text"] = "ERROR" else: # Log individual errors and warnings for data_event, reply_event in zip(data['events'], reply['events']): if reply_event['eventStatus'] != 200: print(('SFR\t%s %s\t%s' % (reply_event['eventStatus'], reply_event.get('eventStatusText', ''), json.dumps(data_event)))) if reply_event['eventStatus'] // 100 != 2: plug.show_error( _('Error: SFR {MSG}').format( MSG='%s, %s' % (data_event['eventName'], reply_event.get( 'eventStatusText', reply_event['eventStatus'])))) if data_event['eventName'] in [ 'addCommanderTravelDock', 'addCommanderTravelFSDJump', 'setCommanderTravelLocation' ]: this.lastlocation = reply_event.get( 'eventData', {}) this.system_link.event_generate( '<<SFRLocation>>', when="tail" ) # calls update_location in main thread elif data_event['eventName'] in [ 'addCommanderShip', 'setCommanderShip' ]: this.lastship = reply_event.get('eventData', {}) this.system_link.event_generate( '<<SFRShip>>', when="tail" ) # calls update_ship in main thread break except: print_exc() retrying += 1 else: if callback: callback(None) else: plug.show_error(_("Error: Can't connect to SFR")) this.status["text"] = "ERROR"
def worker(): while True: item = this.queue.get() if not item: return # Closing else: (url, data, callback) = item retrying = 0 while retrying < 3: try: r = this.session.post(url, data=json.dumps(data, separators=(',', ':')), timeout=_TIMEOUT) r.raise_for_status() reply = r.json() status = reply['header']['eventStatus'] if callback: callback(reply) elif status // 100 != 2: # 2xx == OK (maybe with warnings) # Log fatal errors print 'Inara\t%s %s' % (reply['header']['eventStatus'], reply['header'].get( 'eventStatusText', '')) print json.dumps(data, indent=2, separators=(',', ': ')) plug.show_error( _('Error: Inara {MSG}').format(MSG=reply['header'].get( 'eventStatusText', status))) else: # Log individual errors and warnings for data_event, reply_event in zip(data['events'], reply['events']): if reply_event['eventStatus'] != 200: print 'Inara\t%s %s\t%s' % ( reply_event['eventStatus'], reply_event.get('eventStatusText', ''), json.dumps(data_event)) if reply_event['eventStatus'] // 100 != 2: plug.show_error( _('Error: Inara {MSG}').format( MSG='%s, %s' % (data_event['eventName'], reply_event.get( 'eventStatusText', reply_event['eventStatus'])))) if data_event['eventName'] in [ 'addCommanderTravelDock', 'addCommanderTravelFSDJump', 'setCommanderTravelLocation' ]: eventData = reply_event.get('eventData', {}) this.system = eventData.get('starsystemInaraURL') if config.get('system_provider') == 'Inara': this.system_link[ 'url'] = this.system # Override standard URL function this.station = eventData.get('stationInaraURL') if config.get('station_provider') == 'Inara': this.station_link[ 'url'] = this.station or this.system # Override standard URL function break except: if __debug__: print_exc() retrying += 1 else: if callback: callback(None) else: plug.show_error(_("Error: Can't connect to Inara"))
def worker() -> None: """ Upload worker. Processes `this.queue` until the queued item is None. """ pending = [] # Unsent events closing = False while True: item: Optional[Tuple[str, Mapping[str, Any]]] = this.queue.get() if item: (cmdr, entry) = item else: closing = True # Try to send any unsent events before we close retrying = 0 while retrying < 3: try: if TYPE_CHECKING: # Tell the type checker that these two are bound. # TODO: While this works because of the item check below, these names are still technically unbound # TODO: in some cases, therefore this should be refactored. cmdr: str = "" entry: Mapping[str, Any] = {} if item and entry[ 'event'] not in this.discardedEvents: # TODO: Technically entry can be unbound here. pending.append(entry) # Get list of events to discard if not this.discardedEvents: r = this.session.get( 'https://www.edsm.net/api-journal-v1/discard', timeout=_TIMEOUT) r.raise_for_status() this.discardedEvents = set(r.json()) this.discardedEvents.discard( 'Docked' ) # should_send() assumes that we send 'Docked' events if not this.discardedEvents: logger.error( 'Unexpected empty discarded events list from EDSM. Bailing out of send: ' f'{type(this.discardedEvents)} -- {this.discardedEvents}' ) continue # Filter out unwanted events pending = list( filter( lambda x: x['event'] not in this.discardedEvents, pending)) if should_send(pending): if any(p for p in pending if p['event'] in ('CarrierJump', 'FSDJump', 'Location', 'Docked')): logger.trace( "pending has at least one of " "('CarrierJump', 'FSDJump', 'Location', 'Docked')" " and it passed should_send()") for p in pending: if p['event'] in ('Location'): logger.trace( '"Location" event in pending passed should_send(), ' f'timestamp: {p["timestamp"]}') creds = credentials(cmdr) # TODO: possibly unbound if creds is None: raise ValueError("Unexpected lack of credentials") username, apikey = creds data = { 'commanderName': username.encode('utf-8'), 'apiKey': apikey, 'fromSoftware': applongname, 'fromSoftwareVersion': appversion, 'message': json.dumps(pending, ensure_ascii=False).encode('utf-8'), } if any(p for p in pending if p['event'] in ('CarrierJump', 'FSDJump', 'Location', 'Docked')): data_elided = data.copy() data_elided['apiKey'] = '<elided>' logger.trace( "pending has at least one of " "('CarrierJump', 'FSDJump', 'Location', 'Docked')" " Attempting API call with the following events:") for p in pending: logger.trace(f"Event: {p!r}") if p['event'] in ('Location'): logger.trace( 'Attempting API call for "Location" event with timestamp: ' f'{p["timestamp"]}') logger.trace( f'Overall POST data (elided) is:\n{data_elided}') r = this.session.post( 'https://www.edsm.net/api-journal-v1', data=data, timeout=_TIMEOUT) logger.trace(f'API response content: {r.content}') r.raise_for_status() reply = r.json() msg_num = reply['msgnum'] msg = reply['msg'] # 1xx = OK # 2xx = fatal error # 3&4xx not generated at top-level # 5xx = error but events saved for later processing if msg_num // 100 == 2: logger.warning( f'EDSM\t{msg_num} {msg}\t{json.dumps(pending, separators=(",", ": "))}' ) plug.show_error(_('Error: EDSM {MSG}').format(MSG=msg)) else: if msg_num // 100 == 1: logger.trace('Overall OK') elif msg_num // 100 == 5: logger.trace( 'Event(s) not currently processed, but saved for later' ) else: logger.warning( f'EDSM API call status not 1XX, 2XX or 5XX: {msg.num}' ) for e, r in zip(pending, reply['events']): if not closing and e['event'] in ('StartUp', 'Location', 'FSDJump', 'CarrierJump'): # Update main window's system status this.lastlookup = r # calls update_status in main thread this.system_link.event_generate( '<<EDSMStatus>>', when="tail") if r['msgnum'] // 100 != 1: logger.warning( f'EDSM event with not-1xx status:\n{r["msgnum"]}\n{r["msg"]}\n' f'{json.dumps(e, separators = (",", ": "))}' ) pending = [] break # No exception, so assume success except Exception as e: logger.debug( f'Attempt to send API events: retrying == {retrying}', exc_info=e) retrying += 1 else: plug.show_error(_("Error: Can't connect to EDSM")) if closing: return