""" URL输入处理器 - 供所有插件复用 支持 Base64 和 URL 两种输入方式 """ import base64 import httpx from typing import Optional, Tuple from urllib.parse import urlparse from .http_client import get_http_client MAX_FILE_SIZE = 50 * 1024 * 1024 # 50MB async def resolve_content( content_base64: Optional[str], content_url: Optional[str], ) -> Tuple[bytes, str]: """ 统一解析输入内容 Args: content_base64: Base64编码的内容(优先使用) content_url: 文件URL地址(备选方式) Returns: (原始bytes, 来源说明) Raises: ValueError: 输入无效或下载失败 """ if content_base64: try: return base64.b64decode(content_base64), "base64" except Exception as e: raise ValueError(f"Base64解码失败: {e}") if content_url: parsed = urlparse(content_url) if parsed.scheme not in ("http", "https"): raise ValueError(f"不支持的URL协议: {parsed.scheme}") if not parsed.netloc: raise ValueError(f"无效的URL: {content_url}") try: client = get_http_client() resp = await client.get(content_url) if resp.status_code != 200: raise ValueError(f"下载失败: HTTP {resp.status_code}") content_length = len(resp.content) if content_length > MAX_FILE_SIZE: raise ValueError(f"文件过大: {content_length} bytes (上限 {MAX_FILE_SIZE})") return resp.content, f"url:{content_url}" except httpx.TimeoutException: raise ValueError(f"下载超时") except httpx.RequestError as e: raise ValueError(f"网络请求失败: {e}") raise ValueError("必须提供 content_base64 或 content_url") async def resolve_text_content( content_base64: Optional[str], content_url: Optional[str], encoding: str = "utf-8", ) -> Tuple[str, str]: """ 解析文本内容(自动解码) Args: content_base64: Base64编码的内容 content_url: 文件URL地址 encoding: 文本编码(默认utf-8) Returns: (解码后的文本, 来源说明) """ content, source = await resolve_content(content_base64, content_url) try: return content.decode(encoding), source except UnicodeDecodeError as e: raise ValueError(f"文本解码失败 ({encoding}): {e}") def encode_bytes_to_base64(data: bytes) -> str: """将字节数据编码为 Base64""" return base64.b64encode(data).decode("utf-8") def encode_text_to_base64(text: str, encoding: str = "utf-8") -> str: """将文本编码为 Base64""" return base64.b64encode(text.encode(encoding)).decode("utf-8") def decode_base64_to_bytes(base64_str: str) -> bytes: """将 Base64 解码为字节""" return base64.b64decode(base64_str) def decode_base64_to_text(base64_str: str, encoding: str = "utf-8") -> str: """将 Base64 解码为文本""" return base64.b64decode(base64_str).decode(encoding)