diff --git a/EDMarketConnector.py b/EDMarketConnector.py index be0167b5..7d6fdf90 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -499,73 +499,48 @@ class AppWindow: if system_changed or station_changed: self.status['text'] = '' + # Send interesting events to EDSM if config.getint('output') & config.OUT_SYS_EDSM and not monitor.is_beta: - # Send credits to EDSM on startup - if monitor.credits and (not entry or entry['event'] == 'LoadGame'): - try: - self.status['text'] = _('Sending balance/loan to EDSM...') - self.w.update_idletasks() + self.status['text'] = _('Sending data to EDSM...') + self.w.update_idletasks() + try: + # Send credits to EDSM on startup + if not entry or entry['event'] == 'LoadGame': self.edsm.setcredits(monitor.credits) - self.status['text'] = '' - except Exception as e: - if __debug__: print_exc() - self.status['text'] = unicode(e) - if not config.getint('hotkey_mute'): - hotkeymgr.play_bad() - - # Send shipid to EDSM on startup or change - if monitor.shipid and (not entry or entry['event'] in ['LoadGame', 'ShipyardSwap']): - try: - self.status['text'] = _('Sending shipId to EDSM...') - self.w.update_idletasks() - self.edsm.setshipid(monitor.shipid) - self.status['text'] = '' - except Exception as e: - if __debug__: print_exc() - self.status['text'] = unicode(e) - if not config.getint('hotkey_mute'): - hotkeymgr.play_bad() - - # Send rank info to EDSM on startup or change - if monitor.ranks and (not entry or entry['event'] in ['Progress', 'Promotion']): - try: - self.status['text'] = _('Sending ranks to EDSM...') - self.w.update_idletasks() + + # Send rank info to EDSM on startup or change + if not entry or entry['event'] in ['Progress', 'Promotion']: self.edsm.setranks(monitor.ranks) - self.status['text'] = '' - except Exception as e: - if __debug__: print_exc() - self.status['text'] = unicode(e) - if not config.getint('hotkey_mute'): - hotkeymgr.play_bad() + + # Send ship info to EDSM on startup or change + if not entry or entry['event'] in ['LoadGame', 'ShipyardNew', 'ShipyardSwap']: + self.edsm.setshipid(monitor.shipid) + + # Write EDSM log on change + if monitor.mode and entry and entry['event'] in ['Location', 'FSDJump']: + self.system['image'] = '' + self.edsm.writelog(timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ')), monitor.system, monitor.coordinates, monitor.shipid) + + except Exception as e: + if __debug__: print_exc() + self.status['text'] = unicode(e) + if not config.getint('hotkey_mute'): + hotkeymgr.play_bad() + else: + self.status['text'] = '' + self.edsmpoll() + + elif system_changed: + self.edsm.link(monitor.system) + self.edsmpoll() if not entry or not monitor.mode: - return # Fake event or in CQC + return # Startup or in CQC + # Plugins plug.notify_journal_entry(monitor.cmdr, monitor.system, monitor.station, entry) - - if system_changed: - self.system['image'] = '' - timestamp = timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ')) - - # Backwards compatibility - plug.notify_system_changed(timestamp, monitor.system, monitor.coordinates) - - # Update EDSM if we have coordinates - i.e. Location or FSDJump events - if config.getint('output') & config.OUT_SYS_EDSM and monitor.coordinates: - try: - self.status['text'] = _('Sending flight log to EDSM...') - self.w.update_idletasks() - self.edsm.writelog(timestamp, monitor.system, monitor.coordinates) - self.status['text'] = '' - except Exception as e: - if __debug__: print_exc() - self.status['text'] = unicode(e) - if not config.getint('hotkey_mute'): - hotkeymgr.play_bad() - else: - self.edsm.link(monitor.system) - self.edsmpoll() + if system_changed: # Backwards compatibility + plug.notify_system_changed(timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ')), monitor.system, monitor.coordinates) # Auto-Update after docking if station_changed and not monitor.is_beta and not config.getint('output') & config.OUT_MKT_MANUAL and config.getint('output') & config.OUT_STATION_ANY: @@ -574,8 +549,8 @@ class AppWindow: # Send interesting events to EDDN try: if (config.getint('output') & config.OUT_SYS_EDDN and monitor.cmdr and - (entry['event'] == 'FSDJump' and system_changed or - entry['event'] == 'Docked' and station_changed or + (entry['event'] == 'FSDJump' or + entry['event'] == 'Docked' or entry['event'] == 'Scan' and monitor.system and monitor.coordinates)): # strip out properties disallowed by the schema for thing in ['CockpitBreach', 'BoostUsed', 'FuelLevel', 'FuelUsed', 'JumpDist']: diff --git a/edsm.py b/edsm.py index 311cc305..01f2e4e8 100644 --- a/edsm.py +++ b/edsm.py @@ -36,6 +36,29 @@ class EDSM: EDSM._IMG_NEW = tk.PhotoImage(data = 'R0lGODlhEAAQAMZwANKVHtWcIteiHuiqLPCuHOS1MN22ZeW7ROG6Zuu9MOy+K/i8Kf/DAuvCVf/FAP3BNf/JCf/KAPHHSv7ESObHdv/MBv/GRv/LGP/QBPXOPvjPQfjQSvbRSP/UGPLSae7Sfv/YNvLXgPbZhP7dU//iI//mAP/jH//kFv7fU//fV//ebv/iTf/iUv/kTf/iZ/vgiP/hc/vgjv/jbfriiPriiv7ka//if//jd//sJP/oT//tHv/mZv/sLf/rRP/oYv/rUv/paP/mhv/sS//oc//lkf/mif/sUf/uPv/qcv/uTv/uUv/vUP/qhP/xP//pm//ua//sf//ubf/wXv/thv/tif/slv/tjf/smf/yYP/ulf/2R//2Sv/xkP/2av/0gP/ylf/2df/0i//0j//0lP/5cP/7a//1p//5gf/7ev/3o//2sf/5mP/6kv/2vP/3y//+jP///////////////////////////////////////////////////////////////yH5BAEKAH8ALAAAAAAQABAAAAePgH+Cg4SFhoJKPIeHYT+LhVppUTiPg2hrUkKPXWdlb2xHJk9jXoNJQDk9TVtkYCUkOy4wNjdGfy1UXGJYOksnPiwgFwwYg0NubWpmX1ArHREOFYUyWVNIVkxXQSoQhyMoNVUpRU5EixkcMzQaGy8xhwsKHiEfBQkSIg+GBAcUCIIBBDSYYGiAAUMALFR6FAgAOw==') EDSM._IMG_ERROR = tk.PhotoImage(data = 'R0lGODlhEAAQAKEBAAAAAP///////////yH5BAEKAAIALAAAAAAQABAAAAIwlBWpeR0AIwwNPRmZuVNJinyWuClhBlZjpm5fqnIAHJPtOd3Hou9mL6NVgj2LplEAADs=') # BBC Mode 5 '?' + # Call an EDSM endpoint with args (which should be quoted) + def call(self, endpoint, args): + try: + url = 'https://www.edsm.net/%s?commanderName=%s&apiKey=%s&fromSoftware=%s&fromSoftwareVersion=%s' % ( + endpoint, + urllib2.quote(config.get('edsm_cmdrname').encode('utf-8')), + urllib2.quote(config.get('edsm_apikey')), + urllib2.quote(applongname), + urllib2.quote(appversion), + ) + args + r = self.opener.open(url, timeout=EDSM._TIMEOUT) + reply = json.loads(r.read()) + (msgnum, msg) = reply['msgnum'], reply['msg'] + except: + if __debug__: print_exc() + raise Exception(_("Error: Can't connect to EDSM")) + + # Message numbers: 1xx = OK, 2xx = fatal error, 3xx = error (but not generated in practice), 4xx = ignorable errors + if msgnum // 100 not in (1,4): + raise Exception(_('Error: EDSM {MSG}').format(MSG=msg)) + else: + return reply + # Just set link without doing a lookup def link(self, system_name): self.cancel_lookup() @@ -53,8 +76,7 @@ class EDSM: self.result = { 'img': EDSM._IMG_KNOWN, 'url': 'https://www.edsm.net/show-system?systemName=%s' % urllib2.quote(system_name), 'done': True, 'uncharted': False } else: self.result = { 'img': EDSM._IMG_ERROR, 'url': 'https://www.edsm.net/show-system?systemName=%s' % urllib2.quote(system_name), 'done': True, 'uncharted': False } - r = self.opener.open('https://www.edsm.net/api-v1/system?sysname=%s&coords=1&fromSoftware=%s&fromSoftwareVersion=%s' % (urllib2.quote(system_name), urllib2.quote(applongname), urllib2.quote(appversion)), timeout=EDSM._TIMEOUT) - data = json.loads(r.read()) + data = self.call('api-v1/system', '&sysname=%s&coords=1' % urllib2.quote(system_name)) if data == -1 or not data: # System not present - but don't create it on the assumption that the caller will @@ -87,15 +109,14 @@ class EDSM: def worker(self, system_name, result): try: - r = self.opener.open('https://www.edsm.net/api-v1/system?sysname=%s&coords=1&fromSoftware=%s&fromSoftwareVersion=%s' % (urllib2.quote(system_name), urllib2.quote(applongname), urllib2.quote(appversion)), timeout=EDSM._TIMEOUT) - data = json.loads(r.read()) + data = self.call('api-v1/system', '&sysname=%s&coords=1' % urllib2.quote(system_name)) if data == -1 or not data: # System not present - create it result['img'] = EDSM._IMG_NEW result['uncharted'] = True result['done'] = True # give feedback immediately - requests.get('https://www.edsm.net/api-v1/url?sysname=%s&fromSoftware=%s&fromSoftwareVersion=%s' % (urllib2.quote(system_name), urllib2.quote(applongname), urllib2.quote(appversion)), timeout=EDSM._TIMEOUT) # creates system + self.call('api-v1/url', '&sysname=%s' % urllib2.quote(system_name)) # creates system elif data.get('coords'): result['img'] = EDSM._IMG_KNOWN result['done'] = True @@ -110,109 +131,43 @@ class EDSM: # Send flight log and also do lookup - def writelog(self, timestamp, system_name, coordinates=None): + def writelog(self, timestamp, system_name, coordinates, shipid = None): if system_name in self.FAKE: self.result = { 'img': '', 'url': None, 'done': True, 'uncharted': False } return self.result = { 'img': EDSM._IMG_ERROR, 'url': 'https://www.edsm.net/show-system?systemName=%s' % urllib2.quote(system_name), 'done': True, 'uncharted': False } - try: - url = 'https://www.edsm.net/api-logs-v1/set-log?commanderName=%s&apiKey=%s&systemName=%s&dateVisited=%s&fromSoftware=%s&fromSoftwareVersion=%s' % ( - urllib2.quote(config.get('edsm_cmdrname').encode('utf-8')), - urllib2.quote(config.get('edsm_apikey')), - urllib2.quote(system_name), - urllib2.quote(time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(timestamp))), - urllib2.quote(applongname), - urllib2.quote(appversion) - ) - if coordinates: - url += '&x=%.3f&y=%.3f&z=%.3f' % coordinates - r = self.opener.open(url, timeout=EDSM._TIMEOUT) - reply = json.loads(r.read()) - (msgnum, msg) = reply['msgnum'], reply['msg'] - except: - if __debug__: print_exc() - raise Exception(_("Error: Can't connect to EDSM")) - # Message numbers: 1xx = OK, 2xx = fatal error, 3xx = error (but not generated in practice), 4xx = ignorable errors - if msgnum // 100 not in (1,4): - raise Exception(_('Error: EDSM {MSG}').format(MSG=msg)) - elif reply.get('systemCreated'): + args = '&systemName=%s&dateVisited=%s' % ( + urllib2.quote(system_name), + urllib2.quote(time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(timestamp))), + ) + if coordinates: + args += '&x=%.3f&y=%.3f&z=%.3f' % coordinates + if shipid: + args += '&shipId=%d' % shipid + reply = self.call('api-logs-v1/set-log', args) + + if reply.get('systemCreated'): self.result['img'] = EDSM._IMG_NEW else: self.result['img'] = EDSM._IMG_KNOWN self.syscache.add(system_name) def setranks(self, ranks): - if not ranks: - return - - try: - url = 'https://www.edsm.net/api-commander-v1/set-ranks?commanderName=%s&apiKey=%s&fromSoftware=%s&fromSoftwareVersion=%s' % ( - urllib2.quote(config.get('edsm_cmdrname').encode('utf-8')), - urllib2.quote(config.get('edsm_apikey')), - urllib2.quote(applongname), - urllib2.quote(appversion) - ) + args = '' + if ranks: for k,v in ranks.iteritems(): if v is not None: - url += '&%s=%s' % (k, urllib2.quote('%d;%d' % v)) - r = self.opener.open(url, timeout=EDSM._TIMEOUT) - reply = json.loads(r.read()) - (msgnum, msg) = reply['msgnum'], reply['msg'] - except: - if __debug__: print_exc() - raise Exception(_("Error: Can't connect to EDSM")) - - if msgnum // 100 not in (1,4): - raise Exception(_('Error: EDSM {MSG}').format(MSG=msg)) + args += '&%s=%s' % (k, urllib2.quote('%d;%d' % v)) + if args: + self.call('api-commander-v1/set-ranks', args) def setcredits(self, credits): - if not credits: - return - - try: - url = 'https://www.edsm.net/api-commander-v1/set-credits?commanderName=%s&apiKey=%s&fromSoftware=%s&fromSoftwareVersion=%s' % ( - urllib2.quote(config.get('edsm_cmdrname').encode('utf-8')), - urllib2.quote(config.get('edsm_apikey')), - urllib2.quote(applongname), - urllib2.quote(appversion) - ) - - url += '&%s=%s' % ('balance', urllib2.quote('%d;%d' % credits['balance'])) - url += '&%s=%s' % ('loan', urllib2.quote('%d;%d' % credits['loan'])) - - r = self.opener.open(url, timeout=EDSM._TIMEOUT) - reply = json.loads(r.read()) - (msgnum, msg) = reply['msgnum'], reply['msg'] - except: - if __debug__: print_exc() - raise Exception(_("Error: Can't connect to EDSM")) - - if msgnum // 100 not in (1,4): - raise Exception(_('Error: EDSM {MSG}').format(MSG=msg)) + if credits: + self.call('api-commander-v1/set-credits', '&balance=%d&loan=%d' % credits) def setshipid(self, shipid): - if not shipid: - return - - try: - url = 'https://www.edsm.net/api-commander-v1/set-ship-id?commanderName=%s&apiKey=%s&fromSoftware=%s&fromSoftwareVersion=%s' % ( - urllib2.quote(config.get('edsm_cmdrname').encode('utf-8')), - urllib2.quote(config.get('edsm_apikey')), - urllib2.quote(applongname), - urllib2.quote(appversion) - ) - - url += '&%s=%s' % ('shipId', urllib2.quote('%d;%d' % shipid)) - - r = self.opener.open(url, timeout=EDSM._TIMEOUT) - reply = json.loads(r.read()) - (msgnum, msg) = reply['msgnum'], reply['msg'] - except: - if __debug__: print_exc() - raise Exception(_("Error: Can't connect to EDSM")) - - if msgnum // 100 not in (1,4): - raise Exception(_('Error: EDSM {MSG}').format(MSG=msg)) + if shipid is not None: + self.call('api-commander-v1/set-ship-id', '&shipId=%d' % shipid) diff --git a/monitor.py b/monitor.py index 1be69a13..e4bb925c 100644 --- a/monitor.py +++ b/monitor.py @@ -217,16 +217,20 @@ class EDLogs(FileSystemEventHandler): if entry['event'] == 'Fileheader': self.version = entry['gameversion'] self.is_beta = 'beta' in entry['gameversion'].lower() - self.ranks = None elif entry['event'] == 'LoadGame': self.cmdr = entry['Commander'] - self.shipid = entry['ShipID'] self.mode = entry.get('GameMode') # 'Open', 'Solo', 'Group', or None for CQC + self.shipid = entry.get('ShipID') # None in CQC + self.system = None + self.station = None + self.coordinates = None self.ranks = { "Combat": None, "Trade": None, "Explore": None, "Empire": None, "Federation": None, "CQC": None } - self.credits = { "balance": entry['Credits'], "loan": entry['Loan'] } + self.credits = ( entry['Credits'], entry['Loan'] ) elif entry['event'] == 'NewCommander': self.cmdr = entry['Name'] - elif entry['event'] in ['ShipyardSwap']: + elif entry['event'] == 'ShipyardNew': + self.shipid = entry['NewShipID'] + elif entry['event'] == 'ShipyardSwap': self.shipid = entry['ShipID'] elif entry['event'] in ['Undocked']: self.station = None