from enum import Enum from attr import dataclass, field from functions.timeFormatters import fromString from functions.scrapers.sporza import getJPLMatches, getJPLTable from functions.stringFormatters import leadingZero from datetime import datetime import tabulate class Status(Enum): AfterToday = "--:--" NotStarted = "--:--" Over = "Einde" HalfTime = "Rust" @dataclass class Match: """ Class representing a football match between two teams """ matchDict: dict home: str = field(init=False) homeScore: int = 0 away: str = field(init=False) awayScore: int = 0 start: datetime = field(init=False) date: str = field(init=False) weekDay: str = field(init=False) status: Status = field(init=False) def __attrs_post_init__(self): """ Parse class attributes out of a dictionary returned from an API request """ # The API isn't public, so every single game state is differently formatted self.status = self._getStatus(self.matchDict[Navigation.Status.value]) self.home = self.matchDict[Navigation.HomeTeam.value][Navigation.Name.value] self.away = self.matchDict[Navigation.AwayTeam.value][Navigation.Name.value] if self._hasStarted(): self.homeScore = self.matchDict[Navigation.HomeScore.value] self.awayScore = self.matchDict[Navigation.AwayScore.value] self.start = fromString(self.matchDict["startDateTime"], formatString="%Y-%m-%dT%H:%M:%S.%f%z") self.date = self.start.strftime("%d/%m") self.weekDay = self._getWeekday() def _getStatus(self, status: str): """ Gets the string representation for the status of this match """ # LiveTime only exists if the status is live # Avoids KeyErrors if status.lower() == "live": # Half time if Navigation.LiveMatchPhase.value in self.matchDict and \ self.matchDict[Navigation.LiveMatchPhase.value] == Navigation.HalfTime.value: return Status.HalfTime.value # Current time return self.matchDict[Navigation.LiveTime.value] # If no special status, pull it out of this dict statusses: dict = { "after_today": Status.AfterToday.value, "not_started": Status.NotStarted.value, "end": Status.Over.value } return statusses[status.lower()] def _getWeekday(self): """ Gets the day of the week this match is played on """ day = self.start.weekday() days = ["Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"] return days[day] def getInfo(self): """ Returns a list of all the info of this class in order to create a table """ return [self.weekDay, self.date, self.home, self._getScore(), self.away, self.status] def _getScore(self): """ Returns a string representing the scoreboard """ # No score to show yet, show time when the match starts if not self._hasStarted(): return "{}:{}".format(leadingZero(str(self.start.hour)), leadingZero(str(self.start.minute))) return "{} - {}".format(self.homeScore, self.awayScore) def _hasStarted(self): return self.status not in [Status.AfterToday.value, Status.NotStarted.value] class Navigation(Enum): """ Enum to navigate through the matchdict, seeing as the API is private the keys of the dict could change every now and then so this makes sure a key only has to be changed once. """ AwayTeam = "awayTeam" HomeTeam = "homeTeam" AwayScore = "awayScore" HomeScore = "homeScore" LiveTime = "liveTime" LiveMatchPhase = "liveMatchPhase" HalfTime = "HALF_TIME" Status = "status" Name = "name" def getMatches(matchweek: int): """ Function that constructs the list of matches for a given matchweek """ current_day = getJPLMatches(matchweek) # API request failed if current_day is None: return "Er ging iets fout. Probeer het later opnieuw." matches = list(map(Match, current_day)) matches = list(map(lambda x: x.getInfo(), matches)) header = "Jupiler Pro League - Speeldag {}".format(matchweek) table = tabulate.tabulate(matches, headers=["Dag", "Datum", "Thuis", "Stand", "Uit", "Tijd"]) return "```{}\n\n{}```".format(header, table) def getTable(): """ Function that constructs the current table of the JPL """ rows = getJPLTable() if rows is None: return "Er ging iets fout. Probeer het later opnieuw." # Format every row to work for Tabulate formatted = [_formatRow(row) for row in rows] header = "Jupiler Pro League Klassement" table = tabulate.tabulate(formatted, headers=["#", "Ploeg", "Punten", "M", "M+", "M-", "M=", "D+", "D-", "D+/-"]) return "```{}\n\n{}```".format(header, table) def _formatRow(row): """ Function that formats a row into a list for Tabulate to use """ scoresArray = list([td.renderContents().decode("utf-8") for td in row.find_all("td")])[:9] # Insert the team name into the list scoresArray.insert(1, row.find_all("a")[0].renderContents().decode("utf-8").split("