- Add shared proxy module (bot/utils/proxy.py) to eliminate duplicate SOCKS5 parsing - Fix AI client: escape HTML before Markdown→HTML conversion, unify timeouts, make health check optional and disabled by default, handle 429 retries - Fix ai.py: correct forwarded message handling (aiogram 3.x forward_origin), pass relevant summaries via extra_system_content - Fix dialogue.py: only respond to Astra's messages, use system context instead of prompt injection, answer on the limit message before phase transition - Fix voice.py: load Whisper model in thread pool, safe WAV path generation - Improve database.py: composite indexes, Boolean is_active, upsert file_id cache, add context cleanup helper - Update weather.py and yadisk_download.py to use shared proxy connector - Update yadisk.py: validate URL before cache clear, add download size limit, wrap sync file ops in to_thread - Reuse S3 client via lru_cache - Update setup_commands with /aiclear and /aiuser - Update README, Dockerfile (Python 3.11), docker-compose (mount models) - Pin dependency versions, remove unused httpx[socks] - Add basic pytest tests for layout converter and voice normalization
41 lines
1.0 KiB
Python
41 lines
1.0 KiB
Python
import os
|
|
import logging
|
|
from functools import lru_cache
|
|
|
|
import boto3
|
|
from botocore.config import Config
|
|
|
|
from config import ACCESS_KEY, SECRET_KEY, BUCKET_NAME
|
|
|
|
logger = logging.getLogger("s3_client")
|
|
|
|
ENDPOINT_URL = "https://storage.yandexcloud.net"
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def _build_s3_client():
|
|
return boto3.client(
|
|
"s3",
|
|
endpoint_url=ENDPOINT_URL,
|
|
aws_access_key_id=ACCESS_KEY,
|
|
aws_secret_access_key=SECRET_KEY,
|
|
config=Config(
|
|
connect_timeout=30,
|
|
read_timeout=300,
|
|
retries={"max_attempts": 3},
|
|
),
|
|
)
|
|
|
|
|
|
def upload_file(file_path: str) -> str | None:
|
|
key_name = os.path.basename(file_path)
|
|
try:
|
|
client = _build_s3_client()
|
|
client.upload_file(file_path, BUCKET_NAME, key_name)
|
|
file_url = f"{ENDPOINT_URL}/{BUCKET_NAME}/{key_name}"
|
|
logger.info("Файл загружен в S3: %s", file_url)
|
|
return file_url
|
|
except Exception as exc:
|
|
logger.exception("Ошибка загрузки в S3: %s", exc)
|
|
return None
|