Files
DualHub/fetchRAPLA.py

180 lines
5.4 KiB
Python

import urllib.error
from dateutil.parser import *
import asyncio
import httpx
import icalendar
from icalendar import Calendar, Event
import json
from init import scheduler, app, Rapla, db
async def fetchPlan(session, url):
return await session.get(url=url)
def writeToFile(filename, data):
with open(filename, 'w+') as f:
f.write(data.text)
f.close()
def writeToDB(kurs, url):
new_kurs = Rapla(name=kurs, link=url, file=f"rapla{kurs}.ical")
db.session.add(new_kurs)
db.session.commit()
def parseURL(url: str):
"""
Konvertiert URLs ins korrekte Format. \n
Konvertiert werden: http, www.; page=calendar \n
In: https; page=ical
:param url:
:return str:
"""
rapla = url.find("rapla.")
if rapla == -1:
return 0
elif len(url[:rapla]) == 4 or len(url[:rapla]) > 6:
url = url[rapla:]
http = url.find(":")
if url[:http] == "http":
url = f"https{url[http:]}"
elif http == -1:
url = f"https://{url}"
p = url.find("page=")
u = url.find("&")
if (url[p + 5:u]).lower() == "ical":
return 1, url
elif p != -1:
return 1, f"{url[:p + 5]}ical{url[u:]}"
elif url.find("key") != -1:
return 2, url
else:
return 0, 0
async def getNewRapla(url: str):
"""
Speichert den iCal eines Raplas auf dem Server. \n
Gibt Namen der Datei zurück. \n
TODO: Standort zu Dateibezeichner hinzufügen, um Konflikte zu vermeiden.
:param url:
:return str:
"""
parsed = parseURL(url)
if parsed[0] == 0:
return 0
elif parsed[0] == 1:
url = parsed[1]
elif parsed[0] == 2:
return await buildFromKey(parsed[1])
urlfile = url.find("file=")
kurs = url[urlfile + 5:].upper()
if url[-5:] != ".ical":
try:
async with httpx.AsyncClient() as s:
response = await fetchPlan(s, url)
writeToFile(f"calendars/rapla{kurs}.ical", response)
except urllib.error.URLError:
return -1
writeToDB(kurs, url)
return f"rapla{kurs}.ical"
else:
return url
def getIcal(kurs: str):
"""
Liefert den Namen der Datei des mitgegebenen Kurses.
:param kurs:
:return str:
"""
rapla = Rapla.query.filter(Rapla.name == kurs).first()
try:
return rapla.file
except KeyError:
return None
def getRaplas():
"""
Liefert alle auf dem Server gespeicherten Raplas.
:return (Kursliste, Dateiliste, URL-Liste):
"""
raplas = Rapla.query.all()
kursl = [rapla.name for rapla in raplas]
filel = [rapla.file for rapla in raplas]
urll = [rapla.link for rapla in raplas]
return kursl, filel, urll
async def refreshRapla():
"""
Aktualisiert alle 5 Minuten alle gespeicherten Raplas.
"""
filel = getRaplas()[1]
urll = getRaplas()[2]
jobl = []
async with httpx.AsyncClient() as s:
for i in range(len(filel)):
print(f"Update Rapla: {filel[i][:-5]}")
jobl += [fetchPlan(s, urll[i])]
callist = await asyncio.gather(*jobl, return_exceptions=True)
for cal in range(len(callist)):
writeToFile(f"calendars/{filel[cal]}", callist[cal])
#@scheduler.task('cron', id="raplaschedule", hour='*', day_of_week='*', minute='*/2', week='*')
def raplaschedule():
with app.app_context():
asyncio.run(refreshRapla())
async def buildFromKey(url):
async with httpx.AsyncClient() as s:
page = await s.get(url=url)
if page.text[:10] == "BEGIN:VCAL":
info = page.headers['content-disposition']
kursname = info[info.find('filename=')+9:-4].upper()
writeToDB(kursname, url)
return url
else:
kursname = page.text[page.text.find("<title>") + 7:page.text.find("</title>")]
if len(kursname) > 15:
return 0
start = "2024-08-01"
end = "2024-12-31"
payload = {"url": url, "start": start, "end": end}
req = await s.post(url="https://dh-api.paulmartin.cloud/rapla", data=payload,
headers={'Content-Type': 'application/x-www-form-urlencoded'}, timeout=10)
jsonresp = json.loads(req.text)
cal = Calendar()
cal.add('prodid', '-//Rapla//iCal Plugin//EN')
cal.add('version', '2.0')
for i in jsonresp:
if len(jsonresp[i]) != 0:
for jsonday in jsonresp[i]:
event = Event()
event.add('SUMMARY', jsonday['title'])
event.add('LOCATION', jsonday['ressources'])
event.add('DTSTART', parse(jsonday['startDate'], dayfirst=True))
event.add('DTEND', parse(jsonday['endDate'], dayfirst=True))
try:
teacher = icalendar.vCalAddress(value=jsonday['persons'])
teacher.params["CN"] = jsonday['persons']
except KeyError:
teacher = icalendar.vCalAddress(value="")
teacher.params["CN"] = ""
event.add('ATTENDEE', teacher)
cal.add_component(event)
with open(f"calendars/rapla{kursname}.ical", "wb") as f:
f.write(cal.to_ical())
f.close()
writeToDB(kursname, url)
return f"rapla{kursname}.ical"