14 Commits

8 changed files with 219 additions and 69 deletions

View File

@ -82,7 +82,7 @@ if __name__ == "__main__":
year_donation = int(str(datetime.datetime.now().year)[2:]) + 1 # gets the last two digits of the current year then adds 1 for the current season year_donation = int(str(datetime.datetime.now().year)[2:]) + 1 # gets the last two digits of the current year then adds 1 for the current season
# name based off the 2025 naming system # name based off the 2025 naming system
# Define the path to the Excel file and the lock file # Define the path to the Excel file and the lock file
file_name = f"./Interviews/OR{year_donation}-L-Interview Data.xlsx" file_name = f"../Interviews/OR{year_donation}-L-Interview Data.xlsx"
try: try:
data = ReadDatabase(file_name) data = ReadDatabase(file_name)
print(json.dumps(data, indent=4)) print(json.dumps(data, indent=4))

View File

@ -33,7 +33,8 @@ def ReadDatabase(file_path, lock_path):
# Process each row in the DataFrame to structure data by date and time # Process each row in the DataFrame to structure data by date and time
for _, row in df.iterrows(): for _, row in df.iterrows():
# Convert Date and Start Time to string format for easier comparison # Convert Date and Start Time to string format for easier comparison
date = str(row['Date']).split(" ")[0] # Format date to YYYY-MM-DD date = str(row['Date']).split(" ")[0] # Extract the date part
start_time = str(row['Start Time Slot']) start_time = str(row['Start Time Slot'])
# Calculate the slot capacity and current number of interviewees # Calculate the slot capacity and current number of interviewees

View File

@ -1,6 +1,8 @@
import datetime
from .ReadDB import ReadDatabase from .ReadDB import ReadDatabase
def getSchedulePackager(file_name): def getSchedulePackager(file_name):
""" """
Packages up the response for a http response Packages up the response for a http response
@ -39,7 +41,8 @@ def SelectAppointment (file_name, appointmentJson):
try: try:
validEmail = validate_email(appointmentJson["intervieweeEmail"], check_deliverability=True) validEmail = validate_email(appointmentJson["intervieweeEmail"], check_deliverability=True)
if validEmail: if validEmail:
status = AppendAppointment(file_path=file_name, date=appointmentJson["date"], start_time=appointmentJson["startTime"], interviewee_name=appointmentJson["intervieweeName"], interviewee_email=appointmentJson["intervieweeEmail"]) date_formatted = datetime.datetime.strptime(appointmentJson["date"], '%m/%d/%Y').strftime('%Y-%m-%d')
status = AppendAppointment(file_path=file_name, date=date_formatted, start_time=appointmentJson["startTime"], interviewee_name=appointmentJson["intervieweeName"], interviewee_email=appointmentJson["intervieweeEmail"])
if status: if status:
resBody = {"Success": True, "validEmail": "true"} resBody = {"Success": True, "validEmail": "true"}

View File

@ -45,38 +45,94 @@ def send_email(interviewee_email="darkicewolf50@gmail.com", interviewee_name="br
# Message body # Message body
body = f''' body = f'''
<html lang="en-US"> <html lang="en-US">
<head> <head>
<title>Interview Invitation</title> <title>Interview Invitation</title>
</head> </head>
<body> <body>
<p>Dear {interviewee_name},</p> <p>Dear {interviewee_name},</p>
<p>Your interview has been scheduled on {date} at {start_time} MST.</p> <p>Your interview has been scheduled on {date} at {start_time}</p>
<p> Your interview location is at {location} or will be emailed to you. </p> <p>Please ensure to be available at the designated time.</p>
<p>Please ensure to be available at the designated time.</p> <table
<a role="presentation"
href="https://calendar.google.com/calendar/render?action=TEMPLATE&text=UCalgary+Baja+Interview+with+{interviewee_name}&dates={start_time_google}/{end_time_google}&details=Interview+with+UCalgary+Baja+Team&location={location}" border="0"
target="_blank" cellpadding="0"
> cellspacing="0"
<button type="button" class="AddtoCal">Add to Google Calendar</button> style="width: 100%; margin: 20px 0">
</a> <tr>
<a <td
href="https://outlook.live.com/calendar/0/deeplink/compose?subject=UCalgary+Baja+Interview+with+{interviewee_name}&body=Interview+with+UCalgary+Baja+Team&location={location}&startdt={outlook_start}&enddt={outlook_end}" align="center"
target="_blank" style="width: 48%; margin-right: 1%">
> <a
<button type="button" class="AddtoCal">Add to Outlook Calendar</button> href="https://calendar.google.com/calendar/render?action=TEMPLATE&text=UCalgary+Baja+Interview+with+{interviewee_name}&dates={start_time_google}/{end_time_google}&details=Interview+with+UCalgary+Baja+Team&location={location}"
</a> target="_blank"
<p>Best regards,</p> style="
<p>UCalgary Baja Interview Team</p> text-decoration: none;
<img display: inline-block;
src="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1733003224/UCalgaryBAJA_Logo-2024_mpmljh.png" background-color: #376fc9;
alt="UCalgary Baja Team" color: white;
height="120svh" padding: 10px 20px;
/> font-family: Arial, sans-serif;
</body> font-size: 14px;
</html> border-radius: 4px;
''' border: 2px solid grey;
">
<img
src="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745094071/google-calendar-svgrepo-com_vkmq2n.png"
alt="Google Calendar"
style="
vertical-align: middle;
height: 40px;
margin-right: 10px;
" />
Add to Google Calendar
</a>
</td>
<td
align="center"
style="width: 48%; margin-left: 1%">
<a
href="https://outlook.live.com/calendar/0/deeplink/compose?subject=UCalgary+Baja+Interview+with+{interviewee_name}&body=Interview+with+UCalgary+Baja+Team&location={location}&startdt={outlook_start}&enddt={outlook_end}"
target="_blank"
style="
text-decoration: none;
display: inline-block;
background-color: #376fc9;
color: white;
padding: 10px 20px;
font-family: Arial, sans-serif;
font-size: 14px;
border-radius: 4px;
border: 2px solid grey;
">
<img
src="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745094071/ms-outlook-svgrepo-com_idmyw0.png"
alt="Outlook Logo"
style="
vertical-align: middle;
height: 40px;
margin-right: 10px;
" />
Add to Outlook Calendar
</a>
</td>
</tr>
</table>
<p>Best regards,</p>
<p>UCalgary Baja Interview Team</p>
<img
src="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1733003224/UCalgaryBAJA_Logo-2024_mpmljh.png"
alt="UCalgary Baja Logo"
height="120svh" />
<p>
If you need to change the date or cancel please email
<a href="mailto:uofcbaja@gmail.com">uofcbaja@gmail.com</a>
or reply all to this email
</p>
</body>
</html>
'''
msg.attach(MIMEText(body, 'html')) msg.attach(MIMEText(body, 'html'))
try: try:

View File

@ -1,29 +1,86 @@
<html lang="en-US"> <html lang="en-US">
<head> <head>
<title>Interview Invitation</title> <title>Interview Invitation</title>
</head> </head>
<body> <body>
<p>Dear {interviewee_name},</p> <p>Dear {interviewee_name},</p>
<p>Your interview has been scheduled on {date} at {start_time}</p> <p>Your interview has been scheduled on {date} at {start_time}</p>
<p>Please ensure to be available at the designated time.</p> <p>Please ensure to be available at the designated time.</p>
<a <table
href="https://calendar.google.com/calendar/render?action=TEMPLATE&text=Interview+with+{interviewee_name}&dates=20241130T100000Z/20241130T110000Z&details=Interview+with+UCalgary+Baja+Team&location=ENC37" role="presentation"
target="_blank" border="0"
> cellpadding="0"
<button type="button" class="AddtoCal">Add to Google Calendar</button> cellspacing="0"
</a> style="width: 100%; margin: 20px 0">
<a <tr>
href="https://outlook.live.com/calendar/0/deeplink/compose?subject=Interview+with+{interviewee_name}&body=Interview+with+UCalgary+Baja+Team&location=ENC37&startdt=2024-11-30T10:00:00&enddt=2024-11-30T11:00:00" <td
target="_blank" align="center"
> style="width: 48%; margin-right: 1%">
<button type="button" class="AddtoCal">Add to Outlook Calendar</button> <a
</a> href="https://calendar.google.com/calendar/render?action=TEMPLATE&text=UCalgary+Baja+Interview+with+{interviewee_name}&dates={start_time_google}/{end_time_google}&details=Interview+with+UCalgary+Baja+Team&location={location}"
<p>Best regards,</p> target="_blank"
<p>UCalgary Baja Interview Team</p> style="
<img text-decoration: none;
src="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1733003224/UCalgaryBAJA_Logo-2024_mpmljh.png" display: inline-block;
alt="UCalgary Baja Team" background-color: #376fc9;
height="120svh" color: white;
/> padding: 10px 20px;
</body> font-family: Arial, sans-serif;
font-size: 14px;
border-radius: 4px;
border: 2px solid grey;
">
<img
src="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745094071/google-calendar-svgrepo-com_vkmq2n.png"
alt="Google Calendar"
style="
vertical-align: middle;
height: 40px;
margin-right: 10px;
" />
Add to Google Calendar
</a>
</td>
<td
align="center"
style="width: 48%; margin-left: 1%">
<a
href="https://outlook.live.com/calendar/0/deeplink/compose?subject=UCalgary+Baja+Interview+with+{interviewee_name}&body=Interview+with+UCalgary+Baja+Team&location={location}&startdt={outlook_start}&enddt={outlook_end}"
target="_blank"
style="
text-decoration: none;
display: inline-block;
background-color: #376fc9;
color: white;
padding: 10px 20px;
font-family: Arial, sans-serif;
font-size: 14px;
border-radius: 4px;
border: 2px solid grey;
">
<img
src="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745094071/ms-outlook-svgrepo-com_idmyw0.png"
alt="Outlook Logo"
style="
vertical-align: middle;
height: 40px;
margin-right: 10px;
" />
Add to Outlook Calendar
</a>
</td>
</tr>
</table>
<p>Best regards,</p>
<p>UCalgary Baja Interview Team</p>
<img
src="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1733003224/UCalgaryBAJA_Logo-2024_mpmljh.png"
alt="UCalgary Baja Logo"
height="120svh" />
<p>
If you need to change the date or cancel please email
<a href="mailto:uofcbaja@gmail.com">uofcbaja@gmail.com</a>
or reply all to this email
</p>
</body>
</html> </html>

View File

@ -5,7 +5,7 @@ The Docker Project that runs on the Baja Nas
# BAJA CLoud Backend # BAJA CLoud Backend
Can be found [here](http://darkicewofl50.asuscomm.com:43443/) Can be found [here](https://bajabackend.bajacloud.duckdns.org/)
Reason in "Baja Data 2024 - 2025/W - Software/Brock's Learning.docx" Reason in "Baja Data 2024 - 2025/W - Software/Brock's Learning.docx"

44
main.py
View File

@ -1,5 +1,6 @@
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel from pydantic import BaseModel
from InterviewBooking.NoSheet import NoSheet from InterviewBooking.NoSheet import NoSheet
@ -14,8 +15,32 @@ if not os.path.isfile(file_name):
os.makedirs(os.path.dirname(file_name), exist_ok=True) os.makedirs(os.path.dirname(file_name), exist_ok=True)
NoSheet(file_name) NoSheet(file_name)
app = FastAPI() app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # This allows all origins
allow_credentials=True,
allow_methods=["*"], # Allow all methods (GET, POST, OPTIONS, etc.)
allow_headers=["*"], # Allow all headers
)
"""
YOU MUST ADD CORS MANUALLY TO ANY METHOD USE THIS TEMPLATE
ADD TO JSONRESPONSE
USE APPROPRIATE METHOD fOR THE TYPE IE
@app.get = ... "Access-Control-Allow-Methods": "GET", ...
headers={
"isBase64Encoded": "false", # Header Modification
# Adding CORS headers explicitly
"Access-Control-Allow-Origin": "*", # Allow all origins
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", # Allowed methods
"Access-Control-Allow-Headers": "*", # Allow all headers
},
"""
@app.get("/") @app.get("/")
def get_root(): def get_root():
""" """
@ -37,6 +62,9 @@ def get_root():
return JSONResponse( return JSONResponse(
headers={ headers={
"isBase64Encoded": "false", # Header Modification "isBase64Encoded": "false", # Header Modification
"Access-Control-Allow-Origin": "*", # Allow all origins
"Access-Control-Allow-Methods": "GET", # Allowed methods
"Access-Control-Allow-Headers": "*", # Allow all headers
}, },
content={ content={
"body": res # Ensure res is a dict or do json.dumps to enusre it is stringified "body": res # Ensure res is a dict or do json.dumps to enusre it is stringified
@ -68,6 +96,10 @@ async def getAppointments():
return JSONResponse( return JSONResponse(
headers={ headers={
"isBase64Encoded": "false", # Header Modification "isBase64Encoded": "false", # Header Modification
# Adding CORS headers explicitly
"Access-Control-Allow-Origin": "*", # Allow all origins
"Access-Control-Allow-Methods": "GET", # Allowed methods
"Access-Control-Allow-Headers": "*", # Allow all headers
}, },
content={ content={
"body": res # Ensure res is a dict or do json.dumps to enusre it is stringified "body": res # Ensure res is a dict or do json.dumps to enusre it is stringified
@ -92,8 +124,8 @@ class Appointment(BaseModel):
""" """
intervieweeName: str intervieweeName: str
date: str
startTime: str startTime: str
date: str
intervieweeEmail: str intervieweeEmail: str
@ -111,13 +143,16 @@ async def postSelectInterview(rawRequest: Appointment):
``Contact``: darkicewolf50@gmail.com ``Contact``: darkicewolf50@gmail.com
""" """
requestDict = {key: str(value) for key, value in rawRequest.model_dump().items()}
requestDict = {key: str(value) for key, value in rawRequest.dict().items()}
res = SelectAppointment(file_name, requestDict) res = SelectAppointment(file_name, requestDict)
return JSONResponse( return JSONResponse(
headers={ headers={
"isBase64Encoded": "false", # Header Modification "isBase64Encoded": "false", # Header Modification
# Adding CORS headers explicitly
"Access-Control-Allow-Origin": "*", # Allow all origins
"Access-Control-Allow-Methods": "POST", # Allowed methods
"Access-Control-Allow-Headers": "*", # Allow all headers
}, },
content={ content={
"body": res # Ensure res is a dict or do json.dumps to enusre it is stringified "body": res # Ensure res is a dict or do json.dumps to enusre it is stringified
@ -125,4 +160,3 @@ async def postSelectInterview(rawRequest: Appointment):
# status_code=200 commented out just to show how to change it if you wanted # status_code=200 commented out just to show how to change it if you wanted
) )

View File

@ -1 +0,0 @@
this is only to test a discord webhook, this will be deleted later