# Adlist Converter — RustProxy-style UI A modular Flask/WSGI application that converts a complete, validated hosts/adblock source into a MikroTik-compatible text response. The design uses RustProxy 0.29.3's visual language: dark/light color tokens, dashboard sidebar, typography, panels, controls and compact data tables. ## Deployment compatibility - Existing entrypoints: `app:app` (WSGI), `app:asgi_app` (Gunicorn/Uvicorn via `WsgiToAsgi`). - Existing paths: `/`, `/convert`, `/stats`, `/stats.json`, `/favicon.ico`. - Existing Redis keys and `.env` settings are preserved. - Successful `/convert` GET/HEAD responses retain ETag, 7-day shared cache TTL and conditional 304 handling. Invalid lists return an English error page and `Cache-Control: no-store`. - UI, `/stats` and `/stats.json` are private/no-store. CSS/JS and favicon use content-hashed `v` query strings so immutable assets refresh on upgrades. - The generator only constructs links locally; it **does not** fetch or convert the source as a side effect of typing. ## Project structure ```text app.py Flask/ASGI entrypoint and URL registration config.py Environment configuration source_conversion.py Safe decoding, validation and disk-backed output adlist/ converter.py /convert HTTP route cache.py Cache-Control, ETag response metadata validation.py URL, IP and host-list line validation services.py Redis, request metrics and recent links metrics.py /stats and /stats.json pages.py Dashboard and error rendering templates/ base.html Common sidebar, topbar and theme form.html Generator and recent links stats.html Statistics dashboard error.html English error page static/ css/main.css RustProxy-style dark/light, responsive CSS js/main.js UI behavior (vanilla JS) favicon.svg New local brand icon tests/ Regression checks ``` ## Quick checks ```bash python3 -m compileall -q app.py config.py source_conversion.py adlist python3 -m unittest discover -s tests -p 'test_*.py' -v python3 tests/smoke_routes.py ``` The standalone smoke test uses module stubs when Flask/Redis are unavailable; it is **not** an integrated production test. Run a real Gunicorn/Uvicorn smoke check after deployment. See `DEPLOY.md` for backups, upgrade steps and rollback. See `CACHE_SETUP.md` for RustProxy/Varnish cache configuration.