Add tennis module (Live Tennis API) - #2158
Conversation
|
One correction to my own PR description, before a reviewer trips over it. I wrote that a free API key makes the module usable without payment. That is true for That matters here because I'd rather fix this than leave it ambiguous. Happy to do either:
I lean toward (1) — it keeps the module fully usable on a free key with no upsell surface in your tree, which seems more in keeping with the other sports modules. Say which you prefer and I'll push it. |
5ac4cc8 to
9b91623
Compare
What this adds
A new
tennismodule that displays live, upcoming, or completed tennis matches from the Live Tennis API, in the same shape as the existingfootballandnbascoresports modules.Live matches render per-set games, the current game points (including tiebreaks, shown as
TB 5-3), and a green*beside the player who is serving. Completed matches bold the winner. Upcoming matches show their scheduled start time.Configuration
A free API key (1,000 requests/day) is available at https://livetennisapi.com/subscribe/free, so the module is usable without payment. Key resolution follows
modules/football:apiKey→apikey→$WTF_TENNIS_API_KEY→cfg.ModuleSecret.baseURLis also configurable (defaulthttps://api.livetennisapi.com/api/public/v1) for anyone proxying the API; it is what lets the test suite run end-to-end without a key.Keyboard:
/help,rrefresh,h/←andl/→cycle live → upcoming → completed, mirroringnbascore.Files
modules/tennis/{client,types,settings,widget,display,keyboard}.gomodules/tennis/{client,settings,widget,display,keyboard}_test.goapp/widget_maker.go— +4 lines (one import, onecase), the single registration siteNothing else in the tree is touched.
Testing
Table-driven tests throughout, all HTTP served by
httptest— no API key is required to run the suite, and none is embedded anywhere. Covered: happy path and JSON decoding; query-param construction and omission;401,429,500, malformed JSON and connection-refused paths; the no-key / empty / error / rate-limited widget states; thematchLimitcap;Disabled(); YAML parsing, defaults and key-source precedence; and every rendering branch (tiebreak, winner-bold, missing player →TBD, uneven per-set arrays, sets-only fallback).Also verified by running the built binary under a pty with the module enabled and rendering: the no-key setup hint, a full board of matches, and the 401 error state — no panics in any of them.
Two small things worth flagging
Tennis [ATP]silently loses the[ATP]. The title format avoids brackets, and a test asserts it stays that way.TextView, so they are passed throughtview.Escape()(asjira,subreddit,textfileandtododo).Documentation
Per
CONTRIBUTING.md, the static docs live in wtfutil/wtfdocs. A companion PR addingcontent/modules/sports/tennis.mdis ready —settings.SetDocumentationPath("sports/tennis")here points at it. Happy to open it at the same time, or on request.Disclosures
Vendor disclosure: I work on the Live Tennis API, the service this module consumes. I wrote this module because I wanted it in my own dashboard, but you should weigh it accordingly. Concretely: the module only calls
GET /matches; there is no telemetry, no analytics, no affiliate parameter, and no default API key. Every account tier the module needs is free (1,000 req/day). If you would rather not carry a vendor-authored module, or would prefer it to sit behind a more generic interface, say the word and I'll adapt or withdraw it.AI-assistance disclosure: this module was written with AI assistance (Claude). I have read every line, and the verification above — build, vet, gofmt, golangci-lint at the CI-pinned version,
-racetests, and three live runs of the built binary — is real output from my machine, not model-generated text.CONTRIBUTING.mdhas no AI policy, so I am disclosing this proactively; if the project would prefer such contributions be handled differently, tell me and I'll follow that.I've read
CONTRIBUTING.mdand the Code of Conduct. No CLA or DCO sign-off appears to be required — happy to comply if I've missed one.