From b6a5d7b8edbd5b931b787a4f4d49b831e6467734 Mon Sep 17 00:00:00 2001
From: Jonathan Harris <jonathan@marginal.org.uk>
Date: Fri, 2 Sep 2016 19:58:20 +0100
Subject: [PATCH] Send data to EDDN with Keep-Alive

---
 EDMarketConnector.py |   2 +-
 eddn.py              | 137 +++++++++++++++++++++++--------------------
 2 files changed, 73 insertions(+), 66 deletions(-)

diff --git a/EDMarketConnector.py b/EDMarketConnector.py
index 2e0d9715..59b6e7bd 100755
--- a/EDMarketConnector.py
+++ b/EDMarketConnector.py
@@ -37,7 +37,7 @@ import companion
 import commodity
 from commodity import COMMODITY_BPC, COMMODITY_CSV
 import td
-import eddn
+from eddn import eddn
 import edsm
 import loadout
 import coriolis
diff --git a/eddn.py b/eddn.py
index e5960889..48e59889 100644
--- a/eddn.py
+++ b/eddn.py
@@ -14,78 +14,85 @@ from config import applongname, appversion, config
 from companion import category_map
 
 
-### upload = 'http://localhost:8081/upload/'	# testing
-upload = 'http://eddn-gateway.elite-markets.net:8080/upload/'
-
 timeout= 10	# requests timeout
 module_re = re.compile('^Hpt_|^Int_|_Armour_')
 
 
-def send(cmdr, msg):
-    msg['header'] = {
-        'softwareName'    : '%s [%s]' % (applongname, platform=='darwin' and "Mac OS" or system()),
-        'softwareVersion' : appversion,
-        'uploaderID'      : config.getint('anonymous') and hashlib.md5(cmdr.encode('utf-8')).hexdigest() or cmdr.encode('utf-8'),
-    }
-    msg['message']['timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(config.getint('querytime') or int(time.time())))
+class _EDDN:
 
-    r = requests.post(upload, data=json.dumps(msg), timeout=timeout)
-    if __debug__ and r.status_code != requests.codes.ok:
-        print 'Status\t%s'  % r.status_code
-        print 'URL\t%s'  % r.url
-        print 'Headers\t%s' % r.headers
-        print ('Content:\n%s' % r.text).encode('utf-8')
-    r.raise_for_status()
+    ### UPLOAD = 'http://localhost:8081/upload/'	# testing
+    UPLOAD = 'http://eddn-gateway.elite-markets.net:8080/upload/'
 
+    def __init__(self):
+        self.session = requests.Session()
 
-def export_commodities(data):
-    commodities = []
-    for commodity in data['lastStarport'].get('commodities') or []:
-        if category_map.get(commodity['categoryname'], True):	# Check marketable
-            commodities.append(OrderedDict([
-                ('name',          commodity['name']),
-                ('meanPrice',     int(commodity['meanPrice'])),
-                ('buyPrice',      int(commodity['buyPrice'])),
-                ('stock',         int(commodity['stock'])),
-                ('stockBracket',  commodity['stockBracket']),
-                ('sellPrice',     int(commodity['sellPrice'])),
-                ('demand',        int(commodity['demand'])),
-                ('demandBracket', commodity['demandBracket']),
-            ]))
-            if commodity['statusFlags']:
-                commodities[-1]['statusFlags'] = commodity['statusFlags']
+    def send(self, cmdr, msg):
+        msg['header'] = {
+            'softwareName'    : '%s [%s]' % (applongname, platform=='darwin' and "Mac OS" or system()),
+            'softwareVersion' : appversion,
+            'uploaderID'      : config.getint('anonymous') and hashlib.md5(cmdr.encode('utf-8')).hexdigest() or cmdr.encode('utf-8'),
+        }
+        msg['message']['timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(config.getint('querytime') or int(time.time())))
 
-    # Don't send empty commodities list - schema won't allow it
-    if commodities:
-        send(data['commander']['name'], {
-            '$schemaRef' : 'http://schemas.elite-markets.net/eddn/commodity/3',
-            'message'    : {
-                'systemName'  : data['lastSystem']['name'],
-                'stationName' : data['lastStarport']['name'],
-                'commodities' : commodities,
-            }
-        })
+        r = self.session.post(self.UPLOAD, data=json.dumps(msg), timeout=timeout)
+        if __debug__ and r.status_code != requests.codes.ok:
+            print 'Status\t%s'  % r.status_code
+            print 'URL\t%s'  % r.url
+            print 'Headers\t%s' % r.headers
+            print ('Content:\n%s' % r.text).encode('utf-8')
+        r.raise_for_status()
 
-def export_outfitting(data):
-    # Don't send empty modules list - schema won't allow it
-    if data['lastStarport'].get('modules'):
-        send(data['commander']['name'], {
-            '$schemaRef' : 'http://schemas.elite-markets.net/eddn/outfitting/2',
-            'message'    : {
-                'systemName'  : data['lastSystem']['name'],
-                'stationName' : data['lastStarport']['name'],
-                'modules'     : sorted([module['name'] for module in (data['lastStarport'].get('modules') or {}).values() if module_re.search(module['name']) and module.get('sku') in [None, 'ELITE_HORIZONS_V_PLANETARY_LANDINGS'] and module['name'] != 'Int_PlanetApproachSuite']),
-            }
-        })
+    def export_commodities(self, data):
+        commodities = []
+        for commodity in data['lastStarport'].get('commodities') or []:
+            if category_map.get(commodity['categoryname'], True):	# Check marketable
+                commodities.append(OrderedDict([
+                    ('name',          commodity['name']),
+                    ('meanPrice',     int(commodity['meanPrice'])),
+                    ('buyPrice',      int(commodity['buyPrice'])),
+                    ('stock',         int(commodity['stock'])),
+                    ('stockBracket',  commodity['stockBracket']),
+                    ('sellPrice',     int(commodity['sellPrice'])),
+                    ('demand',        int(commodity['demand'])),
+                    ('demandBracket', commodity['demandBracket']),
+                ]))
+                if commodity['statusFlags']:
+                    commodities[-1]['statusFlags'] = commodity['statusFlags']
 
-def export_shipyard(data):
-    # Don't send empty ships list - shipyard data is only guaranteed present if user has visited the shipyard.
-    if data['lastStarport'].get('ships'):
-        send(data['commander']['name'], {
-            '$schemaRef' : 'http://schemas.elite-markets.net/eddn/shipyard/2',
-            'message'    : {
-                'systemName'  : data['lastSystem']['name'],
-                'stationName' : data['lastStarport']['name'],
-                'ships'       : sorted([ship['name'] for ship in (data['lastStarport']['ships'].get('shipyard_list') or {}).values() + data['lastStarport']['ships'].get('unavailable_list')]),
-            }
-        })
+        # Don't send empty commodities list - schema won't allow it
+        if commodities:
+            self.send(data['commander']['name'], {
+                '$schemaRef' : 'http://schemas.elite-markets.net/eddn/commodity/3',
+                'message'    : {
+                    'systemName'  : data['lastSystem']['name'],
+                    'stationName' : data['lastStarport']['name'],
+                    'commodities' : commodities,
+                }
+            })
+
+    def export_outfitting(self, data):
+        # Don't send empty modules list - schema won't allow it
+        if data['lastStarport'].get('modules'):
+            self.send(data['commander']['name'], {
+                '$schemaRef' : 'http://schemas.elite-markets.net/eddn/outfitting/2',
+                'message'    : {
+                    'systemName'  : data['lastSystem']['name'],
+                    'stationName' : data['lastStarport']['name'],
+                    'modules'     : sorted([module['name'] for module in data['lastStarport']['modules'].itervalues() if module_re.search(module['name']) and module.get('sku') in [None, 'ELITE_HORIZONS_V_PLANETARY_LANDINGS'] and module['name'] != 'Int_PlanetApproachSuite']),
+                }
+            })
+
+    def export_shipyard(self, data):
+        # Don't send empty ships list - shipyard data is only guaranteed present if user has visited the shipyard.
+        if data['lastStarport'].get('ships'):
+            self.send(data['commander']['name'], {
+                '$schemaRef' : 'http://schemas.elite-markets.net/eddn/shipyard/2',
+                'message'    : {
+                    'systemName'  : data['lastSystem']['name'],
+                    'stationName' : data['lastStarport']['name'],
+                    'ships'       : sorted([ship['name'] for ship in data['lastStarport']['ships']['shipyard_list'].values() + data['lastStarport']['ships']['unavailable_list']]),
+                }
+            })
+
+# singleton
+eddn = _EDDN()