2023-11-26 10:30:42 +00:00
|
|
|
import pandas as pd
|
|
|
|
from icalendar import Calendar, Event
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
import uuid
|
|
|
|
import os
|
2023-12-05 13:30:53 +00:00
|
|
|
import requests
|
|
|
|
|
|
|
|
telegram_bot_api_key = USER = os.getenv('TELEGRAM_BOT_API_KEY')
|
|
|
|
telegram_bot_chat_id = USER = os.getenv('TELEGRAM_BOT_CHAT_ID')
|
|
|
|
|
|
|
|
def send_message(message:str)->None:
|
|
|
|
"""Send message to me on Telegram when updated.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
message (str): String of message to send.
|
|
|
|
"""
|
|
|
|
requests.post(f'https://api.telegram.org/bot{telegram_bot_api_key}/sendMessage', json={'chat_id': telegram_bot_chat_id, 'text': message})
|
2023-11-26 10:30:42 +00:00
|
|
|
|
2024-01-13 15:37:08 +00:00
|
|
|
def store_df_as_csv(df:pd.DataFrame, name:str)->None:
|
2023-11-27 09:41:06 +00:00
|
|
|
"""Store dataframe as a CSV file.
|
2023-11-26 10:30:42 +00:00
|
|
|
|
|
|
|
Args:
|
2023-11-27 09:41:06 +00:00
|
|
|
df (pd.DataFrame): Dataframe of fixtures.
|
2024-01-13 15:37:08 +00:00
|
|
|
name (str): Name of the CSV file.
|
2023-11-26 10:30:42 +00:00
|
|
|
"""
|
2024-01-13 15:37:08 +00:00
|
|
|
df.to_csv(f'./{name}.csv', index=False)
|
2024-01-13 16:02:27 +00:00
|
|
|
def compare_dfs(df:pd.DataFrame, name:str)->bool:
|
2023-11-27 09:41:06 +00:00
|
|
|
"""Compare the latest DF with the stored DF for any changes.
|
2023-11-26 10:30:42 +00:00
|
|
|
|
|
|
|
Args:
|
2023-11-27 09:41:06 +00:00
|
|
|
df (pd.DataFrame): Latest copy of fixtures in dataframe
|
2024-01-13 16:02:27 +00:00
|
|
|
name (str): Name of the CSV file.
|
2023-11-26 10:30:42 +00:00
|
|
|
|
|
|
|
Returns:
|
2023-11-27 09:41:06 +00:00
|
|
|
bool: True if match, False if no match.
|
2023-11-26 10:30:42 +00:00
|
|
|
"""
|
2024-01-13 16:02:27 +00:00
|
|
|
df2 = pd.read_csv(f'./{name}.csv')
|
2023-11-26 10:30:42 +00:00
|
|
|
return df.equals(df2)
|
|
|
|
|
|
|
|
def write_calendar(cal:Calendar)->None:
|
2023-11-27 09:41:06 +00:00
|
|
|
"""Write the cal object to an ics file.
|
2023-11-26 10:30:42 +00:00
|
|
|
|
|
|
|
Args:
|
2023-11-27 09:41:06 +00:00
|
|
|
cal (Calendar): iCalendar object with all the ics details.
|
2023-11-26 10:30:42 +00:00
|
|
|
"""
|
|
|
|
f = open(os.path.join('./', 'fixtures.ics'), 'wb')
|
|
|
|
f.write(cal.to_ical())
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
def does_csv_exist()->bool:
|
2023-11-27 09:41:06 +00:00
|
|
|
"""Check if the CSV file exists.
|
2023-11-26 10:30:42 +00:00
|
|
|
|
|
|
|
Returns:
|
2023-11-27 09:41:06 +00:00
|
|
|
bool: True if CSV file exists, False if not.
|
2023-11-26 10:30:42 +00:00
|
|
|
"""
|
|
|
|
return os.path.isfile('./fixtures.csv')
|
|
|
|
|
2024-01-13 15:37:08 +00:00
|
|
|
def make_ordinal(n:int)->str:
|
|
|
|
'''
|
|
|
|
Convert an integer into its ordinal representation::
|
|
|
|
|
|
|
|
make_ordinal(0) => '0th'
|
|
|
|
make_ordinal(3) => '3rd'
|
|
|
|
make_ordinal(122) => '122nd'
|
|
|
|
make_ordinal(213) => '213th'
|
|
|
|
'''
|
|
|
|
n = int(n)
|
|
|
|
if 11 <= (n % 100) <= 13:
|
|
|
|
suffix = 'th'
|
|
|
|
else:
|
|
|
|
suffix = ['th', 'st', 'nd', 'rd', 'th'][min(n % 10, 4)]
|
|
|
|
return str(n) + suffix
|
|
|
|
|
|
|
|
def create_ical_file(df:pd.DataFrame, cal:Calendar, table:pd.DataFrame)->None:
|
2023-11-27 09:41:06 +00:00
|
|
|
"""Create an iCalendar file from a dataframe.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
df (pd.DataFrame): Dataframe of fixtures.
|
|
|
|
cal (Calendar): iCalendar object with all the ics details.
|
2024-01-13 15:37:08 +00:00
|
|
|
table (pd.DataFrame): Dataframe of table details.
|
2023-11-27 09:41:06 +00:00
|
|
|
"""
|
2023-11-26 10:30:42 +00:00
|
|
|
for index, row in df.iterrows():
|
|
|
|
event = Event()
|
2024-01-13 15:37:08 +00:00
|
|
|
match_type = str(row['Type'])
|
|
|
|
home_team = str(row['Home Team'])
|
|
|
|
if ("Tongham") not in home_team:
|
|
|
|
home_team = str(row['Home Team']).replace(" U12","")
|
|
|
|
away_team = str(row['Away Team.1'])
|
|
|
|
if ("Tongham") not in away_team:
|
|
|
|
away_team = str(row['Away Team.1']).replace(" U12","")
|
|
|
|
venue = str(row['Venue'])
|
|
|
|
print(row['Date / Time'], home_team, away_team, venue)
|
2023-11-26 10:30:42 +00:00
|
|
|
start_date_time = datetime.strptime(row['Date / Time'], '%d/%m/%y %H:%M')
|
2023-11-27 09:41:06 +00:00
|
|
|
# Set default 8am start time to normal 930 kickoff time.
|
2023-11-26 10:30:42 +00:00
|
|
|
if start_date_time.hour == 8:
|
|
|
|
start_date_time = start_date_time + timedelta(hours=1, minutes=30)
|
2023-11-27 09:41:06 +00:00
|
|
|
# Arrival time is 30 mins before kickoff time.
|
2023-11-26 10:30:42 +00:00
|
|
|
arrival_time = start_date_time + timedelta(minutes=-30)
|
2024-01-13 15:37:08 +00:00
|
|
|
if match_type == 'L':
|
|
|
|
summary = "(League) " + home_team + f" ({make_ordinal(table.loc[table['Team'] == home_team, 'POS'].iloc[0])})" + f" {str(row['Unnamed: 4'])} " + away_team + f" ({make_ordinal(table.loc[table['Team'] == away_team, 'POS'].iloc[0])})"
|
|
|
|
else:
|
|
|
|
summary = "(Cup) " + home_team + f" {str(row['Unnamed: 4'])} " + away_team
|
|
|
|
event.add('summary', summary)
|
2024-01-09 19:03:18 +00:00
|
|
|
notes = row['Status / Notes']
|
2024-01-13 15:37:08 +00:00
|
|
|
if pd.isna(notes):
|
|
|
|
notes = 'None'
|
|
|
|
event.add('description', "Arrive by - " + str(arrival_time) + "\n Notes - " + notes + "\n Table - \n" + str(table))
|
2023-11-26 10:30:42 +00:00
|
|
|
event.add('dtstart', start_date_time)
|
2023-11-27 09:42:15 +00:00
|
|
|
# End 2 hours after start_date_time
|
2023-11-26 10:30:42 +00:00
|
|
|
event.add('dtend', start_date_time + timedelta(hours=2))
|
|
|
|
event.add('dtstamp', start_date_time)
|
|
|
|
event.add('uid', str(uuid.uuid4()))
|
2024-01-13 15:37:08 +00:00
|
|
|
event.add('location', venue)
|
2023-11-26 10:30:42 +00:00
|
|
|
cal.add_component(event)
|
|
|
|
write_calendar(cal)
|
2024-01-13 15:37:08 +00:00
|
|
|
|
2024-01-13 16:02:27 +00:00
|
|
|
def process_table(table_df:pd.DataFrame)->pd.DataFrame:
|
2024-01-13 15:37:08 +00:00
|
|
|
table_df = table_df[:-1]
|
|
|
|
table_df.drop(table_df.columns[len(table_df.columns)-1], axis=1, inplace=True)
|
2024-01-13 16:02:27 +00:00
|
|
|
table_df['POS'] = table_df['POS'].astype('int')
|
|
|
|
table_df['P'] = table_df['P'].astype('int')
|
|
|
|
table_df['W'] = table_df['W'].astype('int')
|
|
|
|
table_df['D'] = table_df['D'].astype('int')
|
|
|
|
table_df['L'] = table_df['L'].astype('int')
|
|
|
|
table_df['PTS'] = table_df['PTS'].astype('int')
|
2024-01-13 15:37:08 +00:00
|
|
|
store_df_as_csv(table_df, "table")
|
|
|
|
return table_df
|
2023-11-26 10:30:42 +00:00
|
|
|
|
2024-01-13 16:02:27 +00:00
|
|
|
def compare_table():
|
|
|
|
table_df = pd.read_html("https://fulltime.thefa.com/table.html?selectedSeason=19010414&selectedDivision=165601607&ftsTablePageContent.fixtureAnalysisForm.standingsTableDay=13&ftsTablePageContent.fixtureAnalysisForm.standingsTableMonth=0&ftsTablePageContent.fixtureAnalysisForm.standingsTableYear=2024&activeTab=1")[0]
|
|
|
|
store_df_as_csv(table_df, "base_table")
|
|
|
|
return table_df
|
|
|
|
|
2023-11-26 10:30:42 +00:00
|
|
|
cal = Calendar()
|
|
|
|
cal.add('prodid', 'Down Grange Pumas Fixtures')
|
|
|
|
cal.add('version', '2.0')
|
2024-01-13 15:37:08 +00:00
|
|
|
fixtures_df = pd.read_html("https://fulltime.thefa.com/fixtures.html?selectedSeason=19010414&selectedFixtureGroupAgeGroup=11&selectedFixtureGroupKey=1_579285719&selectedDateCode=all&selectedClub=&selectedTeam=466317969&selectedRelatedFixtureOption=3&selectedFixtureDateStatus=&selectedFixtureStatus=&previousSelectedFixtureGroupAgeGroup=11&previousSelectedFixtureGroupKey=1_579285719&previousSelectedClub=&itemsPerPage=25")[0]
|
|
|
|
fixtures_df.head()
|
2024-01-13 16:02:27 +00:00
|
|
|
table = compare_table()
|
2023-11-26 10:30:42 +00:00
|
|
|
exists = does_csv_exist()
|
|
|
|
if exists:
|
2024-01-13 16:02:27 +00:00
|
|
|
fixtures_change = compare_dfs(fixtures_df, "fixtures")
|
|
|
|
table_change = compare_dfs(table, "base_table")
|
|
|
|
if not table_change:
|
|
|
|
send_message("Table has updated")
|
|
|
|
if not all([fixtures_change, table_change]):
|
|
|
|
print("Data Updated, ical updated")
|
2024-01-13 15:37:08 +00:00
|
|
|
store_df_as_csv(fixtures_df, "fixtures")
|
2024-01-13 16:02:27 +00:00
|
|
|
create_ical_file(fixtures_df, cal, process_table(table))
|
2023-12-05 13:30:53 +00:00
|
|
|
send_message("Fixtures updated, ical updated")
|
2023-11-27 14:03:29 +00:00
|
|
|
else:
|
2024-01-13 16:02:27 +00:00
|
|
|
print("No Data Updated, No update to ical")
|
2023-11-26 10:30:42 +00:00
|
|
|
else:
|
2024-01-13 15:37:08 +00:00
|
|
|
store_df_as_csv(fixtures_df, "fixtures")
|
2024-01-13 16:02:27 +00:00
|
|
|
create_ical_file(fixtures_df, cal, process_table(table))
|
2023-12-05 13:30:53 +00:00
|
|
|
send_message("New ical file created")
|
2023-11-27 14:03:29 +00:00
|
|
|
print("New ical file created")
|