obliviously.., duh!

~^▼^~

grades.py

#!/usr/bin/env python3

import os
import pickle
import pytz
import requests
import auth # from auth.py
import json

from datetime import datetime, timedelta

GRADES_FILE = "grades.pkl"

def get(endpoint, credentials):
  headers = {
      "Authorization": f'Bearer {credentials.access_token}',
      "Accept": 'application/json',
      "Origin": 'https://somtoday.nl',
      "Range": 'items=0-1000'
  }

  url = f'{credentials.api_url}{endpoint}'
  response = requests.get(url, headers=headers)

  return response.json()

def fetch_student_id(credentials):
  data = get('/rest/v1/leerlingen', credentials)
  return data['items'][0]['links'][0]['id']

def fetch_grades(student_id, credentials):
  data = get(f'/rest/v1/resultaten/huidigVoorLeerling/{student_id}', credentials)
  items = data['items']

  # We're not interested in averages, we're only interested in the grades themselves.
  useless_types = ["PeriodeGemiddeldeKolom", "RapportGemiddeldeKolom", "SEGemiddeldeKolom"]
  useless_subjects = ["4a-in", "5a-in", "6a-in", "LOB", "MEN", "PWS", "LO"]

  items = list(filter(lambda item: not item['type'] in useless_types, items))
  items = list(filter(lambda item: not item["vak"]["afkorting"] in useless_subjects, items))

  # Filter out grades that do not actually contain a grade. Ghost grades.
  items = list(filter(lambda item: "geldendResultaat" in item or "resultaatLabelAfkorting" in item, items))

  sort_by_datetime = lambda x: parse_item_datetime(x)
  items =  sorted(items, key = sort_by_datetime, reverse = True)

  grade_list = []

  for grade in items:
    try: result = grade["geldendResultaat"]
    # For letter grades, as opposed to 1-10 results.
    except KeyError: result = grade["resultaatLabelAfkorting"]

    datetime = parse_item_datetime(grade).strftime("%d/%m/%Y %H:%M:%S")
    subject = grade["vak"]["naam"]
    title = grade["omschrijving"]
    weight = grade["weging"]

    grade_list.append({
        "result": result,
        "datetime": datetime,
        "subject": subject,
        "title": title,
        "weight": weight
    })

  return grade_list  

def diff_grades(credentials):
  student_id = fetch_student_id(credentials)
  grade_list = fetch_grades(student_id, credentials)

  if grade_list != load_existing_grades():
    write_new_grades(grade_list)

    subject = grade_list[0]["subject"]
    send_notification(f'New grade for {subject}')

def send_notification(message):
  body = {
    "content": message,
    "components": [],
    "actions": {}
  }

  endpoint = "https://discord.com/api/webhooks/..."
  requests.post(endpoint, json=body)

# Helpers

def parse_item_datetime(item):
  return datetime.strptime(item["datumInvoer"], "%Y-%m-%dT%H:%M:%S.%f%z")


def load_existing_grades():
  if not os.path.isfile(GRADES_FILE):
    return []
  else: 
    with open(GRADES_FILE, "rb") as file:
      return pickle.load(file)

def write_new_grades(grades):
  with open(GRADES_FILE, "wb") as file:
    pickle.dump(grades, file)

# Main program :)

credentials = auth.refresh()
student_id = fetch_student_id(credentials)

diff_grades(credentials)

Simple script that sends Discord notifications when teachers publish grades