Skip to content

Commit

Permalink
Course ECP Command (#171)
Browse files Browse the repository at this point in the history
* Spoilering description text of xkcd

Made xkcd_desc an f string, added spoiler `||` on either side so when it's posted to discord it spoilers the text.

* Course ECP Command

Attempting to create a command that takes in a course code, selected year, semester, mode, and campus and then provides the link to the course profile.

Currently it defaults to the current semester and I'm yet to work out how to make it not default.

* Remove unused imports

* Added year parameter to get_course_profile_url

* Course ECP now considers the year, semester, campus and mode input

Need to format the embedded and allow it to take in multiple courses

* Lists multiple course ecps

It assume when requesting you want the same semester, year, mode and campus for all courses.

* Adding suggestions

- Fixed typo
- Clarified error message
- Changes wording of the else statement that in theory should never happen because of the exceptions.

* Made `estimate_current_semester()` in `Offering`  a public method.

Unsure if this will cause issues, doesn't look like it and improve any future use of checking what the estimated current semester is.

* Black formatting

---------

Co-authored-by: Isaac Beh <isaacwbeh@gmail.com>
  • Loading branch information
ew-b and 49Indium authored Nov 2, 2023
1 parent eaadaf8 commit 86b238b
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 17 deletions.
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
110 changes: 110 additions & 0 deletions uqcsbot/course_ecp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
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:
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))
32 changes: 15 additions & 17 deletions uqcsbot/utils/uq_course_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,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 @@ -59,7 +61,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 @@ -93,7 +95,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 @@ -256,23 +258,19 @@ 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

0 comments on commit 86b238b

Please sign in to comment.