Some checks failed
build / test (push) Has been cancelled
This should make scrobbling sports more like tasks. The root scrobbled items are a little more generic, but it's easier to see viewing patterns.
148 lines
4.9 KiB
Python
148 lines
4.9 KiB
Python
import logging
|
|
|
|
import requests
|
|
from dateutil.parser import parse
|
|
from django.conf import settings
|
|
from django.core.files.base import ContentFile
|
|
from django.utils import timezone
|
|
from pysportsdb import TheSportsDbClient
|
|
from sports.models import League, Sport, Team
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
API_KEY = getattr(settings, "THESPORTSDB_API_KEY", "2")
|
|
client = TheSportsDbClient(api_key=API_KEY)
|
|
|
|
|
|
def has_logo(league_or_team) -> bool:
|
|
"""Check if a model instance has a logo (handles both NULL and empty string)."""
|
|
return bool(league_or_team.logo and league_or_team.logo.name)
|
|
|
|
|
|
def enrich_league_logo(league: League) -> None:
|
|
"""Fetch the league badge from TheSportsDB and save it as the league logo."""
|
|
if not league.thesportsdb_id or has_logo(league):
|
|
return
|
|
|
|
url = (
|
|
f"https://www.thesportsdb.com/api/v1/json/{API_KEY}"
|
|
f"/lookupleague.php?id={league.thesportsdb_id}"
|
|
)
|
|
try:
|
|
resp = requests.get(url, timeout=10)
|
|
data = resp.json()
|
|
leagues = data.get("leagues", [])
|
|
if not leagues:
|
|
return
|
|
badge_url = leagues[0].get("strBadge")
|
|
if badge_url:
|
|
r = requests.get(badge_url, timeout=10)
|
|
if r.status_code == 200:
|
|
fname = f"{league.uuid or league.thesportsdb_id}.png"
|
|
league.logo.save(fname, ContentFile(r.content), save=True)
|
|
logger.info(
|
|
"Saved league logo from TheSportsDB",
|
|
extra={"league_id": league.id, "league_name": league.name},
|
|
)
|
|
except Exception as e:
|
|
logger.warning(
|
|
"Failed to fetch league logo from TheSportsDB",
|
|
extra={"league_id": league.id, "error": str(e)},
|
|
)
|
|
|
|
|
|
def enrich_team_logo(team: Team) -> None:
|
|
"""Fetch the team badge from TheSportsDB and save it as the team logo."""
|
|
if not team.thesportsdb_id or has_logo(team):
|
|
return
|
|
|
|
try:
|
|
badge_url = None
|
|
|
|
# Try direct lookup by thesportsdb_id first (more reliable)
|
|
url = (
|
|
f"https://www.thesportsdb.com/api/v1/json/{API_KEY}"
|
|
f"/lookupteam.php?id={team.thesportsdb_id}"
|
|
)
|
|
resp = requests.get(url, timeout=10)
|
|
data = resp.json()
|
|
api_teams = data.get("teams", [])
|
|
if api_teams:
|
|
badge_url = api_teams[0].get("strBadge")
|
|
else:
|
|
# Fall back to name search
|
|
result = client.search_teams(team.name) or {}
|
|
api_teams = result.get("teams", [])
|
|
if api_teams:
|
|
badge_url = api_teams[0].get("strBadge")
|
|
|
|
if badge_url:
|
|
r = requests.get(badge_url, timeout=10)
|
|
if r.status_code == 200:
|
|
fname = f"{team.uuid or team.thesportsdb_id}.png"
|
|
team.logo.save(fname, ContentFile(r.content), save=True)
|
|
logger.info(
|
|
"Saved team logo from TheSportsDB",
|
|
extra={"team_id": team.id, "team_name": team.name},
|
|
)
|
|
except Exception as e:
|
|
logger.warning(
|
|
"Failed to fetch team logo from TheSportsDB",
|
|
extra={"team_id": team.id, "error": str(e)},
|
|
)
|
|
|
|
|
|
def lookup_event_from_thesportsdb(event_id: str) -> dict:
|
|
|
|
try:
|
|
event = client.lookup_event(event_id)["events"][0]
|
|
except TypeError:
|
|
return {}
|
|
|
|
if not event or type(event) != dict:
|
|
return {}
|
|
sport, _created = Sport.objects.get_or_create(thesportsdb_id=event.get("strSport"))
|
|
|
|
# Find or create the league and optionally enrich its logo
|
|
lid = event.get("idLeague")
|
|
league, l_created = League.objects.get_or_create(
|
|
thesportsdb_id=lid,
|
|
defaults={"name": event.get("strLeague", "")},
|
|
)
|
|
if l_created:
|
|
league.name = event.get("strLeague", "")
|
|
league.sport = sport
|
|
league.save(update_fields=["name", "sport"])
|
|
enrich_league_logo(league)
|
|
|
|
try:
|
|
start = parse(event.get("strTimestamp"))
|
|
except:
|
|
start = timezone.now()
|
|
|
|
data_dict = {
|
|
"EventId": event_id,
|
|
"ItemType": sport.default_event_type,
|
|
"Name": event.get("strEvent"),
|
|
"AltName": event.get("strEventAlternate"),
|
|
"Start": start,
|
|
"Provider_thesportsdb": event.get("idEvent"),
|
|
"RunTime": sport.default_event_run_time_seconds,
|
|
"Sport": event.get("strSport"),
|
|
"Season": event.get("strSeason"),
|
|
"LeagueId": lid,
|
|
"LeagueName": event.get("strLeague"),
|
|
"HomeTeamId": event.get("idHomeTeam"),
|
|
"HomeTeamName": event.get("strHomeTeam"),
|
|
"AwayTeamId": event.get("idAwayTeam"),
|
|
"AwayTeamName": event.get("strAwayTeam"),
|
|
"RoundId": event.get("intRound"),
|
|
"PlaybackPosition": None,
|
|
"UtcTimestamp": timezone.now().strftime("%Y-%m-%d %H:%M:%S.%f%z"),
|
|
"IsPaused": False,
|
|
"PlayedToCompletion": False,
|
|
"Source": "Vrobbler",
|
|
}
|
|
|
|
return data_dict
|