From 96c94fae570b2be13421f9b03819d58a0ed3f34b Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Tue, 24 Mar 2026 14:17:18 +0100 Subject: [PATCH] unified data - step 1 --- .../workspace/interfaceFeatureWorkspace.py | 1 - .../workspace/routeFeatureWorkspace.py | 131 ------------------ 2 files changed, 132 deletions(-) diff --git a/modules/features/workspace/interfaceFeatureWorkspace.py b/modules/features/workspace/interfaceFeatureWorkspace.py index 56016ba2..525ac62e 100644 --- a/modules/features/workspace/interfaceFeatureWorkspace.py +++ b/modules/features/workspace/interfaceFeatureWorkspace.py @@ -14,7 +14,6 @@ from modules.features.workspace.datamodelFeatureWorkspace import WorkspaceUserSe from modules.interfaces.interfaceRbac import getRecordsetWithRBAC from modules.security.rbac import RbacClass from modules.shared.configuration import APP_CONFIG -from modules.shared.timeUtils import getUtcTimestamp logger = logging.getLogger(__name__) diff --git a/modules/features/workspace/routeFeatureWorkspace.py b/modules/features/workspace/routeFeatureWorkspace.py index 6b8c529b..1828cba6 100644 --- a/modules/features/workspace/routeFeatureWorkspace.py +++ b/modules/features/workspace/routeFeatureWorkspace.py @@ -1582,137 +1582,6 @@ async def synthesizeVoice( return JSONResponse({"audio": None, "note": "TTS via browser Speech Synthesis API recommended"}) -# ========================================================================= -# Voice Settings Endpoints -# ========================================================================= - -@router.get("/{instanceId}/settings/voice") -@limiter.limit("120/minute") -async def getVoiceSettings( - request: Request, - instanceId: str = Path(...), - context: RequestContext = Depends(getRequestContext), -): - """Load voice settings for the current user and instance.""" - _validateInstanceAccess(instanceId, context) - wsInterface = _getWorkspaceInterface(context, instanceId) - userId = str(context.user.id) - try: - vs = wsInterface.getVoiceSettings(userId) - if not vs: - logger.info(f"GET voice settings: not found for user={userId}, creating defaults") - vs = wsInterface.getOrCreateVoiceSettings(userId) - result = vs.model_dump() if vs else {} - mapKeys = list(result.get("ttsVoiceMap", {}).keys()) if result else [] - logger.info(f"GET voice settings for user={userId}: ttsVoiceMap languages={mapKeys}") - return JSONResponse(result) - except Exception as e: - logger.error(f"Failed to load voice settings for user={userId}: {e}", exc_info=True) - return JSONResponse({"ttsVoiceMap": {}}, status_code=200) - - -@router.put("/{instanceId}/settings/voice") -@limiter.limit("120/minute") -async def updateVoiceSettings( - request: Request, - instanceId: str = Path(...), - body: dict = Body(...), - context: RequestContext = Depends(getRequestContext), -): - """Update voice settings for the current user and instance.""" - _validateInstanceAccess(instanceId, context) - wsInterface = _getWorkspaceInterface(context, instanceId) - userId = str(context.user.id) - - try: - logger.info(f"PUT voice settings for user={userId}, instance={instanceId}, body keys={list(body.keys())}") - vs = wsInterface.getVoiceSettings(userId) - if not vs: - logger.info(f"No existing voice settings, creating new for user={userId}") - createData = { - "userId": userId, - "mandateId": str(context.mandateId) if context.mandateId else "", - "featureInstanceId": instanceId, - } - createData.update(body) - created = wsInterface.createVoiceSettings(createData) - logger.info(f"Created voice settings for user={userId}, ttsVoiceMap keys={list((created or {}).get('ttsVoiceMap', {}).keys())}") - return JSONResponse(created) - - updateData = {k: v for k, v in body.items() if k not in ("id", "userId", "mandateId", "featureInstanceId", "creationDate")} - logger.info(f"Updating voice settings for user={userId}, update keys={list(updateData.keys())}") - updated = wsInterface.updateVoiceSettings(userId, updateData) - logger.info(f"Updated voice settings for user={userId}, ttsVoiceMap keys={list((updated or {}).get('ttsVoiceMap', {}).keys())}") - return JSONResponse(updated) - except Exception as e: - logger.error(f"Failed to update voice settings for user={userId}: {e}", exc_info=True) - return JSONResponse({"error": str(e)}, status_code=500) - - -@router.get("/{instanceId}/voice/languages") -@limiter.limit("120/minute") -async def getVoiceLanguages( - request: Request, - instanceId: str = Path(...), - context: RequestContext = Depends(getRequestContext), -): - """Return available TTS languages.""" - mandateId, _ = _validateInstanceAccess(instanceId, context) - from modules.interfaces.interfaceVoiceObjects import getVoiceInterface - voiceInterface = getVoiceInterface(context.user, mandateId) - languagesResult = await voiceInterface.getAvailableLanguages() - languageList = languagesResult.get("languages", []) if isinstance(languagesResult, dict) else languagesResult - return JSONResponse({"languages": languageList}) - - -@router.get("/{instanceId}/voice/voices") -@limiter.limit("120/minute") -async def getVoiceVoices( - request: Request, - instanceId: str = Path(...), - language: str = Query("de-DE"), - context: RequestContext = Depends(getRequestContext), -): - """Return available TTS voices for a given language.""" - mandateId, _ = _validateInstanceAccess(instanceId, context) - from modules.interfaces.interfaceVoiceObjects import getVoiceInterface - voiceInterface = getVoiceInterface(context.user, mandateId) - voicesResult = await voiceInterface.getAvailableVoices(language) - voiceList = voicesResult.get("voices", []) if isinstance(voicesResult, dict) else voicesResult - return JSONResponse({"voices": voiceList}) - - -@router.post("/{instanceId}/voice/test") -@limiter.limit("30/minute") -async def testVoice( - request: Request, - instanceId: str = Path(...), - body: dict = Body(...), - context: RequestContext = Depends(getRequestContext), -): - """Test a specific voice with a sample text.""" - import base64 - mandateId, _ = _validateInstanceAccess(instanceId, context) - text = body.get("text", "Hallo, das ist ein Stimmtest.") - language = body.get("language", "de-DE") - voiceId = body.get("voiceId") - - from modules.interfaces.interfaceVoiceObjects import getVoiceInterface - voiceInterface = getVoiceInterface(context.user, mandateId) - - try: - result = await voiceInterface.textToSpeech(text=text, languageCode=language, voiceName=voiceId) - if result and isinstance(result, dict): - audioContent = result.get("audioContent") - if audioContent: - audioB64 = base64.b64encode( - audioContent if isinstance(audioContent, bytes) else audioContent.encode() - ).decode() - return JSONResponse({"success": True, "audio": audioB64, "format": "mp3", "text": text}) - return JSONResponse({"success": False, "error": "TTS returned no audio"}) - except Exception as e: - logger.error(f"Voice test failed: {e}") - raise HTTPException(status_code=500, detail=f"TTS test failed: {str(e)}") # =============================================================================