Skip to content

Commit

Permalink
Add Status Updates and Cancelled Courses
Browse files Browse the repository at this point in the history
  • Loading branch information
shiva-menta committed Nov 22, 2024
1 parent 83c02a1 commit 6f8add4
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 12 deletions.
12 changes: 12 additions & 0 deletions backend/courses/management/commands/loadstatus.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import asyncio
import json
import logging

from django.core.management.base import BaseCommand
from tqdm import tqdm

from courses import registrar
from courses.management.commands.sync_path_status import (
get_all_course_status_path,
get_department_codes,
)
from courses.models import Course, Section
from courses.util import (
get_course_and_section,
Expand All @@ -25,6 +30,9 @@ def set_all_status(semester=None, add_status_update=False, verbose=False):
statuses_out_of_sync = []
status_updates_out_of_sync = []

department_codes = get_department_codes()
path_course_to_status = asyncio.run(get_all_course_status_path(semester, department_codes))

for status in tqdm(statuses):
section_code = status.get("section_id_normalized")
if section_code is None:
Expand All @@ -45,6 +53,10 @@ def set_all_status(semester=None, add_status_update=False, verbose=False):
except (Section.DoesNotExist, Course.DoesNotExist):
continue

if section_code in path_course_to_status:
# Defer judgement to Path@Penn status
course_status = path_course_to_status[section_code]

last_status_update = section.last_status_update
current_status = section.status

Expand Down
2 changes: 1 addition & 1 deletion backend/courses/management/commands/registrarimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def registrar_import(semester=None, query=""):
dept.save()

print("Loading course statuses from registrar...")
set_all_status(semester=semester)
set_all_status(semester=semester, add_status_update=True)

recompute_parent_courses(semesters=[semester], verbose=True)
recompute_soft_state(semesters=[semester], verbose=True)
Expand Down
53 changes: 43 additions & 10 deletions backend/courses/management/commands/sync_path_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,46 +22,75 @@
)


def map_path_to_opendata(course_status):
return "O" if course_status == "A" else "C"
def map_path_to_opendata(course_status: str) -> str:
match course_status:
case "A":
return "O"
case "F":
return "C"
case _:
return "X"


def normalize_status(course_status: str) -> str:
match course_status:
case "O":
return "Open"
case "C":
return "Closed"
case _:
return "Cancelled"


def denormalize_section_code(section_code: str) -> str:
return "".join(section_code.split("-"))


def format_webhook_request_body(
section_code: str, new_course_status: str, semester: str
section_code: str, previous_course_status: str, new_course_status: str, semester: str
) -> Dict[str, str]:
return {
"previous_status": "C" if new_course_status == "O" else "O",
"previous_status": previous_course_status,
"status": new_course_status,
"status_code_normalized": "Open" if new_course_status == "O" else "Closed",
"status_code_normalized": normalize_status(new_course_status),
"section_id": denormalize_section_code(section_code),
"section_id_normalized": section_code,
"term": semester,
}


async def send_webhook_request(
async_session: aiohttp.ClientSession, semester: str, course: str, course_status: str
async_session: aiohttp.ClientSession,
semester: str,
course: str,
previous_course_status: str,
course_status: str,
) -> None:
async with webhook_semaphore:
await async_session.post(
url="https://penncoursealert.com/webhook",
data=json.dumps(format_webhook_request_body(course, course_status, semester)),
data=json.dumps(
format_webhook_request_body(course, previous_course_status, course_status, semester)
),
headers={"Content-Type": "application/json", "Authorization": f"Basic {auth.decode()}"},
)


async def send_webhook_requests(
semester: str, course_list: List[str], path_course_to_status: Dict[str, str]
semester: str,
course_list: List[str],
db_course_to_status: Dict[str, str],
path_course_to_status: Dict[str, str],
) -> None:
async with aiohttp.ClientSession() as async_session:
tasks = [
asyncio.create_task(
coro=send_webhook_request(
async_session, semester, course, path_course_to_status[course]
async_session,
semester,
course,
db_course_to_status[course],
path_course_to_status[course],
)
)
for course in course_list
Expand Down Expand Up @@ -162,7 +191,11 @@ def resolve_path_differences(send_data_to_slack=False, verbose=False):
if verbose:
print(f"Inconsistent Courses: {inconsistent_courses}")

asyncio.run(send_webhook_requests(semester, inconsistent_courses, path_course_to_status))
asyncio.run(
send_webhook_requests(
semester, inconsistent_courses, db_course_to_status, path_course_to_status
)
)
if verbose and inconsistent_courses:
print("Sent updates to webhook.")

Expand Down
2 changes: 1 addition & 1 deletion k8s/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export class MyChart extends PennLabsChart {
})

new CronJob(this, 'sync-path-course-statuses', {
schedule: cronTime.everyHour(),
schedule: cronTime.every(30).minutes(),
image: backendImage,
secret,
cmd: ['python', 'manage.py', 'sync_path_status', '--slack'],
Expand Down

0 comments on commit 6f8add4

Please sign in to comment.