Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Course ECP Command #171

Merged
merged 13 commits into from
Nov 2, 2023
1 change: 1 addition & 0 deletions uqcsbot/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ async def main():
"basic",
"cat",
"cowsay",
"course_ecp",
"dominos_coupons",
"error_handler",
"events",
Expand Down
109 changes: 109 additions & 0 deletions uqcsbot/course_ecp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from typing import Optional
import logging
from datetime import datetime
import discord
from discord import app_commands
from discord.ext import commands

from uqcsbot.utils.uq_course_utils import (
Offering,
HttpException,
CourseNotFoundException,
ProfileNotFoundException,
get_course_profile_url,
)
from uqcsbot.yelling import yelling_exemptor

class CourseECP(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot

@app_commands.command()
@app_commands.describe(
course1="The course to find an ECP for.",
course2="The second course to find an ECP for.",
course3="The third course to find an ECP for.",
course4="The fourth course to find an ECP for.",
year="The year to find the course ECP for. Defaults to what UQCSbot believes is the current year.",
semester="The semester to find the course ECP for. Defaults to what UQCSbot believes is the current semester.",
campus="The campus the course is held at. Defaults to St Lucia. Defaults to St Lucia. Note that many external courses are 'hosted' at St Lucia.",
mode="The mode of the course. Defaults to Internal.",
)
@yelling_exemptor(
input_args=["course1, course2, course3, course4"]
)

async def courseecp(
self,
interaction: discord.Interaction,
course1: str,
course2: Optional[str],
course3: Optional[str],
course4: Optional[str],
year: Optional[int] = None,
semester: Optional[Offering.SemesterType] = None,
campus: Offering.CampusType = "St Lucia",
mode: Offering.ModeType = "Internal",
):
"""
Returns the URL of the ECPs for course codes given. Assumes the same semester and year for the course codes given.

"""
await interaction.response.defer(thinking=True)

possible_courses = [course1, course2, course3, course4]
course_names = [c.upper() for c in possible_courses if c != None]
course_name_urls: dict[str,str] = {}
offering = Offering(semester=semester, campus=campus, mode=mode)

try:
for course in course_names:
course_name_urls.update({course: get_course_profile_url(course, offering, year)})
except HttpException as exception:
logging.warning(
f"Received a HTTP response code {exception.status_code} when trying find the course url using get_course_profile_url in course_ecp.py . Error information: {exception.message}"
)
await interaction.edit_original_response(
content=f"Could not contact UQ, please try again."
)
return
except (CourseNotFoundException, ProfileNotFoundException) as exception:
await interaction.edit_original_response(content=exception.message)
return

# If year is none assign it the current year
if not year:
year = datetime.today().year

# If semester is none assign it the current estimated semester
if not semester:
ew-b marked this conversation as resolved.
Show resolved Hide resolved
semester = Offering.estimate_current_semester()

# Create the embedded message with the course names and details
embed = discord.Embed(
title=f"Course ECP: {', '.join(course_names)}",
description=f"For Semester {semester} {year}, {mode}, {campus}"
)

# Add the ECP urls to the embedded message
if course_name_urls:
for course in course_name_urls:
embed.add_field(
name=f"",
value=f"[{course}]({course_name_urls.get(course)}) ",
inline=False,
)
else:
await interaction.edit_original_response(
content=f"No ECP could be found for the courses: {course_names}. The ECP(s) might not be available."
)
return

embed.set_footer(
text="The course ECP might be out of date, be sure to check the course on BlackBoard."
)
await interaction.edit_original_response(embed=embed)
return

async def setup(bot: commands.Bot):
await bot.add_cog(CourseECP(bot))
30 changes: 13 additions & 17 deletions uqcsbot/utils/uq_course_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
"student_section_report.php?report=assessment&profileIds="
)
BASE_CALENDAR_URL = "http://www.uq.edu.au/events/calendar_view.php?category_id=16&year="
OFFERING_PARAMETER = "offer"
BASE_PAST_EXAMS_URL = "https://api.library.uq.edu.au/v1/exams/search/"
# Parameters for the course page
OFFERING_PARAMETER = "offer"
YEAR_PARAMETER = "year"


class Offering:
Expand Down Expand Up @@ -58,7 +60,7 @@ def __init__(
if semester is not None:
self.semester = semester
else:
self.semester = self._estimate_current_semester()
self.semester = self.estimate_current_semester()
self.semester
self.campus = campus
self.mode = mode
Expand Down Expand Up @@ -92,7 +94,7 @@ def get_offering_code(self) -> str:
return offering_code_text.encode("utf-8").hex()

@staticmethod
def _estimate_current_semester() -> SemesterType:
def estimate_current_semester() -> SemesterType:
"""
Returns an estimate of the current semester (represented by an integer) based on the current month. 3 represents summer semester.
"""
Expand Down Expand Up @@ -192,23 +194,17 @@ def get_uq_request(


def get_course_profile_url(
course_name: str, offering: Optional[Offering] = None
course_name: str, offering: Optional[Offering] = None, year: Optional[int] = None,
) -> str:
"""
Returns the URL to the course profile for the given course for a given offering.
If no offering is give, will return the first course profile on the course page.
Returns the URL to the course profile (ECP) for the given course for a given offering.
If no offering or year are given, the first course profile on the course page will be returned.
"""
if offering is None:
course_url = BASE_COURSE_URL + course_name
else:
course_url = (
BASE_COURSE_URL
+ course_name
+ "&"
+ OFFERING_PARAMETER
+ "="
+ offering.get_offering_code()
)
course_url = BASE_COURSE_URL + course_name
if offering:
course_url += "&" + OFFERING_PARAMETER + "=" + offering.get_offering_code()
if year:
course_url += "&" + YEAR_PARAMETER + "=" + str(year)

http_response = get_uq_request(course_url)
if http_response.status_code != requests.codes.ok:
Expand Down
Loading