Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"mein Unterricht" #3

Open
baum-eule opened this issue Sep 8, 2023 · 7 comments
Open

"mein Unterricht" #3

baum-eule opened this issue Sep 8, 2023 · 7 comments
Assignees
Labels
enhancement New feature or request reverse-engineering-hell sh**

Comments

@baum-eule
Copy link

Feature Idee "mein Unterricht"

Es gibt (bei mir an der Schule) einen "mein Unterricht" Tap und diesen könnte man auslesen.
Url: https://start.schulportal.hessen.de/meinunterricht.php

Habe für mich eine Api für "mein Unterricht" gebaut, wobei man nicht sehen kann ob man Anwesend gewesen ist oder welche Noten man hat, weil dieser Teil verschlüsselt gebaut. (Leider in Python)

@alessioC42
Copy link
Member

Moin,
das ist ein Feature, das ich auf jeden Fall noch einbauen wollte. Aber meine Schule hat noch nicht mal die Kurse für dieses Schuljahr angelegt und ich bin gerade etwas überlastet. Wenn du willst, kannst du das implementieren. Wenn nicht, dann kann ich das in nicht allzu ferner Zukunft machen.

Im Moment habe ich eher das Problem das Ganze auf Android laufen zu lassen. (und ich habe auch noch nie was in TS gemacht :/) Sobald ich das auf Android hinbekommen habe, kann man darüber nachdenken, ob man diese Funktionalität dann auch in die App einbauen kann.

@alessioC42 alessioC42 added enhancement New feature or request reverse-engineering-hell sh** labels Sep 8, 2023
@baum-eule
Copy link
Author

Ich kann leider gar kein TS, deswegen kann ich es nicht hier implementieren, aber ich könnte dir, wenn du Zeit hast damit anzufangen, meinen Python Code (der leider Schlecht bis gar nicht Dokumentiert ist) geben.
Sorry das ich kann nur bei reverse Engineering helfen, was ich vielleicht bald bei der Chat Funktion mache die auch die gleiche Verschlüsselung nutzt wie die Noten.

@alessioC42
Copy link
Member

Ich kann auch kein TS xD. Ich habe den Client in JS geschrieben und dachte zuerst, dass es gut wäre, die Anwendung in TypeScript und Vue zu schreiben. Deshalb wollte ich das am Anfang umschreiben. Aber jetzt werde ich doch JS für die Android-App verwenden (eigentlich der einzige Grund für dieses Repo xD).

Dein Code ist sicher hilfreich, auch wenn er, wie du sagst, "schlecht" ist, sollte er zumindest die API Endpoints oder Verschlüsselung zeigen.

Ich habe gesehen, dass Lanis aus irgendeinem Grund eine zweite RSA-Verschlüsselung zusätzlich zur SSL-RSA-Verschlüsselung verwendet, was ich für unnötig halte, aber ich kann nichts dagegen tun.

Ich kann mich um dieses Feature erst kümmern, wenn ich überhaupt in einem Kurs bin. Ab dann sollte es aber kein Problem mehr sein.

@baum-eule
Copy link
Author

Ich kann mich mal in TS einlesen wird aber auch dauern, aber es gibt ja keine Deadline.

Ich habe auch die zweite Verschlüsselung bemerkt, die bei manchen Sachen wie zb dem Chat oder den Noten genutzt wird aber bei anderen Sachen nicht. Ich habe mich leider noch nicht an die Verschlüsselung gemacht werde es aber wahrscheinlich bald machen.

Der Code für die Übersicht Seite:

    def unit(self):
        from bs4 import BeautifulSoup
        import requests
        self.__time_test()
        rt = requests.get(f"https://start.schulportal.hessen.de/meinunterricht.php",
                          cookies=self.__cookie).text

        def r1(rt):
            soup = BeautifulSoup(rt, 'html.parser')
            r = {}
            finp1 = soup.find("table", id="aktuellTable").find("tbody").find_all("tr")
            
            for im in finp1:
                t = {
                    "subject": "",
                    "teacher": "",
                    "date": "",
                    "headline": "",
                    "finish": "",
                    "content": "",
                    "upload": "", # TODO: inplement it
                    "files": {
                        "file": [],
                        "found": False,
                        "all": ""
                    },
                    "subject_id": "",
                    "content_found": True
                }
                tparts = im.find_all("td")

                # part 1
                tp1 = tparts[0]
                t1 = tp1.find("h3").find("a")
                t["subject_id"] = t1["href"].split("id=")[1]
                t["subject"] = t1.find("span").text

                te = self.teacher_search(tp1.find("span", class_="teacher").find("div").find("button")["title"], select=False, raw=True)[0]

                t["teacher"] = te

                # part 2
                tp2 = tparts[1]
                x = tp2.find_all("i")
                if len(x) > 0 and x[0].text == "noch kein Eintrag":
                    t["content_found"] = False
                else:

                    t["headline"] = tp2.find("b", class_="thema").text
                    t["date"] = tp2.find("small").find("span").text

                    h = tparts[1].find_all("div", class_="homework")
                    if len(h) > 0:
                        h = h[0]
                        t["content"] = h.find("div").text

                        # dedection if finish
                        if "hidden" in h.find("span", class_="done")['class']:
                            t["finish"] = False
                        else:
                            t["finish"] = True
                
                # part 3
                tp3 = tparts[2]
                tp3 = tp3.find("div", class_="btn-sameWidth")
                x = tp3.find_all("div", class_="btn-group")
                for i in x:
                    if "files" in i["class"]:
                        from .dfile import dfile
                        t["files"]["found"] = True
                        t2 = i.find("ul").find_all("li")
                        e = self.__url_to_values(t2[-1].find("a")["href"])
                        
                        t2.pop(-1)
                        t2.pop(-1)
                        for i1 in t2:
                            s = i1.find("a").find("small").text.replace("(", "").replace(")", "")
                            t3 = dfile(e["id"], e["e"], i1.find("a")["data-file"], s=s, cookie=self.__cookie)
                            t["files"]["file"].append(t3)
                        t3 = dfile(e["id"], e["e"], b=e["b"], cookie=self.__cookie)
                        t["files"]["all"] = t3

                r[t["subject"]] = t

            return r

        def r2(rt):
            soup = BeautifulSoup(rt, 'html.parser')
            r = {}
            v1 = soup.find("div", id="mappen")
            # part 1
            v = v1.find("div", class_="row").find_all("div", class_="caption")
            for i in v:
                tname = i.find("h2").find("span").text
                tteacher = i.find("button", class_="btn-primary")["title"]
                tteacher = self.teacher_search(tteacher, select=True, raw=True)[0]
                tid = self.__url_to_values(i.find("a", class_="btn btn-primary")["href"])["id"]
                x1 = i.find("a", class_="btn btn-info")
                x2 = i.find("a", class_="btn btn-danger")

                if x1: # "freigegebene Leistungen"
                    t1 = x1.text
                else: 
                    t1 = ""
                
                if x2: # "unerledigte Hausaufgaben bis heute"
                    t2 = x2.text
                else:
                    t2 = ""

                tr = {
                    "subject": tname,
                    "teacher": tteacher,
                    "id": tid,
                    "grades": t1.strip(),
                    "homework_undone": t2.strip(),
                    "old": False
                }
                r[tname] = tr

            # part 2
            v = v1.find("table", class_="table").find("tbody").find_all("tr")
            for i in v:
                i = i.find_all("td")
                tname = i[0].find("a").text.strip()
                tteacher = self.teacher_search(i[1].find("span")["title"], select=True, raw=True)[0]
                tid = self.__url_to_values(i[0].find("a")["href"])["id"]
                tr = {
                    "subject": tname,
                    "teacher": tteacher,
                    "id": tid,
                    "grades": "",
                    "homework_undone": "",
                    "old": True
                }
                r[tname] = tr
            return r
        
        def r3(rt):
            soup = BeautifulSoup(rt, 'html.parser')
            r = {}
            v1 = soup.find("div", id="anwesend").find("table").find("tbody").find_all("tr")
            for i in v1:
                i = i.find_all("td")
                tname = i[0].text
                tid = self.__url_to_values(i[0].find("a")["href"])["id"]
                tteacher = i[1].find("span")["title"]
                tteacher = self.teacher_search(tteacher, select=True, raw=True)[0]
                
                #t_y= i[2].text 
                # TODO: encrypt data by t_y
                tr = {
                    "subject": tname,
                    "teacher": tteacher,
                    "id": tid,
                    "yes": "",
                    "no": "" # TODO: get sample
                }
                r[tname] = tr
            return r

Der Code für die Detail Seite:

    def subject_deail(self, subject_id:str, part= 0):
        # part 0 is part from now of study year 
        # part 1 is part 1 of study year
        # part 2 is part 2 of study year

        from bs4 import BeautifulSoup
        import requests
        url = ""
        if part == 0:
            url=f"https://start.schulportal.hessen.de/meinunterricht.php?a=sus_view&id={subject_id}"
        elif part == 1 or part == 2:
            url=f"https://start.schulportal.hessen.de/meinunterricht.php?a=sus_view&id={subject_id}&halb={part}"
        rt = requests.get(url,
                          cookies=self.__cookie).text
        soup = BeautifulSoup(rt, 'html.parser')
        tpart = soup.find("h1").find("small").text.strip()
        tname = soup.find("h1").text.replace(tpart, "").strip()
        tpart = tpart.split(".")[0]
        tteacher = soup.find("div", id="content").find_all("div", class_="btn-group")[0].find("button")["title"]
        tteacher = self.teacher_search(tteacher, select=True, raw=True)[0]

        def history(rt):
            from .dfile import dfile
            r = {}
            soup = BeautifulSoup(rt, 'html.parser')
            if not soup.find("div", id="history").find("table"):
                return r
            v = soup.find("div", id="history").find("table").find("tbody").find_all("tr")
            for i in v:
                v1 = i.find_all("td")
                tid = i["data-entry"]
                tid2 = v1[0].find("a")["name"].replace("eintrag", "")
                ttime = v1[0].find("small").text.strip()
                tdate = v1[0].text.replace(ttime, "").strip()
                theadline = v1[1].find("big").find("b").text

                c = 1

                if v1[1].find("i", class_="far fa-comment-alt"): # check if content exsist
                    tcontent = v1[1].find("span", class_="markup").text
                    c += 1
                else:
                    tcontent = ""

                if v1[1].find("i", class_="fas fa-home"): # check if homework exsist
                    thomework = v1[1].find_all("span", recursive=False)[c].text
                    if v1[1].find("span", class_="undone hidden"): # check if homework done
                        tdone = True
                    else:
                        tdone = False
                else:
                    tdone = False
                    thomework = ""
                
                if v1[1].find("div", class_="alert alert-info"):
                    t = v1[1].find("div", class_="alert alert-info").find("div", class_="files").find_all("div")
                    t1 = v1[1].find("div", class_="alert alert-info").find("a", class_="btn btn-default btn-sm")["href"]
                    t1 = self.__url_to_values(t1)
                    tall = dfile(t1["id"], t1["e"], b=t1["b"], cookie=self.__cookie)
                    tfiles = {
                        "file": [],
                        "found": True,
                        "all": tall
                    }
                    for i in t:
                        s = i.find("a").find("small").text.replace("(", "").replace(")", "")
                        t2 = dfile(t1["id"], t1["e"], i["data-file"], s=s, cookie=self.__cookie)
                        tfiles["file"].append(t2)
                else:
                    tfiles = {
                        "file": [],
                        "found": False,
                        "all": ""
                    }

                
                tr = {
                    "id": tid,
                    "id2": tid2,
                    "date": tdate,
                    "time": ttime,
                    "headline": theadline,
                    "content": tcontent,
                    "homework": thomework,
                    "done": tdone,
                    "upload": "", # TODO: inplement it
                    "files": tfiles,
                    "presence": "" # TODO: Encrypt data
                }
                r[tid] = tr
            return r

        r = {
            "id": subject_id,
            "subject": tname,
            "part": tpart,
            "teacher": tteacher,
            "history": history(rt)
        }

        return r

(Die Lehrer Suche kann man ausbauen das ist nur eine ID)
Sorry das alles auf Englisch Benannt ist.

@baum-eule
Copy link
Author

Weil du ja eine Android App machen willst währe auch eine Schulsuche nützlich.
Ich hatte für mich mal eine gebaut:

def search_school(school: str):
    import requests
    from bs4 import BeautifulSoup
    school = school.lower()
    r = []
    raw_text = requests.get("https://start.schulportal.hessen.de/").text
    soup = BeautifulSoup(raw_text, 'html.parser')
    item_list = soup.find_all("a", class_="list-group-item")
    for i in item_list:
        if school in i.text.lower():
            x = i.find("small").text
            r.append({
                "school": i.text.replace(" "+x, ""),
                "town": i.find("small").text,
                "id": i["data-id"]
                })
    return r

@alessioC42
Copy link
Member

Die Schulsuche wird auf jeden fall auch noch implementiert! Dazu habe ich bereits diesen API endpunkt gefunden:
https://startcache.schulportal.hessen.de/exporteur.php?a=schoollist

@alessioC42
Copy link
Member

Also die App ist gerade hier und ich bin jetzt dabei "mein unterricht" zu reverse engineeren.

@alessioC42 alessioC42 self-assigned this Nov 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request reverse-engineering-hell sh**
Projects
None yet
Development

No branches or pull requests

2 participants