1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-17 01:22:19 +03:00

Merge pull request #131 from Marginal/2.2

Preparatory changes for 2.2
This commit is contained in:
Jonathan Harris 2016-07-25 20:22:36 +01:00 committed by GitHub
commit 9708345346
20 changed files with 51 additions and 570 deletions

View File

@ -41,12 +41,10 @@ import eddn
import edsm
import loadout
import coriolis
import flightlog
import eddb
import stats
import prefs
import plug
from edproxy import edproxy
from hotkey import hotkeymgr
from monitor import monitor
from theme import theme
@ -252,8 +250,6 @@ class AppWindow:
monitor.set_callback('Dock', self.getandsend)
monitor.set_callback('Jump', self.system_change)
monitor.start(self.w)
edproxy.set_callback(self.system_change)
edproxy.start(self.w)
# First run
if not config.get('username') or not config.get('password'):
@ -309,15 +305,6 @@ class AppWindow:
if __debug__: print_exc()
self.status['text'] = unicode(e)
# Try to obtain exclusive lock on flight log ASAP
if config.getint('output') & config.OUT_LOG_FILE:
try:
flightlog.openlog()
except Exception as e:
if __debug__: print_exc()
if not self.status['text']:
self.status['text'] = unicode(e)
if not getattr(sys, 'frozen', False):
self.updater.checkForUpdates() # Sparkle / WinSparkle does this automatically for packaged apps
@ -390,23 +377,17 @@ class AppWindow:
loadout.export(data)
if config.getint('output') & config.OUT_SHIP_CORIOLIS:
coriolis.export(data)
if config.getint('output') & config.OUT_LOG_FILE:
flightlog.export(data)
if config.getint('output') & config.OUT_LOG_EDSM:
# Catch any EDSM errors here so that they don't prevent station update
if config.getint('output') & config.OUT_SYS_EDSM:
# Silently catch any EDSM errors here so that they don't prevent station update
try:
self.status['text'] = _('Sending data to EDSM...')
self.w.update_idletasks()
edsm.export(data, lambda:self.edsm.lookup(self.system['text'], EDDB.system(self.system['text']))) # Do EDSM lookup during EDSM export
self.status['text'] = ''
self.edsm.lookup(self.system['text'], EDDB.system(self.system['text']))
except Exception as e:
if __debug__: print_exc()
self.status['text'] = unicode(e)
else:
self.edsm.link(self.system['text'])
self.edsmpoll()
if not (config.getint('output') & (config.OUT_CSV|config.OUT_TD|config.OUT_BPC|config.OUT_EDDN)):
if not (config.getint('output') & (config.OUT_MKT_CSV|config.OUT_MKT_TD|config.OUT_MKT_BPC|config.OUT_MKT_EDDN)):
# no station data requested - we're done
pass
@ -421,25 +402,25 @@ class AppWindow:
# No EDDN output?
if (config.getint('output') & config.OUT_EDDN) and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')): # Ignore possibly missing shipyard info
if (config.getint('output') & config.OUT_MKT_EDDN) and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')): # Ignore possibly missing shipyard info
if not self.status['text']:
self.status['text'] = _("Station doesn't have anything!")
# No market output?
elif not (config.getint('output') & config.OUT_EDDN) and not data['lastStarport'].get('commodities'):
elif not (config.getint('output') & config.OUT_MKT_EDDN) and not data['lastStarport'].get('commodities'):
if not self.status['text']:
self.status['text'] = _("Station doesn't have a market!")
else:
if data['lastStarport'].get('commodities'):
if config.getint('output') & config.OUT_CSV:
if config.getint('output') & config.OUT_MKT_CSV:
commodity.export(data, COMMODITY_CSV)
if config.getint('output') & config.OUT_TD:
if config.getint('output') & config.OUT_MKT_TD:
td.export(data)
if config.getint('output') & config.OUT_BPC:
if config.getint('output') & config.OUT_MKT_BPC:
commodity.export(data, COMMODITY_BPC)
if config.getint('output') & config.OUT_EDDN:
if config.getint('output') & config.OUT_MKT_EDDN:
old_status = self.status['text']
if not old_status:
self.status['text'] = _('Sending data to EDDN...')
@ -507,9 +488,7 @@ class AppWindow:
plug.notify_system_changed(timestamp, system, coordinates)
if config.getint('output') & config.OUT_LOG_FILE:
flightlog.writelog(timestamp, system)
if config.getint('output') & config.OUT_LOG_EDSM:
if config.getint('output') & config.OUT_SYS_EDSM:
try:
self.status['text'] = _('Sending data to EDSM...')
self.w.update_idletasks()
@ -590,7 +569,6 @@ class AppWindow:
def onexit(self, event=None):
hotkeymgr.unregister()
flightlog.close()
if platform!='darwin' or self.w.winfo_rooty()>0: # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
config.set('geometry', '+{1}+{2}'.format(*self.w.geometry().split('+')))
config.close()

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Vzhled";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Automaticky vytvořit záznam při vstoupení do systému";
/* Output setting. [prefs.py] */
"Automatically update on docking" = "Automaticky aktualizovat při zadokování";
@ -73,9 +70,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Připojeno k {EDPROXY} na {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Čekej {SS}s";
@ -172,9 +166,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Cesta k souboru";
/* [prefs.py] */
"Flight log in CSV format file" = "Letový záznam ve formátu CSV";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Aussehen";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Automatisch Logbucheintrag bei Systemeintritt anlegen";
/* Output setting. [prefs.py] */
"Automatically update on docking" = "Automatisch beim Andocken aktualisieren";
@ -73,9 +70,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Kompetent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Verbunden mit {EDPROXY} bei {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Wartezeit {SS}s";
@ -172,9 +166,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Speicherort";
/* [prefs.py] */
"Flight log in CSV format file" = "Fluglogbuch im CSV-Format";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Appearance";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Automatically make a log entry on entering a system";
/* Output setting. [prefs.py] */
"Automatically update on docking" = "Automatically update on docking";
@ -73,9 +70,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "cooldown {SS}s";
@ -172,9 +166,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "File location";
/* [prefs.py] */
"Flight log in CSV format file" = "Flight log in CSV format file";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Apariencia";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Crear automáticamente una entrada en el registro al entrar en un sistema";
/* Output setting. [prefs.py] */
"Automatically update on docking" = "Actualizar automáticamente al atracar";
@ -73,9 +70,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competente";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Conectado a {EDPROXY} en {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Espere {SS}s";
@ -172,9 +166,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Localización de archivos";
/* [prefs.py] */
"Flight log in CSV format file" = "Registro de vuelo en formato CSV";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiador";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Apparence";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Ajouter automatiquement une entrée au journal en entrant dans un système";
/* Cmdr stats. [stats.py] */
"Balance" = "Solde";
@ -70,9 +67,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Compétent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connecté à {EDPROXY} sur {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Temps de recharge {SS}s";
@ -169,9 +163,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Emplacement des fichiers";
/* [prefs.py] */
"Flight log in CSV format file" = "Journal de vol au format CSV";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Aspetto";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Inserisce automaticamente una log entry entrando in un sistema";
/* Cmdr stats. [stats.py] */
"Balance" = "Saldo";
@ -70,9 +67,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connesso a {EDPROXY} all'indirizzo {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "disponibile tra {SS} secondi";
@ -169,9 +163,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Percorso del file";
/* [prefs.py] */
"Flight log in CSV format file" = "Flight log in formato CSV";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "表示";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "別の星系に移動したら自動的にフライトログを記録する";
/* Output setting. [prefs.py] */
"Automatically update on docking" = "ドッキングした際に自動でデータを更新する";
@ -73,9 +70,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "{ADDR} の {EDPROXY} に接続しました";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "次回更新まであと {SS}秒";
@ -172,9 +166,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "ファイルの出力先";
/* [prefs.py] */
"Flight log in CSV format file" = "フライトログをCSV形式で記録する";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Izskats";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Automātiski veikt ierakstu ierodoties sistēmā";
/* Cmdr stats. [stats.py] */
"Balance" = "Bilance";
@ -70,9 +67,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Atskaite {SS}";
@ -169,9 +163,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Faila atrašanās vieta";
/* [prefs.py] */
"Flight log in CSV format file" = "Lidojuma ieraksts SCV formāta failā";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiators";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Vormgeving";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Automatisch een log regel aanmaken bij het binnengaan van een stelsel";
/* Output setting. [prefs.py] */
"Automatically update on docking" = "Automatisch bijwerken na landing";
@ -73,9 +70,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Verbonden met {EDPROXY} via {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "wachtperiode {SS}s";
@ -172,9 +166,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Bestand locatie";
/* [prefs.py] */
"Flight log in CSV format file" = "Vlucht log in CSV bestand formaat";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Wygląd";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Stwórz automatycznie wpis w logu po wejściu do systemu";
/* Cmdr stats. [stats.py] */
"Balance" = "Saldo";
@ -70,9 +67,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Połąćzono do {EDPROXY} na {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Oczekiwanie {SS} sek.";
@ -169,9 +163,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Położenie pliku";
/* [prefs.py] */
"Flight log in CSV format file" = "Dziennik lotu w formacie CSV";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Внешний вид";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Автоматически заносить в журнал полета каждую посещённую систему";
/* Cmdr stats. [stats.py] */
"Balance" = "Баланс";
@ -70,9 +67,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Специалист";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "пауза {SS} сек";
@ -169,9 +163,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Сохранять файлы";
/* [prefs.py] */
"Flight log in CSV format file" = "Журнал полета в формате CSV";
/* CQC rank. [stats.py] */
"Gladiator" = "Гладиатор";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Videz";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Shrani podatke v dnevnik leta, ko prispeš v sistem";
/* Cmdr stats. [stats.py] */
"Balance" = "Ravnotežje";
@ -70,9 +67,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Posodobitev v {SS}s";
@ -169,9 +163,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Lokacija datoteke";
/* [prefs.py] */
"Flight log in CSV format file" = "Dnevnik leta v CSV formatu";
/* CQC rank. [stats.py] */
"Gladiator" = "Gladiator";

View File

@ -25,9 +25,6 @@
/* Tab heading in settings. [prefs.py] */
"Appearance" = "Зовнішній вигляд";
/* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Автоматично робити запис у журналі на вході в систему";
/* Cmdr stats. [stats.py] */
"Balance" = "Баланс";
@ -70,9 +67,6 @@
/* Combat rank. [stats.py] */
"Competent" = "Компетентний";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Підключено до {EDPROXY}, адреса {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "очикування {SS} сек";
@ -169,9 +163,6 @@
/* Section heading in settings. [prefs.py] */
"File location" = "Росташування файлу";
/* [prefs.py] */
"Flight log in CSV format file" = "Журнал (log) в CSV форматі";
/* CQC rank. [stats.py] */
"Gladiator" = "Гладіатор";

View File

@ -70,17 +70,17 @@ elif platform=='linux2':
class Config:
OUT_EDDN = 1
OUT_BPC = 2
OUT_TD = 4
OUT_CSV = 8
OUT_SHIP_EDS = 16
OUT_LOG_FILE = 32
#OUT_STAT = 64 # No longer available
OUT_MKT_EDDN = 1
OUT_MKT_BPC = 2
OUT_MKT_TD = 4
OUT_MKT_CSV = 8
OUT_SHIP_EDS = 16
# OUT_SYS_FILE = 32 # No longer supported
# OUT_STAT = 64 # No longer available
OUT_SHIP_CORIOLIS = 128
OUT_LOG_EDSM = 256
OUT_LOG_AUTO = 512
OUT_MANUAL = 1024
OUT_SYS_EDSM = 256
# OUT_SYS_AUTO = 512 # Now always automatic
OUT_MKT_MANUAL = 1024
if platform=='darwin':

View File

@ -1,155 +0,0 @@
#
# Elite: Dangerous Netlog Proxy Server client - https://bitbucket.org/westokyo/edproxy/
#
import json
import socket
import struct
import sys
import threading
from time import time, strptime, mktime
from datetime import datetime
from calendar import timegm
if __debug__:
from traceback import print_exc
from config import config
class _EDProxy:
DISCOVERY_ADDR = '239.45.99.98'
DISCOVERY_PORT = 45551
DISCOVERY_QUERY = 'Query'
DISCOVERY_ANNOUNCE = 'Announce'
SERVICE_NAME = 'edproxy'
SERVICE_HEARTBEAT = 60 # [s]
SERVICE_TIMEOUT = 90 # [s]
MESSAGE_MAX = 1024 # https://bitbucket.org/westokyo/edproxy/src/master/ednet.py?fileviewer=file-view-default#ednet.py-166
MESSAGE_SYSTEM = 'System'
def __init__(self):
self.root = None
self.lock = threading.Lock()
self.addr = None
self.port = None
thread = threading.Thread(target = self._listener)
thread.daemon = True
thread.start()
self.callback = None
self.last_event = None # for communicating the Jump event
# start
self.discover_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.discover()
def set_callback(self, callback):
self.callback = callback
def start(self, root):
self.root = root
self.root.bind_all('<<ProxyJump>>', self.jump) # user-generated
def stop(self):
# Still listening, but stop callbacks
if self.root:
self.root.unbind_all('<<ProxyJump>>')
def status(self):
self.lock.acquire()
if self.addr and self.port:
status = '%s:%d' % (self.addr, self.port)
self.lock.release()
return status
else:
self.lock.release()
self.discover() # Kick off discovery
return None
def jump(self, event):
# Called from Tkinter's main loop
if self.callback and self.last_event:
self.callback(event, *self.last_event)
def close():
self.discover_sock.shutdown()
self.discover_sock = None
# Send a query. _listener should get the response.
def discover(self):
self.discover_sock.sendto(json.dumps({
'type': self.DISCOVERY_QUERY,
'name': self.SERVICE_NAME,
}), (self.DISCOVERY_ADDR, self.DISCOVERY_PORT))
def _listener(self):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
if sys.platform == 'win32':
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
else:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind(('', self.DISCOVERY_PORT))
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, struct.pack('4sL', socket.inet_aton(self.DISCOVERY_ADDR), socket.INADDR_ANY))
while True:
try:
(data, addr) = s.recvfrom(self.MESSAGE_MAX)
msg = json.loads(data)
if msg['name'] == self.SERVICE_NAME and msg['type'] == self.DISCOVERY_ANNOUNCE:
# ignore if already connected to a proxy
if not self.addr or not self.port:
thread = threading.Thread(target = self._worker, args = (msg['ipv4'], int(msg['port'])))
thread.daemon = True
thread.start()
except:
if __debug__: print_exc()
def _worker(self, addr, port):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((addr, port))
s.settimeout(0)
s.sendall(json.dumps({
'Type' : 'Init',
'DateUtc' : datetime.utcnow().isoformat(),
'StartTime' : 'now',
'Register' : [ 'System' ],
}))
except:
if __debug__: print_exc()
return
self.lock.acquire()
self.addr = addr
self.port = port
self.lock.release()
try:
s.settimeout(None) # was self.SERVICE_TIMEOUT, but heartbeat doesn't appear to work so wait indefinitely
while True:
msg = json.loads(s.recv(self.MESSAGE_MAX))
if msg['Type'] == self.MESSAGE_SYSTEM and config.getint('output') & config.OUT_LOG_AUTO:
if 'DateUtc' in msg:
timestamp = timegm(datetime.strptime(msg['DateUtc'], '%Y-%m-%d %H:%M:%S').utctimetuple())
else:
timestamp = mktime(strptime(msg['Date'], '%Y-%m-%d %H:%M:%S')) # from local time
self.last_event = (timestamp, msg['System'], None)
self.root.event_generate('<<ProxyJump>>', when="tail")
except:
if __debug__: print_exc()
self.lock.acquire()
self.addr = self.port = None
self.lock.release()
# Kick off discovery for another proxy
self.discover()
# singleton
edproxy = _EDProxy()

19
edsm.py
View File

@ -7,7 +7,6 @@ import urllib
import Tkinter as tk
from config import applongname, appversion, config
import flightlog
if __debug__:
from traceback import print_exc
@ -139,21 +138,3 @@ def writelog(timestamp, system, edsmlookupfn, coordinates=None):
# 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))
if not config.getint('edsm_historical'):
config.set('edsm_historical', 1)
thread = threading.Thread(target = export_historical, name = 'EDSM export')
thread.daemon = True
thread.start()
# Make best effort to export existing flight log file. Be silent on error.
def export_historical():
try:
for (timestamp, system_name) in flightlog.logs():
r = requests.get('https://www.edsm.net/api-logs-v1/set-log?commanderName=%s&apiKey=%s&systemName=%s&dateVisited=%s&fromSoftware=%s&fromSoftwareVersion=%s' % (urllib.quote(config.get('edsm_cmdrname').encode('utf-8')), urllib.quote(config.get('edsm_apikey')), urllib.quote(system_name), urllib.quote(time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(timestamp))), urllib.quote(applongname), urllib.quote(appversion)), timeout=EDSM._TIMEOUT)
r.raise_for_status()
if r.json()['msgnum'] // 100 == 2:
raise Exception()
except:
if __debug__: print_exc()

View File

@ -1,105 +0,0 @@
# Export poor man's flight log
from collections import defaultdict
import errno
import os
from os.path import join
from sys import platform
import time
from config import config
from companion import ship_map
logfile = None
last_timestamp = last_system = last_ship = None
last_commodities = {}
def openlog():
global logfile
if logfile: return
try:
logfile = open(join(config.get('outdir'), 'Flight Log.csv'), 'a+b')
if platform != 'win32': # open for writing is automatically exclusive on Windows
from fcntl import lockf, LOCK_SH, LOCK_NB
lockf(logfile, LOCK_SH|LOCK_NB)
logfile.seek(0, os.SEEK_END)
if not logfile.tell():
logfile.write('Date,Time,System,Station,Ship,Cargo\r\n')
except EnvironmentError as e:
logfile = None
if e.errno in [errno.EACCES, errno.EAGAIN]:
raise Exception('Can\'t write "Flight Log.csv". Are you editing it in another app?')
else:
raise
except:
logfile = None
raise
def export(data):
querytime = config.getint('querytime') or int(time.time())
commodities = defaultdict(int)
for item in data['ship'].get('cargo',{}).get('items',[]):
if item['commodity'] != 'drones':
commodities[item['commodity']] += item['qty']
writelog(querytime,
data['lastSystem']['name'],
data['commander']['docked'] and data['lastStarport']['name'],
ship_map.get(data['ship']['name'].lower(), data['ship']['name']),
commodities)
def writelog(timestamp, system, station=None, ship=None, commodities={}):
global last_timestamp, last_system, last_ship, last_commodities
if last_system and last_system != system:
_writelog(last_timestamp, last_system, None, last_ship, last_commodities)
if not station:
# If not docked, hold off writing log entry until docked or until system changes
last_timestamp, last_system, last_ship, last_commodities = timestamp, system, ship, commodities
else:
last_system = None
_writelog(timestamp, system, station, ship, commodities)
def _writelog(timestamp, system, station=None, ship=None, commodities={}):
openlog()
logfile.write('%s,%s,%s,%s,%s,%s\r\n' % (
time.strftime('%Y-%m-%d', time.localtime(timestamp)),
time.strftime('%H:%M:%S', time.localtime(timestamp)),
system,
station or '',
ship or '',
','.join([('%d %s' % (commodities[k], k)) for k in sorted(commodities)])))
logfile.flush()
def close():
global last_timestamp, last_system
if last_system:
_writelog(last_timestamp, last_system, None, last_ship, last_commodities)
last_system = None
# return log as list of (timestamp, system_name)
def logs():
entries = []
with open(join(config.get('outdir'), 'Flight Log.csv'), 'rU') as f:
f.readline() # Assume header
for line in f:
if not line.strip(): continue
cols = line.split(',')
assert len(cols) >= 3, cols
entries.append((time.mktime(time.strptime('%sT%s' % (cols[0], cols[1]), '%Y-%m-%dT%H:%M:%S')), cols[2])) # Convert from local time to UTC
return entries

View File

@ -70,52 +70,6 @@ class EDLogs(FileSystemEventHandler):
self.callbacks = { 'Jump': None, 'Dock': None }
self.last_event = None # for communicating the Jump event
def logging_enabled_in_file(self, appconf):
if not isfile(appconf):
return False
with open(appconf, 'rU') as f:
content = f.read().lower()
start = content.find('<network')
end = content.find('</network>')
if start >= 0 and end >= 0:
return bool(re.search('verboselogging\s*=\s*\"1\"', content[start+8:end]))
else:
return False
def enable_logging_in_file(self, appconf):
try:
if not exists(appconf):
with open(appconf, 'wt') as f:
f.write('<AppConfig>\n\t<Network\n\t\tVerboseLogging="1"\n\t>\n\t</Network>\n</AppConfig>\n')
return True
with open(appconf, 'rU') as f:
content = f.read()
f.close()
backup = appconf[:-4] + '_backup.xml'
if exists(backup):
unlink(backup)
rename(appconf, backup)
with open(appconf, 'wt') as f:
start = content.lower().find('<network')
if start >= 0:
f.write(content[:start+8] + '\n\t\tVerboseLogging="1"' + content[start+8:])
else:
start = content.lower().find("</appconfig>")
if start >= 0:
f.write(content[:start] + '\t<Network\n\t\tVerboseLogging="1"\n\t>\n\t</Network>\n' + content[start:])
else:
f.write(content) # eh ?
return False
assert self._logging_enabled()
return self.logging_enabled_in_file(appconf)
except:
if __debug__: print_exc()
return False
def set_callback(self, name, callback):
if name in self.callbacks:
self.callbacks[name] = callback
@ -127,9 +81,6 @@ class EDLogs(FileSystemEventHandler):
return False
if self.running():
return True
if not self._logging_enabled():
# verbose logging reduces likelihood that Docked/Undocked messages will be delayed
self._enable_logging()
self.root.bind_all('<<MonitorJump>>', self.jump) # user-generated
self.root.bind_all('<<MonitorDock>>', self.dock) # user-generated
@ -203,7 +154,7 @@ class EDLogs(FileSystemEventHandler):
while True:
if docked and not updated and not config.getint('output') & config.OUT_MANUAL:
if docked and not updated and not config.getint('output') & config.OUT_MKT_MANUAL:
self.root.event_generate('<<MonitorDock>>', when="tail")
updated = True
if __debug__:
@ -239,7 +190,7 @@ class EDLogs(FileSystemEventHandler):
if __debug__:
print "%s :\t%s %s" % (match.group(2), docked and " docked" or "!docked", updated and " updated" or "!updated")
if system and not docked and config.getint('output') & config.OUT_LOG_AUTO:
if system and not docked and config.getint('output'):
# Convert local time string to UTC date and time
visited_struct = strptime(visited, '%H:%M:%S')
now = localtime()
@ -278,13 +229,6 @@ class EDLogs(FileSystemEventHandler):
else:
return None
def _logging_enabled(self):
return self.logdir and self.logging_enabled_in_file(join(self.logdir, pardir, 'AppConfigLocal.xml'))
def _enable_logging(self):
return self.logdir and self.enable_logging_in_file(join(self.logdir, pardir, 'AppConfigLocal.xml'))
elif platform=='win32':
def _logdir(self):
@ -360,25 +304,10 @@ class EDLogs(FileSystemEventHandler):
return None
def _logging_enabled(self):
return self.logdir and (self.logging_enabled_in_file(join(self.logdir, pardir, 'AppConfigLocal.xml')) or
self.logging_enabled_in_file(join(self.logdir, pardir, 'AppConfig.xml')))
def _enable_logging(self):
return self.logdir and self.enable_logging_in_file(isfile(join(self.logdir, pardir, 'AppConfigLocal.xml')) and join(self.logdir, pardir, 'AppConfigLocal.xml') or join(self.logdir, pardir, 'AppConfig.xml'))
elif platform=='linux2':
def _logdir(self):
return None
def _logging_enabled(self):
return False
def _enable_logging(self):
return False
# singleton
monitor = EDLogs()

View File

@ -11,7 +11,6 @@ from ttkHyperlinkLabel import HyperlinkLabel
import myNotebook as nb
from config import applongname, config
from edproxy import edproxy
from hotkey import hotkeymgr
from l10n import Translations
from monitor import monitor
@ -114,33 +113,27 @@ class PreferencesDialog(tk.Toplevel):
outframe = nb.Frame(notebook)
outframe.columnconfigure(0, weight=1)
output = config.getint('output') or (config.OUT_EDDN | config.OUT_SHIP_EDS) # default settings
output = config.getint('output') or (config.OUT_MKT_EDDN | config.OUT_SHIP_EDS) # default settings
nb.Label(outframe, text=_('Please choose what data to save')).grid(columnspan=2, padx=PADX, sticky=tk.W)
self.out_eddn= tk.IntVar(value = (output & config.OUT_EDDN) and 1)
self.out_eddn= tk.IntVar(value = (output & config.OUT_MKT_EDDN) and 1)
nb.Checkbutton(outframe, text=_('Send station data to the Elite Dangerous Data Network'), variable=self.out_eddn, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_csv = tk.IntVar(value = (output & config.OUT_CSV ) and 1)
self.out_csv = tk.IntVar(value = (output & config.OUT_MKT_CSV ) and 1)
nb.Checkbutton(outframe, text=_('Market data in CSV format file'), variable=self.out_csv, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_bpc = tk.IntVar(value = (output & config.OUT_BPC ) and 1)
self.out_bpc = tk.IntVar(value = (output & config.OUT_MKT_BPC ) and 1)
nb.Checkbutton(outframe, text=_("Market data in Slopey's BPC format file"), variable=self.out_bpc, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_td = tk.IntVar(value = (output & config.OUT_TD ) and 1)
self.out_td = tk.IntVar(value = (output & config.OUT_MKT_TD ) and 1)
nb.Checkbutton(outframe, text=_('Market data in Trade Dangerous format file'), variable=self.out_td, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_auto = tk.IntVar(value = 0 if output & config.OUT_MANUAL else 1) # inverted
self.out_auto_button = nb.Checkbutton(outframe, text=_('Automatically update on docking'), variable=self.out_auto, command=self.outvarchanged) # Output setting
self.out_auto_button.grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_ship_eds= tk.IntVar(value = (output & config.OUT_SHIP_EDS) and 1)
nb.Checkbutton(outframe, text=_('Ship loadout in E:D Shipyard format file'), variable=self.out_ship_eds, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, pady=(5,0), sticky=tk.W)
self.out_ship_coriolis= tk.IntVar(value = (output & config.OUT_SHIP_CORIOLIS) and 1)
nb.Checkbutton(outframe, text=_('Ship loadout in Coriolis format file'), variable=self.out_ship_coriolis, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_log_file = tk.IntVar(value = (output & config.OUT_LOG_FILE) and 1)
nb.Checkbutton(outframe, text=_('Flight log in CSV format file'), variable=self.out_log_file, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, pady=(5,0), sticky=tk.W)
self.out_log_auto = tk.IntVar(value = output & config.OUT_LOG_AUTO and 1 or 0)
self.out_log_auto_button = nb.Checkbutton(outframe, text=_('Automatically make a log entry on entering a system'), variable=self.out_log_auto, command=self.outvarchanged) # Output setting
self.out_log_auto_button.grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.out_log_auto_text = nb.Label(outframe, foreground='firebrick')
self.out_log_auto_text.grid(columnspan=2, padx=(30,0), sticky=tk.W)
self.out_auto = tk.IntVar(value = 0 if output & config.OUT_MKT_MANUAL else 1) # inverted
self.out_auto_button = nb.Checkbutton(outframe, text=_('Automatically update on docking'), variable=self.out_auto, command=self.outvarchanged) # Output setting
self.out_auto_button.grid(columnspan=2, padx=BUTTONX, pady=(5,0), sticky=tk.W)
self.outdir_label = nb.Label(outframe, text=_('File location')) # Section heading in settings
self.outdir_label.grid(padx=BUTTONX, sticky=tk.W)
self.outdir_label.grid(padx=BUTTONX, pady=(5,0), sticky=tk.W)
self.outdir = nb.Entry(outframe, takefocus=False)
if config.get('outdir').startswith(config.home):
self.outdir.insert(0, '~' + config.get('outdir')[len(config.home):])
@ -159,14 +152,11 @@ class PreferencesDialog(tk.Toplevel):
edsmframe.columnconfigure(1, weight=1)
HyperlinkLabel(edsmframe, text='Elite Dangerous Star Map', background=nb.Label().cget('background'), url='https://www.edsm.net/', underline=True).grid(columnspan=2, padx=PADX, sticky=tk.W) # Don't translate
ttk.Separator(edsmframe, orient=tk.HORIZONTAL).grid(columnspan=2, padx=PADX, pady=PADY, sticky=tk.EW)
self.out_log_edsm = tk.IntVar(value = (output & config.OUT_LOG_EDSM) and 1)
nb.Checkbutton(edsmframe, text=_('Send flight log to Elite Dangerous Star Map'), variable=self.out_log_edsm, command=self.outvarchanged).grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.edsm_log_auto_button = nb.Checkbutton(edsmframe, text=_('Automatically make a log entry on entering a system'), variable=self.out_log_auto, command=self.outvarchanged) # Output setting
self.edsm_log_auto_button.grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
self.edsm_log_auto_text = nb.Label(edsmframe, foreground='firebrick')
self.edsm_log_auto_text.grid(columnspan=2, padx=(30,0), sticky=tk.W)
self.edsm_log = tk.IntVar(value = (output & config.OUT_SYS_EDSM) and 1)
self.edsm_log_button = nb.Checkbutton(edsmframe, text=_('Send flight log to Elite Dangerous Star Map'), variable=self.edsm_log, command=self.outvarchanged)
self.edsm_log_button.grid(columnspan=2, padx=BUTTONX, sticky=tk.W)
nb.Label(edsmframe).grid(sticky=tk.W) # big spacer
self.edsm_label = HyperlinkLabel(edsmframe, text=_('Elite Dangerous Star Map credentials'), background=nb.Label().cget('background'), url='https://www.edsm.net/settings/api', underline=True) # Section heading in settings
self.edsm_label.grid(columnspan=2, padx=PADX, sticky=tk.W)
@ -270,7 +260,7 @@ class PreferencesDialog(tk.Toplevel):
self.protocol("WM_DELETE_WINDOW", self._destroy)
# Selectively disable buttons depending on output settings
self.proxypoll()
self.outvarchanged()
self.themevarchanged()
# disable hotkey for the duration
@ -282,41 +272,23 @@ class PreferencesDialog(tk.Toplevel):
self.grab_set()
def proxypoll(self):
self.outvarchanged()
self.after(1000, self.proxypoll)
def outvarchanged(self):
local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship_eds.get() or self.out_ship_coriolis.get() or self.out_log_file.get()
self.out_auto_button['state'] = monitor.logdir and tk.NORMAL or tk.DISABLED
local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship_eds.get() or self.out_ship_coriolis.get()
self.outdir_label['state'] = local and tk.NORMAL or tk.DISABLED
self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED
self.outdir['state'] = local and 'readonly' or tk.DISABLED
edsm_state = self.out_log_edsm.get() and tk.NORMAL or tk.DISABLED
self.edsm_log_button['state'] = monitor.logdir and tk.NORMAL or tk.DISABLED
edsm_state = self.edsm_log.get() and tk.NORMAL or tk.DISABLED
self.edsm_label['state'] = edsm_state
self.edsm_cmdr_label['state'] = edsm_state
self.edsm_apikey_label['state'] = edsm_state
self.edsm_cmdr['state'] = edsm_state
self.edsm_apikey['state'] = edsm_state
proxyaddr = edproxy.status()
self.out_log_auto_text['text'] = ''
self.edsm_log_auto_text['text'] = ''
if monitor.logdir or proxyaddr:
self.out_auto_button['state'] = monitor.logdir and tk.NORMAL or tk.DISABLED # edproxy doesn't send docking status
self.out_log_auto_button['state'] = self.out_log_file.get() and tk.NORMAL or tk.DISABLED
if self.out_log_file.get() and self.out_log_auto.get() and proxyaddr:
self.out_log_auto_text['text'] = _('Connected to {EDPROXY} at {ADDR}').format(EDPROXY = 'edproxy', ADDR = proxyaddr) # Output settings
self.edsm_log_auto_button['state'] = edsm_state
if self.out_log_edsm.get() and self.out_log_auto.get() and proxyaddr:
self.edsm_log_auto_text['text'] = _('Connected to {EDPROXY} at {ADDR}').format(EDPROXY = 'edproxy', ADDR = proxyaddr) # Output settings
else:
self.out_auto_button['state'] = tk.DISABLED
self.out_log_auto_button['state'] = tk.DISABLED
self.edsm_log_auto_button['state'] = tk.DISABLED
def outbrowse(self):
if platform != 'win32':
import tkFileDialog
@ -418,16 +390,14 @@ class PreferencesDialog(tk.Toplevel):
config.set('password', self.password.get().strip())
config.set('output',
(self.out_eddn.get() and config.OUT_EDDN) +
(self.out_bpc.get() and config.OUT_BPC) +
(self.out_td.get() and config.OUT_TD) +
(self.out_csv.get() and config.OUT_CSV) +
(config.OUT_MANUAL if not self.out_auto.get() else 0) +
(self.out_ship_eds.get() and config.OUT_SHIP_EDS) +
(self.out_eddn.get() and config.OUT_MKT_EDDN) +
(self.out_bpc.get() and config.OUT_MKT_BPC) +
(self.out_td.get() and config.OUT_MKT_TD) +
(self.out_csv.get() and config.OUT_MKT_CSV) +
(config.OUT_MKT_MANUAL if not self.out_auto.get() else 0) +
(self.out_ship_eds.get() and config.OUT_SHIP_EDS) +
(self.out_ship_coriolis.get() and config.OUT_SHIP_CORIOLIS) +
(self.out_log_file.get() and config.OUT_LOG_FILE) +
(self.out_log_edsm.get() and config.OUT_LOG_EDSM) +
(self.out_log_auto.get() and config.OUT_LOG_AUTO))
(self.edsm_log.get() and config.OUT_SYS_EDSM))
config.set('outdir', self.outdir.get().startswith('~') and join(config.home, self.outdir.get()[2:]) or self.outdir.get())
config.set('edsm_cmdrname', self.edsm_cmdr.get().strip())