116 lines
3.3 KiB
Python
116 lines
3.3 KiB
Python
import json
|
|
import re
|
|
from datetime import datetime, timedelta, timezone
|
|
from pathlib import Path
|
|
|
|
import pytz
|
|
|
|
ZONES = {"ET": pytz.timezone("America/New_York"), "UTC": timezone.utc}
|
|
|
|
ZONES["EDT"] = ZONES["EST"] = ZONES["ET"]
|
|
|
|
|
|
class Time(datetime):
|
|
TZ = ZONES["ET"]
|
|
|
|
@classmethod
|
|
def now(cls) -> "Time":
|
|
return cls.from_ts(datetime.now(cls.TZ).timestamp())
|
|
|
|
@classmethod
|
|
def from_ts(cls, ts: int | float) -> "Time":
|
|
return cls.fromtimestamp(ts, tz=cls.TZ)
|
|
|
|
def delta(self, **kwargs) -> "Time":
|
|
return self.from_ts((self + timedelta(**kwargs)).timestamp())
|
|
|
|
def clean(self) -> "Time":
|
|
return self.__class__.fromtimestamp(
|
|
self.replace(second=0, microsecond=0).timestamp(),
|
|
tz=self.TZ,
|
|
)
|
|
|
|
def to_tz(self, tzone: str) -> "Time":
|
|
dt = self.astimezone(ZONES[tzone])
|
|
return self.__class__.fromtimestamp(dt.timestamp(), tz=ZONES[tzone])
|
|
|
|
@classmethod
|
|
def from_str(cls, s: str, fmt: str | None = None) -> "Time":
|
|
pattern = r"\b(ET|UTC|EST|EDT)\b"
|
|
|
|
match = re.search(pattern, s)
|
|
|
|
tz = ZONES.get(match[1]) if match else cls.TZ
|
|
|
|
cleaned_str = re.sub(pattern, "", s).strip()
|
|
|
|
if fmt:
|
|
dt = datetime.strptime(cleaned_str, fmt)
|
|
else:
|
|
formats = [
|
|
"%Y-%m-%d %H:%M",
|
|
"%Y-%m-%d %H:%M:%S",
|
|
"%a, %d %b %Y %H:%M:%S %z",
|
|
]
|
|
|
|
for frmt in formats:
|
|
try:
|
|
dt = datetime.strptime(cleaned_str, frmt)
|
|
break
|
|
except ValueError:
|
|
continue
|
|
else:
|
|
return cls.from_ts(31496400)
|
|
|
|
if not dt.tzinfo:
|
|
dt = tz.localize(dt) if hasattr(tz, "localize") else dt.replace(tzinfo=tz)
|
|
|
|
return cls.fromtimestamp(dt.astimezone(cls.TZ).timestamp(), tz=cls.TZ)
|
|
|
|
|
|
class Leagues:
|
|
def __init__(self) -> None:
|
|
self.data = json.loads(
|
|
(Path(__file__).parent / "leagues.json").read_text(encoding="utf-8")
|
|
)
|
|
|
|
self.live_img = "https://i.gyazo.com/978f2eb4a199ca5b56b447aded0cb9e3.png"
|
|
|
|
def teams(self, league: str) -> list[str]:
|
|
return self.data["teams"].get(league, [])
|
|
|
|
def info(self, name: str) -> tuple[str | None, str]:
|
|
name = name.upper()
|
|
|
|
if match := next(
|
|
(
|
|
(tvg_id, league_data.get("logo"))
|
|
for tvg_id, leagues in self.data["leagues"].items()
|
|
for league_entry in leagues
|
|
for league_name, league_data in league_entry.items()
|
|
if name == league_name or name in league_data.get("names", [])
|
|
),
|
|
None,
|
|
):
|
|
tvg_id, logo = match
|
|
|
|
return (tvg_id, logo or self.live_img)
|
|
|
|
return (None, self.live_img)
|
|
|
|
def is_valid(self, event: str, league: str) -> bool:
|
|
if match := re.search(r"(\-|vs.?|at)", event):
|
|
t1, t2 = event.split(match[1])
|
|
|
|
return any(t in self.teams(league) for t in (t1.strip(), t2.strip()))
|
|
|
|
return event.lower() == "nfl redzone" if league == "NFL" else False
|
|
|
|
@property
|
|
def league_names(self) -> list[str]:
|
|
return self.data["teams"].keys()
|
|
|
|
|
|
leagues = Leagues()
|
|
|
|
__all__ = ["leagues", "Time"]
|