| import os |
| import yaml |
| import shutil |
| from pathlib import Path |
| import uuid |
| from datetime import datetime |
| try: |
| import tomllib |
| except ModuleNotFoundError: |
| import tomli as tomllib |
| import streamlit as st |
|
|
| from databases import set_db_path, init_schema, set_blockchain_enabled |
| from api_client import APIClient |
| from utils import ensure_dirs |
| from auth import initialize_auth_system, render_login_form, render_sidebar, require_login |
| from persistent_data_gate import ensure_temp_databases |
| from mobile_verification import render_mobile_verification_screen, get_user_permissions |
| from compliance_client import compliance_client |
| from page_modules.process_video import render_process_video_page |
| from page_modules.analyze_audiodescriptions import render_analyze_audiodescriptions_page |
| from page_modules.statistics import render_statistics_page |
| from page_modules.validation import render_validation_page |
|
|
|
|
| |
| os.environ["STREAMLIT_DATA_DIRECTORY"] = "/tmp/.streamlit" |
| Path("/tmp/.streamlit").mkdir(parents=True, exist_ok=True) |
|
|
| |
| |
| |
| runtime_videos = Path("/tmp/data/videos") |
| if not runtime_videos.exists(): |
| Path("/tmp/data").mkdir(parents=True, exist_ok=True) |
| base_dir = Path(__file__).parent |
| candidates = [ |
| base_dir / "data" / "media", |
| base_dir / "videos", |
| ] |
|
|
| static_videos = None |
| for cand in candidates: |
| if cand.exists(): |
| static_videos = cand |
| break |
|
|
| if static_videos is not None: |
| shutil.copytree(static_videos, runtime_videos, dirs_exist_ok=True) |
|
|
|
|
| |
| def _load_yaml(path="config.yaml") -> dict: |
| with open(path, "r", encoding="utf-8") as f: |
| cfg = yaml.safe_load(f) or {} |
| |
| def _subst(s: str) -> str: |
| return os.path.expandvars(s) if isinstance(s, str) else s |
|
|
| |
| if "api" in cfg: |
| cfg["api"]["base_url"] = _subst(cfg["api"].get("base_url", "")) |
| cfg["api"]["token"] = _subst(cfg["api"].get("token", "")) |
| cfg["api"]["tts_url"] = _subst(cfg["api"].get("tts_url", "")) |
|
|
| if "storage" in cfg and "root_dir" in cfg["storage"]: |
| cfg["storage"]["root_dir"] = _subst(cfg["storage"]["root_dir"]) |
|
|
| if "sqlite" in cfg and "path" in cfg["sqlite"]: |
| cfg["sqlite"]["path"] = _subst(cfg["sqlite"]["path"]) |
|
|
| return cfg |
|
|
| CFG = _load_yaml("config.yaml") |
|
|
| |
| |
| DATA_DIR = "temp" |
|
|
| |
| BACKEND_BASE_URL = ( |
| CFG.get("api", {}).get("base_url") |
| or os.getenv("API_BASE_URL") |
| or "http://localhost:8000" |
| ) |
|
|
| TTS_URL = "https://veureu-tts.hf.space" |
| print(f"🔧 TTS_URL configurada: {TTS_URL}") |
| print(f"🔧 Tipo de TTS_URL: {type(TTS_URL)}") |
| print(f"🔧 Longitud de TTS_URL: {len(TTS_URL)}") |
| print(f"🔧 TTS_URL repr: {repr(TTS_URL)}") |
| USE_MOCK = bool(CFG.get("app", {}).get("use_mock", False)) |
|
|
| COMPLIANCE_CFG = CFG.get("compliance", {}) or {} |
| PRIVATE_BLOCKCHAIN_ENABLE = bool( |
| COMPLIANCE_CFG.get("private_blockchain_enabled", |
| COMPLIANCE_CFG.get("private_blockchain_enable", False)) |
| ) |
| PUBLIC_BLOCKCHAIN_ENABLE = bool( |
| COMPLIANCE_CFG.get("public_blockchain_enabled", |
| COMPLIANCE_CFG.get("public_blockchain_enable", False)) |
| ) |
| MONTHLY_DIGEST_ENABLED = bool(COMPLIANCE_CFG.get("monthly_digest_enabled", False)) |
|
|
| |
| API_TOKEN = CFG.get("api", {}).get("token") or os.getenv("API_SHARED_TOKEN") |
|
|
| |
| api = APIClient(BACKEND_BASE_URL, use_mock=USE_MOCK, data_dir=DATA_DIR, token=API_TOKEN, tts_url=TTS_URL) |
|
|
| os.makedirs(DATA_DIR, exist_ok=True) |
| ensure_dirs(DATA_DIR) |
|
|
| base_dir = Path(__file__).parent |
| ensure_temp_databases(base_dir, api) |
|
|
| DB_PATH = os.path.join(DATA_DIR, "users.db") |
| set_db_path(DB_PATH) |
|
|
| |
| set_blockchain_enabled(PRIVATE_BLOCKCHAIN_ENABLE) |
|
|
| |
| |
| if PUBLIC_BLOCKCHAIN_ENABLE and MONTHLY_DIGEST_ENABLED: |
| try: |
| today = datetime.utcnow().date() |
| if today.day == 1: |
| period = today.strftime("%Y-%m") |
| compliance_client.publish_monthly_digest(period) |
| except Exception: |
| |
| pass |
|
|
| init_schema() |
|
|
| |
| initialize_auth_system(DB_PATH) |
|
|
| |
| if "session_id" not in st.session_state: |
| st.session_state.session_id = str(uuid.uuid4()) |
|
|
| |
| st.session_state.api_client = api |
|
|
| st.set_page_config(page_title="Veureu — Audiodescripció", page_icon="🎬", layout="wide") |
|
|
| |
| st.markdown( |
| """ |
| <style> |
| .stButton > button[kind="primary"] { |
| background-color: #f97316; |
| border-color: #ea580c; |
| color: white; |
| } |
| .stButton > button[kind="primary"]:hover { |
| background-color: #ea580c; |
| border-color: #c2410c; |
| } |
| </style> |
| """, |
| unsafe_allow_html=True, |
| ) |
|
|
| |
| if "user" not in st.session_state: |
| st.session_state.user = None |
|
|
| |
| page, role = render_sidebar() |
|
|
| |
| if not st.session_state.user: |
| st.title("Veureu — Audiodescripció") |
| render_login_form() |
| st.stop() |
|
|
| |
| if st.session_state.user and 'sms_verified' not in st.session_state: |
| st.session_state.sms_verified = None |
|
|
| permissions = None |
| if st.session_state.user: |
| username = st.session_state.user['username'] |
| role = st.session_state.user['role'] |
| |
| |
| permissions = get_user_permissions(role, st.session_state.get('sms_verified')) |
| |
| |
| if permissions["requires_sms"] and st.session_state.sms_verified is None: |
| result = render_mobile_verification_screen(username, role) |
| if result is None: |
| |
| st.stop() |
| |
|
|
| |
| if page == "Processar vídeo nou": |
| require_login(render_login_form) |
| |
| permissions = get_user_permissions(role, st.session_state.get('sms_verified')) |
| if not permissions["procesar_videos"]: |
| st.error("No tens permisos per processar nous vídeos. Verifica el teu mòbil per obtenir accés complet.") |
| st.stop() |
|
|
| render_process_video_page(api, BACKEND_BASE_URL) |
|
|
| elif page == "Analitzar audiodescripcions": |
| require_login(render_login_form) |
| permissions = get_user_permissions(role, st.session_state.get('sms_verified')) |
| render_analyze_audiodescriptions_page(api, permissions) |
|
|
| elif page == "Estadístiques": |
| require_login(render_login_form) |
| render_statistics_page() |
|
|
| elif page == "Validació": |
| require_login(render_login_form) |
| permissions = get_user_permissions(role, st.session_state.get('sms_verified')) |
| render_validation_page(compliance_client, runtime_videos, permissions, username) |
|
|