From 670635562388a4a00fa9f45f28b37301c76d976f Mon Sep 17 00:00:00 2001 From: JJ Date: Thu, 20 Mar 2025 14:11:14 +0000 Subject: readme --- README.md | 67 +++++++++++++++++++++++++++++- package-lock.json | 6 +++ package.json | 1 + pyproject.toml | 7 +--- src/tube_stat/__init__.py | 0 src/tube_stat/cli.py | 77 ---------------------------------- tube_stat/__init__.py | 0 tube_stat/cli.py | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 178 insertions(+), 83 deletions(-) create mode 100644 package-lock.json create mode 100644 package.json delete mode 100644 src/tube_stat/__init__.py delete mode 100644 src/tube_stat/cli.py create mode 100644 tube_stat/__init__.py create mode 100644 tube_stat/cli.py diff --git a/README.md b/README.md index dba56d1..1c876a6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,68 @@ # Tubestat -Python CLI tool to see London tube statuses from the command line +Python CLI tool to see London tube statuses from the command line. + +## Installation + +```console +pipx install tube-stat +``` + +Tubestat relies on a `config.json` file with the following format: + +```json +{ + "APP": "", + "KEY": "" +} +``` + +You will need to sign up for a developer API key and app name at [TFL](https://api.tfl.gov.uk/). + +On Linux and Mac, the app looks for the following path: + +`/Users/$HOME/.config/tubestat/config.json` + +On Windows: + +`/Users/$HOME/AppData/Roaming/tubestat/config.json` + +## Usage + +Return the status on all lines: + +```console +tubestat +``` + +Return the status only on the Bakerloo line, for example: + +```console +tubestat --line bakerloo +``` + +Return the status for both the Bakerloo and Central line, for example: + +```console +tubestat --line bakerloo,central +``` + +All possible lines: + +```console +"bakerloo" +"victoria" +"central" +"circle" +"district" +"hammersmith-city" +"jubilee" +"metropolitan" +"northern" +"piccadilly" +"waterloo-city" +"dlr" +"overground" +"tram" +"elizabeth" +``` diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..99e9e5f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "tube-stat", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/package.json @@ -0,0 +1 @@ +{} diff --git a/pyproject.toml b/pyproject.toml index 6ecf7d1..c1d9ecb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "tube-stat" -version = "0.1.0" +version = "0.1.2" description = "" authors = [ {name = "JJ",email = "nicetry@noemail.com"} @@ -12,11 +12,8 @@ dependencies = [ "requests (>=2.32.3,<3.0.0)" ] -[tool.poetry] -packages = [{include = "tube_stat", from = "src"}] - [tool.poetry.scripts] -tubestat = "src.tube_stat.cli:cli" +tubestat = "tube_stat.cli:cli" [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] diff --git a/src/tube_stat/__init__.py b/src/tube_stat/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/tube_stat/cli.py b/src/tube_stat/cli.py deleted file mode 100644 index c408804..0000000 --- a/src/tube_stat/cli.py +++ /dev/null @@ -1,77 +0,0 @@ -import click -import json -import requests - -with open("./config.json", "r") as e: - config = json.load(e) - -TUBE_LINES = ( - "bakerloo", "victoria", "central", "circle", "district", "hammersmith-city", - "jubilee", "metropolitan", "northern", "piccadilly", "waterloo-city", "dlr", - "overground", "tram" -) -APP = config["APP"] -KEY = config["KEY"] - -def get_line_color(line: str) -> tuple[int, int, int]: - match line: - case "bakerloo": - return (179, 99, 5) - case "victoria": - return (0, 152, 212) - case "central": - return (227, 32, 23) - case "circle": - return (255, 211, 0) - case "district": - return (0, 120, 42) - case "hammersmith-city": - return (243, 169, 187) - case "jubilee": - return (160, 165, 169) - case "metropolitan": - return (155, 0, 86) - case "northern": - return (0, 0, 0) - case "piccadilly": - return (0, 54, 136) - case "waterloo-city": - return (149, 205, 186) - case "dlr": - return (0, 164, 167) - case "overground": - return (238, 124, 14) - case "tram": - return (132, 184, 23) - case _: - return (128, 128, 128) - -@click.command() -@click.option("--line", default=None, help="comma separated tube lines, e.g bakerloo,central") -def cli(line): - if line: - requested_lines = line.split(",") - invalid_lines = [l for l in requested_lines if l not in TUBE_LINES] - if invalid_lines: - raise click.ClickException(f'Invalid tube lines: {', '.join(invalid_lines)}') - else: - requested_lines = ','.join(TUBE_LINES) - req_url = f'https://api.tfl.gov.uk/Line/{requested_lines}/Status?app_id={APP}&app_key={KEY}' - res = requests.get(req_url) - res_json = json.loads(res.text) - print_str = "" - for i, r in enumerate(res_json): - if len(res_json) - 1 != i: - line_break = "\n" - else: - line_break = "" - line_colour = get_line_color(r["id"]) - print_str += f'{click.style(r["name"], bg=line_colour)}: {r["lineStatuses"][0]["statusSeverityDescription"]}{line_break}' - click.echo(print_str) - -if __name__ == "__main__": - try: - cli() - except click.ClickException as e: - click.echo(str(e), err=True) - raise click.exceptions.Exit(1) diff --git a/tube_stat/__init__.py b/tube_stat/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tube_stat/cli.py b/tube_stat/cli.py new file mode 100644 index 0000000..577eaab --- /dev/null +++ b/tube_stat/cli.py @@ -0,0 +1,103 @@ +import click +import os +import json +import requests + +TUBE_LINES = ( + "bakerloo", "victoria", "central", "circle", "district", "hammersmith-city", + "jubilee", "metropolitan", "northern", "piccadilly", "waterloo-city", "dlr", + "overground", "tram", "elizabeth" +) + +def get_line_color(line: str) -> tuple[int, int, int]: + match line: + case "bakerloo": + return (179, 99, 5) + case "victoria": + return (0, 152, 212) + case "central": + return (227, 32, 23) + case "circle": + return (255, 211, 0) + case "district": + return (0, 120, 42) + case "elizabeth": + return (89, 52, 146) + case "hammersmith-city": + return (243, 169, 187) + case "jubilee": + return (160, 165, 169) + case "metropolitan": + return (155, 0, 86) + case "northern": + return (0, 0, 0) + case "piccadilly": + return (0, 54, 136) + case "waterloo-city": + return (149, 205, 186) + case "dlr": + return (0, 164, 167) + case "overground": + return (238, 124, 14) + case "tram": + return (132, 184, 23) + case _: + return (128, 128, 128) + +# Get user config +def get_config() -> dict: + if os.name == "nt": + config_path = os.path.join(os.getenv("APPDATA"), "tubestat", "config.json") + else: + config_path = os.path.join(os.path.expanduser("~"), ".config", "tubestat", "config.json") + print(config_path) + try: + with open(config_path, "r") as r: + json_data = json.load(r) + return {"APP": json_data["APP"], "KEY": json_data["KEY"]} + except Exception: + raise click.ClickException(f'ensure that config.json exists and it is properly configured. Instructions are in the Readme') + +@click.command() +@click.option("--line", default=None, help="comma separated tube lines, e.g bakerloo,central") +def cli(line): + app_data = get_config() + APP = app_data.get("APP") + KEY = app_data.get("KEY") + + if line: + requested_lines = line.split(",") + invalid_lines = [l for l in requested_lines if l not in TUBE_LINES] + if invalid_lines: + raise click.ClickException(f'Invalid tube lines: {', '.join(invalid_lines)}') + else: + requested_lines = ','.join(requested_lines) + else: + requested_lines = ','.join(TUBE_LINES) + + req_url = f'https://api.tfl.gov.uk/Line/{requested_lines}/Status?app_id={APP}&app_key={KEY}' + + try: + res = requests.get(req_url) + res.raise_for_status() + except Exception as e: + raise click.ClickException(f'Invalid api call {e}') + + res_json = json.loads(res.text) + print_str = "" + + for i, r in enumerate(res_json): + if len(res_json) - 1 != i: + line_break = "\n" + else: + line_break = "" + line_colour = get_line_color(r["id"]) + print_str += f'{click.style(r["name"], bg=line_colour)}: {r["lineStatuses"][0]["statusSeverityDescription"]}{line_break}' + click.echo(print_str) + +if __name__ == "__main__": + try: + cli() + except click.ClickException as e: + click.echo(str(e), err=True) + raise click.exceptions.Exit(1) -- cgit v1.2.3