diff --git a/app/handler/response_handler.py b/app/handler/response_handler.py index 1300e71..bbe047d 100644 --- a/app/handler/response_handler.py +++ b/app/handler/response_handler.py @@ -10,6 +10,7 @@ from typing import Any, Dict, List, Optional from app.config.config import settings from app.utils.uploader import ImageUploaderFactory from app.log.logger import get_openai_logger +from app.utils.helpers import is_image_upload_configured logger = get_openai_logger() @@ -251,7 +252,22 @@ def _extract_result( return text, reasoning_content, tool_calls, thought +def _has_inline_image_part(response: Dict[str, Any]) -> bool: + try: + for c in response.get("candidates", []): + for p in c.get("content", {}).get("parts", []): + if isinstance(p, dict) and ("inlineData" in p): + return True + except Exception: + return False + return False + + def _extract_image_data(part: dict) -> str: + # Return empty string if no uploader is configured + if not is_image_upload_configured(): + return "" + image_uploader = None if settings.UPLOAD_PROVIDER == "smms": image_uploader = ImageUploaderFactory.create( @@ -322,6 +338,10 @@ def _extract_tool_calls( def _handle_gemini_stream_response( response: Dict[str, Any], model: str, stream: bool ) -> Dict[str, Any]: + # Early return raw Gemini response if no uploader configured and contains inline images + if not is_image_upload_configured() and _has_inline_image_part(response): + return response + text, reasoning_content, tool_calls, thought = _extract_result( response, model, stream=stream, gemini_format=True ) @@ -339,6 +359,10 @@ def _handle_gemini_stream_response( def _handle_gemini_normal_response( response: Dict[str, Any], model: str, stream: bool ) -> Dict[str, Any]: + # Early return raw Gemini response if no uploader configured and contains inline images + if not is_image_upload_configured() and _has_inline_image_part(response): + return response + text, reasoning_content, tool_calls, thought = _extract_result( response, model, stream=stream, gemini_format=True ) diff --git a/app/service/image/image_create_service.py b/app/service/image/image_create_service.py index 9a3b867..b90ef99 100644 --- a/app/service/image/image_create_service.py +++ b/app/service/image/image_create_service.py @@ -10,6 +10,7 @@ from app.core.constants import VALID_IMAGE_RATIOS from app.domain.openai_models import ImageGenerationRequest from app.log.logger import get_image_create_logger from app.utils.uploader import ImageUploaderFactory +from app.utils.helpers import is_image_upload_configured logger = get_image_create_logger() @@ -97,12 +98,15 @@ class ImageCreateService: image_data = generated_image.image.image_bytes image_uploader = None - if request.response_format == "b64_json": + # Return base64 if explicitly requested or if no uploader is configured + if request.response_format == "b64_json" or not is_image_upload_configured(): base64_image = base64.b64encode(image_data).decode("utf-8") images_data.append( {"b64_json": base64_image, "revised_prompt": request.prompt} ) + continue else: + # Upload to configured provider current_date = time.strftime("%Y/%m/%d") filename = f"{current_date}/{uuid.uuid4().hex[:8]}.png" diff --git a/app/utils/helpers.py b/app/utils/helpers.py index c283654..29778ed 100644 --- a/app/utils/helpers.py +++ b/app/utils/helpers.py @@ -189,3 +189,23 @@ def get_current_version(default_version: str = "0.0.0") -> str: except IOError as e: helper_logger.error(f"Error reading VERSION file ('{version_file}'): {e}. Using default version '{default_version}'.") return default_version + + +def is_image_upload_configured() -> bool: + """Return True only if a valid upload provider is selected and all required settings for that provider are present. Uses lazy import to avoid circular imports.""" + try: + from app.config.config import settings # local import to avoid circular dependency at module import time + except Exception: + return False + + provider = (getattr(settings, "UPLOAD_PROVIDER", "") or "").strip().lower() + if provider == "smms": + return bool(getattr(settings, "SMMS_SECRET_TOKEN", "")) + if provider == "picgo": + return bool(getattr(settings, "PICGO_API_KEY", "")) + if provider == "cloudflare_imgbed": + return all([ + getattr(settings, "CLOUDFLARE_IMGBED_URL", ""), + getattr(settings, "CLOUDFLARE_IMGBED_AUTH_CODE", ""), + ]) + return False