ForcePilot/backend/package/yuxi/channels/adapters/irc/media_vision.py

61 lines
1.7 KiB
Python
Raw Normal View History

from __future__ import annotations
import re
from typing import Any
from yuxi.utils.logging_config import logger
_URL_RE = re.compile(
r"https?://[^\s]+\.(?:png|jpg|jpeg|gif|webp|svg)(?:\?[^\s]*)?",
re.IGNORECASE,
)
def extract_media_urls(text: str) -> list[str]:
return _URL_RE.findall(text)
def has_media_url(text: str) -> bool:
return bool(_URL_RE.search(text))
async def download_media(
url: str,
timeout: float = 15.0,
) -> bytes | None:
import aiohttp
try:
async with aiohttp.ClientSession() as session:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=timeout)) as resp:
if resp.status != 200:
logger.warning(f"IRC media download failed: {url} (status {resp.status})")
return None
content_length = resp.headers.get("Content-Length")
if content_length and int(content_length) > 50 * 1024 * 1024:
logger.warning(f"IRC media too large: {url} ({int(content_length) // 1024 // 1024}MB)")
return None
return await resp.read()
except TimeoutError:
logger.warning(f"IRC media download timeout: {url}")
return None
except Exception as e:
logger.warning(f"IRC media download error: {url} - {e}")
return None
def analyze_urls(text: str) -> list[dict[str, Any]]:
urls = extract_media_urls(text)
result: list[dict[str, Any]] = []
for url in urls:
ext = url.rsplit(".", 1)[-1].split("?")[0].lower()
result.append(
{
"url": url,
"type": "image",
"format": ext,
"size_bytes": None,
}
)
return result