mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-13 07:47:14 +03:00
Switch eddb integration to a plugin
This commit is contained in:
parent
b794e19d75
commit
fe0835be10
8
EDMC.py
8
EDMC.py
@ -24,15 +24,12 @@ import loadout
|
||||
import edshipyard
|
||||
import coriolis
|
||||
import shipyard
|
||||
import eddb
|
||||
import eddn
|
||||
import stats
|
||||
import prefs
|
||||
from config import appcmdname, appversion, update_feed, config
|
||||
|
||||
|
||||
EDDB = eddb.EDDB()
|
||||
|
||||
SERVER_RETRY = 5 # retry pause for Companion servers [s]
|
||||
EXIT_SUCCESS, EXIT_SERVER, EXIT_CREDENTIALS, EXIT_VERIFICATION, EXIT_NOT_DOCKED, EXIT_SYS_ERR = range(6)
|
||||
|
||||
@ -127,7 +124,6 @@ try:
|
||||
|
||||
# Finally - the data looks sane and we're docked at a station
|
||||
print '%s,%s' % (data['lastSystem']['name'], data['lastStarport']['name'])
|
||||
(station_id, has_market, has_outfitting, has_shipyard) = EDDB.station(data['lastSystem']['name'], data['lastStarport']['name'])
|
||||
|
||||
if (args.m or args.o or args.s) and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')): # Ignore possibly missing shipyard info
|
||||
sys.stderr.write("Station doesn't have anything!\n")
|
||||
@ -155,13 +151,11 @@ try:
|
||||
sys.stderr.write("Station doesn't supply outfitting\n")
|
||||
|
||||
if args.s:
|
||||
if has_shipyard and not data['lastStarport'].get('ships') and not args.j:
|
||||
if not data['lastStarport'].get('ships') and not args.j:
|
||||
sleep(SERVER_RETRY)
|
||||
data = session.query()
|
||||
if data['lastStarport'].get('ships'):
|
||||
shipyard.export(data, args.s)
|
||||
elif has_shipyard:
|
||||
sys.stderr.write("Couldn't retrieve shipyard info\n")
|
||||
else:
|
||||
sys.stderr.write("Station doesn't have a shipyard\n")
|
||||
|
||||
|
@ -56,7 +56,6 @@ import td
|
||||
import eddn
|
||||
import edsm
|
||||
import coriolis
|
||||
import eddb
|
||||
import edshipyard
|
||||
import loadout
|
||||
import stats
|
||||
@ -67,7 +66,6 @@ from monitor import monitor
|
||||
from interactions import interactions
|
||||
from theme import theme
|
||||
|
||||
EDDB = eddb.EDDB()
|
||||
|
||||
SERVER_RETRY = 5 # retry pause for Companion servers [s]
|
||||
EDSM_POLL = 0.1
|
||||
@ -80,8 +78,6 @@ CLOCK_THRESHOLD = 11 * 60 * 60 + TZ_THRESHOLD
|
||||
|
||||
class AppWindow:
|
||||
|
||||
STATION_UNDOCKED = u'×' # "Station" name to display when not docked = U+00D7
|
||||
|
||||
# Tkinter Event types
|
||||
EVENT_KEYPRESS = 2
|
||||
EVENT_BUTTON = 4
|
||||
@ -118,22 +114,18 @@ class AppWindow:
|
||||
self.cmdr_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.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.ship = HyperlinkLabel(frame, url = self.shipyard_url)
|
||||
self.system = HyperlinkLabel(frame, compound=tk.RIGHT, url = self.system_url, popup_copy = True)
|
||||
self.station = HyperlinkLabel(frame, url = self.station_url, popup_copy = lambda x: x!=self.STATION_UNDOCKED)
|
||||
|
||||
self.cmdr.grid(row=1, 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:
|
||||
appitem = plugin.get_app(frame)
|
||||
@ -355,7 +347,6 @@ class AppWindow:
|
||||
self.ship_label['text'] = (monitor.captain and _('Role') or # Multicrew role label in 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
|
||||
if platform == 'darwin':
|
||||
self.menubar.entryconfigure(1, label=_('File')) # Menu title
|
||||
@ -480,7 +471,6 @@ class AppWindow:
|
||||
if not monitor.system:
|
||||
self.system['text'] = data['lastSystem']['name']
|
||||
self.system['image'] = ''
|
||||
self.station['text'] = data['commander'].get('docked') and data.get('lastStarport') and data['lastStarport'].get('name') or (EDDB.system(self.system['text']) and self.STATION_UNDOCKED or '')
|
||||
self.status['text'] = ''
|
||||
self.edit_menu.entryconfigure(0, state=tk.NORMAL) # Copy
|
||||
|
||||
@ -515,7 +505,6 @@ class AppWindow:
|
||||
|
||||
else:
|
||||
# Finally - the data looks sane and we're docked at a station
|
||||
(station_id, has_market, has_outfitting, has_shipyard) = EDDB.station(self.system['text'], self.station['text'])
|
||||
|
||||
# No EDDN output?
|
||||
if (config.getint('output') & config.OUT_MKT_EDDN) and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')): # Ignore possibly missing shipyard info
|
||||
@ -544,7 +533,7 @@ class AppWindow:
|
||||
self.w.update_idletasks()
|
||||
self.eddn.export_commodities(data, monitor.is_beta)
|
||||
self.eddn.export_outfitting(data, monitor.is_beta)
|
||||
if has_shipyard and not data['lastStarport'].get('ships'):
|
||||
if monitor.stationtype != 'Outpost' and not data['lastStarport'].get('ships'):
|
||||
# API is flakey about shipyard info - silently retry if missing (<1s is usually sufficient - 5s for margin).
|
||||
self.w.after(int(SERVER_RETRY * 1000), self.retry_for_shipyard)
|
||||
else:
|
||||
@ -634,7 +623,6 @@ class AppWindow:
|
||||
return
|
||||
|
||||
system_changed = monitor.system and self.system['text'] != monitor.system
|
||||
station_changed = monitor.station and self.station['text'] != monitor.station
|
||||
|
||||
# Update main window
|
||||
if monitor.cmdr and monitor.captain:
|
||||
@ -656,7 +644,6 @@ class AppWindow:
|
||||
self.ship_label['text'] = _('Ship') + ':' # Main window
|
||||
self.ship['text'] = ''
|
||||
|
||||
self.station['text'] = monitor.station or (EDDB.system(monitor.system) and self.STATION_UNDOCKED or '')
|
||||
if self.system['text'] != monitor.system:
|
||||
self.system['text'] = monitor.system or ''
|
||||
self.edsm.link(monitor.system)
|
||||
@ -747,7 +734,7 @@ class AppWindow:
|
||||
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 monitor.mode and not config.getint('output') & config.OUT_MKT_MANUAL and config.getint('output') & config.OUT_STATION_ANY:
|
||||
if monitor.mode and monitor.station and entry['event'] in ['StartUp', 'Location', 'Docked'] and not config.getint('output') & config.OUT_MKT_MANUAL and config.getint('output') & config.OUT_STATION_ANY:
|
||||
self.w.after(int(SERVER_RETRY * 1000), self.getandsend)
|
||||
|
||||
# Send interesting events to EDDN
|
||||
@ -863,18 +850,6 @@ class AppWindow:
|
||||
def system_url(self, text):
|
||||
return text and self.edsm.result['url']
|
||||
|
||||
def station_url(self, text):
|
||||
if text:
|
||||
(station_id, has_market, has_outfitting, has_shipyard) = EDDB.station(self.system['text'], self.station['text'])
|
||||
if station_id:
|
||||
return 'https://eddb.io/station/%d' % station_id
|
||||
|
||||
system_id = EDDB.system(self.system['text'])
|
||||
if system_id:
|
||||
return 'https://eddb.io/system/%d' % system_id
|
||||
|
||||
return None
|
||||
|
||||
def cooldown(self):
|
||||
if time() < self.holdofftime:
|
||||
self.button['text'] = self.theme_button['text'] = _('cooldown {SS}s').format(SS = int(self.holdofftime - time())) # Update button in main window
|
||||
@ -888,9 +863,9 @@ class AppWindow:
|
||||
self.w.wm_attributes('-topmost', self.always_ontop.get())
|
||||
|
||||
def copy(self, event=None):
|
||||
if self.system['text']:
|
||||
if monitor.system:
|
||||
self.w.clipboard_clear()
|
||||
self.w.clipboard_append(self.station['text'] == self.STATION_UNDOCKED and self.system['text'] or '%s,%s' % (self.system['text'], self.station['text']))
|
||||
self.w.clipboard_append(monitor.station and '%s,%s' % (monitor.system, monitor.station) or monitor.system)
|
||||
|
||||
def help_general(self, event=None):
|
||||
webbrowser.open('https://github.com/Marginal/EDMarketConnector/wiki')
|
||||
|
@ -135,6 +135,9 @@
|
||||
<Component Guid="*">
|
||||
<File KeyPath="yes" Source="SourceDir\EDMC.exe" />
|
||||
</Component>
|
||||
<Component Guid="*">
|
||||
<File KeyPath="yes" Source="SourceDir\eddb.py" />
|
||||
</Component>
|
||||
<Component Guid="*">
|
||||
<File KeyPath="yes" Source="SourceDir\es.strings" />
|
||||
</Component>
|
||||
@ -443,6 +446,7 @@
|
||||
<ComponentRef Id="EDMarketConnector.ico" />
|
||||
<ComponentRef Id="EDMarketConnector.VisualElementsManifest.xml" />
|
||||
<ComponentRef Id="EDMC.exe" />
|
||||
<ComponentRef Id="eddb.py" />
|
||||
<ComponentRef Id="es.strings" />
|
||||
<ComponentRef Id="fi.strings" />
|
||||
<ComponentRef Id="fr.strings" />
|
||||
|
@ -457,7 +457,7 @@
|
||||
/* Empire rank. [stats.py] */
|
||||
"Squire" = "Squire";
|
||||
|
||||
/* Main window. [EDMarketConnector.py] */
|
||||
/* Main window. [eddb.py] */
|
||||
"Station" = "Station";
|
||||
|
||||
/* [EDMarketConnector.py] */
|
||||
|
45
eddb.py
45
eddb.py
@ -1,47 +1,16 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# eddb.io station database
|
||||
# build databases from files systems.csv and stations.json from http://eddb.io/api
|
||||
#
|
||||
|
||||
import cPickle
|
||||
import csv
|
||||
import os
|
||||
from os.path import dirname, join, normpath
|
||||
import sys
|
||||
from sys import platform
|
||||
import json
|
||||
import requests
|
||||
|
||||
from config import config
|
||||
|
||||
class EDDB:
|
||||
|
||||
HAS_MARKET = 1
|
||||
HAS_OUTFITTING = 2
|
||||
HAS_SHIPYARD = 4
|
||||
|
||||
def __init__(self):
|
||||
with open(join(config.respath, 'systems.p'), 'rb') as h:
|
||||
self.system_ids = cPickle.load(h)
|
||||
with open(join(config.respath, 'stations.p'), 'rb') as h:
|
||||
self.station_ids = cPickle.load(h)
|
||||
|
||||
# system_name -> system_id or 0
|
||||
def system(self, system_name):
|
||||
return self.system_ids.get(system_name, 0) # return 0 on failure (0 is not a valid id)
|
||||
|
||||
# (system_name, station_name) -> (station_id, has_market, has_outfitting, has_shipyard)
|
||||
def station(self, system_name, station_name):
|
||||
(station_id, flags) = self.station_ids.get((self.system_ids.get(system_name), station_name), (0,0))
|
||||
return (station_id, bool(flags & EDDB.HAS_MARKET), bool(flags & EDDB.HAS_OUTFITTING), bool(flags & EDDB.HAS_SHIPYARD))
|
||||
|
||||
|
||||
#
|
||||
# build databases from files systems.csv and stations.json from http://eddb.io/api
|
||||
#
|
||||
if __name__ == "__main__":
|
||||
|
||||
import json
|
||||
import requests
|
||||
|
||||
def download(filename):
|
||||
r = requests.get('https://eddb.io/archive/v5/' + filename, stream=True)
|
||||
@ -153,9 +122,7 @@ if __name__ == "__main__":
|
||||
print '%-20s%8d %8d %11.5f %11.5f %11.5f' % (s['name'], system_ids[s['name']], k, s['x'], s['y'], s['z'])
|
||||
|
||||
# Hack - ensure duplicate system names are pointing at the more interesting system
|
||||
system_ids['Almar'] = 750
|
||||
system_ids['Amo'] = 866
|
||||
system_ids['Arti'] = 60342
|
||||
system_ids['Ogmar'] = 14915 # in bubble, not Colonia
|
||||
system_ids['Ratri'] = 16001 # "
|
||||
system_ids['K Carinae'] = 375886 # both unpopulated
|
||||
@ -179,11 +146,7 @@ if __name__ == "__main__":
|
||||
# station_id by (system_id, station_name)
|
||||
stations = json.loads(download('stations.json').content) # let json do the utf-8 decode
|
||||
station_ids = {
|
||||
(x['system_id'], str(x['name'])) :
|
||||
(x['id'],
|
||||
(EDDB.HAS_MARKET if x['has_market'] else 0) |
|
||||
(EDDB.HAS_OUTFITTING if x['has_outfitting'] else 0) |
|
||||
(EDDB.HAS_SHIPYARD if x['has_shipyard'] else 0))
|
||||
(x['system_id'], str(x['name'])) : x['id']
|
||||
for x in stations if x['max_landing_pad_size']
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.body = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.stationtype = None
|
||||
self.coordinates = None
|
||||
self.started = None # Timestamp of the LoadGame event
|
||||
|
||||
@ -197,7 +198,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
if __debug__:
|
||||
print 'Stopping monitoring Journal'
|
||||
self.currentdir = None
|
||||
self.version = self.mode = self.group = self.cmdr = self.body = self.system = self.station = self.coordinates = None
|
||||
self.version = self.mode = self.group = self.cmdr = self.body = self.system = self.station = self.stationtype = self.coordinates = None
|
||||
self.is_beta = False
|
||||
if self.observed:
|
||||
self.observed = None
|
||||
@ -306,6 +307,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.body = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.stationtype = None
|
||||
self.coordinates = None
|
||||
self.started = None
|
||||
self.state = {
|
||||
@ -332,6 +334,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.body = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.stationtype = None
|
||||
self.coordinates = None
|
||||
self.started = timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ'))
|
||||
self.state.update({
|
||||
@ -374,6 +377,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.state['PaintJob'] = self.canonicalise(entry.get('BuyItem'))
|
||||
elif entry['event'] in ['Undocked']:
|
||||
self.station = None
|
||||
self.stationtype = None
|
||||
elif entry['event'] in ['Location', 'FSDJump', 'Docked']:
|
||||
if entry['event'] != 'Docked':
|
||||
self.body = None
|
||||
@ -383,6 +387,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.coordinates = None # Docked event doesn't include coordinates
|
||||
self.system = entry['StarSystem'] == 'ProvingGround' and 'CQC' or entry['StarSystem']
|
||||
self.station = entry.get('StationName') # May be None
|
||||
self.stationtype = entry.get('StationType') # May be None
|
||||
elif entry['event'] == 'SupercruiseExit':
|
||||
self.body = entry.get('BodyType') == 'Planet' and entry.get('Body')
|
||||
elif entry['event'] == 'SupercruiseEntry':
|
||||
@ -454,6 +459,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.body = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.stationtype = None
|
||||
self.coordinates = None
|
||||
elif entry['event'] == 'ChangeCrewRole':
|
||||
self.role = entry['Role'] != 'Idle' and entry['Role'] or None
|
||||
@ -463,6 +469,7 @@ class EDLogs(FileSystemEventHandler):
|
||||
self.body = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.stationtype = None
|
||||
self.coordinates = None
|
||||
|
||||
return entry
|
||||
|
68
plugins/eddb.py
Normal file
68
plugins/eddb.py
Normal file
@ -0,0 +1,68 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Station display and eddb.io lookup
|
||||
#
|
||||
|
||||
|
||||
import cPickle
|
||||
import csv
|
||||
import os
|
||||
from os.path import dirname, join, normpath
|
||||
import sys
|
||||
|
||||
import Tkinter as tk
|
||||
from ttkHyperlinkLabel import HyperlinkLabel
|
||||
|
||||
from config import config
|
||||
|
||||
|
||||
STATION_UNDOCKED = u'×' # "Station" name to display when not docked = U+00D7
|
||||
|
||||
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:
|
||||
this.system_ids = cPickle.load(h)
|
||||
|
||||
with open(join(config.respath, 'stations.p'), 'rb') as h:
|
||||
this.station_ids = cPickle.load(h)
|
||||
|
||||
|
||||
# system_name -> system_id or 0
|
||||
def system_id(system_name):
|
||||
return this.system_ids.get(system_name, 0) # return 0 on failure (0 is not a valid id)
|
||||
|
||||
# (system_name, station_name) -> station_id or 0
|
||||
def station_id(system_name, station_name):
|
||||
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():
|
||||
return '~eddb'
|
||||
|
||||
def plugin_app(parent):
|
||||
this.station_label = tk.Label(parent, text = _('Station') + ':') # Main window
|
||||
this.station = HyperlinkLabel(parent, url = station_url, popup_copy = lambda x: x != STATION_UNDOCKED)
|
||||
return (this.station_label, this.station)
|
||||
|
||||
def prefs_changed():
|
||||
this.station_label['text'] = _('Station') + ':'
|
||||
|
||||
def journal_entry(cmdr, system, station, entry, state):
|
||||
this.system = system
|
||||
this.station['text'] = station or (system_id(system) and STATION_UNDOCKED or '')
|
||||
|
||||
def cmdr_data(data):
|
||||
this.station['text'] = data['commander']['docked'] and data['lastStarport']['name'] or (system_id(data['lastSystem']['name']) and STATION_UNDOCKED or '')
|
3
setup.py
3
setup.py
@ -65,6 +65,7 @@ if sys.platform=='darwin':
|
||||
APP = 'EDMarketConnector.py'
|
||||
APPCMD = 'EDMC.py'
|
||||
SHORTVERSION = ''.join(VERSION.split('.')[:3])
|
||||
PLUGINS = [ 'plugins/eddb.py' ]
|
||||
|
||||
if sys.platform=='darwin':
|
||||
OPTIONS = { 'py2app':
|
||||
@ -74,6 +75,7 @@ if sys.platform=='darwin':
|
||||
'frameworks': [ 'Sparkle.framework' ],
|
||||
'excludes': [ 'certifi', 'PIL', 'simplejson' ],
|
||||
'iconfile': '%s.icns' % APPNAME,
|
||||
'extra_scripts': PLUGINS,
|
||||
'resources': ['snd_good.wav', 'snd_bad.wav', 'modules.p', 'ships.p', 'stations.p', 'systems.p'],
|
||||
'semi_standalone': True,
|
||||
'site_packages': False,
|
||||
@ -117,6 +119,7 @@ elif sys.platform=='win32':
|
||||
'systems.p',
|
||||
'%s.VisualElementsManifest.xml' % APPNAME,
|
||||
'%s.ico' % APPNAME ] +
|
||||
PLUGINS +
|
||||
[join('L10n',x) for x in os.listdir('L10n') if x.endswith('.strings')] ) ]
|
||||
|
||||
setup(
|
||||
|
BIN
stations.p
BIN
stations.p
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user