scaarup / aula

Fetches information from Aula about your children
GNU General Public License v3.0
54 stars 14 forks source link

AULA - EasyIQ #132

Closed Milfeldt closed 6 months ago

Milfeldt commented 7 months ago

Hej @scaarup Her er hvad jeg umiddelbart synes giver mening ... De er highlighted på billederne, hvis nu jeg er helt galt på den, kan du måske se hvilke jeg skal bruge ;-)

curl "https://www.youtube.com/s/player/6ee8f9ce/www-widgetapi.vflset/www-widgetapi.js" ^ -H "sec-ch-ua: ^\^"Not_A Brand^\^";v=^\^"8^\^", ^\^"Chromium^\^";v=^\^"120^\^", ^\^"Google Chrome^\^";v=^\^"120^\^"" ^ -H "Referer: https://skoleportal.easyiqcloud.dk/" ^ -H "DNT: 1" ^ -H "sec-ch-ua-mobile: ?0" ^ -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ^ -H "sec-ch-ua-platform: ^\^"Windows^\^"" ^ --compressed Svarende til AULA_1 & 2

curl "https://api.easyiqcloud.dk/api/aula/weekinfo" ^ -X "OPTIONS" ^ -H "authority: api.easyiqcloud.dk" ^ -H "accept: */*" ^ -H "accept-language: da-DK,da;q=0.9,en-DK;q=0.8,en;q=0.7,en-US;q=0.6" ^ -H "access-control-request-headers: authorization,content-type,csrfp-token,x-aula-institutionfilter,x-aula-userprofile" ^ -H "access-control-request-method: POST" ^ -H "origin: https://www.aula.dk" ^ -H "referer: https://www.aula.dk/" ^ -H "sec-fetch-dest: empty" ^ -H "sec-fetch-mode: cors" ^ -H "sec-fetch-site: cross-site" ^ -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ^ --compressed

er fra 3 & 4

AULA_.integration.txt AULA_1 AULA_2 AULA_3 AULA_4

scaarup commented 7 months ago

Nogen, der gider paste den loglinje med ""EasyIQ Opgaver response "" ?

scaarup commented 7 months ago

Der er jo en del events, der ikke har nogen ownername eller description - hvad er det mon for noget og skal det med?

{
      "itemid": 726181,
      "IconId": null,
      "ownerunilogin": null,
      "updatedbyunilogin": null,
      "ownername": null,
      "updatedbyname": null,
      "ownerid": 381754,
      "visibility": 0,
      "start": "2024-01-29T00:00:00.0000000",
      "end": "2024-02-12T00:00:00.0000000",
      "isAllDay": null,
      "canEdit": false,
      "diffCount": 0,
      "title": "Skema, aktivitetskalender og Skolekalender",
      "chapterTitle": null,
      "color": "#FF6666",
      "darkerColor": null,
      "itemurl": "%7B%22route%22%3Anull%2C%22controller%22%3A%22Chapter%22%2C%22action%22%3A%22Index%22%2C%22params%22%3A%7B%22planId%22%3A%22726181%22%2C%22chapterId%22%3A%22-1%22%7D%2C%22child%22%3A%22lykk2941%22%7D",
      "icon": "~/Images/Plan/svg/clock.svg",
      "itemType": 5,
      "description": null,
      "RecurrencyTypeId": 0,
      "RecurrencyStartDate": null,
      "RecurrencyEndDate": null,
      "recurringItemId": null,
      "IsSeries": false,
      "IsInstanceOfSeries": false,
      "ActivityIds": [],
      "ActivityIdsCopy": null,
      "activities": null,
      "CourseIds": [],
      "CourseIdsCopy": null,
      "courses": null,
      "Private": false,
      "isFirstLineEmpty": false,
      "timeCreated": null,
      "timeUpdated": null,
      "updatedby": null,
      "Action": null,
      "Controller": null,
      "ActionParameters": null,
      "HtmlObject": null,
      "objectId": null,
      "extensiondata": null,
      "plans": null,
      "planIds": "",
      "prId": null,
      "isClassroom": false
    },
Milfeldt commented 7 months ago

HA uden tid med tidsstempel

scaarup commented 7 months ago

"itemType"

Fedt. Kan du post'e tilhørende json? Så kan det være vi kan finde ud af at se fag osv,

ethante commented 7 months ago

image

image

{ "fromDate": "2024-02-05T00:00:00", "toDate": "2024-02-10T00:00:00", "images": null, "WeekPlan": { "Id": 399696, "ActivityId": 1126108, "ActivityName": "4a", "Year": 2024, "WeekNo": 6, "Text": "", "RawHtml": "", "Visible": true, "TextId": "182675bb-6063-452d-9ffb-cec763d7bfde" }, "otherweekplans": [], "Events": [ { "itemid": 8578504, "IconId": null, "ownerunilogin": "xxxxxxx", "updatedbyunilogin": "xxxxxx", "ownername": "Lene Svane xxxxxx", "updatedbyname": "Lene Svane xxxxx", "ownerid": 538615, "visibility": 3, "start": "2024/02/06 08:00", "end": "2024/02/06 08:45", "isAllDay": false, "canEdit": false, "diffCount": 0, "title": " ", "chapterTitle": null, "color": "#43A6DF", "darkerColor": null, "itemurl": "", "icon": "~\\Images\\Plan\\svg\\open-book.svg", "itemType": 8, "description": "Drengene l&aelig;ser kapitel 13 og 14", "RecurrencyTypeId": 0, "RecurrencyStartDate": null, "RecurrencyEndDate": null, "recurringItemId": null, "IsSeries": false, "IsInstanceOfSeries": false, "ActivityIds": [ 1126108 ], "ActivityIdsCopy": null, "activities": "4a", "CourseIds": [], "CourseIdsCopy": null, "courses": "", "Private": false, "isFirstLineEmpty": false, "timeCreated": "2024-02-01T11:33:21.253", "timeUpdated": "2024-02-04T20:18:48.717", "updatedby": 538615, "Action": null, "Controller": null, "ActionParameters": null, "HtmlObject": null, "objectId": "f1bc5167-747f-48d7-93ab-3b1debbaa731", "extensiondata": null, "plans": null, "planIds": "", "prId": null, "isClassroom": false }, { "itemid": 8601258, "IconId": null, "ownerunilogin": "xxxxxxx", "updatedbyunilogin": "xxxxxx", "ownername": "Lene Svane xxxxxx", "updatedbyname": "Lene Svane xxxxxx", "ownerid": 538615, "visibility": 3, "start": "2024/02/06 08:00", "end": "2024/02/06 08:45", "isAllDay": false, "canEdit": false, "diffCount": 0, "title": " ", "chapterTitle": null, "color": "rgb(255, 106, 0)", "darkerColor": null, "itemurl": "", "icon": "~\\Images\\Plan\\svg\\open-book.svg", "itemType": 8, "description": "<p>Ugens talem&aring;de: \"At have ild i r&oslash;ven\".</p><p>Skriv en s&aelig;tning med talem&aring;den derhjemme til p&aring; fredag - tal om, hvad det betyder (m&aring;ske nogle i 4.a har ild i r&oslash;ven :)</p>", "RecurrencyTypeId": 0, "RecurrencyStartDate": null, "RecurrencyEndDate": null, "recurringItemId": null, "IsSeries": false, "IsInstanceOfSeries": false, "ActivityIds": [ 1126108 ], "ActivityIdsCopy": null, "activities": "4a", "CourseIds": [], "CourseIdsCopy": null, "courses": "", "Private": false, "isFirstLineEmpty": false, "timeCreated": "2024-02-06T08:40:42.447", "timeUpdated": "2024-02-06T18:17:01.9", "updatedby": 538615, "Action": null, "Controller": null, "ActionParameters": null, "HtmlObject": null, "objectId": "10955aa8-6f1d-4dfa-992d-d1ddc5e3f6a1", "extensiondata": null, "plans": null, "planIds": "", "prId": null, "isClassroom": false }, { "itemid": 8601264, "IconId": null, "ownerunilogin": "xxxxxxx", "updatedbyunilogin": null, "ownername": "Lene Svane xxxxxx", "updatedbyname": null, "ownerid": 538615, "visibility": 3, "start": "2024/02/08 08:00", "end": "2024/02/08 08:45", "isAllDay": false, "canEdit": false, "diffCount": 0, "title": " ", "chapterTitle": null, "color": "#43A6DF", "darkerColor": null, "itemurl": "", "icon": "~\\Images\\Plan\\svg\\open-book.svg", "itemType": 8, "description": "Drengene og pigerne l&aelig;ser bogen f&aelig;rdig til torsdag. Husk at medbringe bogen, da den skal afleveres tilbage til CFU.&nbsp;", "RecurrencyTypeId": 0, "RecurrencyStartDate": null, "RecurrencyEndDate": null, "recurringItemId": null, "IsSeries": false, "IsInstanceOfSeries": false, "ActivityIds": [ 1126108 ], "ActivityIdsCopy": null, "activities": "4a", "CourseIds": [], "CourseIdsCopy": null, "courses": "", "Private": false, "isFirstLineEmpty": false, "timeCreated": "2024-02-06T08:42:39.697", "timeUpdated": null, "updatedby": null, "Action": null, "Controller": null, "ActionParameters": null, "HtmlObject": null, "objectId": "7b6246cc-22d1-4559-9174-6865d5eab3cb", "extensiondata": null, "plans": null, "planIds": "", "prId": null, "isClassroom": false }, { "itemid": 8603300, "IconId": null, "ownerunilogin": "xxxxxxx", "updatedbyunilogin": null, "ownername": "Lene Svane xxxxxx", "updatedbyname": null, "ownerid": 538615, "visibility": 3, "start": "2024/02/09 08:00", "end": "2024/02/09 08:45", "isAllDay": false, "canEdit": false, "diffCount": 0, "title": " ", "chapterTitle": null, "color": "rgb(255, 0, 0)", "darkerColor": null, "itemurl": "", "icon": "~\\Images\\Plan\\svg\\open-book.svg", "itemType": 8, "description": "<p>Ugens talem&aring;de: \"At have ild i r&oslash;ven\".</p><p>Skriv en s&aelig;tning med talem&aring;den derhjemme - tal om, hvad det betyder (m&aring;ske nogle i 4.a har ild i r&oslash;ven :)</p>", "RecurrencyTypeId": 0, "RecurrencyStartDate": null, "RecurrencyEndDate": null, "recurringItemId": null, "IsSeries": false, "IsInstanceOfSeries": false, "ActivityIds": [ 1126108 ], "ActivityIdsCopy": null, "activities": "4a", "CourseIds": [], "CourseIdsCopy": null, "courses": "", "Private": false, "isFirstLineEmpty": false, "timeCreated": "2024-02-06T18:17:40.99", "timeUpdated": null, "updatedby": null, "Action": null, "Controller": null, "ActionParameters": null, "HtmlObject": null, "objectId": "139b72bd-5d6e-48ba-84f1-4e79db77b163", "extensiondata": null, "plans": null, "planIds": "", "prId": null, "isClassroom": false }, { "itemid": 726181, "IconId": null, "ownerunilogin": null, "updatedbyunilogin": null, "ownername": null, "updatedbyname": null, "ownerid": 381754, "visibility": 0, "start": "2024-01-29T00:00:00.0000000", "end": "2024-02-12T00:00:00.0000000", "isAllDay": null, "canEdit": false, "diffCount": 0, "title": "Skema, aktivitetskalender og Skolekalender", "chapterTitle": null, "color": "#FF6666", "darkerColor": null, "itemurl": "%7B%22route%22%3Anull%2C%22controller%22%3A%22Chapter%22%2C%22action%22%3A%22Index%22%2C%22params%22%3A%7B%22planId%22%3A%22726181%22%2C%22chapterId%22%3A%22-1%22%7D%2C%22child%22%3A%22lykk2941%22%7D", "icon": "~/Images/Plan/svg/clock.svg", "itemType": 5, "description": null, "RecurrencyTypeId": 0, "RecurrencyStartDate": null, "RecurrencyEndDate": null, "recurringItemId": null, "IsSeries": false, "IsInstanceOfSeries": false, "ActivityIds": [], "ActivityIdsCopy": null, "activities": null, "CourseIds": [], "CourseIdsCopy": null, "courses": null, "Private": false, "isFirstLineEmpty": false, "timeCreated": null, "timeUpdated": null, "updatedby": null, "Action": null, "Controller": null, "ActionParameters": null, "HtmlObject": null, "objectId": null, "extensiondata": null, "plans": null, "planIds": "", "prId": null, "isClassroom": false }, { "itemid": 746491, "IconId": null, "ownerunilogin": null, "updatedbyunilogin": null, "ownername": null, "updatedbyname": null, "ownerid": 381754, "visibility": 0, "start": "2024-01-29T00:00:00.0000000", "end": "2024-02-12T00:00:00.0000000", "isAllDay": null, "canEdit": false, "diffCount": 0, "title": "Møder mm.", "chapterTitle": null, "color": "#B200FF", "darkerColor": null, "itemurl": "%7B%22route%22%3Anull%2C%22controller%22%3A%22Chapter%22%2C%22action%22%3A%22Index%22%2C%22params%22%3A%7B%22planId%22%3A%22746491%22%2C%22chapterId%22%3A%22-1%22%7D%2C%22child%22%3A%22lykk2941%22%7D", "icon": "~\\Images\\Plan\\svg\\child-safe-zone.svg", "itemType": 5, "description": null, "RecurrencyTypeId": 0, "RecurrencyStartDate": null, "RecurrencyEndDate": null, "recurringItemId": null, "IsSeries": false, "IsInstanceOfSeries": false, "ActivityIds": [], "ActivityIdsCopy": null, "activities": null, "CourseIds": [], "CourseIdsCopy": null, "courses": null, "Private": false, "isFirstLineEmpty": false, "timeCreated": null, "timeUpdated": null, "updatedby": null, "Action": null, "Controller": null, "ActionParameters": null, "HtmlObject": null, "objectId": null, "extensiondata": null, "plans": null, "planIds": "", "prId": null, "isClassroom": false } ], "groups": [], "group": null, "weekinfo": { "currentweeknr": "Uge 6", "prevweeknr": "2024-W05", "nextweeknr": "2024-W07", "weekstartdate": "2024-02-05T00:00:00", "weekenddate": "2024-02-10T00:00:00", "todaysweeknr": "2024-W07" }, "notifications": { "latestview": "2024-01-29T07:05:54.88", "notificationlist": [ { "sender": { "fullname": "Mette xxxxxx", "familyname": "xxxxx", "givenname": "Mette", "unilogin": "mett1022", "loginid": 381732, "logintypeid": 2 }, "reciever": { "fullname": "Mette xxxxxx", "familyname": "xxxxxxx", "givenname": "Mette", "unilogin": "xxxxxx", "loginid": 381732, "logintypeid": 2 }, "target": { "fullname": "Liva Marie Stærdahl Søndergaard", "familyname": "Søndergaard", "givenname": "Liva Marie Stærdahl", "unilogin": "xxxxx", "loginid": 2437106, "logintypeid": 1 }, "url": "Overblik/172872", "timestamp": "2024-01-15T11:32:28.137", "read": false, "message": null, "Age": "00:00:00", "notificationtypeid": 1, "notificationtype": null, "data": [], "viewed": true }, { "sender": { "fullname": "Mette xxxxxxx", "familyname": "xxxxx", "givenname": "Mette", "unilogin": "xxxxxxx", "loginid": 381732, "logintypeid": 2 }, "reciever": { "fullname": "Mette xxxxxxx", "familyname": "xxxxxx", "givenname": "Mette", "unilogin": "xxxxxx", "loginid": 381732, "logintypeid": 2 }, "target": { "fullname": "Lykke Anxxxxxrd", "familyname": "Søndergaard", "givenname": "Lykke Anna Stærdahl", "unilogin": "xxxxxx", "loginid": 1001246, "logintypeid": 1 }, "url": "Overblik/120899", "timestamp": "2023-05-30T08:46:13.41", "read": true, "message": null, "Age": "00:00:00", "notificationtypeid": 1, "notificationtype": null, "data": [], "viewed": true } ], "hasmore": false }, "weekplanconfiguration": { "showplans": true, "narrowview_showplans": true, "showweekplanitemplanner": false, "usehtmlwidget": true }, "links": [ { "name": "Skoleportal", "address": "https://skoleportal.easyiqcloud.dk", "ssoenable": true }, { "name": "Meddelelsesbog", "address": "https://skoleportal.easyiqcloud.dk/elevplan", "ssoenable": true } ], "widgetlink": 0 }

tænker denne dato som er i event:

start": "2024/02/06 08:00",

Milfeldt commented 7 months ago

@scaarup jeg sletter den kilomertelange én jeg satte ind lige før?

scaarup commented 7 months ago

@scaarup jeg sletter den kilomertelange én jeg satte ind lige før?

tak :)

scaarup commented 7 months ago

@ethante @Milfeldt nogen, der vil teste den nyeste version?

Og er der nogen, der kan skaffe mig kald og svar til denne her "GetCourseList": image ? Jeg tror vi skal via den for at få de forskellige tilhørende fag:

"ActivityIds": [
        1126108
      ],
ethante commented 7 months ago

jeg for ikke GetCourseList:

image

Men jeg kan godt teste den sidste

ethante commented 7 months ago

image

image

2024-02-13 19:03:58.200 ERROR (MainThread) [custom_components.aula.sensor] Unexpected error fetching sensor data: cannot access local variable 'datetime' where it is not associated with a value

scaarup commented 7 months ago

av! Prøv lige med den næste version

scaarup commented 7 months ago

av! Prøv lige med den næste version

sry, glemte at pushe. Den er der nu.

Milfeldt commented 7 months ago

@scaarup Den 10-11 min 'gamle' tog livet af skema og ugeplan

ethante commented 7 months ago

image image

2024-02-13 19:25:14.285 WARNING (MainThread) [homeassistant.components.sensor] Setup of sensor platform aula is taking over 10 seconds. 2024-02-13 19:25:14.290 ERROR (MainThread) [custom_components.aula.sensor] Unexpected error fetching sensor data: cannot access local variable 'datetime' where it is not associated with a value

same :)

Milfeldt commented 7 months ago

Altså ... @scaarup
Du kunne godt komme på en gang teamviewer imens jeg er logget på AULA? Så kunne du måske finde lige det du mangler? :-)

ethante commented 7 months ago

@scaarup @Milfeldt så fik jeg den fixet 🗡️

image

her er hele min client.py code:

import logging import requests import datetime from bs4 import BeautifulSoup import json, re from .const import ( API, API_VERSION, MIN_UDDANNELSE_API, MEEBOOK_API, SYSTEMATIC_API, EASYIQ_API, ) from homeassistant.exceptions import ConfigEntryNotReady

_LOGGER = logging.getLogger(name)

class Client: huskeliste = {} presence = {} ugep_attr = {} ugepnext_attr = {} widgets = {} tokens = {}

def __init__(self, username, password, schoolschedule, ugeplan):
    self._username = username
    self._password = password
    self._session = None
    self._schoolschedule = schoolschedule
    self._ugeplan = ugeplan

def custom_api_call(self, uri, post_data):
    csrf_token = self._session.cookies.get_dict()["Csrfp-Token"]
    headers = {"csrfp-token": csrf_token, "content-type": "application/json"}
    _LOGGER.debug("custom_api_call: Making API call to " + self.apiurl + uri)
    if post_data == 0:
        response = self._session.get(
            self.apiurl + uri, headers=headers, verify=True
        )
    else:
        try:
            # Check if post_data is valid JSON
            json.loads(post_data)
        except json.JSONDecodeError as e:
            _LOGGER.error("Invalid json supplied as post_data")
            error_msg = {"result": "Fail - invalid json supplied as post_data"}
            return error_msg
        _LOGGER.debug("custom_api_call: post_data:" + post_data)
        response = self._session.post(
            self.apiurl + uri,
            headers=headers,
            json=json.loads(post_data),
            verify=True,
        )
    _LOGGER.debug(response.text)
    try:
        res = response.json()
    except:
        res = {"raw_response": response.text}
    return res

def login(self):
    _LOGGER.debug("Logging in")
    self._session = requests.Session()
    headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/112.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "da,en-US;q=0.7,en;q=0.3",
        "DNT": "1",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "none",
        "Sec-Fetch-User": "?1",
    }
    params = {
        "type": "unilogin",
    }
    response = self._session.get(
        "https://login.aula.dk/auth/login.php",
        params=params,
        headers=headers,
        verify=True,
    )

    _html = BeautifulSoup(response.text, "lxml")
    _url = _html.form["action"]
    headers = {
        "Host": "broker.unilogin.dk",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/112.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "da,en-US;q=0.7,en;q=0.3",
        "Content-Type": "application/x-www-form-urlencoded",
        "Origin": "null",
        "DNT": "1",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "same-origin",
        "Sec-Fetch-User": "?1",
    }
    data = {
        "selectedIdp": "uni_idp",
    }
    response = self._session.post(
        _url,
        headers=headers,
        data=data,
        verify=True,
    )

    user_data = {
        "username": self._username,
        "password": self._password,
        "selected-aktoer": "KONTAKT",
    }
    redirects = 0
    success = False
    url = ""
    while success == False and redirects < 10:
        html = BeautifulSoup(response.text, "lxml")
        url = html.form["action"]

        post_data = {}
        for input in html.find_all("input"):
            if input.has_attr("name") and input.has_attr("value"):
                post_data[input["name"]] = input["value"]
                for key in user_data:
                    if input.has_attr("name") and input["name"] == key:
                        post_data[key] = user_data[key]

        response = self._session.post(url, data=post_data, verify=True)
        if response.url == "https://www.aula.dk:443/portal/":
            success = True
        redirects += 1

    # Find the API url in case of a version change
    self.apiurl = API + API_VERSION
    apiver = int(API_VERSION)
    api_success = False
    while api_success == False:
        _LOGGER.debug("Trying API at " + self.apiurl)
        ver = self._session.get(
            self.apiurl + "?method=profiles.getProfilesByLogin", verify=True
        )
        if ver.status_code == 410:
            _LOGGER.debug(
                "API was expected at "
                + self.apiurl
                + " but responded with HTTP 410. The integration will automatically try a newer version and everything may work fine."
            )
            apiver += 1
        if ver.status_code == 403:
            msg = "Access to Aula API was denied. Please check that you have entered the correct credentials. (Your password automatically expires on regular intervals!)"
            _LOGGER.error(msg)
            raise ConfigEntryNotReady(msg)
        elif ver.status_code == 200:
            self._profiles = ver.json()["data"]["profiles"]
            # _LOGGER.debug("self._profiles "+str(self._profiles))
            api_success = True
        self.apiurl = API + str(apiver)
    _LOGGER.debug("Found API on " + self.apiurl)
    #

    # ver = self._session.get(self.apiurl + "?method=profiles.getProfilesByLogin", verify=True)
    # self._profiles = ver.json()["data"]["profiles"]
    self._profilecontext = self._session.get(
        self.apiurl + "?method=profiles.getProfileContext&portalrole=guardian",
        verify=True,
    ).json()["data"]["institutionProfile"]["relations"]
    _LOGGER.debug("LOGIN: " + str(success))
    _LOGGER.debug(
        "Config - schoolschedule: "
        + str(self._schoolschedule)
        + ", config - ugeplaner: "
        + str(self._ugeplan)
    )

def get_widgets(self):
    detected_widgets = self._session.get(
        self.apiurl + "?method=profiles.getProfileContext", verify=True
    ).json()["data"]["moduleWidgetConfiguration"]["widgetConfigurations"]
    for widget in detected_widgets:
        widgetid = str(widget["widget"]["widgetId"])
        widgetname = widget["widget"]["name"]
        self.widgets[widgetid] = widgetname
    _LOGGER.debug("Widgets found: " + str(self.widgets))

def get_token(self, widgetid, mock=False):
    _LOGGER.debug("Requesting token for widget " + widgetid)
    if mock:
        return "MockToken"
    self._bearertoken = self._session.get(
        self.apiurl + "?method=aulaToken.getAulaToken&widgetId=" + widgetid,
        verify=True,
    ).json()["data"]
    token = "Bearer " + str(self._bearertoken)
    self.tokens[widgetid] = token
    return token

def update_data(self):
    is_logged_in = False
    if self._session:
        response = self._session.get(
            self.apiurl + "?method=profiles.getProfilesByLogin", verify=True
        ).json()
        is_logged_in = response["status"]["message"] == "OK"

    _LOGGER.debug("is_logged_in? " + str(is_logged_in))

    if not is_logged_in:
        self.login()

    self._childnames = {}
    self._institutions = {}
    self._childuserids = []
    self._childids = []
    self._children = []
    self._institutionProfiles = []
    self._childrenFirstNamesAndUserIDs = {}
    for profile in self._profiles:
        for child in profile["children"]:
            self._childnames[child["id"]] = child["name"]
            self._institutions[child["id"]] = child["institutionProfile"][
                "institutionName"
            ]
            self._children.append(child)
            self._childids.append(str(child["id"]))
            self._childuserids.append(str(child["userId"]))
            self._childrenFirstNamesAndUserIDs[child["userId"]] = child[
                "name"
            ].split()[0]
        for institutioncode in profile["institutionProfiles"]:
            if (
                str(institutioncode["institutionCode"])
                not in self._institutionProfiles
            ):
                self._institutionProfiles.append(
                    str(institutioncode["institutionCode"])
                )
    _LOGGER.debug("Child ids and names: " + str(self._childnames))
    _LOGGER.debug("Child ids and institution names: " + str(self._institutions))
    _LOGGER.debug("Institution codes: " + str(self._institutionProfiles))

    self._daily_overview = {}
    for i, child in enumerate(self._children):
        response = self._session.get(
            self.apiurl
            + "?method=presence.getDailyOverview&childIds[]="
            + str(child["id"]),
            verify=True,
        ).json()
        if len(response["data"]) > 0:
            self.presence[str(child["id"])] = 1
            self._daily_overview[str(child["id"])] = response["data"][0]
        else:
            _LOGGER.debug(
                "Unable to retrieve presence data from Aula from child with id "
                + str(child["id"])
                + ". Some data will be missing from sensor entities."
            )
            self.presence[str(child["id"])] = 0
    _LOGGER.debug("Child ids and presence data status: " + str(self.presence))

    # Messages:
    mesres = self._session.get(
        self.apiurl
        + "?method=messaging.getThreads&sortOn=date&orderDirection=desc&page=0",
        verify=True,
    )
    # _LOGGER.debug("mesres "+str(mesres.text))
    self.unread_messages = 0
    unread = 0
    self.message = {}
    for mes in mesres.json()["data"]["threads"]:
        if not mes["read"]:
            # self.unread_messages = 1
            unread = 1
            threadid = mes["id"]
            break
    # if self.unread_messages == 1:
    if unread == 1:
        # _LOGGER.debug("tid "+str(threadid))
        threadres = self._session.get(
            self.apiurl
            + "?method=messaging.getMessagesForThread&threadId="
            + str(threadid)
            + "&page=0",
            verify=True,
        )
        # _LOGGER.debug("threadres "+str(threadres.text))
        if threadres.json()["status"]["code"] == 403:
            self.message["text"] = (
                "Log ind på Aula med MitID for at læse denne besked."
            )
            self.message["sender"] = "Ukendt afsender"
            self.message["subject"] = "Følsom besked"
        else:
            for message in threadres.json()["data"]["messages"]:
                if message["messageType"] == "Message":
                    try:
                        self.message["text"] = message["text"]["html"]
                    except:
                        try:
                            self.message["text"] = message["text"]
                        except:
                            self.message["text"] = "intet indhold..."
                            _LOGGER.warning(
                                "There is an unread message, but we cannot get the text."
                            )
                    try:
                        self.message["sender"] = message["sender"]["fullName"]
                    except:
                        self.message["sender"] = "Ukendt afsender"
                    try:
                        self.message["subject"] = threadres.json()["data"][
                            "subject"
                        ]
                    except:
                        self.message["subject"] = ""
                    self.unread_messages = 1
                    break

    # Calendar:
    if self._schoolschedule == True:
        instProfileIds = ",".join(self._childids)
        csrf_token = self._session.cookies.get_dict()["Csrfp-Token"]
        headers = {"csrfp-token": csrf_token, "content-type": "application/json"}
        start = datetime.datetime.now(datetime.timezone.utc).strftime(
            "%Y-%m-%d 00:00:00.0000%z"
        )
        _end = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(
            days=14
        )
        end = _end.strftime("%Y-%m-%d 00:00:00.0000%z")
        post_data = (
            '{"instProfileIds":['
            + instProfileIds
            + '],"resourceIds":[],"start":"'
            + start
            + '","end":"'
            + end
            + '"}'
        )
        _LOGGER.debug("Fetching calendars...")
        # _LOGGER.debug("Calendar post-data: "+str(post_data))
        res = self._session.post(
            self.apiurl + "?method=calendar.getEventsByProfileIdsAndResourceIds",
            data=post_data,
            headers=headers,
            verify=True,
        )
        try:
            with open("skoleskema.json", "w") as skoleskema_json:
                json.dump(res.text, skoleskema_json)
        except:
            _LOGGER.warn(
                "Got the following reply when trying to fetch calendars: "
                + str(res.text)
            )
    # End of calendar

    # Ugeplaner:
    if self._ugeplan == True:
        guardian = self._session.get(
            self.apiurl + "?method=profiles.getProfileContext&portalrole=guardian",
            verify=True,
        ).json()["data"]["userId"]
        childUserIds = ",".join(self._childuserids)

        if len(self.widgets) == 0:
            self.get_widgets()
        if (
            not "0029" in self.widgets
            and not "0004" in self.widgets
            and not "0062" in self.widgets
            and not "0030" in self.widgets
            and not "0001" in self.widgets
        ):
            _LOGGER.error(
                "You have enabled ugeplaner, but we cannot find any supported widgets (0029,0004,0030,0001) in Aula."
            )
        if "0029" in self.widgets and "0004" in self.widgets:
            _LOGGER.warning(
                "Multiple sources for ugeplaner is untested and might cause problems."
            )

        def ugeplan(week, thisnext):
            if "0029" in self.widgets and "0030" not in self.widgets:
                from datetime import datetime

                token = self.get_token("0029")
                get_payload = (
                    "/ugebrev?assuranceLevel=2&childFilter="
                    + childUserIds
                    + "&currentWeekNumber="
                    + week
                    + "&isMobileApp=false&placement=narrow&sessionUUID="
                    + guardian
                    + "&userProfile=guardian"
                )
                ugeplaner = requests.get(
                    MIN_UDDANNELSE_API + get_payload,
                    headers={"Authorization": token, "accept": "application/json"},
                    verify=True,
                )
                # _LOGGER.debug("ugeplaner status_code "+str(ugeplaner.status_code))
                # _LOGGER.debug("ugeplaner response "+str(ugeplaner.text))
                for person in ugeplaner.json()["personer"]:
                    ugeplan = person["institutioner"][0]["ugebreve"][0]["indhold"]
                    if thisnext == "this":
                        self.ugep_attr[person["navn"].split()[0]] = ugeplan
                    elif thisnext == "next":
                        self.ugepnext_attr[person["navn"].split()[0]] = ugeplan

            if "0030" in self.widgets:
                _LOGGER.debug("In the MU Opgaver flow")
                token = self.get_token("0030")
                get_payload = (
                    "/opgaveliste?assuranceLevel=2&childFilter="
                    + childUserIds
                    + "&currentWeekNumber="
                    + week
                    + "&isMobileApp=false&placement=narrow&sessionUUID="
                    + guardian
                    + "&userProfile=guardian"
                )
                ugeplaner = requests.get(
                    MIN_UDDANNELSE_API + get_payload,
                    headers={"Authorization": token, "accept": "application/json"},
                    verify=True,
                )
                _LOGGER.debug(
                    "MU Opgaver status_code " + str(ugeplaner.status_code)
                )
                _LOGGER.debug("MU Opgaver response " + str(ugeplaner.text))
                for full_name in self._childnames.items():
                    name_parts = full_name.split()
                    first_name = name_parts[0]
                    _ugep = ""
                    for i in ugeplaner.json()["opgaver"]:
                        _LOGGER.debug(
                            "i kuvertnavn split " + str(i["kuvertnavn"].split()[0])
                        )
                        _LOGGER.debug("first_name " + first_name)
                        if i["kuvertnavn"].split()[0] == first_name:
                            _ugep = _ugep + "<h2>" + i["title"] + "</h2>"
                            _ugep = _ugep + "<h3>" + i["kuvertnavn"] + "</h3>"
                            _ugep = _ugep + "Ugedag: " + i["ugedag"] + "<br>"
                            _ugep = _ugep + "Type: " + i["opgaveType"] + "<br>"
                            for h in i["hold"]:
                                _ugep = _ugep + "Hold: " + h["navn"] + "<br>"
                            try:
                                _ugep = _ugep + "Forløb: " + i["forloeb"]["navn"]
                            except:
                                _LOGGER.debug("Did not find forloeb key: " + str(i))
                    if thisnext == "this":
                        self.ugep_attr[first_name] = _ugep
                    elif thisnext == "next":
                        self.ugepnext_attr[first_name] = _ugep
                    _LOGGER.debug("MU Opgaver result: " + str(_ugep))

            # EasyIQ:
            if "0001" in self.widgets:
                _LOGGER.debug("In the EasyIQ flow")
                token = self.get_token("0001")
                csrf_token = self._session.cookies.get_dict()["Csrfp-Token"]

                easyiq_headers = {
                    "x-aula-institutionfilter": str(self._institutionProfiles[0]),
                    "x-aula-userprofile": "guardian",
                    "Authorization": token,
                    "accept": "application/json",
                    "csrfp-token": csrf_token,
                    "origin": "https://www.aula.dk",
                    "referer": "https://www.aula.dk/",
                    "authority": "api.easyiqcloud.dk",
                }

                for child in self._childrenFirstNamesAndUserIDs.items():
                    userid = child[0]
                    first_name = child[1]

                    _LOGGER.debug("EasyIQ headers " + str(easyiq_headers))
                    post_data = {
                        "sessionId": guardian,
                        "currentWeekNr": week,
                        "userProfile": "guardian",
                        "institutionFilter": self._institutionProfiles,
                        "childFilter": [userid],
                    }
                    _LOGGER.debug("EasyIQ post data " + str(post_data))
                    ugeplaner = requests.post(
                        EASYIQ_API + "/weekplaninfo",
                        json=post_data,
                        headers=easyiq_headers,
                        verify=True,
                    )
                    # _LOGGER.debug(
                    #    "EasyIQ Opgaver status_code " + str(ugeplaner.status_code)
                    # )
                    _LOGGER.debug(
                        "EasyIQ Opgaver response " + str(ugeplaner.json())
                    )
                    _ugep = (
                        "<h2>"
                        # + ugeplaner.json()["Weekplan"]["ActivityName"]
                        + " Uge "
                        # + ugeplaner.json()["Weekplan"]["WeekNo"]
                        + "</h2>"
                    )
                    from datetime import datetime

                    def is_correct_format(date_string, format):
                        try:
                            datetime.strptime(date_string, format)
                            return True
                        except ValueError:
                            return False

                    for i in ugeplaner.json()["Events"]:
                        if is_correct_format(i["start"], "%Y/%m/%d %H:%M"):
                            _LOGGER.debug("No Event")
                            start_datetime = datetime.strptime(i["start"], "%Y/%m/%d %H:%M")
                            _LOGGER.debug(start_datetime)
                            end_datetime = datetime.strptime(i["end"], "%Y/%m/%d %H:%M")
                            if start_datetime.date() == end_datetime.date():
                                formatted_start = start_datetime.strftime("%A %H:%M")
                                formatted_end = end_datetime.strftime("- %H:%M")
                                dresult = f"{formatted_start} {formatted_end}"
                            else:
                                formatted_start = start_datetime.strftime("%A")
                                formatted_end = end_datetime.strftime("- %A")
                                dresult = f"{formatted_start} {formatted_end}"
                            _ugep = _ugep + "<br><b>" + dresult + "</b><br>"
                            if i["itemType"] == "5":
                                _ugep = _ugep + "<br><b>" + str(i["title"]) + "</b><br>"
                            else:
                                _ugep = (
                                _ugep + "<br><b>" + str(i["ownername"]) + "</b><br>"
                                )
                            _ugep = _ugep + str(i["description"]) + "<br>"
                        else:
                            _LOGGER.debug("None")
                    if thisnext == "this":
                        self.ugep_attr[first_name] = _ugep
                    elif thisnext == "next":
                        self.ugepnext_attr[first_name] = _ugep
                    _LOGGER.debug("EasyIQ result: " + str(_ugep))

            if "0062" in self.widgets:
                _LOGGER.debug("In the Huskelisten flow...")
                token = self.get_token("0062", False)
                huskelisten_headers = {
                    "Accept": "application/json, text/plain, */*",
                    "Accept-Encoding": "gzip, deflate, br",
                    "Accept-Language": "en-US,en;q=0.9,da;q=0.8",
                    "Aula-Authorization": token,
                    "Origin": "https://www.aula.dk",
                    "Referer": "https://www.aula.dk/",
                    "Sec-Fetch-Dest": "empty",
                    "Sec-Fetch-Mode": "cors",
                    "Sec-Fetch-Site": "cross-site",
                    "User-Agent": "Mozilla/5.0 (X11; CrOS x86_64 15183.51.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
                    "zone": "Europe/Copenhagen",
                }

                children = "&children=".join(self._childuserids)
                institutions = "&institutions=".join(self._institutionProfiles)
                timedelta = datetime.datetime.now() + datetime.timedelta(days=180)
                From = datetime.datetime.now().strftime("%Y-%m-%d")
                dueNoLaterThan = timedelta.strftime("%Y-%m-%d")
                get_payload = (
                    "/reminders/v1?children="
                    + children
                    + "&from="
                    + From
                    + "&dueNoLaterThan="
                    + dueNoLaterThan
                    + "&widgetVersion=1.10&userProfile=guardian&sessionId="
                    + self._username
                    + "&institutions="
                    + institutions
                )
                _LOGGER.debug(
                    "Huskelisten get_payload: " + SYSTEMATIC_API + get_payload
                )
                #
                mock_huskelisten = 0
                #
                if mock_huskelisten == 1:
                    _LOGGER.warning("Using mock data for Huskelisten.")
                    mock_huskelisten = '[{"userName":"Emilie efternavn","userId":164625,"courseReminders":[],"assignmentReminders":[],"teamReminders":[{"id":76169,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-11-29T23:00:00Z","teamId":65240,"teamName":"2A","reminderText":"Onsdagslektie: Matematikfessor.dk: Sænk skibet med plus.","createdBy":"Peter ","lastEditBy":"Peter ","subjectName":"Matematik"},{"id":76598,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-12-06T23:00:00Z","teamId":65240,"teamName":"2A","reminderText":"Julekalender på Skoledu.dk: I skal forsøge at løse dagens kalenderopgave. opgaven kan også godt løses dagen efter.","createdBy":"Peter ","lastEditBy":"Peter Riis","subjectName":"Matematik"},{"id":76599,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-12-13T23:00:00Z","teamId":65240,"teamName":"2A","reminderText":"Julekalender på Skoledu.dk: I skal forsøge at løse dagens kalenderopgave. opgaven kan også godt løses dagen efter.","createdBy":"Peter ","lastEditBy":"Peter ","subjectName":"Matematik"},{"id":76600,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-12-20T23:00:00Z","teamId":65240,"teamName":"2A","reminderText":"Julekalender på Skoledu.dk: I skal forsøge at løse dagens kalenderopgave. opgaven kan også godt løses dagen efter.","createdBy":"Peter Riis","lastEditBy":"Peter Riis","subjectName":"Matematik"}]},{"userName":"Karla","userId":77882,"courseReminders":[],"assignmentReminders":[{"id":0,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-12-08T11:00:00Z","courseId":297469,"teamNames":["5A","5B"],"teamIds":[65271,65258],"courseSubjects":[],"assignmentId":5027904,"assignmentText":"Skriv en novelle"}],"teamReminders":[{"id":76367,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-11-30T23:00:00Z","teamId":65258,"teamName":"5A","reminderText":"Læse resten af kap.1 fra Ternet Ninja ( kopiark) Læs det hele højt eller vælg et afsnit. ","createdBy":"Christina ","lastEditBy":"Christina ","subjectName":"Dansk"}]},{"userName":"Vega  ","userId":206597,"courseReminders":[],"assignmentReminders":[],"teamReminders":[]}]'
                    data = json.loads(mock_huskelisten, strict=False)
                else:
                    response = requests.get(
                        SYSTEMATIC_API + get_payload,
                        headers=huskelisten_headers,
                        verify=True,
                    )
                    try:
                        data = json.loads(response.text, strict=False)
                    except:
                        _LOGGER.error(
                            "Could not parse the response from Huskelisten as json."
                        )
                    # _LOGGER.debug("Huskelisten raw response: "+str(response.text))

                for person in data:
                    name = person["userName"].split()[0]
                    _LOGGER.debug("Huskelisten for " + name)
                    huskel = ""
                    reminders = person["teamReminders"]
                    if len(reminders) > 0:
                        for reminder in reminders:
                            mytime = datetime.datetime.strptime(
                                reminder["dueDate"], "%Y-%m-%dT%H:%M:%SZ"
                            )
                            ftime = mytime.strftime("%A %d. %B")
                            huskel = huskel + "<h3>" + ftime + "</h3>"
                            huskel = (
                                huskel
                                + "<b>"
                                + reminder["subjectName"]
                                + "</b><br>"
                            )
                            huskel = (
                                huskel + "af " + reminder["createdBy"] + "<br><br>"
                            )
                            content = re.sub(
                                r"([0-9]+)(\.)", r"\1\.", reminder["reminderText"]
                            )
                            huskel = huskel + content + "<br><br>"
                    else:
                        huskel = huskel + str(name) + " har ingen påmindelser."
                    self.huskeliste[name] = huskel

            # End Huskelisten
            if "0004" in self.widgets:
                # Try Meebook:
                _LOGGER.debug("In the Meebook flow...")
                token = self.get_token("0004")
                # _LOGGER.debug("Token "+token)
                headers = {
                    "authority": "app.meebook.com",
                    "accept": "application/json",
                    "authorization": token,
                    "dnt": "1",
                    "origin": "https://www.aula.dk",
                    "referer": "https://www.aula.dk/",
                    "sessionuuid": self._username,
                    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
                    "x-version": "1.0",
                }
                childFilter = "&childFilter[]=".join(self._childuserids)
                institutionFilter = "&institutionFilter[]=".join(
                    self._institutionProfiles
                )
                get_payload = (
                    "/relatedweekplan/all?currentWeekNumber="
                    + week
                    + "&userProfile=guardian&childFilter[]="
                    + childFilter
                    + "&institutionFilter[]="
                    + institutionFilter
                )

                mock_meebook = 0
                if mock_meebook == 1:
                    _LOGGER.warning("Using mock data for Meebook ugeplaner.")
                    mock_meebook = '[{"id":490000,"name":"Emilie efternavn","unilogin":"lud...","weekPlan":[{"date":"mandag 28. nov.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"I denne uge er der omlagt uge p\u00e5 hele skolen.\n\nMandag har vi \nKlippeklistredag:\n\nMan m\u00e5 gerne have nissehuer p\u00e5 :)\n\nMedbring gerne en god saks, limstift, skabeloner mm. \n\nB\u00f8rnene skal ogs\u00e5 medbringe et vasket syltet\u00f8jsglas eller lign., som vi skal male p\u00e5. S\u00f8rg gerne for at der ikke er m\u00e6rker p\u00e5:-)\n\n1. lektion: Morgenb\u00e5nd med l\u00e6sning/opgaver\n\n2. lektion: \nVi laver f\u00e6lles julenisser efter en bestemt skabelon.\n\n3. - 5. lektion: \nVi julehygger med musik og kreative projekter. Vi pynter vores f\u00e6lles juletr\u00e6, og synger julesange. \n\n6. lektion:\nAfslutning og oprydning.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]},{"date":"tirsdag 29. nov.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"Omlagt uge:\n\n1. lektion\nMorgenb\u00e5nd med l\u00e6sning og opgaver.\n\n2. lektion\nVi starter p\u00e5 storylineforl\u00f8b om jul. Vi taler om nisser og danner nissefamilier i klassen.\n\n3.-5. lektion\nVi lave et juleprojekt med filt...\n\n6. lektion\nVi arbejder med en kreativ opgave om v\u00e5benskold.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]},{"date":"onsdag 30. nov.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"Omlagt uge:\n\n1. -2. lektion\nVi skal til foredrag med SOS B\u00f8rnebyerne om omvendt julekalender.\n\n3-4. lektion\nVi skriver nissehistorier om nissefamilierne.\n\n5.-6. lektion\nVi laver jule-postel\u00f8b, hvor posterne skal l\u00e6ses med en kodel\u00e6ser.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]},{"date":"torsdag 1. dec.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"Omlagt uge:\n\n1. lektion\nMorgenb\u00e5nd med l\u00e6sning og opgaver. \nVi arbejder med l\u00e6s og forst\u00e5 i en julehistorie.\n\n2.-5. lektion\nVi skal arbejde med et kreativt juleprojekt, hvor der laves huse til nisserne.\n\n6. lektion\nSe SOS b\u00f8rnebyernes julekalender og afrunding af dagen.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]},{"date":"fredag 2. dec.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"1. lektion\nMorgenb\u00e5nd med l\u00e6sning og opgaver samt julehygge, hvor vi l\u00e6ser julehistorie \n\n2. lektion:\nVi skal lave et julerim og skrive det ind p\u00e5 en flot julenisse samt tegne nissen. \n\n3.-4. lektion\nVi skal lave jule-postel\u00f8b p\u00e5 skolen. \n\n5.. lektion\nVi skal l\u00f8se et hemmeligt kodebrev ved hj\u00e6lp af en kodel\u00e6ser. \n\nVi evaluerer og afrunder ugen.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]}]},{"id":630000,"name":"Ann...","unilogin":"ann...","weekPlan":[{"date":"mandag 28. nov.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"I dag skal vi h\u00f8re om jul i Norge og lave Norsk julepynt.\nEfter 12 pausen skal vi h\u00f8re om julen i Danmark f\u00f8r juletr\u00e6et og andestegen.\nVi skal farvel\u00e6gge g\u00e5rdnisserne der passede p\u00e5 g\u00e5rdene i gamle dage.","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]},{"date":"tirsdag 29. nov.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"I dag skal vi arbejde med julen i Gr\u00f8nland og lave gr\u00f8nlandske julehuse.\nEfter 12 pausen skal vi h\u00f8re om JUletr\u00e6et der flytter ind i de danske stuer. Vi skal tale om hvor det stammer fra og hvad der var p\u00e5 juletr\u00e6et i gamle dage . Blandt andet den spiselige pynt.\nVi taler om Peters jul og at der ikke altid har v\u00e6ret en stjerne i toppen. Vi klipper storke til juletr\u00e6stoppen","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]},{"date":"onsdag 30. nov.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"I dag st\u00e5r den p\u00e5 Jul i Finland og finske juletraditioner. Vi klipper finske julestjerner.\nEfter pausen skal vi arbejde videre med jul og julepynt gennem tiden i dk. \nVi skal tale om hvorfor der er flag, trompeter og trommer p\u00e5 tr\u00e6et (krigen i 1864) og vi skal lave gammeldags silkeroser og musetrapper til tr\u00e6et","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]},{"date":"torsdag 1. dec.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"I dag skal vi p\u00e5 en juletur med hygge og posl\u00f8b til trylleskoven \nBussen k\u00f8rer os derud kl 10 og vi er senest tilbage n\u00e5r skoledagen slutter .\nHusk at f\u00e5 varmt praktisk t\u00f8j p\u00e5 og en turtaske med en let tilg\u00e6ngelig madpakke der kan spises i det fri. Regnbukser eller overtr\u00e6ksbukser s\u00e5 man kan sidde p\u00e5 jorden.","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]},{"date":"fredag 2. dec.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"Klippe/ klistre dag .\nHusk at tage lim, saks og kaffe m.m., kop og tallerkner med hjemmefra. Hvis i tager kage med er det til en buffet i klassen.","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]}]}]'
                    data = json.loads(mock_meebook, strict=False)
                else:
                    response = requests.get(
                        MEEBOOK_API + get_payload, headers=headers, verify=True
                    )
                    data = json.loads(response.text, strict=False)
                    # _LOGGER.debug("Meebook ugeplan raw response from week "+week+": "+str(response.text))

                for person in data:
                    _LOGGER.debug("Meebook ugeplan for " + person["name"])
                    ugep = ""
                    ugeplan = person["weekPlan"]
                    for day in ugeplan:
                        ugep = ugep + "<h3>" + day["date"] + "</h3>"
                        if len(day["tasks"]) > 0:
                            for task in day["tasks"]:
                                if not task["pill"] == "Ingen fag tilknyttet":
                                    ugep = ugep + "<b>" + task["pill"] + "</b><br>"
                                ugep = ugep + task["author"] + "<br><br>"
                                content = re.sub(
                                    r"([0-9]+)(\.)", r"\1\.", task["content"]
                                )
                                ugep = ugep + content + "<br><br>"
                        else:
                            ugep = ugep + "-"
                    try:
                        name = person["name"].split()[0]
                    except:
                        name = person["name"]
                    if thisnext == "this":
                        self.ugep_attr[name] = ugep
                    elif thisnext == "next":
                        self.ugepnext_attr[name] = ugep

        now = datetime.datetime.now() + datetime.timedelta(weeks=1)
        thisweek = datetime.datetime.now().strftime("%Y-W%W")
        nextweek = now.strftime("%Y-W%W")
        ugeplan(thisweek, "this")
        ugeplan(nextweek, "next")
        # _LOGGER.debug("End result of ugeplan object: "+str(self.ugep_attr))
    # End of Ugeplaner
    return True
Milfeldt commented 7 months ago

@ethante Den virker ikke hos mig... Får samme melding som den sidste Søren @scaarup lavede

ethante commented 7 months ago

@Milfeldt kan du sende mig din error log sammen med din json, så tester jeg den lige lokalt, du må selvf udskifte unilogin og sådan 🗡️

Milfeldt commented 7 months ago

HAHAHHAAA!!! Blind høne finder også korn. Sad og legede, uden at vide hvad jeg egentlig laver ved det og hvorfor ;-)

Denne virker!

import logging import requests import datetime from bs4 import BeautifulSoup import json, re from .const import ( API, API_VERSION, MIN_UDDANNELSE_API, MEEBOOK_API, SYSTEMATIC_API, EASYIQ_API, ) from homeassistant.exceptions import ConfigEntryNotReady

_LOGGER = logging.getLogger(name)

class Client: huskeliste = {} presence = {} ugep_attr = {} ugepnext_attr = {} widgets = {} tokens = {}

def __init__(self, username, password, schoolschedule, ugeplan):
    self._username = username
    self._password = password
    self._session = None
    self._schoolschedule = schoolschedule
    self._ugeplan = ugeplan

def custom_api_call(self, uri, post_data):
    csrf_token = self._session.cookies.get_dict()["Csrfp-Token"]
    headers = {"csrfp-token": csrf_token, "content-type": "application/json"}
    _LOGGER.debug("custom_api_call: Making API call to " + self.apiurl + uri)
    if post_data == 0:
        response = self._session.get(
            self.apiurl + uri, headers=headers, verify=True
        )
    else:
        try:
            # Check if post_data is valid JSON
            json.loads(post_data)
        except json.JSONDecodeError as e:
            _LOGGER.error("Invalid json supplied as post_data")
            error_msg = {"result": "Fail - invalid json supplied as post_data"}
            return error_msg
        _LOGGER.debug("custom_api_call: post_data:" + post_data)
        response = self._session.post(
            self.apiurl + uri,
            headers=headers,
            json=json.loads(post_data),
            verify=True,
        )
    _LOGGER.debug(response.text)
    try:
        res = response.json()
    except:
        res = {"raw_response": response.text}
    return res

def login(self):
    _LOGGER.debug("Logging in")
    self._session = requests.Session()
    headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/112.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "da,en-US;q=0.7,en;q=0.3",
        "DNT": "1",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "none",
        "Sec-Fetch-User": "?1",
    }
    params = {
        "type": "unilogin",
    }
    response = self._session.get(
        "https://login.aula.dk/auth/login.php",
        params=params,
        headers=headers,
        verify=True,
    )

    _html = BeautifulSoup(response.text, "lxml")
    _url = _html.form["action"]
    headers = {
        "Host": "broker.unilogin.dk",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/112.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "da,en-US;q=0.7,en;q=0.3",
        "Content-Type": "application/x-www-form-urlencoded",
        "Origin": "null",
        "DNT": "1",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Dest": "document",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-Site": "same-origin",
        "Sec-Fetch-User": "?1",
    }
    data = {
        "selectedIdp": "uni_idp",
    }
    response = self._session.post(
        _url,
        headers=headers,
        data=data,
        verify=True,
    )

    user_data = {
        "username": self._username,
        "password": self._password,
        "selected-aktoer": "KONTAKT",
    }
    redirects = 0
    success = False
    url = ""
    while success == False and redirects < 10:
        html = BeautifulSoup(response.text, "lxml")
        url = html.form["action"]

        post_data = {}
        for input in html.find_all("input"):
            if input.has_attr("name") and input.has_attr("value"):
                post_data[input["name"]] = input["value"]
                for key in user_data:
                    if input.has_attr("name") and input["name"] == key:
                        post_data[key] = user_data[key]

        response = self._session.post(url, data=post_data, verify=True)
        if response.url == "https://www.aula.dk:443/portal/":
            success = True
        redirects += 1

    # Find the API url in case of a version change
    self.apiurl = API + API_VERSION
    apiver = int(API_VERSION)
    api_success = False
    while api_success == False:
        _LOGGER.debug("Trying API at " + self.apiurl)
        ver = self._session.get(
            self.apiurl + "?method=profiles.getProfilesByLogin", verify=True
        )
        if ver.status_code == 410:
            _LOGGER.debug(
                "API was expected at "
                + self.apiurl
                + " but responded with HTTP 410. The integration will automatically try a newer version and everything may work fine."
            )
            apiver += 1
        if ver.status_code == 403:
            msg = "Access to Aula API was denied. Please check that you have entered the correct credentials. (Your password automatically expires on regular intervals!)"
            _LOGGER.error(msg)
            raise ConfigEntryNotReady(msg)
        elif ver.status_code == 200:
            self._profiles = ver.json()["data"]["profiles"]
            # _LOGGER.debug("self._profiles "+str(self._profiles))
            api_success = True
        self.apiurl = API + str(apiver)
    _LOGGER.debug("Found API on " + self.apiurl)
    #

    # ver = self._session.get(self.apiurl + "?method=profiles.getProfilesByLogin", verify=True)
    # self._profiles = ver.json()["data"]["profiles"]
    self._profilecontext = self._session.get(
        self.apiurl + "?method=profiles.getProfileContext&portalrole=guardian",
        verify=True,
    ).json()["data"]["institutionProfile"]["relations"]
    _LOGGER.debug("LOGIN: " + str(success))
    _LOGGER.debug(
        "Config - schoolschedule: "
        + str(self._schoolschedule)
        + ", config - ugeplaner: "
        + str(self._ugeplan)
    )

def get_widgets(self):
    detected_widgets = self._session.get(
        self.apiurl + "?method=profiles.getProfileContext", verify=True
    ).json()["data"]["moduleWidgetConfiguration"]["widgetConfigurations"]
    for widget in detected_widgets:
        widgetid = str(widget["widget"]["widgetId"])
        widgetname = widget["widget"]["name"]
        self.widgets[widgetid] = widgetname
    _LOGGER.debug("Widgets found: " + str(self.widgets))

def get_token(self, widgetid, mock=False):
    _LOGGER.debug("Requesting token for widget " + widgetid)
    if mock:
        return "MockToken"
    self._bearertoken = self._session.get(
        self.apiurl + "?method=aulaToken.getAulaToken&widgetId=" + widgetid,
        verify=True,
    ).json()["data"]
    token = "Bearer " + str(self._bearertoken)
    self.tokens[widgetid] = token
    return token

def update_data(self):
    is_logged_in = False
    if self._session:
        response = self._session.get(
            self.apiurl + "?method=profiles.getProfilesByLogin", verify=True
        ).json()
        is_logged_in = response["status"]["message"] == "OK"

    _LOGGER.debug("is_logged_in? " + str(is_logged_in))

    if not is_logged_in:
        self.login()

    self._childnames = {}
    self._institutions = {}
    self._childuserids = []
    self._childids = []
    self._children = []
    self._institutionProfiles = []
    self._childrenFirstNamesAndUserIDs = {}
    for profile in self._profiles:
        for child in profile["children"]:
            self._childnames[child["id"]] = child["name"]
            self._institutions[child["id"]] = child["institutionProfile"][
                "institutionName"
            ]
            self._children.append(child)
            self._childids.append(str(child["id"]))
            self._childuserids.append(str(child["userId"]))
            self._childrenFirstNamesAndUserIDs[child["userId"]] = child[
                "name"
            ].split()[0]
        for institutioncode in profile["institutionProfiles"]:
            if (
                str(institutioncode["institutionCode"])
                not in self._institutionProfiles
            ):
                self._institutionProfiles.append(
                    str(institutioncode["institutionCode"])
                )
    _LOGGER.debug("Child ids and names: " + str(self._childnames))
    _LOGGER.debug("Child ids and institution names: " + str(self._institutions))
    _LOGGER.debug("Institution codes: " + str(self._institutionProfiles))

    self._daily_overview = {}
    for i, child in enumerate(self._children):
        response = self._session.get(
            self.apiurl
            + "?method=presence.getDailyOverview&childIds[]="
            + str(child["id"]),
            verify=True,
        ).json()
        if len(response["data"]) > 0:
            self.presence[str(child["id"])] = 1
            self._daily_overview[str(child["id"])] = response["data"][0]
        else:
            _LOGGER.debug(
                "Unable to retrieve presence data from Aula from child with id "
                + str(child["id"])
                + ". Some data will be missing from sensor entities."
            )
            self.presence[str(child["id"])] = 0
    _LOGGER.debug("Child ids and presence data status: " + str(self.presence))

    # Messages:
    mesres = self._session.get(
        self.apiurl
        + "?method=messaging.getThreads&sortOn=date&orderDirection=desc&page=0",
        verify=True,
    )
    # _LOGGER.debug("mesres "+str(mesres.text))
    self.unread_messages = 0
    unread = 0
    self.message = {}
    for mes in mesres.json()["data"]["threads"]:
        if not mes["read"]:
            # self.unread_messages = 1
            unread = 1
            threadid = mes["id"]
            break
    # if self.unread_messages == 1:
    if unread == 1:
        # _LOGGER.debug("tid "+str(threadid))
        threadres = self._session.get(
            self.apiurl
            + "?method=messaging.getMessagesForThread&threadId="
            + str(threadid)
            + "&page=0",
            verify=True,
        )
        # _LOGGER.debug("threadres "+str(threadres.text))
        if threadres.json()["status"]["code"] == 403:
            self.message["text"] = (
                "Log ind på Aula med MitID for at læse denne besked."
            )
            self.message["sender"] = "Ukendt afsender"
            self.message["subject"] = "Følsom besked"
        else:
            for message in threadres.json()["data"]["messages"]:
                if message["messageType"] == "Message":
                    try:
                        self.message["text"] = message["text"]["html"]
                    except:
                        try:
                            self.message["text"] = message["text"]
                        except:
                            self.message["text"] = "intet indhold..."
                            _LOGGER.warning(
                                "There is an unread message, but we cannot get the text."
                            )
                    try:
                        self.message["sender"] = message["sender"]["fullName"]
                    except:
                        self.message["sender"] = "Ukendt afsender"
                    try:
                        self.message["subject"] = threadres.json()["data"][
                            "subject"
                        ]
                    except:
                        self.message["subject"] = ""
                    self.unread_messages = 1
                    break

    # Calendar:
    if self._schoolschedule == True:
        instProfileIds = ",".join(self._childids)
        csrf_token = self._session.cookies.get_dict()["Csrfp-Token"]
        headers = {"csrfp-token": csrf_token, "content-type": "application/json"}
        start = datetime.datetime.now(datetime.timezone.utc).strftime(
            "%Y-%m-%d 00:00:00.0000%z"
        )
        _end = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(
            days=14
        )
        end = _end.strftime("%Y-%m-%d 00:00:00.0000%z")
        post_data = (
            '{"instProfileIds":['
            + instProfileIds
            + '],"resourceIds":[],"start":"'
            + start
            + '","end":"'
            + end
            + '"}'
        )
        _LOGGER.debug("Fetching calendars...")
        # _LOGGER.debug("Calendar post-data: "+str(post_data))
        res = self._session.post(
            self.apiurl + "?method=calendar.getEventsByProfileIdsAndResourceIds",
            data=post_data,
            headers=headers,
            verify=True,
        )
        try:
            with open("skoleskema.json", "w") as skoleskema_json:
                json.dump(res.text, skoleskema_json)
        except:
            _LOGGER.warn(
                "Got the following reply when trying to fetch calendars: "
                + str(res.text)
            )
    # End of calendar

    # Ugeplaner:
    if self._ugeplan == True:
        guardian = self._session.get(
            self.apiurl + "?method=profiles.getProfileContext&portalrole=guardian",
            verify=True,
        ).json()["data"]["userId"]
        childUserIds = ",".join(self._childuserids)

        if len(self.widgets) == 0:
            self.get_widgets()
        if (
            not "0029" in self.widgets
            and not "0004" in self.widgets
            and not "0062" in self.widgets
            and not "0030" in self.widgets
            and not "0001" in self.widgets
        ):
            _LOGGER.error(
                "You have enabled ugeplaner, but we cannot find any supported widgets (0029,0004,0030,0001) in Aula."
            )
        if "0029" in self.widgets and "0004" in self.widgets:
            _LOGGER.warning(
                "Multiple sources for ugeplaner is untested and might cause problems."
            )

        def ugeplan(week, thisnext):
            if "0029" in self.widgets and "0030" not in self.widgets:
                from datetime import datetime
                token = self.get_token("0029")
                get_payload = (
                    "/ugebrev?assuranceLevel=2&childFilter="
                    + childUserIds
                    + "&currentWeekNumber="
                    + week
                    + "&isMobileApp=false&placement=narrow&sessionUUID="
                    + guardian
                    + "&userProfile=guardian"
                )
                ugeplaner = requests.get(
                    MIN_UDDANNELSE_API + get_payload,
                    headers={"Authorization": token, "accept": "application/json"},
                    verify=True,
                )
                # _LOGGER.debug("ugeplaner status_code "+str(ugeplaner.status_code))
                # _LOGGER.debug("ugeplaner response "+str(ugeplaner.text))
                for person in ugeplaner.json()["personer"]:
                    ugeplan = person["institutioner"][0]["ugebreve"][0]["indhold"]
                    if thisnext == "this":
                        self.ugep_attr[person["navn"].split()[0]] = ugeplan
                    elif thisnext == "next":
                        self.ugepnext_attr[person["navn"].split()[0]] = ugeplan

            if "0030" in self.widgets:
                _LOGGER.debug("In the MU Opgaver flow")
                token = self.get_token("0030")
                get_payload = (
                    "/opgaveliste?assuranceLevel=2&childFilter="
                    + childUserIds
                    + "&currentWeekNumber="
                    + week
                    + "&isMobileApp=false&placement=narrow&sessionUUID="
                    + guardian
                    + "&userProfile=guardian"
                )
                ugeplaner = requests.get(
                    MIN_UDDANNELSE_API + get_payload,
                    headers={"Authorization": token, "accept": "application/json"},
                    verify=True,
                )
                _LOGGER.debug(
                    "MU Opgaver status_code " + str(ugeplaner.status_code)
                )
                _LOGGER.debug("MU Opgaver response " + str(ugeplaner.text))
                for full_name in self._childnames.items():
                    name_parts = full_name.split()
                    first_name = name_parts[0]
                    _ugep = ""
                    for i in ugeplaner.json()["opgaver"]:
                        _LOGGER.debug(
                            "i kuvertnavn split " + str(i["kuvertnavn"].split()[0])
                        )
                        _LOGGER.debug("first_name " + first_name)
                        if i["kuvertnavn"].split()[0] == first_name:
                            _ugep = _ugep + "<h2>" + i["title"] + "</h2>"
                            _ugep = _ugep + "<h3>" + i["kuvertnavn"] + "</h3>"
                            _ugep = _ugep + "Ugedag: " + i["ugedag"] + "<br>"
                            _ugep = _ugep + "Type: " + i["opgaveType"] + "<br>"
                            for h in i["hold"]:
                                _ugep = _ugep + "Hold: " + h["navn"] + "<br>"
                            try:
                                _ugep = _ugep + "Forløb: " + i["forloeb"]["navn"]
                            except:
                                _LOGGER.debug("Did not find forloeb key: " + str(i))
                    if thisnext == "this":
                        self.ugep_attr[first_name] = _ugep
                    elif thisnext == "next":
                        self.ugepnext_attr[first_name] = _ugep
                    _LOGGER.debug("MU Opgaver result: " + str(_ugep))

            # EasyIQ:
            if "0001" in self.widgets:
                _LOGGER.debug("In the EasyIQ flow")
                token = self.get_token("0001")
                csrf_token = self._session.cookies.get_dict()["Csrfp-Token"]

                easyiq_headers = {
                    "x-aula-institutionfilter": str(self._institutionProfiles[0]),
                    "x-aula-userprofile": "guardian",
                    "Authorization": token,
                    "accept": "application/json",
                    "csrfp-token": csrf_token,
                    "origin": "https://www.aula.dk",
                    "referer": "https://www.aula.dk/",
                    "authority": "api.easyiqcloud.dk"
                }

                for child in self._childrenFirstNamesAndUserIDs.items():
                    userid = child[0]
                    first_name = child[1]

                    _LOGGER.debug("EasyIQ headers " + str(easyiq_headers))
                    post_data = {
                        "sessionId": guardian,
                        "currentWeekNr": week,
                        "userProfile": "guardian",
                        "institutionFilter": self._institutionProfiles,
                        "childFilter": [userid]
                    }
                    _LOGGER.debug("EasyIQ post data " + str(post_data))
                    ugeplaner = requests.post(
                        EASYIQ_API + "/weekplaninfo",
                        json=post_data,
                        headers=easyiq_headers,
                        verify=True,
                    )
                    #_LOGGER.debug(
                        #    "EasyIQ Opgaver status_code " + str(ugeplaner.status_code)
                    #)
                    _LOGGER.debug(
                        "EasyIQ Opgaver response " + str(ugeplaner.json())
                    )
                    _ugep = (
                        "<h2>"
                        # + ugeplaner.json()["Weekplan"]["ActivityName"]
                        + " Uge "
                        # + ugeplaner.json()["Weekplan"]["WeekNo"]
                        + "</h2>"
                    )
                    from datetime import datetime

                    def is_correct_format(date_string, format):
                        try:
                            datetime.strptime(date_string, format)
                            return True
                        except ValueError:
                            return False

                    for i in ugeplaner.json()["Events"]:
                        if is_correct_format(i["start"], "%Y/%m/%d %H:%M"):
                            _LOGGER.debug("No Event")
                            start_datetime = datetime.strptime(i["start"], "%Y/%m/%d %H:%M")
                            _LOGGER.debug(start_datetime)
                            end_datetime = datetime.strptime(i["end"], "%Y/%m/%d %H:%M")
                            if start_datetime.date() == end_datetime.date():
                                formatted_start = start_datetime.strftime("%A %H:%M")
                                formatted_end = end_datetime.strftime("- %H:%M")
                                dresult = f"{formatted_start} {formatted_end}"
                            else:
                                formatted_start = start_datetime.strftime("%A")
                                formatted_end = end_datetime.strftime("- %A")
                                dresult = f"{formatted_start} {formatted_end}"
                            _ugep = _ugep + "<b>" + dresult + "</b><br>"
                            if i["itemType"] == "5":
                                _ugep = _ugep + "<br><b>" + str(i["title"]) + "</b><br>"
                            else:
                                _ugep = (
                                _ugep + "<b>" + str(i["ownername"]) + "</b><br>"
                                )

                        _ugep = _ugep + str(i["description"]) + "<br>"

                    if thisnext == "this":
                        self.ugep_attr[first_name] = _ugep
                    elif thisnext == "next":
                        self.ugepnext_attr[first_name] = _ugep
                    _LOGGER.debug("EasyIQ result: " + str(_ugep))

            if "0062" in self.widgets:
                _LOGGER.debug("In the Huskelisten flow...")
                token = self.get_token("0062", False)
                huskelisten_headers = {
                    "Accept": "application/json, text/plain, */*",
                    "Accept-Encoding": "gzip, deflate, br",
                    "Accept-Language": "en-US,en;q=0.9,da;q=0.8",
                    "Aula-Authorization": token,
                    "Origin": "https://www.aula.dk",
                    "Referer": "https://www.aula.dk/",
                    "Sec-Fetch-Dest": "empty",
                    "Sec-Fetch-Mode": "cors",
                    "Sec-Fetch-Site": "cross-site",
                    "User-Agent": "Mozilla/5.0 (X11; CrOS x86_64 15183.51.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
                    "zone": "Europe/Copenhagen",
                }

                children = "&children=".join(self._childuserids)
                institutions = "&institutions=".join(self._institutionProfiles)
                timedelta = datetime.datetime.now() + datetime.timedelta(days=180)
                From = datetime.datetime.now().strftime("%Y-%m-%d")
                dueNoLaterThan = timedelta.strftime("%Y-%m-%d")
                get_payload = (
                    "/reminders/v1?children="
                    + children
                    + "&from="
                    + From
                    + "&dueNoLaterThan="
                    + dueNoLaterThan
                    + "&widgetVersion=1.10&userProfile=guardian&sessionId="
                    + self._username
                    + "&institutions="
                    + institutions
                )
                _LOGGER.debug(
                    "Huskelisten get_payload: " + SYSTEMATIC_API + get_payload
                )
                #
                mock_huskelisten = 0
                #
                if mock_huskelisten == 1:
                    _LOGGER.warning("Using mock data for Huskelisten.")
                    mock_huskelisten = '[{"userName":"Emilie efternavn","userId":164625,"courseReminders":[],"assignmentReminders":[],"teamReminders":[{"id":76169,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-11-29T23:00:00Z","teamId":65240,"teamName":"2A","reminderText":"Onsdagslektie: Matematikfessor.dk: Sænk skibet med plus.","createdBy":"Peter ","lastEditBy":"Peter ","subjectName":"Matematik"},{"id":76598,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-12-06T23:00:00Z","teamId":65240,"teamName":"2A","reminderText":"Julekalender på Skoledu.dk: I skal forsøge at løse dagens kalenderopgave. opgaven kan også godt løses dagen efter.","createdBy":"Peter ","lastEditBy":"Peter Riis","subjectName":"Matematik"},{"id":76599,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-12-13T23:00:00Z","teamId":65240,"teamName":"2A","reminderText":"Julekalender på Skoledu.dk: I skal forsøge at løse dagens kalenderopgave. opgaven kan også godt løses dagen efter.","createdBy":"Peter ","lastEditBy":"Peter ","subjectName":"Matematik"},{"id":76600,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-12-20T23:00:00Z","teamId":65240,"teamName":"2A","reminderText":"Julekalender på Skoledu.dk: I skal forsøge at løse dagens kalenderopgave. opgaven kan også godt løses dagen efter.","createdBy":"Peter Riis","lastEditBy":"Peter Riis","subjectName":"Matematik"}]},{"userName":"Karla","userId":77882,"courseReminders":[],"assignmentReminders":[{"id":0,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-12-08T11:00:00Z","courseId":297469,"teamNames":["5A","5B"],"teamIds":[65271,65258],"courseSubjects":[],"assignmentId":5027904,"assignmentText":"Skriv en novelle"}],"teamReminders":[{"id":76367,"institutionName":"Holme Skole","institutionId":183,"dueDate":"2022-11-30T23:00:00Z","teamId":65258,"teamName":"5A","reminderText":"Læse resten af kap.1 fra Ternet Ninja ( kopiark) Læs det hele højt eller vælg et afsnit. ","createdBy":"Christina ","lastEditBy":"Christina ","subjectName":"Dansk"}]},{"userName":"Vega  ","userId":206597,"courseReminders":[],"assignmentReminders":[],"teamReminders":[]}]'
                    data = json.loads(mock_huskelisten, strict=False)
                else:
                    response = requests.get(
                        SYSTEMATIC_API + get_payload,
                        headers=huskelisten_headers,
                        verify=True,
                    )
                    try:
                        data = json.loads(response.text, strict=False)
                    except:
                        _LOGGER.error(
                            "Could not parse the response from Huskelisten as json."
                        )
                    # _LOGGER.debug("Huskelisten raw response: "+str(response.text))

                for person in data:
                    name = person["userName"].split()[0]
                    _LOGGER.debug("Huskelisten for " + name)
                    huskel = ""
                    reminders = person["teamReminders"]
                    if len(reminders) > 0:
                        for reminder in reminders:
                            mytime = datetime.datetime.strptime(
                                reminder["dueDate"], "%Y-%m-%dT%H:%M:%SZ"
                            )
                            ftime = mytime.strftime("%A %d. %B")
                            huskel = huskel + "<h3>" + ftime + "</h3>"
                            huskel = (
                                huskel
                                + "<b>"
                                + reminder["subjectName"]
                                + "</b><br>"
                            )
                            huskel = (
                                huskel + "af " + reminder["createdBy"] + "<br><br>"
                            )
                            content = re.sub(
                                r"([0-9]+)(\.)", r"\1\.", reminder["reminderText"]
                            )
                            huskel = huskel + content + "<br><br>"
                    else:
                        huskel = huskel + str(name) + " har ingen påmindelser."
                    self.huskeliste[name] = huskel

            # End Huskelisten
            if "0004" in self.widgets:
                # Try Meebook:
                _LOGGER.debug("In the Meebook flow...")
                token = self.get_token("0004")
                # _LOGGER.debug("Token "+token)
                headers = {
                    "authority": "app.meebook.com",
                    "accept": "application/json",
                    "authorization": token,
                    "dnt": "1",
                    "origin": "https://www.aula.dk",
                    "referer": "https://www.aula.dk/",
                    "sessionuuid": self._username,
                    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
                    "x-version": "1.0",
                }
                childFilter = "&childFilter[]=".join(self._childuserids)
                institutionFilter = "&institutionFilter[]=".join(
                    self._institutionProfiles
                )
                get_payload = (
                    "/relatedweekplan/all?currentWeekNumber="
                    + week
                    + "&userProfile=guardian&childFilter[]="
                    + childFilter
                    + "&institutionFilter[]="
                    + institutionFilter
                )

                mock_meebook = 0
                if mock_meebook == 1:
                    _LOGGER.warning("Using mock data for Meebook ugeplaner.")
                    mock_meebook = '[{"id":490000,"name":"Emilie efternavn","unilogin":"lud...","weekPlan":[{"date":"mandag 28. nov.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"I denne uge er der omlagt uge p\u00e5 hele skolen.\n\nMandag har vi \nKlippeklistredag:\n\nMan m\u00e5 gerne have nissehuer p\u00e5 :)\n\nMedbring gerne en god saks, limstift, skabeloner mm. \n\nB\u00f8rnene skal ogs\u00e5 medbringe et vasket syltet\u00f8jsglas eller lign., som vi skal male p\u00e5. S\u00f8rg gerne for at der ikke er m\u00e6rker p\u00e5:-)\n\n1. lektion: Morgenb\u00e5nd med l\u00e6sning/opgaver\n\n2. lektion: \nVi laver f\u00e6lles julenisser efter en bestemt skabelon.\n\n3. - 5. lektion: \nVi julehygger med musik og kreative projekter. Vi pynter vores f\u00e6lles juletr\u00e6, og synger julesange. \n\n6. lektion:\nAfslutning og oprydning.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]},{"date":"tirsdag 29. nov.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"Omlagt uge:\n\n1. lektion\nMorgenb\u00e5nd med l\u00e6sning og opgaver.\n\n2. lektion\nVi starter p\u00e5 storylineforl\u00f8b om jul. Vi taler om nisser og danner nissefamilier i klassen.\n\n3.-5. lektion\nVi lave et juleprojekt med filt...\n\n6. lektion\nVi arbejder med en kreativ opgave om v\u00e5benskold.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]},{"date":"onsdag 30. nov.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"Omlagt uge:\n\n1. -2. lektion\nVi skal til foredrag med SOS B\u00f8rnebyerne om omvendt julekalender.\n\n3-4. lektion\nVi skriver nissehistorier om nissefamilierne.\n\n5.-6. lektion\nVi laver jule-postel\u00f8b, hvor posterne skal l\u00e6ses med en kodel\u00e6ser.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]},{"date":"torsdag 1. dec.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"Omlagt uge:\n\n1. lektion\nMorgenb\u00e5nd med l\u00e6sning og opgaver. \nVi arbejder med l\u00e6s og forst\u00e5 i en julehistorie.\n\n2.-5. lektion\nVi skal arbejde med et kreativt juleprojekt, hvor der laves huse til nisserne.\n\n6. lektion\nSe SOS b\u00f8rnebyernes julekalender og afrunding af dagen.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]},{"date":"fredag 2. dec.","tasks":[{"id":3069630,"type":"comment","author":"Met...","group":"3.a - ugeplan","pill":"Ingen fag tilknyttet","content":"1. lektion\nMorgenb\u00e5nd med l\u00e6sning og opgaver samt julehygge, hvor vi l\u00e6ser julehistorie \n\n2. lektion:\nVi skal lave et julerim og skrive det ind p\u00e5 en flot julenisse samt tegne nissen. \n\n3.-4. lektion\nVi skal lave jule-postel\u00f8b p\u00e5 skolen. \n\n5.. lektion\nVi skal l\u00f8se et hemmeligt kodebrev ved hj\u00e6lp af en kodel\u00e6ser. \n\nVi evaluerer og afrunder ugen.","editUrl":"https://app.meebook.com//arsplaner/dlap//956783//202248"}]}]},{"id":630000,"name":"Ann...","unilogin":"ann...","weekPlan":[{"date":"mandag 28. nov.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"I dag skal vi h\u00f8re om jul i Norge og lave Norsk julepynt.\nEfter 12 pausen skal vi h\u00f8re om julen i Danmark f\u00f8r juletr\u00e6et og andestegen.\nVi skal farvel\u00e6gge g\u00e5rdnisserne der passede p\u00e5 g\u00e5rdene i gamle dage.","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]},{"date":"tirsdag 29. nov.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"I dag skal vi arbejde med julen i Gr\u00f8nland og lave gr\u00f8nlandske julehuse.\nEfter 12 pausen skal vi h\u00f8re om JUletr\u00e6et der flytter ind i de danske stuer. Vi skal tale om hvor det stammer fra og hvad der var p\u00e5 juletr\u00e6et i gamle dage . Blandt andet den spiselige pynt.\nVi taler om Peters jul og at der ikke altid har v\u00e6ret en stjerne i toppen. Vi klipper storke til juletr\u00e6stoppen","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]},{"date":"onsdag 30. nov.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"I dag st\u00e5r den p\u00e5 Jul i Finland og finske juletraditioner. Vi klipper finske julestjerner.\nEfter pausen skal vi arbejde videre med jul og julepynt gennem tiden i dk. \nVi skal tale om hvorfor der er flag, trompeter og trommer p\u00e5 tr\u00e6et (krigen i 1864) og vi skal lave gammeldags silkeroser og musetrapper til tr\u00e6et","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]},{"date":"torsdag 1. dec.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"I dag skal vi p\u00e5 en juletur med hygge og posl\u00f8b til trylleskoven \nBussen k\u00f8rer os derud kl 10 og vi er senest tilbage n\u00e5r skoledagen slutter .\nHusk at f\u00e5 varmt praktisk t\u00f8j p\u00e5 og en turtaske med en let tilg\u00e6ngelig madpakke der kan spises i det fri. Regnbukser eller overtr\u00e6ksbukser s\u00e5 man kan sidde p\u00e5 jorden.","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]},{"date":"fredag 2. dec.","tasks":[{"id":3090189,"type":"comment","author":"May...","group":"0C (22/23)","pill":"B\u00f8rnehaveklasse, B\u00f8rnehaveklassen, Dansk, Matematik","content":"Klippe/ klistre dag .\nHusk at tage lim, saks og kaffe m.m., kop og tallerkner med hjemmefra. Hvis i tager kage med er det til en buffet i klassen.","editUrl":"https://app.meebook.com//arsplaner/dlap//899210//202248"}]}]}]'
                    data = json.loads(mock_meebook, strict=False)
                else:
                    response = requests.get(
                        MEEBOOK_API + get_payload, headers=headers, verify=True
                    )
                    data = json.loads(response.text, strict=False)
                    # _LOGGER.debug("Meebook ugeplan raw response from week "+week+": "+str(response.text))

                for person in data:
                    _LOGGER.debug("Meebook ugeplan for " + person["name"])
                    ugep = ""
                    ugeplan = person["weekPlan"]
                    for day in ugeplan:
                        ugep = ugep + "<h3>" + day["date"] + "</h3>"
                        if len(day["tasks"]) > 0:
                            for task in day["tasks"]:
                                if not task["pill"] == "Ingen fag tilknyttet":
                                    ugep = ugep + "<b>" + task["pill"] + "</b><br>"
                                ugep = ugep + task["author"] + "<br><br>"
                                content = re.sub(
                                    r"([0-9]+)(\.)", r"\1\.", task["content"]
                                )
                                ugep = ugep + content + "<br><br>"
                        else:
                            ugep = ugep + "-"
                    try:
                        name = person["name"].split()[0]
                    except:
                        name = person["name"]
                    if thisnext == "this":
                        self.ugep_attr[name] = ugep
                    elif thisnext == "next":
                        self.ugepnext_attr[name] = ugep

        now = datetime.datetime.now() + datetime.timedelta(weeks=1)
        thisweek = datetime.datetime.now().strftime("%Y-W%W")
        nextweek = now.strftime("%Y-W%W")
        ugeplan(thisweek, "this")
        ugeplan(nextweek, "next")
        # _LOGGER.debug("End result of ugeplan object: "+str(self.ugep_attr))
    # End of Ugeplaner
    return True
ethante commented 7 months ago

hvad ændrede du i forhold til den jeg lagde op?

ethante commented 7 months ago

@Milfeldt okay, lavede lige en test for at se om der var forskel, de er identiske :D men dejligt det også køre for din nu, jeg ændrede bare week til at være noget konstant, for at teste med data der var noget i, derefter ændrede jeg det bare tilbage igen

ethante commented 7 months ago

Det eneste der kunne være fedt nu, skulle da lige være at ville være ændret til dansk i mandag til søndag :D

Milfeldt commented 7 months ago

@ethante jeg kommer den i pastebin, der sker noget underligt når vi paster den i <> https://pastebin.com/n9MhvyVb Jeg har din og den redigerede udgave af din i compare i VSC, der er de ikke ens. Jeg fjernede nogle kommaer, linieskift og en else - logger linie og lidt mere, uden at vide hvorfor, intuition efter at have leget meget med Marlin?

Milfeldt commented 7 months ago

@ethante

Jeg kører HA på engelsk, så det havde jeg ikke opdaget :-)

ethante commented 7 months ago

@scaarup kan du tage min kode, og ændre det til dansk afhængig af system valgt sprog? :P would be awesome

Milfeldt commented 7 months ago

endelig

scaarup commented 6 months ago

@scaarup kan du tage min kode, og ændre det til dansk afhængig af system valgt sprog? :P would be awesome

Kan I give mig det kode jeg skal bruge? Det må være fra linjen, der starter med if "0001" in self.widgets: til if'en er slut.

Milfeldt commented 6 months ago

@scaarup Jeg er ikke sikker på ... men værsgod.

` # EasyIQ: if "0001" in self.widgets: _LOGGER.debug("In the EasyIQ flow") token = self.get_token("0001") csrf_token = self._session.cookies.get_dict()["Csrfp-Token"]

                easyiq_headers = {
                    "x-aula-institutionfilter": str(self._institutionProfiles[0]),
                    "x-aula-userprofile": "guardian",
                    "Authorization": token,
                    "accept": "application/json",
                    "csrfp-token": csrf_token,
                    "origin": "https://www.aula.dk",
                    "referer": "https://www.aula.dk/",
                    "authority": "api.easyiqcloud.dk"
                }

                for child in self._childrenFirstNamesAndUserIDs.items():
                    userid = child[0]
                    first_name = child[1]

                    _LOGGER.debug("EasyIQ headers " + str(easyiq_headers))
                    post_data = {
                        "sessionId": guardian,
                        "currentWeekNr": week,
                        "userProfile": "guardian",
                        "institutionFilter": self._institutionProfiles,
                        "childFilter": [userid]
                    }
                    _LOGGER.debug("EasyIQ post data " + str(post_data))
                    ugeplaner = requests.post(
                        EASYIQ_API + "/weekplaninfo",
                        json=post_data,
                        headers=easyiq_headers,
                        verify=True,
                    )
                    #_LOGGER.debug(
                        #    "EasyIQ Opgaver status_code " + str(ugeplaner.status_code)
                    #)
                    _LOGGER.debug(
                        "EasyIQ Opgaver response " + str(ugeplaner.json())
                    )
                    _ugep = (
                        "<h2>"
                        # + ugeplaner.json()["Weekplan"]["ActivityName"]
                        + " Uge "
                        # + ugeplaner.json()["Weekplan"]["WeekNo"]
                        + "</h2>"
                    )
                    from datetime import datetime

                    def is_correct_format(date_string, format):
                        try:
                            datetime.strptime(date_string, format)
                            return True
                        except ValueError:
                            return False

                    for i in ugeplaner.json()["Events"]:
                        if is_correct_format(i["start"], "%Y/%m/%d %H:%M"):
                            _LOGGER.debug("No Event")
                            start_datetime = datetime.strptime(i["start"], "%Y/%m/%d %H:%M")
                            _LOGGER.debug(start_datetime)
                            end_datetime = datetime.strptime(i["end"], "%Y/%m/%d %H:%M")
                            if start_datetime.date() == end_datetime.date():
                                formatted_start = start_datetime.strftime("%A %H:%M")
                                formatted_end = end_datetime.strftime("- %H:%M")
                                dresult = f"{formatted_start} {formatted_end}"
                            else:
                                formatted_start = start_datetime.strftime("%A")
                                formatted_end = end_datetime.strftime("- %A")
                                dresult = f"{formatted_start} {formatted_end}"
                            _ugep = _ugep + "<b>" + dresult + "</b><br>"
                            if i["itemType"] == "5":
                                _ugep = _ugep + "<br><b>" + str(i["title"]) + "</b><br>"
                            else:
                                _ugep = (
                                _ugep + "<b>" + str(i["ownername"]) + "</b><br>"
                                )

                        _ugep = _ugep + str(i["description"]) + "<br>"

                    if thisnext == "this":
                        self.ugep_attr[first_name] = _ugep
                    elif thisnext == "next":
                        self.ugepnext_attr[first_name] = _ugep
                    _LOGGER.debug("EasyIQ result: " + str(_ugep))`
Milfeldt commented 6 months ago
            # EasyIQ:
            if "0001" in self.widgets:
                _LOGGER.debug("In the EasyIQ flow")
                token = self.get_token("0001")
                csrf_token = self._session.cookies.get_dict()["Csrfp-Token"]

                easyiq_headers = {
                    "x-aula-institutionfilter": str(self._institutionProfiles[0]),
                    "x-aula-userprofile": "guardian",
                    "Authorization": token,
                    "accept": "application/json",
                    "csrfp-token": csrf_token,
                    "origin": "https://www.aula.dk",
                    "referer": "https://www.aula.dk/",
                    "authority": "api.easyiqcloud.dk"
                }

                for child in self._childrenFirstNamesAndUserIDs.items():
                    userid = child[0]
                    first_name = child[1]

                    _LOGGER.debug("EasyIQ headers " + str(easyiq_headers))
                    post_data = {
                        "sessionId": guardian,
                        "currentWeekNr": week,
                        "userProfile": "guardian",
                        "institutionFilter": self._institutionProfiles,
                        "childFilter": [userid]
                    }
                    _LOGGER.debug("EasyIQ post data " + str(post_data))
                    ugeplaner = requests.post(
                        EASYIQ_API + "/weekplaninfo",
                        json=post_data,
                        headers=easyiq_headers,
                        verify=True,
                    )
                    #_LOGGER.debug(
                        #    "EasyIQ Opgaver status_code " + str(ugeplaner.status_code)
                    #)
                    _LOGGER.debug(
                        "EasyIQ Opgaver response " + str(ugeplaner.json())
                    )
                    _ugep = (
                        "<h2>"
                        # + ugeplaner.json()["Weekplan"]["ActivityName"]
                        + " Uge "
                        # + ugeplaner.json()["Weekplan"]["WeekNo"]
                        + "</h2>"
                    )
                    from datetime import datetime

                    def is_correct_format(date_string, format):
                        try:
                            datetime.strptime(date_string, format)
                            return True
                        except ValueError:
                            return False

                    for i in ugeplaner.json()["Events"]:
                        if is_correct_format(i["start"], "%Y/%m/%d %H:%M"):
                            _LOGGER.debug("No Event")
                            start_datetime = datetime.strptime(i["start"], "%Y/%m/%d %H:%M")
                            _LOGGER.debug(start_datetime)
                            end_datetime = datetime.strptime(i["end"], "%Y/%m/%d %H:%M")
                            if start_datetime.date() == end_datetime.date():
                                formatted_start = start_datetime.strftime("%A %H:%M")
                                formatted_end = end_datetime.strftime("- %H:%M")
                                dresult = f"{formatted_start} {formatted_end}"
                            else:
                                formatted_start = start_datetime.strftime("%A")
                                formatted_end = end_datetime.strftime("- %A")
                                dresult = f"{formatted_start} {formatted_end}"
                            _ugep = _ugep + "<b>" + dresult + "</b><br>"
                            if i["itemType"] == "5":
                                _ugep = _ugep + "<br><b>" + str(i["title"]) + "</b><br>"
                            else:
                                _ugep = (
                                _ugep + "<b>" + str(i["ownername"]) + "</b><br>"
                                )

                        _ugep = _ugep + str(i["description"]) + "<br>"

                    if thisnext == "this":
                        self.ugep_attr[first_name] = _ugep
                    elif thisnext == "next":
                        self.ugepnext_attr[first_name] = _ugep
                    _LOGGER.debug("EasyIQ result: " + str(_ugep))
Milfeldt commented 6 months ago

@scaarup @ethante Jeg lagde lige mærke til, at i ugeplan står der ikke ugetal på, hvis dato også kunne komme på, ville det være godt, det har mine unger lettere ved og oftest bedre styr på end jeg ;-)

ethante commented 6 months ago

@scaarup her for du min kode

https://codefile.io/f/rIurOZs3gb

ethante commented 6 months ago

Jeg kan godt se på det med dato samt uge nummer, men det bliver ikke lige i dag tænker jeg

scaarup commented 6 months ago

Jeg har prøvet at merge jeres kode ind, samt smide ugenr som en overskrift. Der er en update på branch'en. Ift. at oversætte fx ugedage. Så lader det ikke til at være muligt, at oversætte disse vha. HA's translate system. Men det graver jeg lige lidt videre i.

ethante commented 6 months ago

Jeg kommer med en lille ændring i det, da den fejlede på linje: 508

ændrede fra: week.split("-W")

til : week.split("-W")[1]

for at tage den sidste i listen. ellers virker det fint, har også testet med

import locale locale.setlocale(locale.LC_ALL, 'da_DK.UTF-8')

via python selv, virker det som det skal, men ikke i HA

Milfeldt commented 6 months ago

yay! Det kører, jeg var også kommet frem til linie (jeg NÆGTER at skrive linje) 508, så jeg har siddet og leget (fordi jeg ikke kan 'sproget') med udelukkelsesmetoden med din @scaarup kode og min, flyttet og slettet og sammenlignet, genstartet o.s.v. Jeg skulle have tjekket min mail for en time siden @ethante ;-) ... Godt gået og tak til jer.

ethante commented 6 months ago

@scaarup @Milfeldt jeg har lavet en lille tilføjelse mere, rent hacks :P bare for at få det på dansk, but it works

jeg har tilføjet:

import calendar

derefter jeg har tilføjet en metode:

`def findDay(date): day, month, year = (int(i) for i in date.split(' '))
dayNumber = calendar.weekday(year, month, day)

days = [ "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"]

return days[dayNumber]`

som retunere dagen

som jeg så bruger i for loop:

    if start_datetime.date() == end_datetime.date():
        formatted_day = findDay(start_datetime.strftime("%d %m %Y"))
        formatted_start = start_datetime.strftime(" %H:%M")
        formatted_end = end_datetime.strftime("- %H:%M")
        dresult = f"{formatted_day} {formatted_start} {formatted_end}"
    else:
        formatted_start = findDay(start_datetime.strftime("%d %m %Y"))
        formatted_end = findDay(end_datetime.strftime("%d %m %Y"))
        dresult = f"{formatted_start} - {formatted_end}"

alt kan ses her https://paste.ofcode.org/34HByeuR2nhKrUtUyjeMUYT

husk jeg har ændret week i post call til statisk, så jeg har data til at teste med:

image

Milfeldt commented 6 months ago

@ethante Fungerer også her :-) Efter jeg ændrede linie 487 fra "2024-w06" til week ;-)

scaarup commented 6 months ago

Jeg ville nok have løst det lidt anderledes, måske med en dictionary hvori man kunne slå et ugedag-nummer op til et navn:

                    weekday_names = {
                        0: "Mandag",
                        1: "Tirsdag",
                        2: "Onsdag",
                        3: "Torsdag",
                        4: "Fredag",
                        5: "Lørdag",
                        6: "Søndag",
                    }
                    weekday_number = datetime.datetime.now().weekday()
                    weekday_name = weekday_names.get(weekday_number, "Invalid weekday")

Men jeres ændringer er efterhånden lidt for uoverskuelige at "merge" ind i det jeg sidder og arbejder på :).

Jeg har kopieret hele blokken med "if "0001" in self.widgets:" fra https://paste.ofcode.org/34HByeuR2nhKrUtUyjeMUYT ind i branchen. Eneste ændring burde være, at "import calendar" sker inde i blokken. I kan jo lige teste om det virker.

Milfeldt commented 6 months ago

@scaarup Afprøvet og fundet i orden :-)

scaarup commented 6 months ago

@ethante @Milfeldt , hvis ikke der er indvendinger, så ryger det i næste release.

Milfeldt commented 6 months ago

Bare husk at rette linie 499 fra "2024-W06" til week ;-)

scaarup commented 6 months ago

Bare husk at rette linie 499 fra "2024-W06" til week ;-)

Tak - god pointe :)

Milfeldt commented 6 months ago

@scaarup @ethante Ugeplan er 'Not avaliable' lagde først mærke til det i går, efter sidste AULA opdatering...

diskoclaus commented 5 months ago

Jeg har siddet og undret mig lidt. I nogle få dage havde jeg ugeplanen via EasyIQ inde under hver af børens sensor. Nu står der bare

Ugeplan Not available Ugeplan next Not available

Når jeg kigger i koden, kommer jeg aldrig ind i dette loop hvor jeg forventer den burde hente informationerne:

                for child in self._childrenFirstNamesAndUserIDs.items():
                    userid = child[0]
                    first_name = child[1]

Jeg udskrev lidt mere i loggen så nu ser den sådan ud:

            _
 /\        | |
/  \  _   _| | __ _

/ /\ | | | | |/ ` | / ____ \ || | | (| | // __,||_,_| Aula integration, version: 0.1.38 This is a custom integration If you have any issues with this you need to open an issue here: https://github.com/scaarup/aula/issues

2024-04-06 10:28:29.380 DEBUG (SyncWorker_11) [custom_components.aula.client] is_logged_in? False 2024-04-06 10:28:29.380 DEBUG (SyncWorker_11) [custom_components.aula.client] Logging in 2024-04-06 10:28:31.244 DEBUG (SyncWorker_11) [custom_components.aula.client] Trying API at https://www.aula.dk/api/v18 2024-04-06 10:28:31.384 DEBUG (SyncWorker_11) [custom_components.aula.client] Found API on https://www.aula.dk/api/v18 2024-04-06 10:28:31.542 DEBUG (SyncWorker_11) [custom_components.aula.client] LOGIN: True 2024-04-06 10:28:31.542 DEBUG (SyncWorker_11) [custom_components.aula.client] Config - schoolschedule: True, config - ugeplaner: True 2024-04-06 10:28:31.543 DEBUG (SyncWorker_11) [custom_components.aula.client] Child ids and names: {3775XX: 'XX Nielsen', 45983XX: 'XX Nielsen'} 2024-04-06 10:28:31.543 DEBUG (SyncWorker_11) [custom_components.aula.client] Child ids and institution names: {3775XX: 'XXX Skole', 45983XX: 'XXX Skole'} 2024-04-06 10:28:31.543 DEBUG (SyncWorker_11) [custom_components.aula.client] Institution codes: ['2650XX'] 2024-04-06 10:28:31.606 DEBUG (SyncWorker_11) [custom_components.aula.client] Unable to retrieve presence data from Aula from child with id 377505. Some data will be missing from sensor entities. 2024-04-06 10:28:31.680 DEBUG (SyncWorker_11) [custom_components.aula.client] Unable to retrieve presence data from Aula from child with id 4598348. Some data will be missing from sensor entities. 2024-04-06 10:28:31.680 DEBUG (SyncWorker_11) [custom_components.aula.client] Child ids and presence data status: {'3775XX': 0, '45983XX': 0} 2024-04-06 10:28:32.155 DEBUG (SyncWorker_11) [custom_components.aula.client] Fetching calendars... 2024-04-06 10:28:32.522 DEBUG (SyncWorker_11) [custom_components.aula.client] In the EasyIQ flow 2024-04-06 10:28:32.522 DEBUG (SyncWorker_11) [custom_components.aula.client] Requesting new token for widget 0001 2024-04-06 10:28:32.598 DEBUG (SyncWorker_11) [custom_components.aula.client] easyiq_headers: {'x-aula-institutionfilter': '2650XX', 'x-aula-userprofile': 'guardian', 'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImFlZTg0OTYwOTg3MDRkNjFlNWI4ZmYyNWJmZGQxNDJhZjkzZjE2YjAifQ.eyJpc3MiOiJBdWxhIiwiaWF0IjoxNzEyMzkyMTEyLjU3MTI4NCwiYXVkIjoiMDAwMSIsIkFzc3VyYW5jZUxldmVsIjoyLCJpc1BpbG90IjpmYWxzZSwiZXhwIjoxNzEyMzk1NzExLCJqdGkiOiI2NjExMDdhZDkwOGYyOC43MDMwOTUwNyIsInN1YiI6ImNsYXU4ODE2In0.QUHWWV34rC5jTHXUUcE9R7ljooe1eLe_w9Gy3vW8mmPFvu8rTaqmU-nMw_wOGCoYGCocXYEBuOnIsaPyTZAHXSA7BBAUs-ygGGhKs3MKW5l8-cpf_2RYdb3A5UG5W-8FsvJzerlov_iabU3FLLocfBTUAFfaIe0DAc', 'accept': 'application/json', 'csrfp-token': '004926de9415d2957b2f4cddc2483227', 'origin': 'https://www.aula.dk', 'referer': 'https://www.aula.dk/', 'authority': 'api.easyiqcloud.dk'} 2024-04-06 10:28:32.598 DEBUG (SyncWorker_11) [custom_components.aula.client] In the EasyIQ flow 2024-04-06 10:28:32.598 DEBUG (SyncWorker_11) [custom_components.aula.client] Reusing existing token for widget 0001 2024-04-06 10:28:32.598 DEBUG (SyncWorker_11) [custom_components.aula.client] easyiq_headers: {'x-aula-institutionfilter': '2650XX', 'x-aula-userprofile': 'guardian', 'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImFlZTg0OTYwOTg3MDRkNjFlNWI4ZmYyNWJmZGQxNDJhZjkzZjE2YjAifQ.eyJpc3MiOiJBdWxhIiwiaWF0IjoxNzEyMzkyMTEyLjU3MTI4NCwiYXVkIjoiMDAwMSIsIkFzc3VyYW5jZUxldmVsIjoyLCJpc1BpbG90IjpmYWxzZSwiZXhwIjoxNzEyMzk1NzExLCJqdGkiOiI2NjExMDdhZDkwOGYyOC43MDMwOTUwNyIsInN1YiI6ImNsYXU4ODE2In0.QUHWWV34rC5jTHXUUcE9R7ljooe1eLe_w9Gy3vW8mmPFvu8rTaqmU-nMw_wOGCoYGCocXYEBuOnIsaPyTZAHXSA7BBAUs-ygGGhKs3MKW5l8-cpf_2RYdb3A5UG5W-8FsvJzerlov_iabU3FLLocfBTUAFfaIe0DA', 'accept': 'application/json', 'csrfp-token': '004926de9415d2957b2f4cddc2483227', 'origin': 'https://www.aula.dk', 'referer': 'https://www.aula.dk/', 'authority': 'api.easyiqcloud.dk'} 2024-04-06 10:28:32.601 DEBUG (MainThread) [custom_components.aula.sensor] Finished fetching sensor data in 3.221 seconds (success: True) 2024-04-06 10:28:32.698 DEBUG (SyncWorker_7) [custom_components.aula.client] is_logged_in? True 2024-04-06 10:28:32.698 DEBUG (SyncWorker_7) [custom_components.aula.client] Child ids and names: {3775XX: 'XX Nielsen', 4598348: 'XX Nielsen'} 2024-04-06 10:28:32.698 DEBUG (SyncWorker_7) [custom_components.aula.client] Child ids and institution names: {3775XX: 'XXX Skole', 45983XX: 'XXX Skole'} 2024-04-06 10:28:32.698 DEBUG (SyncWorker_7) [custom_components.aula.client] Institution codes: ['2650XX'] 2024-04-06 10:28:32.777 DEBUG (SyncWorker_7) [custom_components.aula.client] Unable to retrieve presence data from Aula from child with id 3775XX. Some data will be missing from sensor entities. 2024-04-06 10:28:32.864 DEBUG (SyncWorker_7) [custom_components.aula.client] Unable to retrieve presence data from Aula from child with id 45983XX. Some data will be missing from sensor entities. 2024-04-06 10:28:32.864 DEBUG (SyncWorker_7) [custom_components.aula.client] Child ids and presence data status: {'3775XX': 0, '45983XX': 0}

Navne, ID-numre og ca. halvdelen af token er erstattet med XX'er eller bare slettet :)