From 3fbe90f8fdc67d484dc47a44e4f1e192304d7f51 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Tue, 28 Sep 2010 18:48:25 +0200 Subject: Check package status when adding (start) and checking (status) your own trackings. --- modules/tracking.py | 100 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 37 deletions(-) (limited to 'modules') diff --git a/modules/tracking.py b/modules/tracking.py index 405514e..9d1ee9d 100644 --- a/modules/tracking.py +++ b/modules/tracking.py @@ -8,6 +8,7 @@ cfg_section = 'module/tracking' import urllib2, datetime, re from lxml import etree +from twisted.internet import reactor from twisted.internet.task import LoopingCall from sqlalchemy import create_engine, Column, Integer, String, DateTime, ForeignKey from sqlalchemy.ext.declarative import declarative_base @@ -28,6 +29,7 @@ class Consignment(Base): code = Column(String, nullable = False, unique = True) label = Column(String) added = Column(DateTime, nullable = False) + last = Column(DateTime) packages = relation('Package', backref = 'consignment', primaryjoin = 'Package.consignment_id == Consignment.id') @@ -51,6 +53,8 @@ class Package(Base): self.consignment_id = consignment_id self.code = code +class NoPackageFound(Exception): pass + class Module: url = 'http://sporing.posten.no/sporing.xml?q=%s' @@ -60,7 +64,7 @@ class Module: self.tracking = [] self.lc = LoopingCall(self.lc_callback) if bot: - self.lc.start(config.getfloat(cfg_section, 'interval'), False) + #self.lc.start(config.getfloat(cfg_section, 'interval'), False) self.irc.register_keyword('!track', self) def stop(self): @@ -99,7 +103,7 @@ class Module: ns = 'http://www.bring.no/sporing/1.0' packages = xml.find('//{%s}PackageSet' % (ns,)) if packages is None: - raise Exception('No packages found for \002%s\002.' % code) + raise NoPackageFound('No packages found for \002%s\002.' % code) results = [] for package in packages: @@ -127,6 +131,7 @@ class Module: session.add(consignment) session.commit() msg = 'Now tracking \002%s\002.' % code + reactor.callLater(1, self.track_update, code, True) except IntegrityError as e: msg = 'Already tracking \002%s\002.' % code finally: @@ -160,6 +165,7 @@ class Module: consignments = consignments.filter(Consignment.nick == nick) results = [] for row in consignments: + self.track_update(row.code) i = 0 if row.label: label = ' (%s)' % row.label @@ -193,7 +199,7 @@ class Module: msg = 'Failed to fetch tracking data for \002%s\002.' % code.decode('utf8') else: msg = 'No tracking number given or registered.' - except Exception as e: + except NoPackageFound as e: msg = str(e) finally: session.close() @@ -280,51 +286,71 @@ class Module: else: self.irc.msg(channel if not channel == self.irc.nickname else nick.split('!')[0], 'No data returned (this is a bug).') + # called by start and status + def track_update(self, code, announce = False): + try: + session = Session() + consignment = session.query(Consignment).filter(Consignment.code == code).one() + self.update_consignment(session, consignment, announce) + session.commit() + finally: + session.close() + + def update_consignment(self, session, consignment, announce = True): + now = datetime.datetime.utcnow() + td = datetime.timedelta(seconds = config.getint(cfg_section, 'cache_time')) + # return if consignment was cached within cache_time seconds + if consignment.last and consignment.last > now - td: + return + consignment.last = now + label = (' (%s)' % consignment.label if consignment.label else '') + target = consignment.channel or consignment.nick + target = target.encode('utf-8') + removed = False + data_ = self.track(consignment.code) + if not data_: + return + for data in data_: + try: + package = session.query(Package).filter_by(code = data[0]).one() + except NoResultFound: + package = Package(consignment.id, data[0]) + session.add(package) + package = session.query(Package).filter_by(code = data[0]).one() + + if package.last == None or data[1] > package.last: + code = data[0] + last = data[1] + desc = data[2] + msg = '%s: \002%s\002%s %s - %s' % (consignment.nick.encode('utf-8'), package.code.encode('utf-8'), label.encode('utf-8'), last, desc) + if desc.startswith('Sendingen er utlevert'): + session.delete(package) + msg += ' (Package delivered - tracking stopped)' + removed = True + else: + package.last = last + package.status = desc + session.add(package) + if announce: + self.irc.msg(target, msg) + if removed and len(consignment.packages) == 0: + msg = '%s: \002%s\002%s is no longer being tracked' % (consignment.nick, consignment.code, label) + if announce: + self.irc.msg(target, msg.encode('utf-8')) + session.delete(consignment) + def lc_callback(self): try: session = Session() consignments = session.query(Consignment).filter(Consignment.channel.in_(config.get(self.irc.factory.server, 'channels').split())) for row in consignments: - label = (' (%s)' % row.label if row.label else '') - target = row.channel or row.nick - target = target.encode('utf-8') - removed = False - data_ = self.track(row.code) - if not data_: - continue - for data in data_: - try: - package = session.query(Package).filter_by(code = data[0]).one() - except: - package = Package(row.id, data[0]) - session.add(package) - package = session.query(Package).filter_by(code = data[0]).one() - - if package.last == None or data[1] > package.last: - code = data[0] - last = data[1] - desc = data[2] - msg = '%s: \002%s\002%s %s - %s' % (row.nick.encode('utf-8'), package.code.encode('utf-8'), label.encode('utf-8'), last, desc) - if desc.startswith('Sendingen er utlevert'): - session.delete(package) - msg += ' (Package delivered - tracking stopped)' - removed = True - else: - package.last = last - package.status = desc - session.add(package) - self.irc.msg(target, msg) - if removed and len(row.packages) == 0: - msg = '%s: \002%s\002%s is no longer being tracked' % (row.nick, row.code, label) - self.irc.msg(target, msg.encode('utf-8')) - session.delete(row) + update_consignment(session, row) session.commit() finally: session.close() if __name__ == '__main__': import sys, ConfigParser, os - from twisted.internet import reactor config = ConfigParser.ConfigParser() config.read([os.path.expanduser('~/.fot')]) m = Module(None) -- cgit v1.2.3