правки для деплоя через Coolify

This commit is contained in:
a.grigorev
2026-09-04 15:14:29 +03:00
parent 161fd6576b
commit 1098ff4991
11 changed files with 276 additions and 384 deletions
+44 -3
View File
@@ -1,15 +1,56 @@
import base64
import binascii
import json
import logging
import re
from functools import lru_cache
from pathlib import Path
from typing import Any
import gspread
from gspread.utils import InsertDataOption, ValueInputOption
from app import config
logger = logging.getLogger(__name__)
sheets_api = gspread.service_account(filename="google-auth/key.json")
# Таймаут HTTP-запросов (сек): защита от зависания при проблемах с сетью/Google API
sheets_api.set_timeout(30)
_SHEETS_HTTP_TIMEOUT = 30
def _load_service_account_info(raw: str) -> dict[str, Any]:
"""Разобрать ключ из переменной окружения: чистый JSON или его base64."""
raw = raw.strip()
if not raw.startswith("{"):
try:
raw = base64.b64decode(raw, validate=True).decode("utf-8")
except (binascii.Error, UnicodeDecodeError) as e:
raise ValueError(
"GOOGLE_SERVICE_ACCOUNT_JSON: ожидается JSON ключа сервисного "
"аккаунта или его base64"
) from e
return json.loads(raw)
@lru_cache(maxsize=1)
def get_client() -> gspread.Client:
"""Клиент Google Sheets. Создаётся при первом обращении, не при импорте."""
if config.GOOGLE_SERVICE_ACCOUNT_JSON:
info = _load_service_account_info(config.GOOGLE_SERVICE_ACCOUNT_JSON)
client = gspread.service_account_from_dict(info)
logger.info("Google Sheets: ключ загружен из GOOGLE_SERVICE_ACCOUNT_JSON")
else:
key_path = Path(config.GOOGLE_SERVICE_ACCOUNT_FILE)
if not key_path.is_file():
raise FileNotFoundError(
f"Ключ сервисного аккаунта Google не найден: {key_path}. "
"Задайте GOOGLE_SERVICE_ACCOUNT_JSON или положите файл по пути "
"GOOGLE_SERVICE_ACCOUNT_FILE"
)
client = gspread.service_account(filename=str(key_path))
logger.info("Google Sheets: ключ загружен из файла %s", key_path)
client.set_timeout(_SHEETS_HTTP_TIMEOUT)
return client
# HTTP коды, при которых стоит сбросить кэш листа (устаревший объект)
_CACHE_INVALIDATE_CODES = frozenset({401, 403, 404, 429})
@@ -31,7 +72,7 @@ def parse_google_sheets_url(url: str) -> tuple[str, int | None]:
def get_sheet(sheet_link: str) -> gspread.Worksheet:
spreadsheet_id, worksheet_id = parse_google_sheets_url(sheet_link)
spreadsheet = sheets_api.open_by_key(spreadsheet_id)
spreadsheet = get_client().open_by_key(spreadsheet_id)
if worksheet_id is not None:
return spreadsheet.get_worksheet_by_id(worksheet_id)
return spreadsheet.sheet1