#!/usr/bin/env python import os from datetime import datetime, timedelta import requests import bs4 from bs4 import BeautifulSoup from init_api import get_service import dotenv class Match: def __init__(self, team1: str, team2: str, score1: int, score2: int, raw_time: str, stage: str, roundName: str): self.team1 = team1 self.team2 = team2 self.score1 = score1 self.score2 = score2 self.stage = stage self.roundName = roundName self.time = datetime(*list(map(lambda v: int(v), raw_time.split(",")))) self.eventId = None def get_format(self) -> int: if self.stage == "Play-In": if self.roundName == "Qualifiers" or self.roundName == "EMEA vs NA": return 5 return 3 if self.stage == "Swiss": if self.roundName in ["Round 1", "Round 2"]: return 1 if self.roundName == "Round 3" and self.time.day == 22: return 1 return 3 if self.stage == "Knockout": return 5 def event_data(self): return { "start": { "dateTime": self.time.isoformat() + "Z" }, "end": { "dateTime": (self.time + timedelta(hours=self.get_format())).isoformat() + "Z" }, "summary": f"{self.team1} - {self.team2}", "description": f"{self.stage} {self.roundName} BO{self.get_format()}\n{self.score1} - {self.score2}" } def update_event(self): api = get_service() api.events().update( calendarId=os.environ["CALENDAR_ID"], eventId=self.eventId, body=self.event_data() ).execute() def create_event(self): api = get_service() api.events().insert( calendarId=os.environ["CALENDAR_ID"], body=self.event_data() ).execute() def is_in_calendar(self, calendar_events): for event in calendar_events: if datetime.fromisoformat(event["start"]["dateTime"][:-1]) == self.time: self.eventId = event["id"] return True return False def __repr__(self): return f"{self.team1:3} - {self.time} - {self.team2}" def fetch_matches(): sources = [ "https://lol.fandom.com/wiki/2023_Worlds_Qualifying_Series", "https://lol.fandom.com/wiki/2023_Season_World_Championship/Play-In", "https://lol.fandom.com/wiki/2023_Season_World_Championship/Main_Event" ] stages = ["Play-In", "Swiss", "Knockout"] matches: list[Match] = [] for src in sources: fetched_data = requests.get(src).text soup = BeautifulSoup(fetched_data, "html.parser") match_lists: list[bs4.Tag] = soup.find_all(attrs={"class": "matchlist"}) for match_list in match_lists: roundName = match_list.find("tr").find("th").find(recursive=False, string=True).text raw_matches: list[bs4.Tag] = match_list.find_all(attrs={"class", "ml-row"}) # somehow identify stage... stage = stages[0] if (src == sources[0] or src == sources[1]) else \ (stages[1] if "Round" in roundName else stages[2]) for raw_match in raw_matches: raw_time = raw_match.find(attrs={"class", "TimeInLocal"}).text scores = raw_match.find_all(attrs={"class", "matchlist-score"}) scores = [0, 0] if not scores else tuple(map(lambda v: int(v.text), scores)) score1 = scores[0] score2 = scores[1] team1 = raw_match.find(attrs={"class", "matchlist-team1"}).find(attrs={"class", "teamname"}).text team2 = raw_match.find(attrs={"class", "matchlist-team2"}).find(attrs={"class", "teamname"}).text matches.append(Match(team1, team2, score1, score2, raw_time, stage, roundName)) return matches def get_calendar_events(): api = get_service() start = "2023-04-01T00:00:00Z" end = "2023-11-20T00:00:00Z" calendarId = os.environ.get("CALENDAR_ID") events = api.events().list( calendarId=calendarId, timeMin=start, timeMax=end, maxResults=2500, singleEvents=True, orderBy='startTime' ).execute()["items"] return events def delete_calendar_events(): api = get_service() calendarId = os.environ.get("CALENDAR_ID") events = get_calendar_events() for event in events: api.events().delete(calendarId=calendarId, eventId=event["id"]).execute() print("Deleted all calendar events") def update(): dotenv.load_dotenv() events = get_calendar_events() for match in fetch_matches(): print(f"Processing match: {match}") if match.is_in_calendar(events): print(f"Event found: {match.eventId}") match.update_event() print("Event updated") else: match.create_event() print("Event created") print("") if __name__ == "__main__": update()