303 lines
10 KiB
Python
303 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Created on Thu Feb 24 08:51:58 2022
|
|
@author: antoine
|
|
"""
|
|
|
|
################
|
|
### UniSquat ###
|
|
################
|
|
|
|
"""
|
|
Indique toutes les salles disponibles dans les différents départements de
|
|
l'Université de Strasbourg.
|
|
"""
|
|
|
|
|
|
# Modules :
|
|
import requests
|
|
import icalendar
|
|
|
|
from objects import Room
|
|
from objects import Dept
|
|
|
|
# Fonctions :
|
|
|
|
# def room(name, start, end, is_free):
|
|
# """
|
|
# Retourne un dictionnaire contenant le nom, la prochaine date à laquelle elle est occupée, ainsi que la prochaine date à laquelle elle est libre.
|
|
|
|
# Parameters
|
|
# ----------
|
|
# name : str
|
|
# Le nom de la salle.
|
|
# start : datetime.datetime
|
|
# Salle occupée : heure de début de la prochaine période de disponibilité.
|
|
# Salle libre : inutilisé (vaut la date du jour à 00:00).
|
|
# end : datetime.datetime
|
|
# Salle occupée : heure de fin de la prochaine période de disponibilité.
|
|
# Salle libre : heure de fin de disponibilité.
|
|
# is_free : bool
|
|
# Indique si la salle est libre ('True') ou non ('False').
|
|
|
|
# Returns
|
|
# -------
|
|
# dict
|
|
# Un dictionnaire contenant ces 4 informations, avec le même nom en clef.
|
|
|
|
# """
|
|
|
|
# # return {"name":name, "occupied_at":occupied_at, "free_at":free_at, "free":free_at.timestamp() > occupied_at.timestamp()}
|
|
# return {"name":name, "start":start, "end":end, "is_free":is_free}
|
|
|
|
|
|
def sched_get(date, link, enddate = None) :
|
|
"""
|
|
Récupère l'emploi du temps de toutes les salles (pour le moment, juste
|
|
de l'UFR) sur ADE depuis le site de l'Unistra.
|
|
|
|
Parameters
|
|
----------
|
|
date : datetime.datetime()
|
|
Date du calendrier à télécharger (date de début si une date de fin
|
|
'enddate' est indiquée).
|
|
|
|
Optionnels:
|
|
link:
|
|
Un lien vers lequel effectuer la recherche, des informations seront remplacées :
|
|
$YEAR$ : l'année
|
|
$MONTH$ : le mois
|
|
$DAY$ : le jour
|
|
Par défaut, sera un lien des salles de l'UFR.
|
|
enddate : datetime.datetime()
|
|
Date de fin du calendrier à télécharger (par défaut, il s'agit de
|
|
la date de début).
|
|
|
|
Returns
|
|
-------
|
|
bytes
|
|
Le texte du résultat de la requête.
|
|
"""
|
|
|
|
# if not link:
|
|
# link = "https://adecons.unistra.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=30626&projectId=8&calType=ical&firstDate=$YEAR1$-$MONTH1$-$DAY1$&lastDate=$YEAR2$-$MONTH2$-$DAY2$"
|
|
|
|
link += "&firstDate=$YEAR1$-$MONTH1$-$DAY1$&lastDate=$YEAR2$-$MONTH2$-$DAY2$"
|
|
|
|
day1 = str(date.day)
|
|
month1 = str(date.month)
|
|
year1 = str(date.year)
|
|
|
|
finallink = link.replace("$DAY1$", day1)
|
|
finallink = finallink.replace("$MONTH1$", month1)
|
|
finallink = finallink.replace("$YEAR1$", year1)
|
|
|
|
if enddate != None :
|
|
day2 = str(enddate.day)
|
|
month2 = str(enddate.month)
|
|
year2 = str(enddate.year)
|
|
|
|
finallink = finallink.replace("$DAY2$", day2)
|
|
finallink = finallink.replace("$MONTH2$", month2)
|
|
finallink = finallink.replace("$YEAR2$", year2)
|
|
|
|
else :
|
|
finallink = finallink.replace("$DAY2$", day1)
|
|
finallink = finallink.replace("$MONTH2$", month1)
|
|
finallink = finallink.replace("$YEAR2$", year1)
|
|
|
|
|
|
r = requests.get(finallink)
|
|
|
|
return r.content
|
|
|
|
|
|
def get_depts(filename) :
|
|
"""
|
|
Crée une liste de tous les départements disponibles.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
filename : str
|
|
Nom du fichier contenant les départements, et les liens
|
|
permettant d'accéder au fichier iCal des salles du département.
|
|
|
|
Returns
|
|
-------
|
|
dept_list : list
|
|
Liste des départements.
|
|
"""
|
|
|
|
dept_list = list()
|
|
|
|
dept_file = open(filename, "r")
|
|
|
|
i = 0
|
|
|
|
# dept = Dept("", "", [])
|
|
|
|
dfile_content = dept_file.readlines()
|
|
|
|
ident = 0 # Compteur pour les identifiants des départements
|
|
|
|
for i in range(0, len(dfile_content) - 1, 2) :
|
|
dept_list.append(Dept(ident, dfile_content[i], dfile_content[i + 1], []))
|
|
ident += 1
|
|
|
|
# for l in dfile_content :
|
|
# """
|
|
# Une fois sur 2, on va :
|
|
# - soit enregistrer le nom du département
|
|
# - soit enregistrer son lien, et stocker le département dans la liste
|
|
# """
|
|
|
|
# if i == 0 :
|
|
# print(l)
|
|
# dept.name = l
|
|
# i = 1
|
|
# else :
|
|
# print(l)
|
|
# dept.link = l
|
|
# dept_list.append(dept)
|
|
# i = 0
|
|
|
|
dept_file.close()
|
|
|
|
return dept_list
|
|
|
|
|
|
def get_tot_rooms(datet, depts, ignore_list) :
|
|
"""
|
|
Crée une liste de toutes les salles des départements choisis.
|
|
|
|
Parameters
|
|
----------
|
|
datet : datetime.datetime()
|
|
Date pour la recherche de salles.
|
|
|
|
dept : list
|
|
Liste des départements dans lesquel chercher des salles.
|
|
|
|
ignore_list : list
|
|
Liste des noms de salles à ignorer.
|
|
|
|
Returns
|
|
-------
|
|
total_rooms : list
|
|
Liste des salles.
|
|
"""
|
|
|
|
total_rooms = list()
|
|
|
|
margintime = 1 # Marge de temps (en mois) pour le début du calendrier (il se peut que des salles existent et soient dispos, mais qu'elles ne sont pas affichées dans l'EDT du jour choisi, donc on prend l'EDT du mois)
|
|
|
|
cal_start = datet
|
|
|
|
if cal_start.month == 1 :
|
|
cal_start.replace(year = cal_start.year - 1)
|
|
cal_start.replace(month = 12)
|
|
else :
|
|
cal_start.replace(month = cal_start.month - margintime)
|
|
|
|
# Récupération des calendriers correspondants aux liens des départements, sur une période de 'margintime' mois :
|
|
cals = list() # Liste des emplois du temps des départements choisis
|
|
for d in depts :
|
|
result = sched_get(datet, d.link, datet.replace(month = datet.month + margintime))
|
|
cals.append(icalendar.Calendar.from_ical(result))
|
|
|
|
rnamelist = [] # Contient le nom de toutes les salles indiquées dans la section "LOCATION"
|
|
|
|
# Parcours de ces calendriers, pour faire la liste de toutes les salles :
|
|
for cal in cals :
|
|
for comp in cal.walk() : # Événements
|
|
if comp.name == "VEVENT" :
|
|
# Ajout de la salle dans le dictionnaire, si elle n'y est pas :
|
|
roomname = str(comp.get("location"))
|
|
if roomname not in rnamelist :
|
|
rnamelist.append(roomname)
|
|
start = datet.replace(hour = 0, minute = 0, second=0) # Par défaut, l'heure de début de disponibilité est aujourd'hui à 00:00
|
|
end = datet.replace(hour = 23, minute = 59, second = 59) # Par défaut, l'heure de fin de la prochaine période disponibilité est aujourd'hui à 23:59
|
|
is_free = True # Par défaut, la salle est libre
|
|
total_rooms.append(Room(roomname, start, end, is_free))
|
|
|
|
return total_rooms
|
|
|
|
|
|
def getrooms(datet, depts, ignore_list) :
|
|
"""
|
|
Ajout des informations supplémentaires à la liste des salles
|
|
(heures de début-fin de dispo, indicateur de dispo).
|
|
|
|
Parameters
|
|
----------
|
|
datet : datetime.datetime()
|
|
Date pour la recherche de salles.
|
|
|
|
dept : list
|
|
Liste des départements dans lesquel chercher des salles.
|
|
|
|
ignore_list : list
|
|
Liste des noms de salles à ignorer.
|
|
|
|
Returns
|
|
-------
|
|
total_rooms : list
|
|
Liste des salles.
|
|
"""
|
|
|
|
# Création de la liste de toutes les salles :
|
|
total_rooms = get_tot_rooms(datet, depts, ignore_list)
|
|
|
|
# Récupération des calendriers correspondants au lien du département :
|
|
cals = list() # Liste des emplois du temps des départements choisis
|
|
for d in depts :
|
|
result = sched_get(datet, d.link, datet)
|
|
cals.append(icalendar.Calendar.from_ical(result))
|
|
|
|
# Ajout des infos supplémentaires sur les salles (heures de début-fin de dispo, indicateur de dispo), s'il y en a :
|
|
for cal in cals :
|
|
# Première boucle, pour déterminer les salles occupées :
|
|
for comp in cal.walk() : # Événements
|
|
if comp.name == "VEVENT" :
|
|
# Récupération des infos :
|
|
datestart = comp.decoded("dtstart")
|
|
dateend = comp.decoded("dtend")
|
|
roomname = str(comp.get("location"))
|
|
|
|
# L'événement se passe maintenant (salle occupée maintenant) :
|
|
if datestart.timestamp() <= datet.timestamp() and dateend.timestamp() > datet.timestamp() :
|
|
start = dateend # L'heure de début de la prochaine période de disponibilité est la fin de l'événement
|
|
end = datet.replace(hour = 23, minute = 59, second = 59) # Par défaut, l'heure de fin de la prochaine période disponibilité est aujourd'hui à 23:59
|
|
is_free = False
|
|
for r in total_rooms :
|
|
if r.name == roomname :
|
|
r.start = start
|
|
r.end = end
|
|
r.is_free = is_free
|
|
|
|
# Deuxième boucle, pour ajouter les heures de dispos des salles :
|
|
for comp in cal.walk() : # Événements
|
|
if comp.name == "VEVENT" :
|
|
# Récupération des infos :
|
|
datestart = comp.decoded("dtstart")
|
|
dateend = comp.decoded("dtend")
|
|
roomname = str(comp.get("location"))
|
|
|
|
# L'événement se passe prochainement (salle occupée à l'occasion de cet événement) :
|
|
if datestart.timestamp() > datet.timestamp() :
|
|
for r in total_rooms :
|
|
if r.name == roomname :
|
|
if datestart.timestamp() < r.end.timestamp() :
|
|
if datestart.timestamp() == r.start.timestamp() :
|
|
start = dateend
|
|
end = r.end
|
|
else :
|
|
start = r.end
|
|
end = datestart
|
|
r.start = start
|
|
r.end = end
|
|
|
|
return total_rooms
|