Skip to content

Commit

Permalink
Merge pull request #2 from mario872/issue-1-branch-timetable-url
Browse files Browse the repository at this point in the history
Issue 1 branch timetable url
  • Loading branch information
mario872 authored Apr 3, 2024
2 parents b362f50 + 53e2b9e commit afac94b
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 86 deletions.
124 changes: 79 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,122 +70,156 @@ Below is the general structure of one day, in one week that timetable returns:
```
[
{
"date": "Mon Feb 12 00:00:00 2024",
"periods": [
{
"is_now": False,
"start": "7:30",
"end": "8:50",
"start_time_date": "Fri Apr 5 07:30:00 2024",
"end_time_date": "Fri Apr 5 08:50:00 2024",
"full_name": None,
"name": None,
"room": None,
"teacher": None,
"border_colour": None,
"background_colour": None,
"start": None,
"end": None,
},
{
"full_name": "PDHPE Yr13",
"name": "13PDHY",
"room": "GF.05",
"teacher": "teacher_name",
"border_colour": "85EE88",
"background_colour": "E0FAE1",
"start": None,
"end": None,
"is_now": False,
"start": "8:50",
"end": "10:08",
"start_time_date": "Fri Apr 5 08:50:00 2024",
"end_time_date": "Fri Apr 5 10:08:00 2024",
"full_name": "Art Yr8",
"name": "8ART8",
"room": "DF.09",
"border_colour": "FF7FFF",
"background_colour": "FFDFFF",
"teacher": "Miss T. Glennan",
},
{
"is_now": True,
"start": "10:08",
"end": "10:28",
"start_time_date": "Fri Apr 5 10:08:00 2024",
"end_time_date": "Fri Apr 5 10:28:00 2024",
"full_name": None,
"name": None,
"room": None,
"teacher": None,
"border_colour": None,
"background_colour": None,
"start": None,
"end": None,
},
{
"full_name": "Mathematics Yr13",
"name": "13MATG",
"room": "EG.04",
"teacher": "teacher_name",
"border_colour": "FF7F7F",
"background_colour": "FFDFDF",
"start": None,
"end": None,
"is_now": False,
"start": "10:28",
"end": "11:45",
"start_time_date": "Fri Apr 5 10:28:00 2024",
"end_time_date": "Fri Apr 5 11:45:00 2024",
"full_name": "PDHPE Yr8",
"name": "8PDHY",
"room": "COLA1",
"border_colour": "85EE88",
"background_colour": "E0FAE1",
"teacher": "Mr P. Littlejohn",
},
{
"is_now": False,
"start": "11:45",
"end": "11:50",
"start_time_date": "Fri Apr 5 11:45:00 2024",
"end_time_date": "Fri Apr 5 11:50:00 2024",
"full_name": None,
"name": None,
"room": None,
"teacher": None,
"border_colour": None,
"background_colour": None,
"start": None,
"end": None,
},
{
"full_name": "LAN Yr13",
"name": "13LAY",
"is_now": False,
"start": "11:55",
"end": "13:08",
"start_time_date": "Fri Apr 5 11:55:00 2024",
"end_time_date": "Fri Apr 5 13:08:00 2024",
"full_name": "LAN Yr8",
"name": "8LAY",
"room": "GF.16",
"teacher": "teacher_name",
"border_colour": "FFBF7F",
"background_colour": "FFEFDF",
"start": None,
"end": None,
"teacher": "Mr A. Gollan",
},
{
"is_now": False,
"start": "13:08",
"end": "13:28",
"start_time_date": "Fri Apr 5 13:08:00 2024",
"end_time_date": "Fri Apr 5 13:28:00 2024",
"full_name": None,
"name": None,
"room": None,
"teacher": None,
"border_colour": None,
"background_colour": None,
"start": None,
"end": None,
},
{
"is_now": False,
"start": "13:28",
"end": "13:48",
"start_time_date": "Fri Apr 5 13:28:00 2024",
"end_time_date": "Fri Apr 5 13:48:00 2024",
"full_name": None,
"name": None,
"room": None,
"teacher": None,
"border_colour": None,
"background_colour": None,
"start": None,
"end": None,
},
{
"full_name": "English Yr13",
"name": "13ENGY",
"room": "FF.06",
"teacher": "teacher_name",
"border_colour": "FFF884",
"background_colour": "FFFDE0",
"start": None,
"end": None,
"is_now": False,
"start": "13:48",
"end": "15:05",
"start_time_date": "Fri Apr 5 13:48:00 2024",
"end_time_date": "Fri Apr 5 15:05:00 2024",
"full_name": "Science Yr8",
"name": "8SCIY",
"room": "DG.04",
"border_colour": "84E6DD",
"background_colour": "E0F8F6",
"teacher": "Mr A. Vamvakaris",
},
{
"is_now": False,
"start": "15:05",
"end": "16:25",
"start_time_date": "Fri Apr 5 15:05:00 2024",
"end_time_date": "Fri Apr 5 16:25:00 2024",
"full_name": None,
"name": None,
"room": None,
"teacher": None,
"border_colour": None,
"background_colour": None,
"start": None,
"end": None,
},
{
"is_now": False,
"start": "15:05",
"end": "15:15",
"start_time_date": "Fri Apr 5 15:05:00 2024",
"end_time_date": "Fri Apr 5 15:15:00 2024",
"full_name": None,
"name": None,
"room": None,
"teacher": None,
"border_colour": None,
"background_colour": None,
"start": None,
"end": None,
},
],
"is_today": True
"date": "Fri Apr 5 00:00:00 2024",
"is_today": False,
}
]
```
Yes, that is actually my timetable for one day, no I am not in year 13, no I am not telling you what year I am in.
The general gist of how sentralify returns your timetable is 14 dictionaries in a list, each containing the date, and another list of 11 periods, with various values shown above. In each day, it also incudes the ```"is_today"``` key, which indicated whether the data was pulled from the cyclical timetable (False), or the daily timetable (True). If you wanted to access Period 1's room for example, you would run ```sentralify(config)['timetable'][0]['periods'][1]['room']```
Expand Down
2 changes: 1 addition & 1 deletion sentralify/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def sentralify(config: dict, timetable: bool = True, notices: bool = True, calen
notices = Sentral.generate_notices(scraper.save_notices(page))
data['notices'] = notices
if timetable:
timetable = Sentral.generate_timetable(scraper.save_timetable(page), daily_timetable)
timetable = Sentral.generate_timetable(scraper.save_timetable(page))
data['timetable'] = timetable
if calendar:
calendar = Sentral.generate_calendar(scraper.save_calendar(page))
Expand Down
95 changes: 56 additions & 39 deletions sentralify/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
# Main generators class

class generators:
def generate_timetable(data: list, daily_timetable: list):
def generate_timetable(data: list):
"""
Takes a list of the JSON data scraped from the backend timetable page and moulds it
into a nice Python dictionary with only the information that is needed for most applications
Expand All @@ -45,51 +45,68 @@ def generate_timetable(data: list, daily_timetable: list):
# use this url instead: https://base_rul_here.sentral.com.au/s-Y7eXkn/portal2/timetable/getFullTimetableInDates/student_id_here/undefined/true
# It's a much better formatted version of the timetable


timetable = [] # This will store the timetable days and periods
for week in range(2): # Two weeks are returned by the JSON
for day in range(5): # Only five days in a school week, not seven!
current_day = {'date': datetime.strptime(data[week]['dates'][day]['date_name'], '%Y-%m-%d'), 'periods': [], 'is_today': None} # The variable for this iteration of the loop
timetable.append({}) # Add the new day to the timetable

for period in range(11): # There are eleven periods in every day, because of before school, recess, period 2-3 break, lunch 1, lunch 2, and after school.
current_day['periods'].append({}) # Add a blank space for this period in the list
# If the current period is today, then draw from the daily timetble instead of the cyclical timetable
if current_day['date'].day == datetime.now().day and current_day['date'].month == datetime.now().month:
current_period = daily_timetable[period]
current_day['is_today'] = True
else: # Otherwise, just draw from the cyclical timetable's data
current_period = data[week]['periods'][period]['days'][str(day + 1)]
current_day['is_today'] = False
# This is to add five days onto the day loop number for week B
if week == 0:
timetable_day = day
else:
timetable_day = day + 5

try: # Because period 0, recess, etc. don't have lessons, we get an IndexError when trying to access them
current_day['periods'][period]['full_name'] = current_period['lessons'][0]['subject_name']
current_day['periods'][period]['name'] = current_period['lessons'][0]['lesson_class_name']
try: # If there are no teachers (or room), then we get a KeyError instead
current_day['periods'][period]['room'] = current_period['lessons'][0]['room_name']
current_day['periods'][period]['teacher'] = current_period['lessons'][0]['teachers'][0]
except KeyError:
current_day['periods'][period]['room'] = None
current_day['periods'][period]['teacher'] = None
current_day['periods'][period]['border_colour'] = current_period['lessons'][0]['class_border_colour']
current_day['periods'][period]['background_colour'] = current_period['lessons'][0]['class_background_colour']
except IndexError:
current_day['periods'][period]['full_name'] = None
current_day['periods'][period]['name'] = None
current_day['periods'][period]['room'] = None
current_day['periods'][period]['border_colour'] = None
current_day['periods'][period]['background_colour'] = None
current_day['periods'][period]['teacher'] = None

try: # We can try to get the start and end for the period, but sometimes, Sentral doesn't add that either!
current_day['periods'][period]['start'] = current_period['period_start_time']
current_day['periods'][period]['end'] = current_period['period_end_time']
except KeyError:
current_day['periods'][period]['start'] = None
current_day['periods'][period]['end'] = None
current_day_data = data[week]['dates'][str(day+1)] # This makes it easier to reference just the day we need
timetable[timetable_day]['periods'] = [] # Add a blank space for this day in the list
timetable[timetable_day]['date'] = parse(current_day_data['date_name']).strftime('%c') # Add the date to the day
timetable[timetable_day]['is_today'] = current_day_data['is_today'] # Add is_today to the day

current_day['date'] = current_day['date'].strftime('%c')

timetable.append(current_day) # Add all of today's periods to the timetable
for period in range(len(current_day_data['period'])): # Instead of asusuming it will be eleven periosd, this just returns however many periods there are
timetable[timetable_day]['periods'].append({}) # Make space for a new period on the day

timetable[timetable_day]['periods'][period]['is_now'] = current_day_data['period'][period]['is_now'] # Add is_now to the period, a new parameter
if current_day_data['period'][period]['start_time'] != None: # Checking that Sentral igves th estart time
timetable[timetable_day]['periods'][period]['start'] = current_day_data['period'][period]['start_time'] # The generic hour:minute start time
timetable[timetable_day]['periods'][period]['end'] = current_day_data['period'][period]['end_time'] # The generic hour:minute end time
timetable[timetable_day]['periods'][period]['start_time_date'] = datetime( # This creates a datetime object with the full date and time of the start of the period
year=parse(timetable[timetable_day]['date']).year,
month=parse(timetable[timetable_day]['date']).month,
day=parse(timetable[timetable_day]['date']).day,
hour=int(current_day_data['period'][period]['start_time'].split(':')[0]),
minute=int(current_day_data['period'][period]['start_time'].split(':')[1])
).strftime('%c')
timetable[timetable_day]['periods'][period]['end_time_date'] = datetime( # This creates a datetime object with the full date and time of the end of the period/
year=parse(timetable[timetable_day]['date']).year,
month=parse(timetable[timetable_day]['date']).month,
day=parse(timetable[timetable_day]['date']).day,
hour=int(current_day_data['period'][period]['end_time'].split(':')[0]),
minute=int(current_day_data['period'][period]['end_time'].split(':')[1])
).strftime('%c')
else: # Sometimes, if it's a holiday, or Sentral wants to be annoying they don't give the start time or end time
timetable[timetable_day]['periods'][period]['start'] = None
timetable[timetable_day]['periods'][period]['end'] = None
timetable[timetable_day]['periods'][period]['start_time_date'] = None
timetable[timetable_day]['periods'][period]['end_time_date'] = None

if current_day_data['period'][period]['lessons'] != []: # If it's a period without a lesson, then there's nothing in the lesson parameter
timetable[timetable_day]['periods'][period]['full_name'] = current_day_data['period'][period]['lessons'][0]['subject_name']
timetable[timetable_day]['periods'][period]['name'] = current_day_data['period'][period]['lessons'][0]['lesson_class_name']
timetable[timetable_day]['periods'][period]['room'] = current_day_data['period'][period]['lessons'][0]['room_name']
timetable[timetable_day]['periods'][period]['border_colour'] = current_day_data['period'][period]['lessons'][0]['class_border_colour']
timetable[timetable_day]['periods'][period]['background_colour'] = current_day_data['period'][period]['lessons'][0]['class_background_colour']
try: # This checks that there is a teacher during the lesson
timetable[timetable_day]['periods'][period]['teacher'] = current_day_data['period'][period]['lessons'][0]['teachers'][0] # The 0 at the end could be a mistake, if anyone knows, please open an issue
except KeyError: # If there's not set it to None
timetable[timetable_day]['periods'][period]['teacher'] = None
else: # If there isn't a lesson on, then it's not a proper period
timetable[timetable_day]['periods'][period]['full_name'] = None
timetable[timetable_day]['periods'][period]['name'] = None
timetable[timetable_day]['periods'][period]['room'] = None
timetable[timetable_day]['periods'][period]['teacher'] = None
timetable[timetable_day]['periods'][period]['border_colour'] = None
timetable[timetable_day]['periods'][period]['background_colour'] = None

return timetable


Expand Down
2 changes: 1 addition & 1 deletion sentralify/scrapers.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ def save_timetable(self, page):
# Anyway, this just scrapes the page for the json, and converts it to a dictionary that python can acess.
# I found this url after watching some kids at my school go into the network tab in dev tools in Chrome, and look at what Sentral was accessing. Thank you!

page.goto(f"https://{self.config['base_url']}.sentral.com.au/s-Y7eXkn/portal2/timetable/getFullTimetable/{str(self.student_id)}")
page.goto(f"https://{self.config['base_url']}.sentral.com.au/s-Y7eXkn/portal2/timetable/getFullTimetableInDates/{str(self.student_id)}/undefined/true")
return json.loads(BeautifulSoup(page.content(), "lxml").text)

def save_notices(self, page):
Expand Down

0 comments on commit afac94b

Please sign in to comment.