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)