Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 27 additions & 36 deletions plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,11 @@
"plugin_path": "plugins/baseball-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-04",
"last_updated": "2026-10-05",
"verified": true,
"screenshot": "",
"latest_version": "1.57.2",
"ledmatrix_min_version": "3.8.0",
"commit": "39a7a451aa6e13679e7319300248102e4597a1c5"
"latest_version": "1.57.3",
"ledmatrix_min_version": "3.8.0"
},
{
"id": "basketball-scoreboard",
Expand All @@ -104,12 +103,11 @@
"plugin_path": "plugins/basketball-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-03",
"last_updated": "2026-10-05",
"verified": true,
"screenshot": "",
"latest_version": "1.42.1",
"ledmatrix_min_version": "3.8.0",
"commit": "c202cd9a6f4b421d7cee4445b707a4e300b45490"
"latest_version": "1.42.2",
"ledmatrix_min_version": "3.8.0"
},
{
"id": "calendar",
Expand Down Expand Up @@ -280,12 +278,11 @@
"plugin_path": "plugins/football-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-04",
"last_updated": "2026-10-05",
"verified": true,
"screenshot": "",
"latest_version": "3.18.7",
"ledmatrix_min_version": "3.8.0",
"commit": "37f2f954c06f24ffb760b9ddbb019e0b0c7156d5"
"latest_version": "3.18.8",
"ledmatrix_min_version": "3.8.0"
},
{
"id": "geochron",
Expand Down Expand Up @@ -382,13 +379,12 @@
"plugin_path": "plugins/hockey-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-03",
"last_updated": "2026-10-05",
"verified": true,
"screenshot": "",
"latest_version": "1.42.3",
"latest_version": "1.42.4",
"icon": "fas fa-hockey-puck",
"ledmatrix_min_version": "3.8.0",
"commit": "c202cd9a6f4b421d7cee4445b707a4e300b45490"
"ledmatrix_min_version": "3.8.0"
},
{
"id": "lacrosse-scoreboard",
Expand All @@ -408,13 +404,12 @@
"plugin_path": "plugins/lacrosse-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-02",
"last_updated": "2026-10-05",
"verified": true,
"screenshot": "",
"latest_version": "1.36.3",
"latest_version": "1.36.4",
"icon": "fas fa-baseball-ball",
"ledmatrix_min_version": "3.8.0",
"commit": "886d2038d22a35c962beac0ea261543339cffec9"
"ledmatrix_min_version": "3.8.0"
},
{
"id": "birdnet-go",
Expand Down Expand Up @@ -844,12 +839,11 @@
"plugin_path": "plugins/soccer-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-04",
"last_updated": "2026-10-05",
"verified": true,
"screenshot": "",
"latest_version": "2.39.4",
"ledmatrix_min_version": "3.8.0",
"commit": "e73d2090f04bd9f3df1d8af4563bbbc028d70012"
"latest_version": "2.39.5",
"ledmatrix_min_version": "3.8.0"
},
{
"id": "static-image",
Expand Down Expand Up @@ -1004,13 +998,12 @@
"plugin_path": "plugins/ufc-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-04",
"last_updated": "2026-10-05",
"verified": true,
"screenshot": "",
"latest_version": "1.19.4",
"latest_version": "1.19.5",
"icon": "fas fa-fist-raised",
"ledmatrix_min_version": "3.8.0",
"commit": "bf7fcf0170ebce40f0c561979cadd85bdf974205"
"ledmatrix_min_version": "3.8.0"
},
{
"id": "weather",
Expand Down Expand Up @@ -1164,10 +1157,9 @@
"downloads": 0,
"verified": true,
"screenshot": "",
"latest_version": "1.35.2",
"last_updated": "2026-10-02",
"ledmatrix_min_version": "3.8.0",
"commit": "886d2038d22a35c962beac0ea261543339cffec9"
"latest_version": "1.35.3",
"last_updated": "2026-10-05",
"ledmatrix_min_version": "3.8.0"
},
{
"id": "tidbyt-baseball-scoreboard",
Expand Down Expand Up @@ -1210,12 +1202,11 @@
"plugin_path": "plugins/nrl-scoreboard",
"stars": 0,
"downloads": 0,
"last_updated": "2026-10-02",
"last_updated": "2026-10-05",
"verified": true,
"screenshot": "",
"latest_version": "1.34.2",
"ledmatrix_min_version": "3.8.0",
"commit": "886d2038d22a35c962beac0ea261543339cffec9"
"latest_version": "1.34.3",
"ledmatrix_min_version": "3.8.0"
},
{
"id": "jellyfin-now-playing",
Expand Down
8 changes: 8 additions & 0 deletions plugins/afl-scoreboard/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## [1.35.3] - 2026-10-05

### Changed
- No change in behaviour. `SportsLive._is_game_really_over` is now one body in
all nine scoreboards; each declares `FINAL_PERIOD`, the period from which a
0:00 clock ends a game (None: the clock never does). Here it is None: the
clock counts up.

## [1.35.2] - 2026-10-02

### Documentation
Expand Down
10 changes: 8 additions & 2 deletions plugins/afl-scoreboard/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "afl-scoreboard",
"name": "AFL Scoreboard",
"version": "1.35.2",
"version": "1.35.3",
"author": "ChuckBuilds",
"description": "Live, recent, and upcoming AFL (Australian Football League) games with real-time scores and game status.",
"category": "sports",
Expand All @@ -18,6 +18,12 @@
"afl_upcoming"
],
"versions": [
{
"version": "1.35.3",
"released": "2026-10-05",
"ledmatrix_min_version": "3.8.0",
"notes": "No change in behaviour. SportsLive._is_game_really_over is now one body in all nine scoreboards; each declares FINAL_PERIOD, the period from which a 0:00 clock ends a game (None: the clock never does). Here it is None: the clock counts up."
},
{
"version": "1.35.2",
"released": "2026-10-02",
Expand Down Expand Up @@ -537,7 +543,7 @@
"ledmatrix_min": "2.0.0"
}
],
"last_updated": "2026-10-02",
"last_updated": "2026-10-05",
"stars": 0,
"downloads": 0,
"verified": true,
Expand Down
42 changes: 35 additions & 7 deletions plugins/afl-scoreboard/sports.py
Original file line number Diff line number Diff line change
Expand Up @@ -3113,6 +3113,9 @@ def display(self, force_clear=False) -> bool:

class SportsLive(SportsCelebrationMixin, SportsLiveSharedMixin, SportsCore):
SKIN_MODE = "live"
#: Period from which a 0:00 clock ends a game (see _is_game_really_over).
#: None: the clock counts up, so only the final status ends a game.
FINAL_PERIOD: Optional[int] = None

def __init__(
self,
Expand Down Expand Up @@ -3554,15 +3557,15 @@ def format_score(score):
self.logger.error(f"Error displaying live game: {e}", exc_info=True)

def _is_game_really_over(self, game: Dict) -> bool:
"""Check if a game appears to be over even if API says it's live.
"""Whether a game ESPN still lists as live has in fact ended.

AFL-specific: clock counts UP (e.g., 75', 90+3'), so we check for
'final' in period_text. The 0:00 clock check used in countdown-clock
sports doesn't apply here.
It has when its period text says final. From period ``FINAL_PERIOD``
on, a clock at 0:00 ends it too, unless the score is level: a tie at
the end of regulation goes to overtime, and a game that does end tied
says final. With ``FINAL_PERIOD = None`` the clock never ends a game.
"""
game_str = f"{game.get('away_abbr')}@{game.get('home_abbr')}"

# Check if period_text indicates final
# ESPN can send the key as null, and .get()'s default only covers a
# missing key, so a None here crashed the whole live update.
raw_period_text = game.get("period_text")
Expand All @@ -3574,9 +3577,34 @@ def _is_game_really_over(self, game: Dict) -> bool:
)
return True

# Same for a null or non-numeric period: treat it as period 0.
try:
period = int(game.get("period") or 0)
except (TypeError, ValueError, OverflowError):
period = 0
# Only a clock string is read: "0:00" and ":00" are zero; ":40" is not.
clock = game.get("clock")
clock_at_zero = isinstance(clock, str) and clock.replace(":", "").strip() in ("000", "00")

if self.FINAL_PERIOD is not None and period >= self.FINAL_PERIOD and clock_at_zero:
try:
tied = int(game["away_score"]) == int(game["home_score"])
except (KeyError, TypeError, ValueError, OverflowError):
tied = False # a missing or unreadable score leaves it to the clock
if not tied:
self.logger.debug(
f"_is_game_really_over({game_str}): "
f"returning True - clock at 0:00 (clock='{clock}', period={period})"
)
return True
self.logger.debug(
f"_is_game_really_over({game_str}): "
f"returning False - tied at 0:00 (period={period}), overtime next"
)
return False

self.logger.debug(
f"_is_game_really_over({game_str}): returning False "
f"(period_text='{period_text}', period={game.get('period', 0)})"
f"_is_game_really_over({game_str}): returning False"
)
return False

Expand Down
5 changes: 3 additions & 2 deletions plugins/afl-scoreboard/test_null_period_really_over.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ def check(label, is_over, game, expected):
FAILURES.append(label)


# The method only touches self.logger, so a stand-in instance is enough.
_probe = SimpleNamespace(logger=logging.getLogger("null_period_probe"))
# The method reads only self.logger and FINAL_PERIOD, so a stand-in is enough.
_probe = SimpleNamespace(logger=logging.getLogger("null_period_probe"),
FINAL_PERIOD=sports.SportsLive.FINAL_PERIOD)


def shared_is_over(game):
Expand Down
9 changes: 9 additions & 0 deletions plugins/baseball-scoreboard/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## [1.57.3] - 2026-10-05

### Changed
- No change in behaviour: baseball games carry no period, so the 0:00 clock
rule never applied. `SportsLive._is_game_really_over` is now one body in all
nine scoreboards; each declares `FINAL_PERIOD`, the period from which a 0:00
clock ends a game (None: the clock never does). Here it is None. The
postponed/suspended check in `BaseballLive` is unchanged.

## [1.57.0] - 2026-10-02

### Added
Expand Down
10 changes: 8 additions & 2 deletions plugins/baseball-scoreboard/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "baseball-scoreboard",
"name": "Baseball Scoreboard",
"version": "1.57.2",
"version": "1.57.3",
"update_interval": 60,
"author": "ChuckBuilds",
"description": "Live, recent, and upcoming baseball games across MLB, MiLB, and NCAA Baseball with real-time scores and schedules",
Expand Down Expand Up @@ -31,6 +31,12 @@
"branch": "main",
"plugin_path": "plugins/baseball-scoreboard",
"versions": [
{
"version": "1.57.3",
"released": "2026-10-05",
"ledmatrix_min_version": "3.8.0",
"notes": "No change in behaviour: baseball games carry no period, so the 0:00 clock rule never applied. SportsLive._is_game_really_over is now one body in all nine scoreboards; each declares FINAL_PERIOD, the period from which a 0:00 clock ends a game (None: the clock never does). Here it is None. The postponed/suspended check in BaseballLive is unchanged."
},
{
"version": "1.57.2",
"released": "2026-10-04",
Expand Down Expand Up @@ -854,7 +860,7 @@
"ledmatrix_min_version": "2.0.0"
}
],
"last_updated": "2026-10-04",
"last_updated": "2026-10-05",
"stars": 0,
"downloads": 0,
"verified": true,
Expand Down
Loading
Loading