# Foro accesible de La Sala de Juegos

Cliente de escritorio accesible para [qcsalon.net](https://qcsalon.net/),
escrito en Python 3 y wxPython. La versión actual es la 1.12.0.

## Funciones

- Inicio de sesión, renovación de sesiones caducadas y reconexión manual.
- Almacenamiento opcional de usuario y contraseña para entrar automáticamente.
  La contraseña se cifra mediante DPAPI y no forma parte del código.
- Navegación por foros, temas, mensajes y todas sus páginas.
- La lista de temas anuncia título, autor, respuestas, páginas y último
  mensaje, sin recitar información ausente. Al detener la selección, una
  consulta diferida y almacenada en caché completa el resultado real
  únicamente en el panel de detalle.
- Las cantidades grandes de temas y mensajes se convierten a palabras
  naturales en español para evitar que el lector anuncie grupos de cifras
  separados.
- Salto directo a cualquier página y accesos a la primera, anterior, siguiente
  y última.
- Lectura, redacción y respuesta de mensajes privados.
- Búsqueda por texto, foro, autor o título.
- Creación de temas, respuestas y encuestas.
- Respuesta con cita Markdown del mensaje seleccionado.
- Edición de mensajes propios y modificación de temas cuando el servidor
  ofrece esas acciones.
- Votos positivos y negativos en mensajes y temas.
- Respuesta a encuestas de una o varias opciones.
- Suscripción y desuscripción de foros y temas.
- Notificaciones de Windows cuando cambian las suscripciones mientras el
  cliente permanece abierto, más una bandeja local de novedades leídas y no
  leídas.
- Favoritos, historial de temas y borradores.
- Exportación completa de un tema a Markdown o texto desde la lista de temas o
  desde el tema abierto. Muestra el progreso por páginas, guarda cada página
  terminada y puede reanudar el mismo archivo desde el último mensaje sin
  descargar otra vez el principio. Incluye autores, fechas, puntuaciones y
  encuesta.
- Sonidos identificativos configurables por separado para conexión,
  reconexión, desconexión, pérdida de red, sesión caducada, límite temporal,
  Atrás, Adelante, apertura, paginación, actualización, guardado, copia,
  publicación, voto, suscripción, búsqueda, operación completada, error y
  novedades. Opciones ofrece una pestaña para activarlos individualmente.
- Copia del contenido o del enlace del elemento seleccionado.
- Filtro local temporal por texto y opción para mostrar solo temas no leídos.
- Vista previa accesible del Markdown al redactar mediante el paquete local
  `wx-accessible-webview`.

Las acciones disponibles cambian según la vista, el elemento seleccionado y
los permisos que publica qcsalon.net. El cliente no presenta operaciones que
el servidor no haya concedido a la sesión.

## Interfaz accesible

La ventana principal contiene únicamente cuatro elementos visibles:

1. El encabezado de la vista.
2. El indicador `Página X de Y`.
3. Una lista principal.
4. Un campo de lectura de solo lectura.

No hay barra de herramientas, botones permanentes, árbol, pestañas, filtro
fijo ni controles de paginación ocupando la ventana. Las operaciones están en
la barra de menús, en el menú contextual dinámico y en los atajos de teclado.

La lista de Inicio ofrece estas doce entradas:

- Todos los foros.
- Mensajes privados.
- Escribir un mensaje privado.
- Buscar.
- Novedades de suscripciones.
- Suscripciones.
- Favoritos.
- Historial.
- Borradores.
- Últimas participaciones.
- Temas recientes.
- Temas populares.

Las flechas recorren la lista y `Enter` abre el elemento seleccionado. `F6`
cambia entre Lista y Lectura; `Mayús+F6` vuelve a la zona anterior.
`Alt+Flecha izquierda` y `Alt+Flecha derecha` recorren el historial de vistas
como en un navegador. Se restauran la página, el filtro, el elemento o mensaje
seleccionado, la posición de lectura y el foco de Lista o Lectura.

Los editores mantienen un `wx.TextCtrl` nativo para escribir. La vista previa
usa WebView2 cuando está disponible y cae a texto de solo lectura si no lo
está. El renderizador admite los elementos habituales de Markdown, incluidos
encabezados, énfasis, listas, citas, código, enlaces y tablas, y elimina HTML
ejecutable, esquemas de enlace peligrosos e imágenes remotas.

## Atajos

| Atajo | Acción |
| --- | --- |
| `Ctrl+L` | Conectar |
| `Ctrl+Mayús+L` | Reconectar |
| `Ctrl+H` | Volver a Inicio |
| `Alt+Flecha izquierda` | Volver |
| `Alt+Flecha derecha` | Avanzar |
| `F5` | Actualizar |
| `Alt+Inicio` / `Alt+Fin` | Primera / última página |
| `Alt+RePág` / `Alt+AvPág` | Página anterior / siguiente |
| `Ctrl+G` | Ir a un número de página |
| `Enter` | Abrir el elemento seleccionado |
| `Ctrl+F` | Buscar en el foro |
| `Ctrl+K` | Abrir el filtro temporal de la lista |
| `Ctrl+D` | Añadir o quitar favorito |
| `Ctrl+N` | Crear un tema en el foro abierto |
| `Ctrl+Mayús+N` | Escribir un mensaje privado |
| `Ctrl+R` | Responder al tema o privado abierto |
| `Ctrl+Mayús+R` | Responder citando |
| `Ctrl+E` | Editar un mensaje propio |
| `Ctrl+M` | Modificar un tema propio |
| `Ctrl+P` | Responder una encuesta |
| `Ctrl+B` | Suscribirse o desuscribirse |
| `Ctrl+Arriba` / `Ctrl+Abajo` | Votar un mensaje |
| `Ctrl+Mayús+Arriba` / `Ctrl+Mayús+Abajo` | Votar un tema |
| `Ctrl+Mayús+C` | Copiar enlace |
| `Ctrl+Mayús+D` | Copiar contenido |
| `Ctrl+Mayús+E` | Exportar todas las páginas del tema |
| `Mayús+F10` | Abrir las acciones del elemento |
| `F6` / `Mayús+F6` | Cambiar entre Lista y Lectura |
| `F1` | Mostrar la ayuda de atajos |

## Instalación y ejecución

Requiere Windows y Python 3. Instale las dependencias:

```powershell
cd E:\Antigravity\LaSala
python -m pip install -r requirements.txt
```

También puede usar `install_dependencies.bat`.

Inicie el cliente con cualquiera de estas opciones:

```powershell
python main.py
.\run_client.bat
```

## Distribución con cx_Freeze

Instale las dependencias de construcción y ejecute el script:

```powershell
python -m pip install -r requirements-build.txt
.\build_exe.ps1
```

El resultado se crea en:

```text
dist\LaSalaForoAccesible\LaSalaForoAccesible.exe
dist\LaSalaForoAccesible-cxFreeze.zip
```

La distribución incluye Python 3.13, wxPython, WebView2Loader, el paquete local
`wx-accessible-webview` con su licencia y los runtimes MSVC v17 que incorpora
cx_Freeze. Antes de construir genera la biblioteca completa de sonidos y copia
`data\sounds` junto al ejecutable. No requiere una instalación independiente
de Python ni del redistribuible de Visual C++.

## Datos portátiles y registros

Todo lo que genera el cliente se concentra en la carpeta `data`. Al ejecutar
el código fuente se utiliza:

```text
E:\Antigravity\LaSala\data
```

En la distribución autónoma se utiliza `data` junto al ejecutable:

```text
dist\LaSalaForoAccesible\data
```

Su contenido es:

- `settings.json`: preferencias, favoritos, historial, borradores y estado de
  las notificaciones.
- `credentials.dat`: usuario y contraseña opcionales cifrados mediante DPAPI.
- `exports`: destino predeterminado de las exportaciones.
- `logs`: registros detallados de diagnóstico.
- `sounds`: sonidos identificativos generados localmente.
- `bin`: componentes auxiliares de la distribución.

Cada inicio crea un archivo de sesión distinto en `data\logs`. Se registran
arranque, plataforma, tareas, solicitudes HTTPS sin parámetros ni contenido,
respuestas, pausas, errores y excepciones no controladas. La rotación elimina
automáticamente el más antiguo y conserva siempre un máximo de cinco logs.

DPAPI vincula las credenciales a la cuenta de Windows que las guardó. El menú
Archivo permite olvidarlas. El proceso de compilación nunca introduce en el
ZIP credenciales, preferencias o logs del equipo de desarrollo.

## Conexión

El cliente reutiliza una única sesión HTTPS, ejecuta las operaciones de forma
serializada y deja al menos 0,8 segundos entre peticiones. Las lecturas se
reintentan ante fallos transitorios, se respeta `Retry-After` y HTTP 429, y se
intenta renovar una vez una sesión caducada. Las escrituras de resultado
incierto no se repiten automáticamente para evitar mensajes o votos
duplicados.

El monitor opcional consulta cada cinco minutos los cambios en las
suscripciones. Si una exportación se detiene por un límite temporal, informa
del tiempo indicado por el servidor y conserva un checkpoint en el propio
archivo. Al elegir después el mismo nombre, continúa desde la última página y
el último mensaje completos.

## Pruebas y comprobaciones

```powershell
python -m unittest discover -v
python -m ruff check --no-cache lasala_client tests main.py setup_cxfreeze.py
python main.py --smoke-ui --require-webview
python main.py --smoke-network
```

Hay 44 pruebas automáticas. Cubren el análisis del HTML, acciones y cargas
útiles, paginación, navegación Atrás/Adelante, apertura con Enter, filtro
temporal, restauración del mensaje y del foco, exportación reanudable,
progreso accesible, preferencias de sonidos, accesibilidad de diálogos,
renderizado seguro de Markdown, datos portátiles, rotación de logs, DPAPI y el
límite de 30 KiB por módulo Python propio. Las pruebas no publican contenido en
la cuenta real.

`--smoke-ui` construye y destruye la interfaz sin abrir la ventana principal.
`--require-webview` exige que la vista previa use WebView2.
`--smoke-network` realiza únicamente una lectura de la portada del sitio.

## Estructura actual

- `main.py`: punto de entrada y comprobaciones rápidas.
- `setup_cxfreeze.py`: configuración de cx_Freeze.
- `build_exe.ps1`: construcción de la carpeta autónoma y el ZIP.
- `lasala_client/api.py`: sesión HTTPS, autenticación y acciones remotas.
- `lasala_client/app_logging.py`: log de sesión, excepciones y rotación.
- `lasala_client/data_paths.py`: resolución de la carpeta portátil `data`.
- `lasala_client/html_parser.py`: interpretación del HTML del foro.
- `lasala_client/models.py`: modelos de los datos remotos.
- `lasala_client/settings.py`: preferencias y datos locales.
- `lasala_client/credentials.py`: cifrado DPAPI de credenciales.
- `lasala_client/dialogs.py`: diálogos accesibles y editores Markdown.
- `lasala_client/manual_dialog.py`: manual accesible integrado.
- `lasala_client/options_dialog.py`: opciones de sesión, red y sonidos.
- `lasala_client/progress_dialog.py`: progreso accesible de exportación.
- `lasala_client/sounds.py`: generación, reproducción y preferencias de sonido.
- `lasala_client/humanize.py`: pronunciación natural de cantidades del foro.
- `lasala_client/topic_export.py`: checkpoints y escritura incremental.
- `lasala_client/tor.py`: gestor del transporte Tor opcional existente.
- `lasala_client/markdown_render.py`: conversión y saneamiento de Markdown.
- `lasala_client/ui.py`: composición de la ventana y de sus mixins activos.
- `lasala_client/ui_minimal.py`: los cuatro controles principales, foco,
  filtro temporal e historial.
- `lasala_client/ui_commands.py`: menús, atajos, Inicio, acciones contextuales
  y paginación.
- `lasala_client/ui_core.py`: tareas, inicio de sesión y conexión.
- `lasala_client/ui_views.py`: carga y presentación de vistas.
- `lasala_client/ui_actions.py`: publicación, votos, suscripciones y
  utilidades.
- `lasala_client/ui_help.py`: ayuda, información de versión y cierre.
- `lasala_client/ui_models.py`: estado mínimo de navegación de la interfaz.
- `tests/`: pruebas automáticas sin publicaciones reales.
- `data/`: datos portátiles generados por la aplicación.
- `adjuntos/wx-accessible-webview/`: widget local de vista previa accesible.

Todos los módulos Python propios se mantienen por debajo de 30 KiB.
