import os import configparser from flask import Flask, request, render_template_string, redirect, url_for app = Flask(__name__) DATA_DIR = "/data" def get_poll_files(): if not os.path.exists(DATA_DIR): return [] return [f for f in os.listdir(DATA_DIR) if f.endswith('.encuesta')] def load_poll(filename): filepath = os.path.join(DATA_DIR, filename) if not os.path.exists(filepath): return None config = configparser.ConfigParser() config.read(filepath, encoding='utf-8') poll_id = filename.replace('.encuesta', '') titulo = config.get('encuesta', 'titulo', fallback=poll_id) pregunta = config.get('encuesta', 'pregunta', fallback='') # Leer el estado de la encuesta (por defecto True si no existe el campo) activa_raw = config.get('encuesta', 'activa', fallback='true').lower() activa = activa_raw in ['true', '1', 'yes', 'si'] options = [] votes = [] if 'opciones' in config and 'votos' in config: for key in config['opciones']: options.append(config['opciones'][key]) votes.append(int(config['votos'].get(key, '0'))) return { "id": poll_id, "filename": filename, "titulo": titulo, "pregunta": pregunta, "activa": activa, "options": options, "votes": votes } def save_vote(filename, option_index): filepath = os.path.join(DATA_DIR, filename) config = configparser.ConfigParser() config.read(filepath, encoding='utf-8') # Seguridad: verificar si sigue activa antes de guardar activa_raw = config.get('encuesta', 'activa', fallback='true').lower() if activa_raw not in ['true', '1', 'yes', 'si']: return False key = str(option_index + 1) current_votes = int(config.get('votos', key, fallback='0')) config.set('votos', key, str(current_votes + 1)) with open(filepath, 'w', encoding='utf-8') as f: config.write(f) return True HTML_LAYOUT = """ Encuestas
{{ content | safe }}
""" @app.route('/') def home(): files = get_poll_files() active_polls = [] closed_polls = [] for f in files: poll = load_poll(f) if poll: if poll["activa"]: active_polls.append(poll) else: closed_polls.append(poll) content = "

Panel de Encuestas

" # BLOQUE: Encuestas Activas content += '
Encuestas Activas
' if not active_polls: content += "

No hay encuestas activas en este momento.

" else: for poll in active_polls: content += f'''
ACTIVA
{poll["titulo"]}
{poll["pregunta"]}

Votar / Resultados
''' # BLOQUE: Encuestas Finalizadas content += '
Encuestas Finalizadas
' if not closed_polls: content += "

No hay encuestas finalizadas.

" else: for poll in closed_polls: content += f'''
FINALIZADA
{poll["titulo"]}
{poll["pregunta"]}

Ver Resultados
''' return render_template_string(HTML_LAYOUT, content=content) @app.route('/poll/') def show_poll(poll_id): filename = f"{poll_id}.encuesta" poll = load_poll(filename) if not poll: return "Encuesta no encontrada", 404 # Si la encuesta NO está activa, forzar siempre la vista de resultados voted = (request.args.get('voted') == '1') or (not poll["activa"]) # Mostrar el título encima de la pregunta content = f'''
{poll["titulo"]}

{poll["pregunta"]}

''' if not poll["activa"]: content += '

⚠️ Esta encuesta ha finalizado. Solo se pueden consultar los resultados.

' if voted: total = sum(poll["votes"]) content += "

Resultados:

" bar_class = "bar" if poll["activa"] else "bar bar-closed" for i, opt in enumerate(poll["options"]): count = poll["votes"][i] percent = round((count / total * 100), 1) if total > 0 else 0 content += f'''
{opt}
{count} votos ({percent}%)
''' content += f'

Total de votos: {total}

' content += f'Volver al listado' else: content += f'
' for i, opt in enumerate(poll["options"]): content += f'''
''' content += '' content += f'

Ver resultados sin votar' content += '
' return render_template_string(HTML_LAYOUT, content=content) @app.route('/vote/', methods=['POST']) def vote(poll_id): filename = f"{poll_id}.encuesta" poll = load_poll(filename) # Si la encuesta está desactivada, ignorar el intento de voto if not poll or not poll["activa"]: return redirect(url_for('show_poll', poll_id=poll_id)) idx = int(request.form.get('option')) save_vote(filename, idx) return redirect(url_for('show_poll', poll_id=poll_id, voted=1)) if __name__ == '__main__': app.run(host='0.0.0.0', port=8080)