From 0cc57aaf16f269262ea9aa27f97c932ab2c43ef9 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Thu, 23 May 2013 19:32:06 +0200 Subject: tracking: Added fedex support. --- modules/tracking.py | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/modules/tracking.py b/modules/tracking.py index 1d84fce..20b6ae5 100644 --- a/modules/tracking.py +++ b/modules/tracking.py @@ -6,7 +6,7 @@ info = { cfg_section = 'module/tracking' -import urllib2, datetime, re +import urllib2, datetime, re, pytz, json, urllib from xml.etree import ElementTree as ET from twisted.internet import reactor from twisted.internet.task import LoopingCall @@ -100,13 +100,16 @@ class TrackingModuleMeta(type): class TrackingModule(object): __metaclass__ = TrackingModuleMeta + def splitcode(self, code): + return code_split(code)[-1] + class PostenModule(TrackingModule): name = 'posten' url = 'http://sporing.posten.no/sporing.xml?q=%s' def get_xml(self, url): try: - u = urllib2.urlopen(url, timeout = config.getfloat('module/tracking', 'timeout')) + u = urllib2.urlopen(url, timeout = config.getfloat(cfg_section, 'timeout')) except Exception as e: raise PackageError(str(e)) if u.headers['content-type'].startswith('application/xml'): @@ -123,6 +126,7 @@ class PostenModule(TrackingModule): return url def track(self, code): + code = self.splitcode(code) xml = self.get_xml(self.url % code) if not xml: return @@ -155,6 +159,40 @@ class PostenModule(TrackingModule): results.append(TrackingResult(code, isodate, desc, status == 'DELIVERED', previous_code = previous_code)) return results +class FedexModule(TrackingModule): + name = 'fedex' + + def get_url(self, code = None): + url = 'https://www.fedex.com/fedextrack/index.html' + if code: + url += '?tracknumbers=' + code + return url + + def track(self, code): + code = self.splitcode(code) + data = {'TrackPackagesRequest': {'appType': 'wtrk', 'uniqueKey': '', 'processingParameters': {'anonymousTransaction': True, 'clientId': 'WTRK', 'returnDetailedErrors': True, 'returnLocalizedDateTime': False}, 'trackingInfoList': [{'trackNumberInfo': {'trackingNumber': code, 'trackingQualifier': '', 'trackingCarrier': ''}}]}} + url = 'https://www.fedex.com/trackingCal/track?' + urllib.urlencode({'data': json.dumps(data), 'action': 'trackpackages', 'locale': 'en_US', 'format': 'json', 'version': 99}) + u = urllib2.urlopen(url) + data = u.read() + u.close() + for m in re.findall(r'(\\x[a-fA-F\d]{2})', data): + data = data.replace(m, chr(int(m[-2:], 16))) + data = json.loads(data) + response = data['TrackPackagesResponse'] + packages = response['packageList'] + results = [] + for package in packages: + lastevent = package['scanEventList'][0] + date = datetime.datetime.strptime('%s %s' % (lastevent['date'], lastevent['time']), '%Y-%m-%d %H:%M:%S') + if lastevent['gmtOffset']: + tz = pytz.timezone('Etc/GMT' + ('+' if lastevent['gmtOffset'][0] == '-' else '-') + str(int(lastevent['gmtOffset'][1:3]))) + date = tz.localize(date).astimezone(pytz.timezone(config.get(cfg_section, 'local_timezone'))).replace(tzinfo = None) + status = lastevent['status'].encode('utf-8') + if lastevent['scanLocation']: + status += ' (%s)' % lastevent['scanLocation'].encode('utf-8') + results.append(TrackingResult(code, date, status, lastevent['isDelivered'])) + return results + def code_split(code): if ':' in code: return code.split(':') @@ -343,7 +381,7 @@ class Module: results = [] for consignment in consignments: for package in consignment.packages: - m = get_tracking_module(package.code) + m = get_tracking_module('%s:%s' % (consignment.type, package.code)) msg.append(m.get_url(package.code)) if not len(msg): # Rreturn an error only if we got a code to filter with. -- cgit v1.2.3