๐Ÿ“… Calendar file generator for triathlonlive.tv upcoming events triathlon-live-calendar.fly.dev

Adds `show` command

+30
+7
README.md
··· 21 21 $ uv run python -m triathlon_live_calendar generate tri-calendar.ics 22 22 ``` 23 23 24 + Showing the contents of a `.ics` file or URL: 25 + 26 + ```console 27 + $ uv run python -m triathlon_live_calendar show tri-calendar.ics 28 + $ uv run python -m triathlon_live_calendar show https://triathlon-live-calendar.fly.dev/ 29 + ``` 30 + 24 31 Try `python -m triathlon_live_calendar --help` for more details ; ) 25 32 26 33 ## Contributing
+23
triathlon_live_calendar/__main__.py
··· 4 4 from pathlib import Path 5 5 from typing import Optional 6 6 7 + from httpx import get 8 + from ics import Calendar 7 9 from typer import Option, Typer, echo 8 10 from uvicorn import run 9 11 ··· 70 72 logger = Logger(LEVELS[log_level]) 71 73 contents = asyncio.run(calendar(logger)) 72 74 path.write_text(contents.serialize()) 75 + 76 + 77 + @app.command() 78 + def show(source: str): 79 + """Shows the contents of a .ics file or URL.""" 80 + if source.startswith("http://") or source.startswith("https://"): 81 + response = get(source, timeout=30) 82 + response.raise_for_status() 83 + data = response.text 84 + else: 85 + data = Path(source).read_text() 86 + 87 + cal = Calendar(data) 88 + events = sorted(cal.events, key=lambda e: e.begin) 89 + echo(f"{len(events)} event(s) found\n") 90 + for event in events: 91 + begin = event.begin.format("YYYY-MM-DD HH:mm") 92 + echo(f" {begin} | {event.duration} | {event.name}") 93 + if event.url: 94 + echo(f" {' ' * 18}{event.url}") 95 + echo() 73 96 74 97 75 98 if __name__ == "__main__":