diff --git a/cogs/school.py b/cogs/school.py index a206e64..06a0dfe 100644 --- a/cogs/school.py +++ b/cogs/school.py @@ -42,9 +42,9 @@ class School(commands.Cog): embed.set_footer(text="Omwille van de coronamaatregelen is er een beperkter aanbod, en kan je enkel nog eten afhalen. Ter plaatse eten is niet meer mogelijk.") await ctx.send(embed=embed) - # @commands.command(name="Les", aliases=["Class", "Classes", "Sched", "Schedule"], usage="[Dag]*") + @commands.command(name="Les", aliases=["Class", "Classes", "Sched", "Schedule"], usage="[Dag]*") # @commands.check(checks.allowedChannels) - # @help.Category(category=Category.School) + @help.Category(category=Category.School) async def les(self, ctx, day=None): date = les.find_target_date(day) diff --git a/data/schedule.py b/data/schedule.py index f286b60..177b9d0 100644 --- a/data/schedule.py +++ b/data/schedule.py @@ -143,6 +143,7 @@ class Schedule: self.schedule_dict: Dict = self.load_schedule_file() self.start_date = fromArray(self.schedule_dict["semester_start"]) self.end_date = fromArray(self.schedule_dict["semester_end"]) + self._forward_to_semester() # Semester is over if self.end_date < self.day: @@ -167,6 +168,14 @@ class Schedule: self.weekday_str = intToWeekday(self.day.weekday()) + def _forward_to_semester(self): + """ + In case the semester hasn't started yet, fast forward the current date + by a week until it's no longer necessary + """ + while self.day < self.start_date: + self.day += timedelta(weeks=1) + def check_holidays(self): """ Do all holiday-related stuff here to avoid multiple loops @@ -234,6 +243,22 @@ class Schedule: return HolidayEmbed(self) slots: List[List[Timeslot]] = [self.find_slots_for_course(course) for course in self.schedule_dict["schedule"]] + minor_slots = {} + + # Find minor slots + for minor in self.schedule_dict["minors"]: + m_slots = [] + for course in minor["schedule"]: + # Go over every course + m_slots.append(self.find_slots_for_course(course)) + + # Flatten list + m_slots = [item for sublist in m_slots for item in sublist] + # Sort by timestamp + m_slots.sort(key=lambda x: x.start_time) + + minor_slots[minor["name"]] = m_slots + slots_flattened = [item for sublist in slots for item in sublist] # Sort by timestamp @@ -244,7 +269,7 @@ class Schedule: if not not_canceled: return NoClassEmbed(self, slots_flattened) - return ScheduleEmbed(self, slots_flattened, not_canceled) + return ScheduleEmbed(self, slots_flattened, not_canceled, minor_slots) @dataclass @@ -270,6 +295,9 @@ class LesEmbed(ABC): def get_extras(self) -> str: return "" + def add_minors(self, embed: Embed): + pass + def get_online_links(self) -> str: return "" @@ -289,6 +317,8 @@ class LesEmbed(ABC): if links: embed.add_field(name="Online links", value=links, inline=False) + self.add_minors(embed) + # Add extras if there are any extras = self.get_extras() if extras: @@ -332,10 +362,27 @@ class ScheduleEmbed(LesEmbed): """ slots: List[Timeslot] slots_not_canceled: List[Timeslot] + minor_slots: Dict[str, List[Timeslot]] def get_description(self) -> str: return "\n".join(list(f"{entry}" for entry in self.slots_not_canceled)) + def add_minors(self, embed: Embed): + for minor, slots in self.minor_slots.items(): + if not slots: + continue + + not_canceled = list(filter(lambda x: not x.canceled, slots)) + info = "\n".join(list(str(entry) for entry in not_canceled)) + + special = list(filter(lambda x: x.is_special or x.canceled, slots)) + + # Add extra info about this minor + if special: + info += "\n" + "\n".join(list(entry.get_special_fmt_str() for entry in special)) + + embed.add_field(name=f"Minor {minor}", value=info, inline=False) + def get_extras(self) -> str: special = list(filter(lambda x: x.is_special or x.canceled, self.slots)) diff --git a/files/schedules/31.json b/files/schedules/31.json index 8edbf90..1128639 100644 --- a/files/schedules/31.json +++ b/files/schedules/31.json @@ -1,101 +1,217 @@ { - "semester_start": [1, 7, 2021], - "semester_end": [1, 8, 2021], + "semester_start": [27, 9, 2021], + "semester_end": [23, 12, 2021], "holidays": [ { - "start_date": [2, 7, 2021, 23, 59, 59], - "end_date": [10, 8, 2021, 23, 59, 59] + "start_date": [1, 11, 2021, 0, 0, 0], + "end_date": [2, 11, 2021, 23, 59, 59] + }, + { + "start_date": [11, 11, 2021, 0, 0, 0], + "end_date": [11, 11, 2021, 23, 59, 59] + } + ], + "minors": [ + { + "name": "Beveiliging en parallelle systemen", + "online_links": { + "zoom": "https://ufora.ugent.be/d2l/ext/rp/439235/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826" + }, + "schedule": [ + { + "course": "Modelleren en Simuleren", + "slots": [ + { + "location": { + "campus": "Sterre", + "building": "S12", + "room": "0.1" + }, + "time": { + "day": "maandag", + "start": 1000, + "end": 1300 + } + }, + { + "location": { + "campus": "Sterre", + "building": "S9", + "room": "3.1 Konrad Zuse" + }, + "time": { + "day": "dinsdag", + "start": 1130, + "end": 1300 + } + }, + { + "location": { + "campus": "Sterre", + "building": "S9", + "room": "3.1 Konrad Zuse" + }, + "time": { + "day": "donderdag", + "start": 1430, + "end": 1600 + } + } + ] + }, + { + "course": "Parallelle Computersystemen", + "online_links": { + "zoom": "https://ufora.ugent.be/d2l/ext/rp/449671/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826" + }, + "slots": [ + { + "location": { + "campus": "Ardoyen", + "building": "iGent 126", + "room": "Auditorium 1" + }, + "time": { + "day": "woensdag", + "start": 1430, + "end": 1730 + } + }, + { + "location": { + "campus": "Ardoyen", + "building": "iGent 126", + "room": "Auditorium 1" + }, + "time": { + "day": "vrijdag", + "start": 830, + "end": 1130 + } + } + ] + } + ] + }, + { + "name": "Elektrotechniek en Telecommunicatie", + "schedule": [ + { + "course": "Inleiding tot Telecommunicatie", + "slots": [ + { + "location": { + "campus": "Ardoyen", + "building": "iGent 125", + "room": "Systems" + }, + "time": { + "day": "maandag", + "start": 1000, + "end": 1300 + } + }, + { + "location": { + "campus": "Ardoyen", + "building": "iGent 125", + "room": "Systems" + }, + "time": { + "day": "dinsdag", + "start": 1300, + "end": 1600 + } + } + ] + }, + { + "course": "Wiskundige Modellering", + "slots": [ + { + "location": { + "campus": "Sterre", + "building": "S9", + "room": "1.1" + }, + "time": { + "day": "maandag", + "start": 830, + "end": 1000 + } + }, + { + "location": { + "campus": "Sterre", + "building": "S8", + "room": "3.2" + }, + "time": { + "day": "donderdag", + "start": 1430, + "end": 1600 + } + }, + { + "location": { + "campus": "Sterre", + "building": "S8", + "room": "3.2" + }, + "time": { + "day": "vrijdag", + "start": 830, + "end": 1130 + } + } + ] + } + ] + }, + { + "name": "Onderwijs", + "schedule": [] } ], "schedule": [ { - "course": "Computerarchitectuur", + "course": "Algoritmen en Datastructuren 3", "online_links": { - "zoom": "https://ufora.ugent.be/d2l/ext/rp/228912/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826", - "msteams": "https://teams.microsoft.com/l/team/19%3ad7295f0bc4634a61b461504d4a7134b3%40thread.tacv2/conversations?groupId=8755cb96-1ef5-4ea3-b806-eeebf8a85ae8&tenantId=d7811cde-ecef-496c-8f91-a1786241b99c" - }, - "slots": [ - ] - }, - { - "course": "Multimedia", - "online_links": { - "zoom": "https://ugent-be.zoom.us/j/94248831947?pwd=ZCt4UnBLSzViZnFEQmkzWE5SYnF2QT09" + "zoom": "https://ufora.ugent.be/d2l/ext/rp/437923/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826" }, "slots": [ { "location": { "campus": "Sterre", "building": "S9", - "room": "A3" + "room": "3.1 Konrad Zuse" }, - "time": { - "day": "woensdag", - "start": 1130, - "end": 1330 - } - }, - { - "online": "zoom", - "time": { - "day": "vrijdag", - "start": 1300, - "end": 1530 - } - } - ] - }, - { - "course": "Wetenschappelijk Rekenen", - "online_links": { - "zoom": "https://ufora.ugent.be/d2l/ext/rp/236404/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826" - }, - "slots": [ - { - "online": "zoom", "time": { "day": "dinsdag", - "start": 1130, - "end": 1300 - } - }, - { - "online": "zoom", - "time": { - "day": "woensdag", - "start": 1500, - "end": 1800 - } - }, - { - "online": "zoom", - "time": { - "day": "donderdag", "start": 830, "end": 1000 } - } - ] - }, - { - "course": "Software Engineering Lab 1", - "online_links": { - "zoom": "https://ufora.ugent.be/d2l/ext/rp/235800/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826", - "msteams": "https://teams.microsoft.com/l/team/19%3a4dfd5b2fb1ae4aa9b72706aa3a0d6867%40thread.tacv2/conversations?groupId=256d5c58-5d53-43f5-9436-497b0c852c75&tenantId=d7811cde-ecef-496c-8f91-a1786241b99c" - }, - "slots": [ + }, { - "online": "msteams", + "location": { + "campus": "Sterre", + "building": "S9", + "room": "1.1 Alan Turing" + }, "time": { "day": "dinsdag", - "start": 1430, - "end": 1700 + "start": 1000, + "end": 1130 } }, { - "online": "msteams", + "location": { + "campus": "Sterre", + "building": "S9", + "room": "1.1 Alan Turing" + }, "time": { - "day": "vrijdag", + "day": "woensdag", "start": 830, "end": 1130 } @@ -103,34 +219,77 @@ ] }, { - "course": "Webdevelopment", + "course": "Artificiële Intelligentie", "online_links": { - "zoom": "https://ugent-be.zoom.us/j/93166767783?pwd=MWdvb1BnNnlPSnAyNk52QmRzdjcwdz09" + "zoom": "https://ufora.ugent.be/d2l/ext/rp/439739/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826" }, "slots": [ { - "weeks": { - "6": { - "canceled": true - } - }, "location": { "campus": "Sterre", - "building": "S9", - "room": "A3" + "building": "S8", + "room": "0.1" }, "time": { - "day": "woensdag", - "start": 900, - "end": 1100 + "day": "maandag", + "start": 1430, + "end": 1730 } }, { - "online": "zoom", + "location": { + "campus": "Sterre", + "building": "S9", + "room": "1.1 Alan Turing" + }, + "time": { + "day": "woensdag", + "start": 1130, + "end": 1300 + } + }, + { + "location": { + "campus": "Sterre", + "building": "S9", + "room": "3.1 Konrad Zuse" + }, "time": { "day": "donderdag", - "start": 1000, - "end": 1300 + "start": 1300, + "end": 1430 + } + } + ] + }, + { + "course": "Besturingssystemen", + "online_links": { + "zoom": "https://ufora.ugent.be/d2l/ext/rp/442814/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826" + }, + "slots": [ + { + "location": { + "campus": "Ardoyen", + "building": "iGent 126", + "room": "Auditorium 1" + }, + "time": { + "day": "donderdag", + "start": 830, + "end": 1130 + } + }, + { + "location": { + "campus": "Ardoyen", + "building": "iGent 126", + "room": "Auditorium 1" + }, + "time": { + "day": "vrijdag", + "start": 1300, + "end": 1600 } } ] diff --git a/functions/ufora_notifications.py b/functions/ufora_notifications.py index 26a5419..05dac44 100644 --- a/functions/ufora_notifications.py +++ b/functions/ufora_notifications.py @@ -1,21 +1,28 @@ import re -import feedparser from data.embeds import UforaNotification +import feedparser import json +from settings import UFORA_TOKEN course_urls = { - "Algoritmen en Datastructuren 2": "https://ufora.ugent.be/d2l/le/news/rss/222018/course?token=aehhv6utkf46t8cc102e0&ou=222018", - "Communicatienetwerken": "https://ufora.ugent.be/d2l/le/news/rss/221184/course?token=aehhv6utkf46t8cc102e0&ou=221184", - "Computerarchitectuur": "https://ufora.ugent.be/d2l/le/news/rss/228912/course?token=aehhv6utkf46t8cc102e0&ou=228912", - "Functioneel Programmeren": "https://ufora.ugent.be/d2l/le/news/rss/236396/course?token=aehhv6utkf46t8cc102e0&ou=236396", - "Multimedia": "https://ufora.ugent.be/d2l/le/news/rss/236949/course?token=aehhv6utkf46t8cc102e0&ou=236949", - "Software Engineering Lab 1": "https://ufora.ugent.be/d2l/le/news/rss/235800/course?token=aehhv6utkf46t8cc102e0&ou=235800", - "Statistiek en Probabiliteit": "https://ufora.ugent.be/d2l/le/news/rss/236398/course?token=aehhv6utkf46t8cc102e0&ou=236398", - "Systeemprogrammeren": "https://ufora.ugent.be/d2l/le/news/rss/222035/course?token=aehhv6utkf46t8cc102e0&ou=222035", - "Webdevelopment": "https://ufora.ugent.be/d2l/le/news/rss/223449/course?token=aehhv6utkf46t8cc102e0&ou=223449", - "Wetenschappelijk Rekenen": "https://ufora.ugent.be/d2l/le/news/rss/236404/course?token=aehhv6utkf46t8cc102e0&ou=236404" + "Algoritmen en Datastructuren 3": "https://ufora.ugent.be/d2l/le/news/rss/437923/course?token=", + "Artificiële Intelligentie": "https://ufora.ugent.be/d2l/le/news/rss/439739/course?token=", + "Automaten, Berekenbaarheid en Complexiteit": "https://ufora.ugent.be/d2l/le/news/rss/439079/course?token=", + "Besturingssystemen": "https://ufora.ugent.be/d2l/le/news/rss/442814/course?token=", + "Communicatienetwerken": "https://ufora.ugent.be/d2l/le/news/rss/447014/course?token=", + "Computationele Biologie": "https://ufora.ugent.be/d2l/le/news/rss/448904/course?token=", + "Computerarchitectuur": "https://ufora.ugent.be/d2l/le/news/rss/439172/course?token=", + "Informatiebeveiliging": "https://ufora.ugent.be/d2l/le/news/rss/444476/course?token=", + "Inleiding tot Telecommunicatie": "https://ufora.ugent.be/d2l/le/news/rss/450232/course?token=", + "Logisch Programmeren": "https://ufora.ugent.be/d2l/le/news/rss/443368/course?token=", + "Modelleren en Simuleren": "https://ufora.ugent.be/d2l/le/news/rss/439235/course?token=", + "Parallelle Computersystemen": "https://ufora.ugent.be/d2l/le/news/rss/449671/course?token=", + "Software Engineering Lab 2": "https://ufora.ugent.be/d2l/le/news/rss/445170/course?token=", + "Statistiek en Probabiliteit": "https://ufora.ugent.be/d2l/le/news/rss/445169/course?token=", + "Wetenschappelijk Rekenen": "https://ufora.ugent.be/d2l/le/news/rss/445174/course?token=", + "Wiskundige Modellering": "https://ufora.ugent.be/d2l/le/news/rss/446530/course?token=" } @@ -36,7 +43,7 @@ def run(): notifications[course] = [] # Get the updated feed - feed = feedparser.parse(url) + feed = feedparser.parse(f"url{UFORA_TOKEN}") # Filter out old notifications feed = list(filter(lambda f: _parse_ids(f["id"])[0] not in notifications[course], feed.entries)) diff --git a/settings.py b/settings.py index c7d212b..038fd89 100644 --- a/settings.py +++ b/settings.py @@ -21,6 +21,7 @@ SANDBOX = _to_bool(os.getenv("SANDBOX", "true")) URBANDICTIONARY = os.getenv("URBANDICTIONARY", "") IMGFLIP_NAME = os.getenv("IMGFLIPNAME", "") IMGFLIP_PASSWORD = os.getenv("IMGFLIPPASSWORD", "") +UFORA_TOKEN = os.getenv("UFORA_TOKEN", "") # Database credentials DB_USERNAME = os.getenv("DBUSERNAME", "")