File size: 4,933 Bytes
ffb0c3a 743deb5 ffb0c3a 743deb5 ffb0c3a 743deb5 ffb0c3a 743deb5 ffb0c3a 743deb5 ffb0c3a 743deb5 ffb0c3a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
from fastapi import FastAPI, Query,Path
from fastapi.responses import HTMLResponse
from pydantic import BaseModel,Field
from typing import Annotated
from bs4 import BeautifulSoup,ResultSet
import requests
from hashlib import md5
from enum import Enum
EVA_MAIN_URL:str = "https://eva.fing.edu.uy"
EVA_CATEGORY_URL:str = f"{EVA_MAIN_URL}/course/index.php?categoryid={{cat_id}}"
EVA_COURSE_URL:str=f"{EVA_MAIN_URL}/course/view.php?id={{course_id}}"
EVA_FORUM_URL:str=f"{EVA_MAIN_URL}/mod/forum/view.php?id={{forum_id}}"
EVA_RESOURCES_URL:str=f"{EVA_MAIN_URL}/course/resources.php?id={{course_id}}"
app:FastAPI = FastAPI(title="EVA API(No oficial)")
class Estado(Enum):
ABIERTO = 1
CERRADO = 0
class TipoMaterial(Enum):
PÁGINA = 0
ARCHIVO = 1
FORO = 2
CARPETA = 3
URL = 4
class Instituto(BaseModel):
id:int
nombre:str
class Curso(BaseModel):
estado:Estado = Estado.CERRADO
nombre:str
id:int
class Material(BaseModel):
tema:str
tipo:TipoMaterial = TipoMaterial.PÁGINA
estado:Estado = Estado.CERRADO
descripcion: str | None = None
def insertar_dentro(lista:list[str],opcion) -> any:
return {lista.pop(0):{"info":
{'url':opcion.get('value'),
'id':int(opcion.get('value').split("=",1)[-1])}
} if len(lista)==0 else insertar_dentro(lista,opcion)}
def parse_dict(d1:dict,d2:dict)->dict:
claves_repetidas =list( set(d1.keys()) & set(d2.keys()))
claves_d1_unicas = list(set(d1.keys())-set(d2.keys()))
claves_d2_unicas = list(set(d2.keys())-set(d1.keys()))
nuevo_diccionario = {}
for key in claves_repetidas:
nuevo_diccionario[key] = parse_dict(d1[key],d2[key])
for key in claves_d1_unicas:
nuevo_diccionario[key]= d1[key]
for key in claves_d2_unicas:
nuevo_diccionario[key]= d2[key]
return nuevo_diccionario
def obtener_institutos() -> dict:
response = requests.get(EVA_CATEGORY_URL.format(cat_id=2))
scraper = BeautifulSoup(response.text,'html.parser')
opciones:ResultSet = scraper.find_all("option")
selecciones:dict = {}
for opcion in list(opciones):
carpeta:list[str]= opcion.getText().split(" / ")
if len(carpeta)<=1: continue
a = insertar_dentro(carpeta,opcion)
selecciones = parse_dict(selecciones,a)
return selecciones
def obtener_cursos(category_id:str|int)->list[Curso]:
def format_option(opcion):
opcion = opcion.parent
is_locked = len(opcion.find_all("i"))<2
nombre=opcion.find('div',class_='coursename').getText()
id=int(opcion.find('a').get('href').split("=")[-1])
return Curso(**{
"estado":Estado.CERRADO if is_locked else Estado.ABIERTO,
"nombre":nombre,
"id":id
})
response = requests.get(EVA_CATEGORY_URL.format(cat_id=category_id))
scraper = BeautifulSoup(response.text,'html.parser')
opciones:ResultSet = scraper.find_all('div',class_="coursename")
fixed_opciones = list(map(format_option,opciones))
return fixed_opciones
def obtener_recursos(course_id:str|int)->list[Material]:
def format_recourse(recurso):
datos = recurso.find_all("td")
tema = datos[0].getText()
info = datos[1]
tipo:str = info.find("img").get("alt")
url = info.find("a").get("href")
tema += info.find("a").getText() if tipo=="URL" else ''
descripcion=datos[2].getText()
return Material(**{"tema":tema.strip(),
"tipo":TipoMaterial[tipo.upper()],
"url":url,
"descripcion":descripcion})
response = requests.get(EVA_RESOURCES_URL.format(course_id=course_id))
scraper = BeautifulSoup(response.text,'html.parser')
recursos = scraper.find("table",class_="generaltable mod_index").find_all("tr")[1:]
recursos_formateados = list(map(format_recourse,recursos))
return recursos_formateados
def obtener_hilos(foro_id:int)->list:
response = requests.get(EVA_FORUM_URL.format(forum_id=foro_id))
#scraper = BeautifulSoup(response.text,'html.parser')
return HTMLResponse(content=response.text,status_code=200);
return str(scraper)
@app.get('/institutos',tags=["institutos"],description="Lista los institutos",response_model=dict,name="Institutos")
def ob_ins():
return obtener_institutos()
@app.get('/cursos/{instituto_id}',tags=["cursos"],response_model=list[Curso])
def get_courses(instituto_id:Annotated[int,Path(title="ID del instituto",description="ID DEL INSTITUTO")]):
return obtener_cursos(instituto_id)
@app.get('/recursos/{curso_id}',tags=["cursos","recursos"],response_model=list[Material],description="Obtiene los recursos del curso")
def get_recursos(curso_id:Annotated[int,Path(title="ID del curso")]):
return obtener_recursos(curso_id)
@app.get('/foros/{foro_id}')
def get_foro_data(foro_id:Annotated[int,Path(title="ID del foro")]):
return obtener_hilos(foro_id) |