aboutsummaryrefslogtreecommitdiff
path: root/modules/nr.py
diff options
context:
space:
mode:
authorGravatar dngfx2018-08-31 10:50:37 +0100
committerGravatar dngfx2018-08-31 10:50:37 +0100
commitabed9cf4ea71dcbad2dd2c049683b8d14b942e09 (patch)
tree3e40caf63fa7e1500469f4ad9a0c45c51808aad4 /modules/nr.py
parentFix a copy paste fail in IRCLineHandler that caused PARTs to be handled as QUITs (diff)
signature
Reformat
Diffstat (limited to 'modules/nr.py')
-rw-r--r--modules/nr.py593
1 files changed, 390 insertions, 203 deletions
diff --git a/modules/nr.py b/modules/nr.py
index 7716b567..e365f10d 100644
--- a/modules/nr.py
+++ b/modules/nr.py
@@ -14,35 +14,42 @@ from suds import WebFault
URL = 'https://lite.realtime.nationalrail.co.uk/OpenLDBSVWS/wsdl.aspx?ver=2016-02-16'
+
class Module(object):
_name = "NR"
PASSENGER_ACTIVITIES = ["U", "P", "R"]
- COLOURS = [Utils.COLOR_LIGHTBLUE, Utils.COLOR_GREEN, Utils.COLOR_RED, Utils.COLOR_CYAN, Utils.COLOR_LIGHTGREY, Utils.COLOR_ORANGE]
+ COLOURS = [Utils.COLOR_LIGHTBLUE, Utils.COLOR_GREEN, Utils.COLOR_RED,
+ Utils.COLOR_CYAN, Utils.COLOR_LIGHTGREY, Utils.COLOR_ORANGE]
def __init__(self, bot):
self.bot = bot
self._client = None
bot.events.on("received").on("command").on("nrtrains"
- ).hook(self.trains, min_args=1,
- help="Get train/bus services for a station (Powered by NRE)",
- usage="<crs_id>")
+ ).hook(self.trains,
+ min_args=1,
+ help="Get train/bus services for a station (Powered by NRE)",
+ usage="<crs_id>")
bot.events.on("received").on("command").on("nrservice"
- ).hook(self.service, min_args=1,
- help="Get train service information for a UID, headcode or RID (Powered by NRE)",
- usage="<service_id>")
+ ).hook(self.service,
+ min_args=1,
+ help="Get train service information for a UID, headcode or RID (Powered by NRE)",
+ usage="<service_id>")
bot.events.on("received").on("command").on("nrhead"
- ).hook(self.head, min_args=1,
- help="Get information for a given headcode/UID/RID (Powered by NRE)",
- usage="<headcode>")
+ ).hook(self.head, min_args=1,
+ help="Get information for a given headcode/UID/RID (Powered by NRE)",
+ usage="<headcode>")
bot.events.on("received").on("command").on("nrcode"
- ).hook(self.service_code, min_args=1,
- help="Get the text for a given delay/cancellation code (Powered by NRE)",
- usage="<code>")
+ ).hook(self.service_code,
+ min_args=1,
+ help="Get the text for a given delay/cancellation code (Powered by NRE)",
+ usage="<code>")
bot.events.on("telegram").on("command").on("nrtrains").hook(self.trains)
- bot.events.on("telegram").on("command").on("nrcode").hook(self.service_code)
+ bot.events.on("telegram").on("command").on("nrcode").hook(
+ self.service_code)
bot.events.on("telegram").on("command").on("nrhead").hook(self.head)
- bot.events.on("telegram").on("command").on("nrservice").hook(self.service)
+ bot.events.on("telegram").on("command").on("nrservice").hook(
+ self.service)
@property
def client(self):
@@ -70,11 +77,11 @@ class Module(object):
else:
params[arg.replace("!", "")] = '!' not in arg
- ret = {k: v[0] for k,v in defaults.items()}
+ ret = {k: v[0] for k, v in defaults.items()}
ret["default"] = True
ret["errors"] = []
- for k,v in params.items():
+ for k, v in params.items():
if not k in defaults.keys():
ret["errors"].append((k, "Invalid parameter"))
continue
@@ -83,7 +90,8 @@ class Module(object):
continue
ret["default"] = False
ret[k] = v if len(defaults[k]) == 2 else defaults[k][2](v)
- ret["errors_summary"] = ", ".join(['"%s": %s' % (a[0], a[1]) for a in ret["errors"]])
+ ret["errors_summary"] = ", ".join(
+ ['"%s": %s' % (a[0], a[1]) for a in ret["errors"]])
return ret
def process(self, service):
@@ -100,10 +108,12 @@ class Module(object):
times[a] = {"orig": service[a]}
if len(service[a]) > 5:
- times[a]["datetime"] = datetime.strptime(service[a], "%Y-%m-%dT%H:%M:%S")
+ times[a]["datetime"] = datetime.strptime(service[a],
+ "%Y-%m-%dT%H:%M:%S")
else:
times[a]["datetime"] = datetime.strptime(
- datetime.now().date().isoformat() + "T" + service[a][:4],
+ datetime.now().date().isoformat() + "T" + service[a][
+ :4],
"%Y-%m-%dT%H%M"
)
times[a]["ut"] = times[a]["datetime"].timestamp()
@@ -112,17 +122,22 @@ class Module(object):
for k, a in times.items():
if not a["orig"]: continue
- a["short"] = a["datetime"].strftime("%H%M") if len(a["orig"]) > 5 else a["orig"]
- a["shortest"] = "%02d" % a["datetime"].minute if -300 < a["ut"]-ut_now < 1800 else a["short"]
+ a["short"] = a["datetime"].strftime("%H%M") if len(
+ a["orig"]) > 5 else a["orig"]
+ a["shortest"] = "%02d" % a["datetime"].minute if -300 < a[
+ "ut"] - ut_now < 1800 else a["short"]
a["prefix"] = k[2] + ("s" if k[0] == "s" else "")
a["estimate"] = k[0] == "e"
a["schedule"] = k[0] == "s"
- a["on_time"] = a["ut"] - times["s"+ k[1:]]["ut"] < 300
+ a["on_time"] = a["ut"] - times["s" + k[1:]]["ut"] < 300
a["status"] = 1 if a["on_time"] else 2
if "a" + k[1:] in service: a["status"] = {"d": 0, "a": 3}[k[2]]
if k[0] == "s": a["status"] = 4
- arr, dep = [times[a] for a in a_types if times[a]["ut"]], [times[a] for a in d_types if times[a]["ut"]]
+ arr, dep = [times[a] for a in a_types if times[a]["ut"]], [times[a] for
+ a in d_types
+ if times[a][
+ "ut"]]
times["arrival"] = (arr + dep + [nonetime])[0]
times["departure"] = (dep + arr + [nonetime])[0]
times["a"], times["d"] = (arr + [nonetime])[0], (dep + [nonetime])[0]
@@ -130,9 +145,13 @@ class Module(object):
times["max_sched"] = {"ut": max(times["sta"]["ut"], times["std"]["ut"])}
return times
- def activities(self, string): return [a+b.strip() for a,b in list(zip(*[iter(string)]*2)) if (a+b).strip()]
+ def activities(self, string):
+ return [a + b.strip() for a, b in list(zip(*[iter(string)] * 2)) if
+ (a + b).strip()]
- def reduced_activities(self, string): return [a for a in self.activities(string) if a in self.PASSENGER_ACTIVITIES]
+ def reduced_activities(self, string):
+ return [a for a in self.activities(string) if
+ a in self.PASSENGER_ACTIVITIES]
def trains(self, event):
client = self.client
@@ -143,30 +162,51 @@ class Module(object):
schedule = {}
location_code = event["args_split"][0].upper()
- filter = self.filter(' '.join(event["args_split"][1:]) if len(event["args_split"]) > 1 else "", {
- "dest": ('', lambda x: x.isalpha() and len(x)==3),
- "origin":('', lambda x: x.isalpha() and len(x)==3),
- "inter": ('', lambda x: x.isalpha() and len(x)==3, lambda x: x.upper()),
- "toc": ('', lambda x: x.isalpha() and len(x) == 2),
- "dedup": (False, lambda x: type(x)==type(True)),
- "plat": ('', lambda x: len(x) <= 3),
- "type": ("departure", lambda x: x in ["departure", "arrival", "both"]),
- "terminating": (False, lambda x: type(x)==type(True)),
- "period": (120, lambda x: x.isdigit() and 1 <= int(x) <= 480, lambda x: int(x)),
- "nonpassenger": (False, lambda x: type(x)==type(True)),
- "time": ("", lambda x: len(x)==4 and x.isdigit()),
- "date": ("", lambda x: len(x)==10),
- "tops": (None, lambda x: len(x)<4 and x.isdigit()),
- "power": (None, lambda x: x.upper() in ["EMU", "DMU", "HST", "D", "E"], lambda x: x.upper()),
- "crs": (False, lambda x: type(x)==type(True)),
- "st": (False, lambda x: type(x)==type(True))
- })
+ filter = self.filter(' '.join(event["args_split"][1:]) if len(
+ event["args_split"]) > 1 else "", {
+ "dest": (
+ '', lambda x: x.isalpha() and len(x) == 3),
+ "origin": (
+ '', lambda x: x.isalpha() and len(x) == 3),
+ "inter": (
+ '', lambda x: x.isalpha() and len(x) == 3,
+ lambda x: x.upper()),
+ "toc": (
+ '', lambda x: x.isalpha() and len(x) == 2),
+ "dedup": (
+ False, lambda x: type(x) == type(True)),
+ "plat": ('', lambda x: len(x) <= 3),
+ "type": ("departure",
+ lambda x: x in ["departure",
+ "arrival", "both"]),
+ "terminating": (
+ False, lambda x: type(x) == type(True)),
+ "period": (120,
+ lambda x: x.isdigit() and 1 <= int(
+ x) <= 480, lambda x: int(x)),
+ "nonpassenger": (
+ False, lambda x: type(x) == type(True)),
+ "time": (
+ "", lambda x: len(x) == 4 and x.isdigit()),
+ "date": ("", lambda x: len(x) == 10),
+ "tops": (
+ None, lambda x: len(x) < 4 and x.isdigit()),
+ "power": (None,
+ lambda x: x.upper() in ["EMU", "DMU",
+ "HST", "D",
+ "E"],
+ lambda x: x.upper()),
+ "crs": (
+ False, lambda x: type(x) == type(True)),
+ "st": (False, lambda x: type(x) == type(True))
+ })
if filter["errors"]:
return event["stderr"].write("Filter: " + filter["errors_summary"])
- if filter["inter"] and filter["type"]!="departure":
- return event["stderr"].write("Filtering by intermediate stations is only supported for departures.")
+ if filter["inter"] and filter["type"] != "departure":
+ return event["stderr"].write(
+ "Filtering by intermediate stations is only supported for departures.")
nr_filterlist = client.factory.create("filterList")
if filter["inter"]: nr_filterlist.crs.append(filter["inter"])
@@ -177,30 +217,41 @@ class Module(object):
now = now.replace(minute=int(filter["time"][2:]))
if filter["date"]:
newdate = datetime.strptime(filter["date"], "%Y-%m-%d").date()
- now = now.replace(day=newdate.day, month=newdate.month, year=newdate.year)
+ now = now.replace(day=newdate.day, month=newdate.month,
+ year=newdate.year)
- method = client.service.GetArrivalDepartureBoardByCRS if len(location_code) == 3 else client.service.GetArrivalDepartureBoardByTIPLOC
+ method = client.service.GetArrivalDepartureBoardByCRS if len(
+ location_code) == 3 else client.service.GetArrivalDepartureBoardByTIPLOC
try:
- query = method(100, location_code, now.isoformat().split(".")[0], filter["period"],
- nr_filterlist, "to", '', "PBS", filter["nonpassenger"])
+ query = method(100, location_code, now.isoformat().split(".")[0],
+ filter["period"],
+ nr_filterlist, "to", '', "PBS",
+ filter["nonpassenger"])
except WebFault as detail:
- if str(detail) == "Server raised fault: 'Invalid crs code supplied'":
+ if str(
+ detail) == "Server raised fault: 'Invalid crs code supplied'":
return event["stderr"].write("Invalid CRS code.")
else:
return event["stderr"].write("An error occurred.")
- nrcc_severe = len([a for a in query["nrccMessages"][0] if a["severity"] == "Major"]) if "nrccMessages" in query else 0
+ nrcc_severe = len([a for a in query["nrccMessages"][0] if a[
+ "severity"] == "Major"]) if "nrccMessages" in query else 0
if event.get("external"):
- station_summary = "%s (%s) - %s (%s):\n" % (query["locationName"], query["crs"], query["stationManager"],
- query["stationManagerCode"])
+ station_summary = "%s (%s) - %s (%s):\n" % (
+ query["locationName"], query["crs"], query["stationManager"],
+ query["stationManagerCode"])
else:
- station_summary = "%s (%s, %s%s)" % (query["locationName"], query["crs"], query["stationManagerCode"],
- ", %s%s severe messages%s" % (Utils.color(Utils.COLOR_RED), nrcc_severe, Utils.color(Utils.FONT_RESET)) if nrcc_severe else ""
- )
+ station_summary = "%s (%s, %s%s)" % (
+ query["locationName"], query["crs"], query["stationManagerCode"],
+ ", %s%s severe messages%s" % (
+ Utils.color(Utils.COLOR_RED), nrcc_severe,
+ Utils.color(Utils.FONT_RESET)) if nrcc_severe else ""
+ )
if not "trainServices" in query and not "busServices" in query and not "ferryServices" in query:
- return event["stdout"].write("%s: No services for the next %s minutes" % (
- station_summary, filter["period"]))
+ return event["stdout"].write(
+ "%s: No services for the next %s minutes" % (
+ station_summary, filter["period"]))
trains = []
services = []
@@ -209,107 +260,152 @@ class Module(object):
if "ferryServices" in query: services += query["ferryServices"][0]
for t in services:
parsed = {
- "rid" : t["rid"],
- "uid" : t["uid"],
- "head" : t["trainid"],
+ "rid": t["rid"],
+ "uid": t["uid"],
+ "head": t["trainid"],
"platform": '?' if not "platform" in t else t["platform"],
- "platform_hidden": "platformIsHidden" in t and t["platformIsHidden"],
+ "platform_hidden": "platformIsHidden" in t and t[
+ "platformIsHidden"],
"platform_prefix": "",
"toc": t["operatorCode"],
- "cancelled" : t["isCancelled"] if "isCancelled" in t else False,
- "delayed" : t["departureType"]=="Delayed" if "departureType" in t else None,
- "cancel_reason" : t["cancelReason"]["value"] if "cancelReason" in t else "",
- "delay_reason" : t["delayReason"]["value"] if "delayReason" in t else "",
- "terminating" : not "std" in t and not "etd" in t and not "atd" in t,
- "bus" : t["trainid"]=="0B00",
- "times" : self.process(t),
- "activity" : self.reduced_activities(t["activities"]),
- }
- parsed["destinations"] = [{"name": a["locationName"], "tiploc": a["tiploc"],
- "crs": a["crs"] if "crs" in a else '', "code": a["crs"] if "crs"
- in a else a["tiploc"], "via": a["via"] if "via" in a else ''}
+ "cancelled": t["isCancelled"] if "isCancelled" in t else False,
+ "delayed": t[
+ "departureType"] == "Delayed" if "departureType" in t else None,
+ "cancel_reason": t["cancelReason"][
+ "value"] if "cancelReason" in t else "",
+ "delay_reason": t["delayReason"][
+ "value"] if "delayReason" in t else "",
+ "terminating": not "std" in t and not "etd" in t and not "atd" in t,
+ "bus": t["trainid"] == "0B00",
+ "times": self.process(t),
+ "activity": self.reduced_activities(t["activities"]),
+ }
+ parsed["destinations"] = [
+ {"name": a["locationName"], "tiploc": a["tiploc"],
+ "crs": a["crs"] if "crs" in a else '',
+ "code": a["crs"] if "crs"
+ in a else a["tiploc"],
+ "via": a["via"] if "via" in a else ''}
for a in t["destination"][0]]
- parsed["origins"] = [{"name": a["locationName"], "tiploc": a["tiploc"],
- "crs": a["crs"] if "crs" in a else '', "code": a["crs"] if "crs"
- in a else a["tiploc"], "via": a["via"] if "via" in a else ''}
+ parsed["origins"] = [
+ {"name": a["locationName"], "tiploc": a["tiploc"],
+ "crs": a["crs"] if "crs" in a else '',
+ "code": a["crs"] if "crs"
+ in a else a["tiploc"],
+ "via": a["via"] if "via" in a else ''}
for a in t["origin"][0]]
- parsed["departure_only"] = location_code in [a["code"] for a in parsed["origins"]]
+ parsed["departure_only"] = location_code in [a["code"] for a in
+ parsed["origins"]]
if parsed["cancelled"] or parsed["delayed"]:
for k, time in parsed["times"].items():
- time["short"], time["on_time"], time["status"], time["prefix"] = (
- "%s:%s" % ("C" if parsed["cancel_reason"] else "D", parsed["cancel_reason"] or parsed["delay_reason"] or "?"),
+ time["short"], time["on_time"], time["status"], time[
+ "prefix"] = (
+ "%s:%s" % ("C" if parsed["cancel_reason"] else "D",
+ parsed["cancel_reason"] or parsed[
+ "delay_reason"] or "?"),
False, 2, ""
- )
+ )
trains.append(parsed)
if eagle_url:
- summary_query = Utils.get_url("%s/json/summaries/%s?uids=%s" % (eagle_url, now.date().isoformat(), "%20".join([a["uid"] for a in trains])), json=True, headers={"x-eagle-key": self.bot.config["eagle-api-key"]})
+ summary_query = Utils.get_url("%s/json/summaries/%s?uids=%s" % (
+ eagle_url, now.date().isoformat(),
+ "%20".join([a["uid"] for a in trains])), json=True, headers={
+ "x-eagle-key": self.bot.config["eagle-api-key"]})
if summary_query:
for t in trains:
summary = summary_query[t["uid"]]
t.update(summary)
- summary_plat = summary.get("platforms", {}).get(query["crs"])
- if summary_plat and t["platform"]=="?":
+ summary_plat = summary.get("platforms", {}).get(
+ query["crs"])
+ if summary_plat and t["platform"] == "?":
t["platform"], t["platform_prefix"] = summary_plat, "s"
for t in trains:
- t["dest_summary"] = "/".join(["%s%s" %(a["code"]*filter["crs"] or a["name"], " " + a["via"]
- if a["via"] else '') for a in t["destinations"]])
- t["origin_summary"] = "/".join(["%s%s" %(a["code"]*filter["crs"] or a["name"], " " + a["via"]
- if a["via"] else '') for a in t["origins"]])
+ t["dest_summary"] = "/".join(["%s%s" % (
+ a["code"] * filter["crs"] or a["name"], " " + a["via"]
+ if a["via"] else '') for a in t["destinations"]])
+ t["origin_summary"] = "/".join(["%s%s" % (
+ a["code"] * filter["crs"] or a["name"], " " + a["via"]
+ if a["via"] else '') for a in t["origins"]])
- trains = sorted(trains, key=lambda t: t["times"]["max_sched"]["ut"] if filter["type"]=="both" else t["times"]["st" + filter["type"][0]]["ut"])
+ trains = sorted(trains,
+ key=lambda t: t["times"]["max_sched"]["ut"] if filter[
+ "type"] == "both" else
+ t["times"]["st" + filter["type"][0]]["ut"])
trains_filtered = []
train_locs_toc = []
for train in trains:
if not True in [
- (train["destinations"], train["toc"]) in train_locs_toc and (filter["dedup"] or filter["default"]),
- filter["dest"] and not filter["dest"].upper() in [a["code"] for a in train["destinations"]],
- filter["origin"] and not filter["origin"].upper() in [a["code"] for a in train["origins"]],
+ (train["destinations"], train["toc"]) in train_locs_toc and (
+ filter["dedup"] or filter["default"]),
+ filter["dest"] and not filter["dest"].upper() in [a["code"] for
+ a in train[
+ "destinations"]],
+ filter["origin"] and not filter["origin"].upper() in [a["code"]
+ for a in
+ train[
+ "origins"]],
filter["toc"] and not filter["toc"].upper() == train["toc"],
filter["plat"] and not filter["plat"] == train["platform"],
filter["type"] == "departure" and train["terminating"],
filter["type"] == "arrival" and train["departure_only"],
filter["terminating"] and not train["terminating"],
- filter["tops"] and not filter["tops"] in train.get("tops_possible", []),
- filter["power"] and not filter["power"]==train.get("power_type", None),
+ filter["tops"] and not filter["tops"] in train.get(
+ "tops_possible", []),
+ filter["power"] and not filter["power"] == train.get(
+ "power_type", None),
]:
train_locs_toc.append((train["destinations"], train["toc"]))
trains_filtered.append(train)
if event.get("external"):
trains_string = "\n".join(["%-6s %-4s %-2s %-3s %1s%-6s %1s %s" % (
- t["uid"], t["head"], t["toc"], "bus" if t["bus"] else t["platform"],
+ t["uid"], t["head"], t["toc"],
+ "bus" if t["bus"] else t["platform"],
"~" if t["times"]["both"]["estimate"] else '',
t["times"]["both"]["prefix"] + t["times"]["both"]["short"],
- "←" if t["terminating"] or filter["type"]=="arrival" else "→",
- t["origin_summary"] if t["terminating"] or filter["type"]=="arrival" else t["dest_summary"]
- ) for t in trains_filtered])
+ "←" if t["terminating"] or filter["type"] == "arrival" else "→",
+ t["origin_summary"] if t["terminating"] or filter[
+ "type"] == "arrival" else t["dest_summary"]
+ ) for t in trains_filtered])
else:
trains_string = ", ".join(["%s%s (%s, %s%s%s%s, %s%s%s%s%s)" % (
- "from " if not filter["type"][0] in "ad" and t["terminating"] else '',
- t["origin_summary"] if t["terminating"] or filter["type"]=="arrival" else t["dest_summary"],
+ "from " if not filter["type"][0] in "ad" and t[
+ "terminating"] else '',
+ t["origin_summary"] if t["terminating"] or filter[
+ "type"] == "arrival" else t["dest_summary"],
t["uid"],
t["platform_prefix"],
"bus" if t["bus"] else t["platform"],
"*" if t["platform_hidden"] else '',
- "?" if "platformsAreUnreliable" in query and query["platformsAreUnreliable"] else '',
- t["times"][filter["type"]]["prefix"].replace(filter["type"][0], '') if not t["cancelled"] else "",
+ "?" if "platformsAreUnreliable" in query and query[
+ "platformsAreUnreliable"] else '',
+ t["times"][filter["type"]]["prefix"].replace(filter["type"][0],
+ '') if not t[
+ "cancelled"] else "",
Utils.color(colours[t["times"][filter["type"]]["status"]]),
- t["times"][filter["type"]]["shortest"*filter["st"] or "short"],
+ t["times"][filter["type"]][
+ "shortest" * filter["st"] or "short"],
Utils.color(Utils.FONT_RESET),
- bool(t["activity"])*", " + "+".join(t["activity"]),
- ) for t in trains_filtered])
+ bool(t["activity"]) * ", " + "+".join(t["activity"]),
+ ) for t in trains_filtered])
if event.get("external"):
event["stdout"].write("%s%s\n%s" % (
- station_summary, "\n calling at %s" % filter["inter"] if filter["inter"] else '', trains_string))
+ station_summary,
+ "\n calling at %s" % filter["inter"] if filter["inter"] else '',
+ trains_string))
else:
- event["stdout"].write("%s%s: %s" % (station_summary, " departures calling at %s" % filter["inter"] if filter["inter"] else '', trains_string))
+ event["stdout"].write("%s%s: %s" % (station_summary,
+ " departures calling at %s" %
+ filter["inter"] if filter[
+ "inter"] else '',
+ trains_string))
def service(self, event):
client = self.client
@@ -317,8 +413,9 @@ class Module(object):
external = event.get("external", False)
SCHEDULE_STATUS = {"B": "perm bus", "F": "freight train", "P": "train",
- "S": "ship", "T": "trip", "1": "train", "2": "freight",
- "3": "trip", "4": "ship", "5": "bus"}
+ "S": "ship", "T": "trip", "1": "train",
+ "2": "freight",
+ "3": "trip", "4": "ship", "5": "bus"}
eagle_key = self.bot.config["eagle-api-key"]
eagle_url = self.bot.config["eagle-api-url"]
@@ -327,10 +424,13 @@ class Module(object):
service_id = event["args_split"][0]
- filter = self.filter(' '.join(event["args_split"][1:]) if len(event["args_split"]) > 1 else "", {
- "passing": (False, lambda x: type(x)==type(True)),
- "type": ("arrival", lambda x: x in ["arrival", "departure"])
- })
+ filter = self.filter(' '.join(event["args_split"][1:]) if len(
+ event["args_split"]) > 1 else "", {
+ "passing": (
+ False, lambda x: type(x) == type(True)),
+ "type": ("arrival", lambda x: x in ["arrival",
+ "departure"])
+ })
if filter["errors"]:
event["stderr"].write("Filter: " + filter["errors_summary"])
@@ -338,18 +438,27 @@ class Module(object):
rid = service_id
if len(service_id) <= 8:
- query = client.service.QueryServices(service_id, datetime.utcnow().date().isoformat(),
- datetime.utcnow().time().strftime("%H:%M:%S+0000"))
+ query = client.service.QueryServices(service_id,
+ datetime.utcnow().date().isoformat(),
+ datetime.utcnow().time().strftime(
+ "%H:%M:%S+0000"))
if eagle_url:
- schedule_query = Utils.get_url("%s/json/schedule/%s/%s" % (eagle_url, service_id, datetime.now().date().isoformat()), json=True, headers={"x-eagle-key": eagle_key})
+ schedule_query = Utils.get_url("%s/json/schedule/%s/%s" % (
+ eagle_url, service_id, datetime.now().date().isoformat()),
+ json=True, headers={
+ "x-eagle-key": eagle_key})
if schedule_query:
schedule = schedule_query["current"]
if not query and not schedule:
- return event["stdout"].write("No service information is available for this identifier.")
+ return event["stdout"].write(
+ "No service information is available for this identifier.")
if query and len(query["serviceList"][0]) > 1:
- return event["stdout"].write("Identifier refers to multiple services: " +
- ", ".join(["%s (%s->%s)" % (a["uid"], a["originCrs"], a["destinationCrs"]) for a in query["serviceList"][0]]))
+ return event["stdout"].write(
+ "Identifier refers to multiple services: " +
+ ", ".join(["%s (%s->%s)" % (
+ a["uid"], a["originCrs"], a["destinationCrs"]) for a in
+ query["serviceList"][0]]))
if query: rid = query["serviceList"][0][0]["rid"]
if query:
@@ -357,123 +466,181 @@ class Module(object):
query = client.service.GetServiceDetailsByRID(rid)
if schedule:
sources.append("Eagle/SCHEDULE")
- if not query: query = {"trainid": schedule["signalling_id"] or "0000", "operator": schedule["operator_name"] or schedule["atoc_code"]}
- stype = "class %s %s" % (schedule_query["tops_inferred"], schedule["power_type"]) if schedule_query["tops_inferred"] else schedule["power_type"]
- for k,v in {
+ if not query: query = {
+ "trainid": schedule["signalling_id"] or "0000",
+ "operator": schedule["operator_name"] or schedule[
+ "atoc_code"]}
+ stype = "class %s %s" % (
+ schedule_query["tops_inferred"], schedule["power_type"]) if \
+ schedule_query["tops_inferred"] else schedule["power_type"]
+ for k, v in {
"operatorCode": schedule["atoc_code"],
- "serviceType": stype if stype else SCHEDULE_STATUS[schedule["status"]],
+ "serviceType": stype if stype else SCHEDULE_STATUS[
+ schedule["status"]],
}.items():
query[k] = v
disruptions = []
if "cancelReason" in query:
- disruptions.append("Cancelled (%s%s)" % (query["cancelReason"]["value"], " at " + query["cancelReason"]["_tiploc"] if query["cancelReason"]["_tiploc"] else ""))
+ disruptions.append("Cancelled (%s%s)" % (
+ query["cancelReason"]["value"],
+ " at " + query["cancelReason"]["_tiploc"] if query["cancelReason"][
+ "_tiploc"] else ""))
if "delayReason" in query:
- disruptions.append("Delayed (%s%s)" % (query["delayReason"]["value"], " at " + query["delayReason"]["_tiploc"] if query["delayReason"]["_tiploc"] else ""))
+ disruptions.append("Delayed (%s%s)" % (
+ query["delayReason"]["value"],
+ " at " + query["delayReason"]["_tiploc"] if query["delayReason"][
+ "_tiploc"] else ""))
if disruptions and not external:
- disruptions = Utils.color(Utils.COLOR_RED) + ", ".join(disruptions) + Utils.color(Utils.FONT_RESET) + " "
+ disruptions = Utils.color(Utils.COLOR_RED) + ", ".join(
+ disruptions) + Utils.color(Utils.FONT_RESET) + " "
elif disruptions and external:
disruptions = ", ".join(disruptions)
- else: disruptions = ""
+ else:
+ disruptions = ""
stations = []
- for station in query["locations"][0] if "locations" in query else schedule["locations"]:
+ for station in query["locations"][0] if "locations" in query else \
+ schedule["locations"]:
if "locations" in query:
parsed = {"name": station["locationName"],
- "crs": (station["crs"] if "crs" in station else station["tiploc"]).rstrip(),
- "tiploc": station["tiploc"].rstrip(),
- "called": "atd" in station,
- "passing": station["isPass"] if "isPass" in station else False,
- "first": len(stations) == 0,
- "last" : False,
- "cancelled" : station["isCancelled"] if "isCancelled" in station else False,
- "associations": [],
- "length": station["length"] if "length" in station else None,
- "times": self.process(station),
- "platform": station["platform"] if "platform" in station else None,
- "activity": self.activities(station["activities"]) if "activities" in station else [],
- "activity_p": self.reduced_activities(station["activities"]) if "activities" in station else [],
- }
+ "crs": (
+ station["crs"] if "crs" in station else station[
+ "tiploc"]).rstrip(),
+ "tiploc": station["tiploc"].rstrip(),
+ "called": "atd" in station,
+ "passing": station[
+ "isPass"] if "isPass" in station else False,
+ "first": len(stations) == 0,
+ "last": False,
+ "cancelled": station[
+ "isCancelled"] if "isCancelled" in station else False,
+ "associations": [],
+ "length": station[
+ "length"] if "length" in station else None,
+ "times": self.process(station),
+ "platform": station[
+ "platform"] if "platform" in station else None,
+ "activity": self.activities(station[
+ "activities"]) if "activities" in station else [],
+ "activity_p": self.reduced_activities(station[
+ "activities"]) if "activities" in station else [],
+ }
if parsed["cancelled"]:
- parsed["times"]["arrival"].update({"short": "Cancelled", "on_time": False, "status": 2})
- parsed["times"]["departure"].update({"short": "Cancelled", "on_time": False, "status": 2})
+ parsed["times"]["arrival"].update(
+ {"short": "Cancelled", "on_time": False, "status": 2})
+ parsed["times"]["departure"].update(
+ {"short": "Cancelled", "on_time": False, "status": 2})
- associations = station["associations"][0] if "associations" in station else []
+ associations = station["associations"][
+ 0] if "associations" in station else []
for assoc in associations:
parsed_assoc = {
"uid_assoc": assoc.uid,
- "category": {"divide": "VV", "join": "JJ", "next": "NP"}[assoc["category"]],
- "from": parsed["first"], "direction": assoc["destTiploc"].rstrip()==parsed["tiploc"],
- "origin_name": assoc["origin"], "origin_tiploc": assoc["originTiploc"],
- "origin_crs": assoc["originCRS"] if "originCRS" in assoc else None,
+ "category":
+ {"divide": "VV", "join": "JJ", "next": "NP"}[
+ assoc["category"]],
+ "from": parsed["first"],
+ "direction": assoc["destTiploc"].rstrip() == parsed[
+ "tiploc"],
+ "origin_name": assoc["origin"],
+ "origin_tiploc": assoc["originTiploc"],
+ "origin_crs": assoc[
+ "originCRS"] if "originCRS" in assoc else None,
- "dest_name": assoc["destination"], "dest_tiploc": assoc["destTiploc"],
- "dest_crs": assoc["destCRS"] if "destCRS" in assoc else None,
+ "dest_name": assoc["destination"],
+ "dest_tiploc": assoc["destTiploc"],
+ "dest_crs": assoc[
+ "destCRS"] if "destCRS" in assoc else None,
- "far_name": assoc["destination"], "far_tiploc": assoc["destTiploc"],
- "far_crs": assoc["destCRS"] if "destCRS" in assoc else None,
- }
+ "far_name": assoc["destination"],
+ "far_tiploc": assoc["destTiploc"],
+ "far_crs": assoc[
+ "destCRS"] if "destCRS" in assoc else None,
+ }
if parsed_assoc["direction"]:
- parsed_assoc.update({"far_name": parsed_assoc["origin_name"],
- "far_tiploc": parsed_assoc["origin_tiploc"], "far_crs": parsed_assoc["origin_crs"]})
+ parsed_assoc.update(
+ {"far_name": parsed_assoc["origin_name"],
+ "far_tiploc": parsed_assoc["origin_tiploc"],
+ "far_crs": parsed_assoc["origin_crs"]})
parsed["associations"].append(parsed_assoc)
else:
parsed = {"name": (station["name"] or "none"),
- "crs": station["crs"] if station["crs"] else station["tiploc"],
- "tiploc": station["tiploc"],
- "called": False,
- "passing": bool(station.get("pass")),
- "first": len(stations) == 0,
- "last" : False,
- "cancelled" : False,
- "length": None,
- "times": self.process(station["dolphin_times"]),
- "platform": station["platform"],
- "associations": station["associations"] or [],
- "activity": self.activities(station["activity"]),
- "activity_p": self.reduced_activities(station["activity"]),
- }
+ "crs": station["crs"] if station["crs"] else station[
+ "tiploc"],
+ "tiploc": station["tiploc"],
+ "called": False,
+ "passing": bool(station.get("pass")),
+ "first": len(stations) == 0,
+ "last": False,
+ "cancelled": False,
+ "length": None,
+ "times": self.process(station["dolphin_times"]),
+ "platform": station["platform"],
+ "associations": station["associations"] or [],
+ "activity": self.activities(station["activity"]),
+ "activity_p": self.reduced_activities(
+ station["activity"]),
+ }
stations.append(parsed)
[a for a in stations if a["called"] or a["first"]][-1]["last"] = True
- for station in stations[0:[k for k,v in enumerate(stations) if v["last"]][0]]:
+ for station in stations[
+ 0:[k for k, v in enumerate(stations) if v["last"]][0]]:
if not station["first"]: station["called"] = True
for station in stations:
for assoc in station["associations"]:
- assoc["summary"] = "{arrow} {assoc[category]} {assoc[uid_assoc]} {dir_arrow} {assoc[far_name]} ({code})".format(assoc=assoc, arrow=assoc["from"]*"<-" or "->", dir_arrow=(assoc["direction"])*"<-" or "->", code=assoc["far_crs"] or assoc["far_tiploc"])
+ assoc[
+ "summary"] = "{arrow} {assoc[category]} {assoc[uid_assoc]} {dir_arrow} {assoc[far_name]} ({code})".format(
+ assoc=assoc, arrow=assoc["from"] * "<-" or "->",
+ dir_arrow=(assoc["direction"]) * "<-" or "->",
+ code=assoc["far_crs"] or assoc["far_tiploc"])
if station["passing"]:
- station["times"]["arrival"]["status"], station["times"]["departure"]["status"] = 5, 5
+ station["times"]["arrival"]["status"], \
+ station["times"]["departure"]["status"] = 5, 5
elif station["called"]:
- station["times"]["arrival"]["status"], station["times"]["departure"]["status"] = 0, 0
+ station["times"]["arrival"]["status"], \
+ station["times"]["departure"]["status"] = 0, 0
station["summary"] = "%s%s (%s%s%s%s%s%s%s)%s" % (
"*" * station["passing"],
station["name"],
- station["crs"] + ", " if station["name"] != station["crs"] else '',
- station["length"] + " cars, " if station["length"] and (station["first"] or (station["last"]) or station["associations"]) else '',
+ station["crs"] + ", " if station["name"] != station[
+ "crs"] else '',
+ station["length"] + " cars, " if station["length"] and (
+ station["first"] or (station["last"]) or station[
+ "associations"]) else '',
("~" if station["times"][filter["type"]]["estimate"] else '') +
- station["times"][filter["type"]]["prefix"].replace(filter["type"][0], ""),
- Utils.color(colours[station["times"][filter["type"]]["status"]]),
+ station["times"][filter["type"]]["prefix"].replace(
+ filter["type"][0], ""),
+ Utils.color(
+ colours[station["times"][filter["type"]]["status"]]),
station["times"][filter["type"]]["short"],
Utils.color(Utils.FONT_RESET),
- ", "*bool(station["activity_p"]) + "+".join(station["activity_p"]),
+ ", " * bool(station["activity_p"]) + "+".join(
+ station["activity_p"]),
", ".join([a["summary"] for a in station["associations"]]),
- )
- station["summary_external"] = "%1s%-5s %1s%-5s %-3s %-3s %-3s %s%s" % (
- "~"*station["times"]["a"]["estimate"] + "s"*(station["times"]["a"]["schedule"]),
+ )
+ station[
+ "summary_external"] = "%1s%-5s %1s%-5s %-3s %-3s %-3s %s%s" % (
+ "~" * station["times"]["a"]["estimate"] + "s" * (
+ station["times"]["a"]["schedule"]),
station["times"]["a"]["short"],
- "~"*station["times"]["d"]["estimate"] + "s"*(station["times"]["d"]["schedule"]),
+ "~" * station["times"]["d"]["estimate"] + "s" * (
+ station["times"]["d"]["schedule"]),
station["times"]["d"]["short"],
station["platform"] or '',
",".join(station["activity"]) or '',
station["crs"] or station["tiploc"],
station["name"],
- "\n" + "\n".join([a["summary"] for a in station["associations"]]) if station["associations"] else "",
- )
+ "\n" + "\n".join(
+ [a["summary"] for a in station["associations"]]) if station[
+ "associations"] else "",
+ )
stations_filtered = []
for station in stations:
@@ -483,8 +650,10 @@ class Module(object):
continue
stations_filtered.append(station)
- if station["first"] and not station["last"] and filter["default"] and not external:
- stations_filtered.append({"summary": "(...)", "summary_external": "(...)"})
+ if station["first"] and not station["last"] and filter[
+ "default"] and not external:
+ stations_filtered.append(
+ {"summary": "(...)", "summary_external": "(...)"})
done_count = len([s for s in stations if s["called"]])
total_count = len(stations)
@@ -492,39 +661,57 @@ class Module(object):
event["stdout"].write("%s: %s\n%s%s (%s) %s %s\n\n%s" % (
service_id, ", ".join(sources),
disruptions + "\n" if disruptions else '',
- query["operator"], query["operatorCode"], query["trainid"], query["serviceType"],
+ query["operator"], query["operatorCode"], query["trainid"],
+ query["serviceType"],
"\n".join([s["summary_external"] for s in stations_filtered])
- ))
+ ))
else:
- event["stdout"].write("%s%s %s %s (%s%s%s/%s/%s): %s" % (disruptions, query["operatorCode"],
- query["trainid"], query["serviceType"],
- Utils.color(Utils.COLOR_LIGHTBLUE), done_count, Utils.color(Utils.FONT_RESET),
- len(stations_filtered), total_count,
- ", ".join([s["summary"] for s in stations_filtered])))
+ event["stdout"].write("%s%s %s %s (%s%s%s/%s/%s): %s" % (
+ disruptions, query["operatorCode"],
+ query["trainid"], query["serviceType"],
+ Utils.color(Utils.COLOR_LIGHTBLUE), done_count,
+ Utils.color(Utils.FONT_RESET),
+ len(stations_filtered), total_count,
+ ", ".join([s["summary"] for s in stations_filtered])))
def head(self, event):
client = self.client
service_id = event["args_split"][0]
- query = client.service.QueryServices(service_id, datetime.utcnow().date().isoformat(),
- datetime.utcnow().time().strftime("%H:%M:%S+0000"))
+ query = client.service.QueryServices(service_id,
+ datetime.utcnow().date().isoformat(),
+ datetime.utcnow().time().strftime(
+ "%H:%M:%S+0000"))
if not query:
- return event["stderr"].write("No currently running services match this identifier")
+ return event["stderr"].write(
+ "No currently running services match this identifier")
services = query["serviceList"][0]
if event.get("external"):
- event["stdout"].write("\n".join(["{a.uid:6} {a.trainid:4} {a.originName} ({a.originCrs}) → {a.destinationName} ({a.destinationCrs})".format(a=a) for a in services]))
+ event["stdout"].write("\n".join([
+ "{a.uid:6} {a.trainid:4} {a.originName} ({a.originCrs}) → {a.destinationName} ({a.destinationCrs})".format(
+ a=a) for a in services]))
else:
- event["stdout"].write(", ".join(["h/%s r/%s u/%s rs/%s %s (%s) -> %s (%s)" % (a["trainid"], a["rid"], a["uid"], a["rsid"], a["originName"], a["originCrs"], a["destinationName"], a["destinationCrs"]) for a in services]))
+ event["stdout"].write(", ".join([
+ "h/%s r/%s u/%s rs/%s %s (%s) -> %s (%s)" % (
+ a["trainid"], a["rid"],
+ a["uid"], a["rsid"],
+ a["originName"], a["originCrs"],
+ a["destinationName"],
+ a["destinationCrs"]) for a in
+ services]))
def service_code(self, event):
client = self.client
if not event["args"].isnumeric():
- return event["stderr"].write("The delay/cancellation code must be a number")
- reasons = {a["code"]:(a["lateReason"], a["cancReason"]) for a in client.service.GetReasonCodeList()[0]}
+ return event["stderr"].write(
+ "The delay/cancellation code must be a number")
+ reasons = {a["code"]: (a["lateReason"], a["cancReason"]) for a in
+ client.service.GetReasonCodeList()[0]}
if event["args"] in reasons:
- event["stdout"].write("%s: %s" % (event["args"], " / ".join(reasons[event["args"]])))
+ event["stdout"].write(
+ "%s: %s" % (event["args"], " / ".join(reasons[event["args"]])))
else:
event["stdout"].write("This doesn't seem to be a valid reason code")