Skip to content

[LiveTennisApiBridge] add - #5090

Open
bensynapse wants to merge 1 commit into
RSS-Bridge:masterfrom
bensynapse:livetennis-bridge
Open

bensynapse wants to merge 1 commit into
RSS-Bridge:masterfrom
bensynapse:livetennis-bridge

Conversation

@bensynapse

Copy link
Copy Markdown

Disclosure: I work on the Live Tennis API, the vendor this bridge reads. It is a paid API with a free tier (no card). If a bridge for a service the author is involved with is unwelcome, say so and I will close this. AI tooling was used while writing it; I understand the code and have run the checks below myself.

What it adds

A bridge over the Live Tennis API's public v1 endpoints, one item per match:

Feed mode Endpoint
Live matches GET /matches?status=live
Today, still to start GET /matches?status=upcoming&from=<today>&to=<today>
Today, finished GET /matches?status=completed&from=<today>&to=<today>
Upcoming fixtures GET /fixtures

Filters: tour (ATP / WTA / Challenger / ITF / Juniors / all), draw (singles / doubles / both), an optional player-name substring, and a limit. Tour and draw are lists because the API's own enums bound them. The player name is free text and is matched locally on the two player names, because the API's player filter takes numeric player ids and resolving a name would cost a second request out of a 100-a-day budget.

Item titles carry the players, the games in each set and the status, for example "Jannik Sinner v Carlos Alcaraz 6-4 3-6 4-4 (live) — Wimbledon". The content adds tournament and round, surface, draw, format, sets, games per set, the game in progress, who is serving, whether the receiver is a point from the break, and both players with country and ranking where known. A retirement reads "(Carlos Alcaraz retired)". A match every source lost before a result reads "(closed unfinished, result unresolved)" and asserts no winner.

Why

No bridge in the tree publishes live match state or scores for any sport. The closest are ABolaBridge, a sports newspaper's news feed, and SleeperFantasyFootballBridge, fantasy-league alerts. Both are article or alert feeds rather than live sport.

Cache timeout

CACHE_TIMEOUT is 900, so fifteen minutes. One feed fetch costs exactly one API request and the free tier allows 100 a day, so a feed served through this cache costs at most 96 a day however often a reader polls it. The framework enforces that, not the bridge. Each distinct set of feed parameters is cached separately, which the docs page spells out.

No key configured

The key is read from [LiveTennisApiBridge] api_key in config.ini.php, or the matching environment variable, and never from a feed parameter, since feed URLs get shared and logged. config.default.ini.php gains that one section with an empty default. With no key the bridge raises a configuration error naming the section and the key; nothing else in config.default.ini.php is touched and no other bridge changes behaviour. The key is sent as an X-API-Key header, never in the query string, so it stays out of access logs, the HTTP cache key and exception messages. A 401, a 403 where the plan does not include the endpoint, a 429, a 400 and a non-JSON body each produce a named bridge error rather than a PHP warning or a stack trace.

Also adds docs/10_Bridge_Specific/LiveTennisApiBridge.md, matching the pages the other configured bridges have.

Verification

Run in a php:8.3-cli container with the repo mounted:

  • composer install, then composer test: 3349 tests, 34957 assertions, 2 skipped. Baseline without this change is 3343 / 34856 / 2, so the six new tests are the BridgeImplementationTest cases for this bridge and both skips are pre-existing.
  • composer lint: clean, 624 files.
  • phpcompatibility in the form the Lint workflow uses (global phpcs, testVersion 7.4-): clean, 636 files.
  • No executable .php files.
  • The four endpoints were probed live with a deliberately invalid key. Each answers 401, and the resulting bridge error names the cause without ever including the key. /health answers 200 without a key.
  • Item building was exercised against payloads shaped like the documented Match / Score / Fixture schemas, including a thirteen-case break-point truth table (advantage receiver, receiver at 40 against 0, 15 and 30, deuce, advantage server, tiebreak, null server, null points) and rows carrying nothing but an id. Items were then pushed through FeedItem. No warnings under error_reporting=E_ALL.

Not verified: a live 200 payload, since the key lives on the vendor side rather than on my build machine. The 403, 429 and 400 paths are code paths I did not trigger against production.

One practical note: prtester will show this bridge's configuration error unless a key is present in the environment it runs in, so a red result there is not necessarily a defect. I am happy to send a maintainer a key privately if you want the rendered feed in CI or for review.

Tennis scores from the Live Tennis API for ATP, WTA, Challenger and ITF: live
matches, today's schedule, today's finished matches and upcoming fixtures, one
item per match.

The bridge needs an api key, read from the [LiveTennisApiBridge] section of
config.ini.php and sent as a header rather than in the query string. With no key
it reports a configuration error naming the section and the key.

CACHE_TIMEOUT is 900 so that a feed costs at most 96 requests a day, inside the
vendor's 100 a day free tier.
@LordArrin

Copy link
Copy Markdown
Contributor

@bensynapse
I ported your bridge to my fork - with docs. Can add you as maintainer, if you want - or make some other changes.

@bensynapse

Copy link
Copy Markdown
Author

Thanks for porting the bridge and adding documentation. I found it in bridges-v2/LiveTennisApiBridge.php in your fork. I can't commit to an ongoing maintainer role yet, so please leave the maintainer entry unassigned for now; no need to hold up your work on that.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants