Resuelto conflicto en X

This commit is contained in:
jlimolina 2025-06-09 11:48:00 +02:00
parent 758da0ad4c
commit e9264bc6ce
9 changed files with 348 additions and 96 deletions

122
app.py
View file

@ -4,6 +4,7 @@ import sys
import hashlib
import re
import csv
import math
from io import StringIO
from datetime import datetime, timedelta
import logging
@ -69,46 +70,71 @@ def home():
cat_id=int(cat_id) if cat_id else None, cont_id=int(cont_id) if cont_id else None, pais_id=int(pais_id) if pais_id else None)
@app.route("/feeds")
def feeds():
feeds_, categorias, continentes, paises = [], [], [], []
try:
with get_conn() as conn:
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cursor:
cursor.execute("""
SELECT f.id, f.nombre, f.descripcion, f.url, f.categoria_id, f.pais_id,
f.activo, f.fallos, c.nombre as cat_nom, p.nombre as pais_nom
FROM feeds f
LEFT JOIN categorias c ON f.categoria_id = c.id
LEFT JOIN paises p ON f.pais_id = p.id
ORDER BY f.nombre
""")
feeds_ = cursor.fetchall()
cursor.execute("SELECT id, nombre FROM categorias ORDER BY nombre")
categorias = cursor.fetchall()
cursor.execute("SELECT id, nombre FROM continentes ORDER BY nombre")
continentes = cursor.fetchall()
cursor.execute("SELECT id, nombre, continente_id FROM paises ORDER BY nombre")
paises = cursor.fetchall()
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al leer feeds: {db_err}", exc_info=True)
flash("Error de base de datos al cargar la gestión de feeds.", "error")
return render_template("index.html", feeds=feeds_, categorias=categorias, continentes=continentes, paises=paises)
@app.route("/add", methods=["POST"])
def add_feed():
nombre = request.form.get("nombre")
def dashboard():
stats = {'feeds_totales': 0, 'noticias_totales': 0, 'feeds_caidos': 0}
try:
with get_conn() as conn:
with conn.cursor() as cursor:
cursor.execute(
"INSERT INTO feeds (nombre, descripcion, url, categoria_id, pais_id, idioma) VALUES (%s, %s, %s, %s, %s, %s)",
(nombre, request.form.get("descripcion"), request.form.get("url"), request.form.get("categoria_id"), request.form.get("pais_id"), (request.form.get("idioma", "").strip() or None))
)
flash(f"Feed '{nombre}' añadido correctamente.", "success")
cursor.execute("SELECT COUNT(*) FROM feeds;")
stats['feeds_totales'] = cursor.fetchone()[0]
cursor.execute("SELECT COUNT(*) FROM noticias;")
stats['noticias_totales'] = cursor.fetchone()[0]
cursor.execute("SELECT COUNT(*) FROM feeds WHERE activo = FALSE;")
stats['feeds_caidos'] = cursor.fetchone()[0]
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al agregar feed: {db_err}", exc_info=True)
flash(f"Error al añadir el feed: {db_err}", "error")
return redirect(url_for("feeds"))
app.logger.error(f"[DB ERROR] Al calcular estadísticas del dashboard: {db_err}")
flash("Error al conectar con la base de datos para mostrar el resumen.", "error")
return render_template("dashboard.html", stats=stats)
@app.route("/feeds/manage")
def manage_feeds():
page = request.args.get('page', 1, type=int)
per_page = 10
offset = (page - 1) * per_page
feeds_list = []
total_feeds = 0
try:
with get_conn() as conn:
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cursor:
cursor.execute("SELECT COUNT(*) FROM feeds")
total_feeds = cursor.fetchone()[0]
cursor.execute("SELECT * FROM feeds ORDER BY nombre LIMIT %s OFFSET %s", (per_page, offset))
feeds_list = cursor.fetchall()
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al obtener lista de feeds: {db_err}")
flash("Error al obtener la lista de feeds.", "error")
total_pages = math.ceil(total_feeds / per_page)
return render_template("feeds_list.html", feeds=feeds_list, page=page, total_pages=total_pages, total_feeds=total_feeds)
@app.route("/feeds/add", methods=['GET', 'POST'])
def add_feed():
if request.method == 'POST':
nombre = request.form.get("nombre")
try:
with get_conn() as conn:
with conn.cursor() as cursor:
cursor.execute(
"INSERT INTO feeds (nombre, descripcion, url, categoria_id, pais_id, idioma) VALUES (%s, %s, %s, %s, %s, %s)",
(nombre, request.form.get("descripcion"), request.form.get("url"), request.form.get("categoria_id"), request.form.get("pais_id"), (request.form.get("idioma", "").strip() or None))
)
flash(f"Feed '{nombre}' añadido correctamente.", "success")
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al agregar feed: {db_err}", exc_info=True)
flash(f"Error al añadir el feed: {db_err}", "error")
return redirect(url_for("dashboard"))
categorias, paises = [], []
try:
with get_conn() as conn:
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cursor:
cursor.execute("SELECT id, nombre FROM categorias ORDER BY nombre")
categorias = cursor.fetchall()
cursor.execute("SELECT id, nombre FROM paises ORDER BY nombre")
paises = cursor.fetchall()
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al cargar formulario para añadir feed: {db_err}")
flash("No se pudieron cargar las categorías o países.", "error")
return render_template("add_feed.html", categorias=categorias, paises=paises)
@app.route("/edit/<int:feed_id>", methods=["GET", "POST"])
def edit_feed(feed_id):
@ -124,8 +150,7 @@ def edit_feed(feed_id):
(request.form.get("nombre"), request.form.get("descripcion"), request.form.get("url"), request.form.get("categoria_id"), request.form.get("pais_id"), idioma, activo, feed_id)
)
flash("Feed actualizado correctamente.", "success")
return redirect(url_for("feeds"))
return redirect(url_for("manage_feeds"))
cursor.execute("SELECT * FROM feeds WHERE id = %s", (feed_id,))
feed = cursor.fetchone()
cursor.execute("SELECT id, nombre FROM categorias ORDER BY nombre")
@ -135,12 +160,10 @@ def edit_feed(feed_id):
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al editar feed: {db_err}", exc_info=True)
flash(f"Error al editar el feed: {db_err}", "error")
return redirect(url_for("feeds"))
return redirect(url_for("manage_feeds"))
if not feed:
flash("No se encontró el feed solicitado.", "error")
return redirect(url_for("feeds"))
return redirect(url_for("manage_feeds"))
return render_template("edit_feed.html", feed=feed, categorias=categorias, paises=paises)
@app.route("/delete/<int:feed_id>")
@ -153,7 +176,7 @@ def delete_feed(feed_id):
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al eliminar feed: {db_err}", exc_info=True)
flash(f"Error al eliminar el feed: {db_err}", "error")
return redirect(url_for("feeds"))
return redirect(url_for("manage_feeds"))
@app.route("/reactivar_feed/<int:feed_id>")
def reactivar_feed(feed_id):
@ -165,7 +188,7 @@ def reactivar_feed(feed_id):
except psycopg2.Error as db_err:
app.logger.error(f"[DB ERROR] Al reactivar feed: {db_err}", exc_info=True)
flash(f"Error al reactivar el feed: {db_err}", "error")
return redirect(url_for("feeds"))
return redirect(url_for("manage_feeds"))
@app.route("/backup_feeds")
def backup_feeds():
@ -183,21 +206,18 @@ def backup_feeds():
feeds_ = cursor.fetchall()
if not feeds_:
flash("No hay feeds para exportar.", "warning")
return redirect(url_for("feeds"))
return redirect(url_for("dashboard"))
si = StringIO()
writer = csv.DictWriter(si, fieldnames=[desc[0] for desc in cursor.description])
writer.writeheader()
writer.writerows([dict(row) for row in feeds_])
output = si.getvalue()
si.close()
return Response(output, mimetype="text/csv", headers={"Content-Disposition": "attachment;filename=feeds_backup.csv"})
except Exception as e:
app.logger.error(f"[ERROR] Al hacer backup de feeds: {e}", exc_info=True)
flash("Error al generar el backup.", "error")
return redirect(url_for("feeds"))
return redirect(url_for("dashboard"))
@app.route("/restore_feeds", methods=["GET", "POST"])
def restore_feeds():
@ -211,7 +231,6 @@ def restore_feeds():
reader = csv.DictReader(file_stream)
rows = list(reader)
n_ok, n_err = 0, 0
with get_conn() as conn:
with conn.cursor() as cursor:
for row in rows:
@ -242,8 +261,7 @@ def restore_feeds():
except Exception as e:
app.logger.error(f"Error al restaurar feeds desde CSV: {e}", exc_info=True)
flash(f"Ocurrió un error general al procesar el archivo: {e}", "error")
return redirect(url_for("feeds"))
return redirect(url_for("dashboard"))
return render_template("restore_feeds.html")
def sumar_fallo_feed(cursor, feed_id):