1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-13 15:57:14 +03:00

Make system and station info websites configurable

This commit is contained in:
Jonathan Harris 2018-04-03 01:03:07 +01:00
parent 014a04de16
commit 0eaa61bdd9
15 changed files with 184 additions and 156 deletions

11
EDMC.py
View File

@ -100,7 +100,6 @@ try:
sys.exit(EXIT_SYS_ERR) sys.exit(EXIT_SYS_ERR)
# Get data from Companion API # Get data from Companion API
session = companion.Session()
if args.p: if args.p:
cmdrs = config.get('cmdrs') or [] cmdrs = config.get('cmdrs') or []
if args.p in cmdrs: if args.p in cmdrs:
@ -112,17 +111,17 @@ try:
else: else:
raise companion.CredentialsError raise companion.CredentialsError
username = config.get('fdev_usernames')[idx] username = config.get('fdev_usernames')[idx]
session.login(username, config.get_password(username), monitor.is_beta) companion.session.login(username, config.get_password(username), monitor.is_beta)
elif config.get('cmdrs'): elif config.get('cmdrs'):
cmdrs = config.get('cmdrs') or [] cmdrs = config.get('cmdrs') or []
if monitor.cmdr not in cmdrs: if monitor.cmdr not in cmdrs:
raise companion.CredentialsError raise companion.CredentialsError
username = config.get('fdev_usernames')[cmdrs.index(monitor.cmdr)] username = config.get('fdev_usernames')[cmdrs.index(monitor.cmdr)]
session.login(username, config.get_password(username), monitor.is_beta) companion.session.login(username, config.get_password(username), monitor.is_beta)
else: # <= 2.25 not yet migrated else: # <= 2.25 not yet migrated
session.login(config.get('username'), config.get('password'), monitor.is_beta) companion.session.login(config.get('username'), config.get('password'), monitor.is_beta)
querytime = int(time()) querytime = int(time())
data = session.station() data = companion.session.station()
config.set('querytime', querytime) config.set('querytime', querytime)
# Validation # Validation
@ -204,7 +203,7 @@ try:
if (args.s or args.n) and not args.j and not data['lastStarport'].get('ships') and data['lastStarport']['services'].get('shipyard'): if (args.s or args.n) and not args.j and not data['lastStarport'].get('ships') and data['lastStarport']['services'].get('shipyard'):
# Retry for shipyard # Retry for shipyard
sleep(SERVER_RETRY) sleep(SERVER_RETRY)
data2 = session.station() data2 = companion.session.station()
if (data2['commander'].get('docked') and # might have undocked while we were waiting for retry in which case station data is unreliable if (data2['commander'].get('docked') and # might have undocked while we were waiting for retry in which case station data is unreliable
data2.get('lastSystem', {}).get('name') == monitor.system and data2.get('lastSystem', {}).get('name') == monitor.system and
data2.get('lastStarport', {}).get('name') == monitor.station): data2.get('lastStarport', {}).get('name') == monitor.station):

View File

@ -49,9 +49,6 @@ import commodity
from commodity import COMMODITY_CSV from commodity import COMMODITY_CSV
import td import td
import eddn import eddn
import coriolis
import edshipyard
import loadout
import stats import stats
import prefs import prefs
import plug import plug
@ -79,7 +76,6 @@ class AppWindow:
def __init__(self, master): def __init__(self, master):
self.holdofftime = config.getint('querytime') + companion.holdoff self.holdofftime = config.getint('querytime') + companion.holdoff
self.session = companion.Session()
self.eddn = eddn.EDDN(self) self.eddn = eddn.EDDN(self)
self.w = master self.w = master
@ -108,15 +104,23 @@ class AppWindow:
self.cmdr_label = tk.Label(frame) self.cmdr_label = tk.Label(frame)
self.ship_label = tk.Label(frame) self.ship_label = tk.Label(frame)
self.system_label = tk.Label(frame)
self.station_label = tk.Label(frame)
self.cmdr_label.grid(row=1, column=0, sticky=tk.W) self.cmdr_label.grid(row=1, column=0, sticky=tk.W)
self.ship_label.grid(row=2, column=0, sticky=tk.W) self.ship_label.grid(row=2, column=0, sticky=tk.W)
self.system_label.grid(row=3, column=0, sticky=tk.W)
self.station_label.grid(row=4, column=0, sticky=tk.W)
self.cmdr = tk.Label(frame, anchor=tk.W) self.cmdr = tk.Label(frame, compound=tk.RIGHT, anchor=tk.W, name = 'cmdr')
self.ship = HyperlinkLabel(frame, url = self.shipyard_url) self.ship = HyperlinkLabel(frame, compound=tk.RIGHT, url = self.shipyard_url, name = 'ship')
self.system = HyperlinkLabel(frame, compound=tk.RIGHT, url = self.system_url, popup_copy = True, name = 'system')
self.station = HyperlinkLabel(frame, compound=tk.RIGHT, url = self.station_url, name = 'station')
self.cmdr.grid(row=1, column=1, sticky=tk.EW) self.cmdr.grid(row=1, column=1, sticky=tk.EW)
self.ship.grid(row=2, column=1, sticky=tk.EW) self.ship.grid(row=2, column=1, sticky=tk.EW)
self.system.grid(row=3, column=1, sticky=tk.EW)
self.station.grid(row=4, column=1, sticky=tk.EW)
for plugin in plug.PLUGINS: for plugin in plug.PLUGINS:
appitem = plugin.get_app(frame) appitem = plugin.get_app(frame)
@ -291,8 +295,8 @@ class AppWindow:
# Migration from <= 2.25 # Migration from <= 2.25
if not config.get('cmdrs') and config.get('username') and config.get('password'): if not config.get('cmdrs') and config.get('username') and config.get('password'):
try: try:
self.session.login(config.get('username'), config.get('password'), False) companion.session.login(config.get('username'), config.get('password'), False)
data = self.session.profile() data = companion.session.profile()
prefs.migrate(data['commander']['name']) prefs.migrate(data['commander']['name'])
except: except:
if __debug__: print_exc() if __debug__: print_exc()
@ -341,6 +345,8 @@ class AppWindow:
self.cmdr_label['text'] = _('Cmdr') + ':' # Main window self.cmdr_label['text'] = _('Cmdr') + ':' # Main window
self.ship_label['text'] = (monitor.state['Captain'] and _('Role') or # Multicrew role label in main window self.ship_label['text'] = (monitor.state['Captain'] and _('Role') or # Multicrew role label in main window
_('Ship')) + ':' # Main window _('Ship')) + ':' # Main window
self.system_label['text'] = _('System') + ':' # Main window
self.station_label['text'] = _('Station') + ':' # Main window
self.button['text'] = self.theme_button['text'] = _('Update') # Update button in main window self.button['text'] = self.theme_button['text'] = _('Update') # Update button in main window
if platform == 'darwin': if platform == 'darwin':
self.menubar.entryconfigure(1, label=_('File')) # Menu title self.menubar.entryconfigure(1, label=_('File')) # Menu title
@ -379,7 +385,7 @@ class AppWindow:
raise companion.CredentialsError() raise companion.CredentialsError()
idx = config.get('cmdrs').index(monitor.cmdr) idx = config.get('cmdrs').index(monitor.cmdr)
username = config.get('fdev_usernames')[idx] username = config.get('fdev_usernames')[idx]
self.session.login(username, config.get_password(username), monitor.is_beta) companion.session.login(username, config.get_password(username), monitor.is_beta)
self.status['text'] = '' self.status['text'] = ''
except companion.VerificationRequired: except companion.VerificationRequired:
if not self.authdialog: if not self.authdialog:
@ -395,7 +401,7 @@ class AppWindow:
def verify(self, callback, code): def verify(self, callback, code):
self.authdialog = None self.authdialog = None
try: try:
self.session.verify(code) companion.session.verify(code)
config.save() # Save settings now for use by command-line app config.save() # Save settings now for use by command-line app
except Exception as e: except Exception as e:
if __debug__: print_exc() if __debug__: print_exc()
@ -427,7 +433,7 @@ class AppWindow:
try: try:
querytime = int(time()) querytime = int(time())
data = self.session.station() data = companion.session.station()
config.set('querytime', querytime) config.set('querytime', querytime)
# Validation # Validation
@ -556,7 +562,7 @@ class AppWindow:
def retry_for_shipyard(self, tries): def retry_for_shipyard(self, tries):
# Try again to get shipyard data and send to EDDN. Don't report errors if can't get or send the data. # Try again to get shipyard data and send to EDDN. Don't report errors if can't get or send the data.
try: try:
data = self.session.station() data = companion.session.station()
if __debug__: if __debug__:
print 'Retry for shipyard - ' + (data['commander'].get('docked') and (data.get('lastStarport', {}).get('ships') and 'Success' or 'Failure') or 'Undocked!') print 'Retry for shipyard - ' + (data['commander'].get('docked') and (data.get('lastStarport', {}).get('ships') and 'Success' or 'Failure') or 'Undocked!')
if not data['commander'].get('docked'): if not data['commander'].get('docked'):
@ -713,46 +719,15 @@ class AppWindow:
if not config.getint('hotkey_mute'): if not config.getint('hotkey_mute'):
hotkeymgr.play_bad() hotkeymgr.play_bad()
def shipyard_url(self, shipname=None): def shipyard_url(self, shipname):
return plug.invoke(config.get('shipyard_provider'), 'EDSY', 'shipyard_url', monitor.ship(), monitor.is_beta)
if not monitor.cmdr or not monitor.mode: def system_url(self, system):
return False # In CQC - do nothing return plug.invoke(config.get('system_provider'), 'EDSM', 'system_url', monitor.system)
if config.getint('shipyard') == config.SHIPYARD_EDSHIPYARD: def station_url(self, station):
return edshipyard.url(monitor.is_beta) return plug.invoke(config.get('station_provider'), 'eddb', 'station_url', monitor.system, monitor.station)
elif config.getint('shipyard') == config.SHIPYARD_CORIOLIS:
pass # Fall through
else:
assert False, config.getint('shipyard')
return False
self.status['text'] = _('Fetching data...')
self.w.update_idletasks()
try:
data = self.session.profile()
except companion.VerificationRequired:
if not self.authdialog:
self.authdialog = prefs.AuthenticationDialog(self.w, partial(self.verify, self.shipyard_url))
except companion.ServerError as e:
self.status['text'] = str(e)
return
except Exception as e:
if __debug__: print_exc()
self.status['text'] = str(e)
return
if not data.get('commander', {}).get('name'):
self.status['text'] = _("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
self.status['text'] = _("Where are you?!") # Shouldn't happen
elif not data.get('ship', {}).get('name') or not data.get('ship', {}).get('modules'):
self.status['text'] = _("What are you flying?!") # Shouldn't happen
elif (monitor.state['ShipID'] is not None and data['ship']['id'] != monitor.state['ShipID']) or (monitor.state['ShipType'] and data['ship']['name'].lower() != monitor.state['ShipType']):
self.status['text'] = _('Error: Frontier server is lagging') # Raised when Companion API server is returning old data, e.g. when the servers are too busy
else:
self.status['text'] = ''
return coriolis.url(data, monitor.is_beta)
# Recursively filter '*_Localised' keys from dict # Recursively filter '*_Localised' keys from dict
def filter_localised(self, d): def filter_localised(self, d):
@ -798,7 +773,7 @@ class AppWindow:
self.w.update_idletasks() self.w.update_idletasks()
try: try:
data = self.session.station() data = companion.session.station()
self.status['text'] = '' self.status['text'] = ''
f = tkFileDialog.asksaveasfilename(parent = self.w, f = tkFileDialog.asksaveasfilename(parent = self.w,
defaultextension = platform=='darwin' and '.json' or '', defaultextension = platform=='darwin' and '.json' or '',
@ -827,7 +802,7 @@ class AppWindow:
plug.notify_stop() plug.notify_stop()
self.eddn.close() self.eddn.close()
self.updater.close() self.updater.close()
self.session.close() companion.session.close()
config.close() config.close()
self.w.destroy() self.w.destroy()

View File

@ -228,12 +228,18 @@
</Component> </Component>
</Directory> </Directory>
<Directory Id="plugins" Name="plugins"> <Directory Id="plugins" Name="plugins">
<Component Guid="*">
<File KeyPath="yes" Source="SourceDir\plugins\coriolis.py" />
</Component>
<Component Guid="*"> <Component Guid="*">
<File KeyPath="yes" Source="SourceDir\plugins\eddb.py" /> <File KeyPath="yes" Source="SourceDir\plugins\eddb.py" />
</Component> </Component>
<Component Guid="*"> <Component Guid="*">
<File KeyPath="yes" Source="SourceDir\plugins\edsm.py" /> <File KeyPath="yes" Source="SourceDir\plugins\edsm.py" />
</Component> </Component>
<Component Guid="*">
<File KeyPath="yes" Source="SourceDir\plugins\edsy.py" />
</Component>
<Component Guid="*"> <Component Guid="*">
<File KeyPath="yes" Source="SourceDir\plugins\inara.py" /> <File KeyPath="yes" Source="SourceDir\plugins\inara.py" />
</Component> </Component>

View File

@ -385,3 +385,7 @@ def ship_file_name(ship_name, ship_type):
'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9']: 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9']:
name = name + '_' name = name + '_'
return name.translate({ ord(x): u'_' for x in ['\0', '<', '>', ':', '"', '/', '\\', '|', '?', '*'] }) return name.translate({ ord(x): u'_' for x in ['\0', '<', '>', ':', '"', '/', '\\', '|', '?', '*'] })
# singleton
session = Session()

View File

@ -108,10 +108,6 @@ class Config:
OUT_SYS_EDDN = 2048 OUT_SYS_EDDN = 2048
OUT_SYS_DELAY = 4096 OUT_SYS_DELAY = 4096
# shipyard setting
SHIPYARD_EDSHIPYARD = 0
SHIPYARD_CORIOLIS = 1
if platform=='darwin': if platform=='darwin':
def __init__(self): def __init__(self):

View File

@ -1,34 +1,18 @@
#!/usr/bin/python #!/usr/bin/python
# #
# Export ship loadout in Coriolis format # build ship and module databases from https://github.com/EDCD/coriolis-data/
# #
import base64 import base64
from collections import OrderedDict from collections import OrderedDict
import cPickle import cPickle
import json import json
import StringIO
import gzip
from config import config from config import config
import outfitting import outfitting
import companion import companion
# Return a URL for the current ship
def url(data, is_beta):
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')
#
# build ship and module databases from https://github.com/EDCD/coriolis-data/
#
if __name__ == "__main__": if __name__ == "__main__":
data = json.load(open('coriolis-data/dist/index.json')) data = json.load(open('coriolis-data/dist/index.json'))

View File

@ -1,19 +1,16 @@
import cPickle # Export ship loadout in E:D Shipyard plain text format
import base64 import cPickle
from collections import defaultdict from collections import defaultdict
import json
import os import os
from os.path import join from os.path import join
import re import re
import StringIO
import time import time
import gzip
from config import config from config import config
import companion import companion
import outfitting import outfitting
from monitor import monitor
# Map API ship names to E:D Shipyard ship names # Map API ship names to E:D Shipyard ship names
ship_map = dict(companion.ship_map) ship_map = dict(companion.ship_map)
@ -160,16 +157,3 @@ def export(data, filename=None):
filename = join(config.get('outdir'), '%s.%s.txt' % (ship, time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime(querytime)))) filename = join(config.get('outdir'), '%s.%s.txt' % (ship, time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime(querytime))))
with open(filename, 'wt') as h: with open(filename, 'wt') as h:
h.write(string) h.write(string)
# Return a URL for the current ship
def url(is_beta):
string = json.dumps(monitor.ship(), ensure_ascii=False, sort_keys=True, separators=(',', ':')).encode('utf-8') # most compact representation
if not string:
return False
out = StringIO.StringIO()
with gzip.GzipFile(fileobj=out, mode='w') as f:
f.write(string)
return (is_beta and 'http://www.edshipyard.com/beta/#/I=' or 'http://www.edshipyard.com/#/I=') + base64.urlsafe_b64encode(out.getvalue()).replace('=', '%3D')

View File

@ -1,3 +1,5 @@
# Export ship loadout in Companion API json format
import json import json
import os import os
from os.path import join from os.path import join
@ -8,7 +10,6 @@ from config import config
import companion import companion
# Export ship loadout in Companion API json format
def export(data, filename=None): def export(data, filename=None):
string = json.dumps(companion.ship(data), ensure_ascii=False, indent=2, sort_keys=True, separators=(',', ': ')).encode('utf-8') # pretty print string = json.dumps(companion.ship(data), ensure_ascii=False, indent=2, sort_keys=True, separators=(',', ': ')).encode('utf-8') # pretty print

47
plugins/coriolis.py Normal file
View File

@ -0,0 +1,47 @@
# Coriolis ship export
import base64
import gzip
import json
import StringIO
import companion
import plug
# Migrate settings from <= 3.01
from config import config
if not config.get('shipyard_provider') and config.getint('shipyard'):
config.set('shipyard_provider', 'Coriolis')
config.delete('shipyard')
def plugin_start():
return 'Coriolis'
# Return a URL for the current ship
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['ShipID'] is not None and data['ship']['id'] != loadout['ShipID']) or (loadout['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')

View File

@ -3,23 +3,18 @@
# Station display and eddb.io lookup # Station display and eddb.io lookup
# #
import cPickle import cPickle
import csv import csv
import os import os
from os.path import dirname, join, normpath from os.path import join
import sys import sys
import Tkinter as tk
from ttkHyperlinkLabel import HyperlinkLabel
from config import config from config import config
STATION_UNDOCKED = u'×' # "Station" name to display when not docked = U+00D7 STATION_UNDOCKED = u'×' # "Station" name to display when not docked = U+00D7
this = sys.modules[__name__] # For holding module globals this = sys.modules[__name__] # For holding module globals
this.system = None # name of current system
with open(join(config.respath, 'systems.p'), 'rb') as h: with open(join(config.respath, 'systems.p'), 'rb') as h:
this.system_ids = cPickle.load(h) this.system_ids = cPickle.load(h)
@ -28,6 +23,15 @@ with open(join(config.respath, 'stations.p'), 'rb') as h:
this.station_ids = cPickle.load(h) this.station_ids = cPickle.load(h)
# Main window clicks
def station_url(system_name, station_name):
if station_id(system_name, station_name):
return 'https://eddb.io/station/%d' % station_id(system_name, station_name)
elif system_id(system_name):
return 'https://eddb.io/system/%d' % system_id(system_name)
else:
return None
# system_name -> system_id or 0 # system_name -> system_id or 0
def system_id(system_name): def system_id(system_name):
return this.system_ids.get(system_name, 0) # return 0 on failure (0 is not a valid id) return this.system_ids.get(system_name, 0) # return 0 on failure (0 is not a valid id)
@ -36,34 +40,20 @@ def system_id(system_name):
def station_id(system_name, station_name): def station_id(system_name, station_name):
return this.station_ids.get((this.system_ids.get(system_name), station_name), 0) return this.station_ids.get((this.system_ids.get(system_name), station_name), 0)
def station_url(text):
if text:
station = station_id(this.system, text)
if station:
return 'https://eddb.io/station/%d' % station
system = system_id(this.system)
if system:
return 'https://eddb.io/system/%d' % system
return None
def plugin_start(): def plugin_start():
return '~eddb' return 'eddb'
def plugin_app(parent): def plugin_app(parent):
this.station_label = tk.Label(parent, text = _('Station') + ':') # Main window this.station = parent.children['station'] # station label in main window
this.station = HyperlinkLabel(parent, url = station_url, popup_copy = lambda x: x != STATION_UNDOCKED) this.station.configure(popup_copy = lambda x: x != STATION_UNDOCKED)
return (this.station_label, this.station)
def prefs_changed(cmdr, is_beta):
this.station_label['text'] = _('Station') + ':'
def journal_entry(cmdr, is_beta, system, station, entry, state): def journal_entry(cmdr, is_beta, system, station, entry, state):
this.system = system this.system = system
this.station['text'] = station or (system_id(system) and STATION_UNDOCKED or '') this.station['text'] = station or (system_id(system) and STATION_UNDOCKED or '')
this.station.update_idletasks()
def cmdr_data(data, is_beta): def cmdr_data(data, is_beta):
this.system = data['lastSystem']['name'] this.system = data['lastSystem']['name']
this.station['text'] = data['commander']['docked'] and data['lastStarport']['name'] or (system_id(data['lastSystem']['name']) and STATION_UNDOCKED or '') this.station['text'] = data['commander']['docked'] and data['lastStarport']['name'] or (system_id(data['lastSystem']['name']) and STATION_UNDOCKED or '')
this.station.update_idletasks()

View File

@ -16,8 +16,6 @@ import myNotebook as nb
from config import appname, applongname, appversion, config from config import appname, applongname, appversion, config
import companion import companion
import coriolis
import edshipyard
import outfitting import outfitting
import plug import plug
@ -26,7 +24,6 @@ if __debug__:
EDSM_POLL = 0.1 EDSM_POLL = 0.1
_TIMEOUT = 20 _TIMEOUT = 20
FAKE = ['CQC', 'Training', 'Destination'] # Fake systems that shouldn't be sent to EDSM
this = sys.modules[__name__] # For holding module globals this = sys.modules[__name__] # For holding module globals
@ -44,6 +41,15 @@ this.newgame = False # starting up - batch initial burst of events
this.newgame_docked = False # starting up while docked this.newgame_docked = False # starting up while docked
this.navbeaconscan = 0 # batch up burst of Scan events after NavBeaconScan this.navbeaconscan = 0 # batch up burst of Scan events after NavBeaconScan
# Main window clicks
def system_url(system_name):
return 'https://www.edsm.net/en/system?systemName=%s' % urllib2.quote(system_name)
def station_url(system_name, station_name):
return 'https://www.edsm.net/en/system?systemName=%s&stationName=%s' % (urllib2.quote(system_name), urllib2.quote(station_name))
def plugin_start(): def plugin_start():
# Can't be earlier since can only call PhotoImage after window is created # Can't be earlier since can only call PhotoImage after window is created
this._IMG_KNOWN = tk.PhotoImage(data = 'R0lGODlhEAAQAMIEAFWjVVWkVWS/ZGfFZ////////////////yH5BAEKAAQALAAAAAAQABAAAAMvSLrc/lAFIUIkYOgNXt5g14Dk0AQlaC1CuglM6w7wgs7rMpvNV4q932VSuRiPjQQAOw==') # green circle this._IMG_KNOWN = tk.PhotoImage(data = 'R0lGODlhEAAQAMIEAFWjVVWkVWS/ZGfFZ////////////////yH5BAEKAAQALAAAAAAQABAAAAMvSLrc/lAFIUIkYOgNXt5g14Dk0AQlaC1CuglM6w7wgs7rMpvNV4q932VSuRiPjQQAOw==') # green circle
@ -75,10 +81,8 @@ def plugin_start():
return 'EDSM' return 'EDSM'
def plugin_app(parent): def plugin_app(parent):
this.system_label = tk.Label(parent, text = _('System') + ':') # Main window this.system = parent.children['system'] # system label in main window
this.system = HyperlinkLabel(parent, compound=tk.RIGHT, popup_copy = True)
this.system.bind_all('<<EDSMStatus>>', update_status) this.system.bind_all('<<EDSMStatus>>', update_status)
return (this.system_label, this.system)
def plugin_stop(): def plugin_stop():
# Signal thread to close and wait for it # Signal thread to close and wait for it
@ -143,7 +147,6 @@ def prefsvarchanged():
this.label['state'] = this.cmdr_label['state'] = this.cmdr_text['state'] = this.user_label['state'] = this.user['state'] = this.apikey_label['state'] = this.apikey['state'] = this.log.get() and this.log_button['state'] or tk.DISABLED this.label['state'] = this.cmdr_label['state'] = this.cmdr_text['state'] = this.user_label['state'] = this.user['state'] = this.apikey_label['state'] = this.apikey['state'] = this.log.get() and this.log_button['state'] or tk.DISABLED
def prefs_changed(cmdr, is_beta): def prefs_changed(cmdr, is_beta):
this.system_label['text'] = _('System') + ':' # Main window
config.set('edsm_out', this.log.get()) config.set('edsm_out', this.log.get())
if cmdr and not is_beta: if cmdr and not is_beta:
@ -188,12 +191,6 @@ def journal_entry(cmdr, is_beta, system, station, entry, state):
if this.system['text'] != system: if this.system['text'] != system:
this.system['text'] = system or '' this.system['text'] = system or ''
this.system['image'] = '' this.system['image'] = ''
if not system or system in FAKE:
this.system['url'] = None
this.lastlookup = True
else:
this.system['url'] = 'https://www.edsm.net/show-system?systemName=%s' % urllib2.quote(system)
this.lastlookup = False
this.system.update_idletasks() this.system.update_idletasks()
this.multicrew = bool(state['Role']) this.multicrew = bool(state['Role'])
@ -243,7 +240,7 @@ def journal_entry(cmdr, is_beta, system, station, entry, state):
this.queue.put((cmdr, entry)) this.queue.put((cmdr, entry))
if entry['event'] == 'Loadout' and 'EDShipyard' not in this.discardedEvents: if entry['event'] == 'Loadout' and 'EDShipyard' not in this.discardedEvents:
url = edshipyard.url(is_beta) url = plug.invoke('EDSY', None, 'shipyard_url', entry, is_beta)
if this.lastloadout != url: if this.lastloadout != url:
this.lastloadout = url this.lastloadout = url
this.queue.put((cmdr, { this.queue.put((cmdr, {
@ -259,12 +256,6 @@ def cmdr_data(data, is_beta):
if not this.system['text']: if not this.system['text']:
this.system['text'] = system this.system['text'] = system
this.system['image'] = '' this.system['image'] = ''
if not system or system in FAKE:
this.system['url'] = None
this.lastlookup = True
else:
this.system['url'] = 'https://www.edsm.net/show-system?systemName=%s' % urllib2.quote(system)
this.lastlookup = False
this.system.update_idletasks() this.system.update_idletasks()
# Send ship info to EDSM # Send ship info to EDSM
@ -275,7 +266,10 @@ def cmdr_data(data, is_beta):
timestamp = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) timestamp = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
if 'Coriolis' not in this.discardedEvents: if 'Coriolis' not in this.discardedEvents:
this.queue.put((cmdr, { this.queue.put((cmdr, {
'event': 'Coriolis', 'timestamp': timestamp, '_shipId': data['ship']['id'], 'url': coriolis.url(data, is_beta) 'event': 'Coriolis',
'timestamp': timestamp,
'_shipId': data['ship']['id'],
'url': plug.invoke('Coriolis', None, 'shipyard_url', entry, is_beta, data)
})) }))
this.lastship = ship this.lastship = ship

22
plugins/edsy.py Normal file
View File

@ -0,0 +1,22 @@
# EDShipyard ship export
import base64
import gzip
import json
import StringIO
def plugin_start():
return 'EDSY'
# Return a URL for the current ship
def shipyard_url(loadout, is_beta):
string = json.dumps(loadout, ensure_ascii=False, sort_keys=True, separators=(',', ':')).encode('utf-8') # most compact representation
if not string:
return False
out = StringIO.StringIO()
with gzip.GzipFile(fileobj=out, mode='w') as f:
f.write(string)
return (is_beta and 'http://www.edshipyard.com/beta/#/I=' or 'http://www.edshipyard.com/#/I=') + base64.urlsafe_b64encode(out.getvalue()).replace('=', '%3D')

View File

@ -46,10 +46,17 @@ this.loadout = None
this.fleet = None this.fleet = None
this.shipswap = False # just swapped ship this.shipswap = False # just swapped ship
# URLs
# Main window clicks
this.system = None this.system = None
this.station = None this.station = None
def system_url(system_name):
return this.system
def station_url(system_name, station_name):
return this.station
def plugin_start(): def plugin_start():
this.thread = Thread(target = worker, name = 'Inara worker') this.thread = Thread(target = worker, name = 'Inara worker')
@ -715,10 +722,10 @@ def worker():
print 'Inara\t%s %s\t%s' % (reply_event['eventStatus'], reply_event.get('eventStatusText', ''), json.dumps(data_event)) print 'Inara\t%s %s\t%s' % (reply_event['eventStatus'], reply_event.get('eventStatusText', ''), json.dumps(data_event))
if reply_event['eventStatus'] // 100 != 2: 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'])))) 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']: elif data_event['eventName'] in ['addCommanderTravelDock', 'addCommanderTravelFSDJump', 'setCommanderTravelLocation']:
eventData = reply_event.get('eventData', {}) eventData = reply_event.get('eventData', {})
this.system = eventData.get('starsystemInaraURL') this.system = eventData.get('starsystemInaraURL')
this.station = eventData.get('stationInaraURL') this.station = eventData.get('stationInaraURL')
break break
except: except:
if __debug__: print_exc() if __debug__: print_exc()

View File

@ -233,21 +233,38 @@ class PreferencesDialog(tk.Toplevel):
self.hotkey_text.insert(0, self.hotkey_code and hotkeymgr.display(self.hotkey_code, self.hotkey_mods) or _('None')) # No hotkey/shortcut currently defined self.hotkey_text.insert(0, self.hotkey_code and hotkeymgr.display(self.hotkey_code, self.hotkey_mods) or _('None')) # No hotkey/shortcut currently defined
self.hotkey_text.bind('<FocusIn>', self.hotkeystart) self.hotkey_text.bind('<FocusIn>', self.hotkeystart)
self.hotkey_text.bind('<FocusOut>', self.hotkeyend) self.hotkey_text.bind('<FocusOut>', self.hotkeyend)
self.hotkey_text.grid(row=20, column=1, columnspan=2, padx=PADX, pady=(5,0), sticky=tk.W) self.hotkey_text.grid(row=20, column=1, columnspan=2, pady=(5,0), sticky=tk.W)
self.hotkey_only_btn = nb.Checkbutton(configframe, text=_('Only when Elite: Dangerous is the active app'), variable=self.hotkey_only, state = self.hotkey_code and tk.NORMAL or tk.DISABLED) # Hotkey/Shortcut setting self.hotkey_only_btn = nb.Checkbutton(configframe, text=_('Only when Elite: Dangerous is the active app'), variable=self.hotkey_only, state = self.hotkey_code and tk.NORMAL or tk.DISABLED) # Hotkey/Shortcut setting
self.hotkey_only_btn.grid(columnspan=4, padx=PADX, pady=(5,0), sticky=tk.W) self.hotkey_only_btn.grid(columnspan=4, padx=PADX, pady=(5,0), sticky=tk.W)
self.hotkey_play_btn = nb.Checkbutton(configframe, text=_('Play sound'), variable=self.hotkey_play, state = self.hotkey_code and tk.NORMAL or tk.DISABLED) # Hotkey/Shortcut setting self.hotkey_play_btn = nb.Checkbutton(configframe, text=_('Play sound'), variable=self.hotkey_play, state = self.hotkey_code and tk.NORMAL or tk.DISABLED) # Hotkey/Shortcut setting
self.hotkey_play_btn.grid(columnspan=4, padx=PADX, sticky=tk.W) self.hotkey_play_btn.grid(columnspan=4, padx=PADX, sticky=tk.W)
ttk.Separator(configframe, orient=tk.HORIZONTAL).grid(columnspan=4, padx=PADX, pady=PADY*4, sticky=tk.EW) ttk.Separator(configframe, orient=tk.HORIZONTAL).grid(columnspan=4, padx=PADX, pady=PADY*4, sticky=tk.EW)
nb.Label(configframe, text=_('Preferred Shipyard')).grid(columnspan=4, padx=PADX, sticky=tk.W) # Setting to decide which ship outfitting website to link to - either E:D Shipyard or Coriolis. nb.Label(configframe, text=_('Preferred websites')).grid(row=30, columnspan=4, padx=PADX, sticky=tk.W) # Settings prompt for preferred ship loadout, system and station info websites
self.shipyard = tk.IntVar(value = config.getint('shipyard'))
nb.Radiobutton(configframe, text='E:D Shipyard', variable=self.shipyard, value=config.SHIPYARD_EDSHIPYARD).grid(columnspan=3, padx=BUTTONX, pady=(5,0), sticky=tk.W) self.shipyard_provider = tk.StringVar(value = config.get('shipyard_provider') in plug.provides('shipyard_url') and config.get('shipyard_provider') or 'EDSY')
nb.Radiobutton(configframe, text='Coriolis', variable=self.shipyard, value=config.SHIPYARD_CORIOLIS ).grid(columnspan=3, padx=BUTTONX, sticky=tk.W) nb.Label(configframe, text=_('Shipyard')).grid(row=31, padx=PADX, pady=2*PADY, sticky=tk.W) # Setting to decide which ship outfitting website to link to - either E:D Shipyard or Coriolis
self.shipyard_button = nb.OptionMenu(configframe, self.shipyard_provider, self.shipyard_provider.get(), *plug.provides('shipyard_url'))
self.shipyard_button.configure(width = 15)
self.shipyard_button.grid(row=31, column=1, sticky=tk.W)
self.system_provider = tk.StringVar(value = config.get('system_provider') in plug.provides('system_url') and config.get('system_provider') or 'EDSM')
nb.Label(configframe, text=_('System')).grid(row=32, padx=PADX, pady=2*PADY, sticky=tk.W)
self.system_button = nb.OptionMenu(configframe, self.system_provider, self.system_provider.get(), *plug.provides('system_url'))
self.system_button.configure(width = 15)
self.system_button.grid(row=32, column=1, sticky=tk.W)
self.station_provider = tk.StringVar(value = config.get('station_provider') in plug.provides('station_url') and config.get('station_provider') or 'eddb')
nb.Label(configframe, text=_('Station')).grid(row=33, padx=PADX, pady=2*PADY, sticky=tk.W)
self.station_button = nb.OptionMenu(configframe, self.station_provider, self.station_provider.get(), *plug.provides('station_url'))
self.station_button.configure(width = 15)
self.station_button.grid(row=33, column=1, sticky=tk.W)
nb.Label(configframe).grid(sticky=tk.W) # big spacer nb.Label(configframe).grid(sticky=tk.W) # big spacer
notebook.add(configframe, text=_('Configuration')) # Tab heading in settings notebook.add(configframe, text=_('Configuration')) # Tab heading in settings
self.languages = Translations().available_names() self.languages = Translations().available_names()
self.lang = tk.StringVar(value = self.languages.get(config.get('language'), _('Default'))) # Appearance theme and language setting self.lang = tk.StringVar(value = self.languages.get(config.get('language'), _('Default'))) # Appearance theme and language setting
self.always_ontop = tk.BooleanVar(value = config.getint('always_ontop')) self.always_ontop = tk.BooleanVar(value = config.getint('always_ontop'))
@ -567,7 +584,9 @@ class PreferencesDialog(tk.Toplevel):
config.set('hotkey_mods', self.hotkey_mods) config.set('hotkey_mods', self.hotkey_mods)
config.set('hotkey_always', int(not self.hotkey_only.get())) config.set('hotkey_always', int(not self.hotkey_only.get()))
config.set('hotkey_mute', int(not self.hotkey_play.get())) config.set('hotkey_mute', int(not self.hotkey_play.get()))
config.set('shipyard', self.shipyard.get()) config.set('shipyard_provider', self.shipyard_provider.get())
config.set('system_provider', self.system_provider.get())
config.set('station_provider', self.station_provider.get())
lang_codes = { v: k for k, v in self.languages.iteritems() } # Codes by name lang_codes = { v: k for k, v in self.languages.iteritems() } # Codes by name
config.set('language', lang_codes.get(self.lang.get()) or '') config.set('language', lang_codes.get(self.lang.get()) or '')

View File

@ -66,7 +66,7 @@ if sys.platform=='darwin':
APP = 'EDMarketConnector.py' APP = 'EDMarketConnector.py'
APPCMD = 'EDMC.py' APPCMD = 'EDMC.py'
SHORTVERSION = ''.join(VERSION.split('.')[:3]) SHORTVERSION = ''.join(VERSION.split('.')[:3])
PLUGINS = [ 'plugins/eddb.py', 'plugins/edsm.py', 'plugins/inara.py' ] PLUGINS = [ 'plugins/coriolis.py', 'plugins/eddb.py', 'plugins/edsm.py', 'plugins/edsy.py', 'plugins/inara.py' ]
if sys.platform=='darwin': if sys.platform=='darwin':
OPTIONS = { 'py2app': OPTIONS = { 'py2app':