···2121$ uv run python -m triathlon_live_calendar generate tri-calendar.ics
2222```
23232424+Showing the contents of a `.ics` file or URL:
2525+2626+```console
2727+$ uv run python -m triathlon_live_calendar show tri-calendar.ics
2828+$ uv run python -m triathlon_live_calendar show https://triathlon-live-calendar.fly.dev/
2929+```
3030+2431Try `python -m triathlon_live_calendar --help` for more details ; )
25322633## Contributing
+23
triathlon_live_calendar/__main__.py
···44from pathlib import Path
55from typing import Optional
6677+from httpx import get
88+from ics import Calendar
79from typer import Option, Typer, echo
810from uvicorn import run
911···7072 logger = Logger(LEVELS[log_level])
7173 contents = asyncio.run(calendar(logger))
7274 path.write_text(contents.serialize())
7575+7676+7777+@app.command()
7878+def show(source: str):
7979+ """Shows the contents of a .ics file or URL."""
8080+ if source.startswith("http://") or source.startswith("https://"):
8181+ response = get(source, timeout=30)
8282+ response.raise_for_status()
8383+ data = response.text
8484+ else:
8585+ data = Path(source).read_text()
8686+8787+ cal = Calendar(data)
8888+ events = sorted(cal.events, key=lambda e: e.begin)
8989+ echo(f"{len(events)} event(s) found\n")
9090+ for event in events:
9191+ begin = event.begin.format("YYYY-MM-DD HH:mm")
9292+ echo(f" {begin} | {event.duration} | {event.name}")
9393+ if event.url:
9494+ echo(f" {' ' * 18}{event.url}")
9595+ echo()
739674977598if __name__ == "__main__":