v1.2.3: Fix SIU SSL, matching de comisiones/equipos, credencial QR ampliada y actualizacion de beneficios

This commit is contained in:
2026-08-28 14:12:44 -03:00
parent b2d31db5a8
commit 29284ae131
13 changed files with 741 additions and 183 deletions
+53 -12
View File
@@ -7,7 +7,7 @@ import { AuthService } from './auth.service';
@Injectable({ providedIn: 'root' })
export class SiuService {
constructor(private authService: AuthService) {}
private readonly BASE_URL = 'https://siuuniciu.eastus2.cloudapp.azure.com/caba';
private readonly BASE_URL = 'https://autogestion.udelaciudad.edu.ar/caba';
async getAcademicHistory(dni: string, pass: string, carreraId: string = '30'): Promise<any[]> {
try {
@@ -49,7 +49,27 @@ export class SiuService {
const rawHtml = resCursada.data;
// Buscamos el bloque on_arrival que contiene "info_materia" (donde están las inscripciones)
// 1. Extraer directamente de "notificaciones" donde SIU provee el array JSON "asignaciones"
const regexNotif = /on_arrival\((\{.*?"id":"notificaciones".*?\})\);/s;
const matchNotif = rawHtml.match(regexNotif);
if (matchNotif && matchNotif[1]) {
try {
const jsonNotif = JSON.parse(matchNotif[1]);
const asignaciones = jsonNotif.info?.asignaciones;
if (Array.isArray(asignaciones) && asignaciones.length > 0) {
return asignaciones.map((asig: any) => ({
nombre: asig.NOMBRE_MATERIA || asig.MATERIA,
codigo: asig.NOMBRE || asig.MATERIA, // ej: "ASIG00127-E1-TD"
comision: asig.COMISION,
dia: asig.DIA_SEMANA
}));
}
} catch (e) {
console.warn('No se pudieron leer asignaciones estructuradas:', e);
}
}
// 2. Fallback: extraer del bloque HTML "info_materia" (tabla .js-mis-inscripciones)
const regex = /on_arrival\((\{.*?"id":"info_materia".*?\})\);/s;
const match = rawHtml.match(regex);
@@ -59,7 +79,7 @@ export class SiuService {
return this.parseInscripcionesActivasHtml(contentHtml);
}
return []; // Quizás no tiene inscripciones activas
return [];
} catch (error) {
console.error('Error SIU Active Inscriptions:', error);
return [];
@@ -254,20 +274,41 @@ export class SiuService {
private parseInscripcionesActivasHtml(html: string): any[] {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
// Buscamos los elementos que contienen los nombres de las materias (según el HTML del usuario)
const rows = Array.from(doc.querySelectorAll('.js-mis-inscripciones td'));
// Buscamos los elementos que contienen las inscripciones activas
const rows = Array.from(doc.querySelectorAll('.js-mis-inscripciones td, .inscripciones-lista td, .cuadro_materias td, table.tabla_cursada td'));
return rows.map(td => {
const results: any[] = [];
for (const td of rows) {
const text = td.textContent?.trim() || '';
// Formato esperado: "Nombre Materia - ASIG00125"
const parts = text.split(' - ');
if (parts.length >= 2) {
if (!text || text.length < 5) continue;
// Caso 1: "Nombre Materia - ASIG00127-E1-TD"
if (text.includes(' - ')) {
const parts = text.split(' - ');
const codigo = parts[parts.length - 1].trim();
const nombre = parts.slice(0, -1).join(' - ').trim();
return { nombre, codigo };
if (codigo.toUpperCase().includes('ASIG') || codigo.length >= 4) {
results.push({ nombre, codigo });
continue;
}
}
return null;
}).filter(item => item !== null);
// Caso 2: "Nombre Materia (ASIG00127-E1-TD)"
const matchParen = text.match(/^(.*?)\s*\((ASIG[^\)]+)\)/i);
if (matchParen) {
results.push({ nombre: matchParen[1].trim(), codigo: matchParen[2].trim() });
continue;
}
// Caso 3: contiene código ASIG embebido
const matchAsig = text.match(/(ASIG[A-Z0-9\-_]+)/i);
if (matchAsig) {
const codigo = matchAsig[1].trim();
const nombre = text.replace(codigo, '').replace(/[-–()]/g, '').trim();
results.push({ nombre, codigo });
}
}
return results;
}
private parseHtmlSubjects(html: string): any[] {