FIXED: timeoutError with gif seach and sending

This commit is contained in:
Your Name 2026-07-22 12:41:11 +03:00
parent 1b71c63919
commit d811fc1b4e
11 changed files with 52 additions and 28 deletions

BIN
chat.db

Binary file not shown.

View File

@ -1,22 +1,20 @@
"""
controllers/tenor.py GIPHY API proxy (requests-based).
"""
import json import json
import logging import logging
import requests import requests
from bottle import route, request, response from bottle import route, request, response
import redis
redis_server = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
_giphy_key: str = "GIPHY_API_KEY" _giphy_key: str = "NR2vkCSTVKnwBx9IavODcsqeSt9Sreze"
_session = requests.Session() _session = requests.Session()
_session.headers.update({'User-Agent': 'GIPHY-Proxy/1.0'}) _session.headers.update({'User-Agent': 'GIPHY-Proxy/1.0'})
GIPHY_BASE = "https://api.giphy.com/v1/gifs" GIPHY_BASE = "https://api.giphy.com/v1/gifs"
def init(tenor_cfg): def init(tenor_cfg):
global _giphy_key global _giphy_key
if hasattr(tenor_cfg, 'api_key') and tenor_cfg.api_key: if hasattr(tenor_cfg, 'api_key') and tenor_cfg.api_key:
@ -25,23 +23,26 @@ def init(tenor_cfg):
else: else:
logger.warning("No GIPHY API key configured, using default placeholder") logger.warning("No GIPHY API key configured, using default placeholder")
def _build_params(query_params, extra=None): def _build_params(query_params, extra=None):
params = { params = {
"api_key": _giphy_key, "api_key": _giphy_key,
"limit": query_params.get("limit", "20"), "limit": int(query_params.get("limit", "20")),
"rating": query_params.get("rating", "g"), "rating": query_params.get("rating", "g"),
"lang": query_params.get("lang", "en"), "lang": query_params.get("lang", "en"),
} }
# Обработка offset
try:
if query_params.get("offset"): if query_params.get("offset"):
params["offset"] = query_params["offset"] params["offset"] = int(query_params["offset"])
else:
params["offset"] = 0
except ValueError:
params["offset"] = 0
if extra: if extra:
params.update(extra) params.update(extra)
return params return params
def _transform_giphy_result(gif): def _transform_giphy_result(gif):
"""Convert GIPHY format -> unified {id, title, file: {hd, md, sm, xs}}."""
images = gif.get("images", {}) images = gif.get("images", {})
return { return {
"id": gif.get("id"), "id": gif.get("id"),
@ -56,10 +57,9 @@ def _transform_giphy_result(gif):
"blur_preview": images.get("preview_gif", {}).get("url", ""), "blur_preview": images.get("preview_gif", {}).get("url", ""),
} }
def _fetch_giphy(endpoint, params): def _fetch_giphy(endpoint, params):
url = f"{GIPHY_BASE}/{endpoint}" url = f"{GIPHY_BASE}/{endpoint}"
logger.debug(f"GET {url}") logger.debug(f"GET {url} with params {params}")
try: try:
resp = _session.get(url, params=params, timeout=15) resp = _session.get(url, params=params, timeout=15)
resp.raise_for_status() resp.raise_for_status()
@ -68,13 +68,16 @@ def _fetch_giphy(endpoint, params):
if isinstance(results, dict): if isinstance(results, dict):
results = [results] results = [results]
transformed = [_transform_giphy_result(g) for g in results] transformed = [_transform_giphy_result(g) for g in results]
per_page = int(params.get("limit", 20))
current_offset = int(params.get("offset", 0))
total_results = len(transformed)
return { return {
"success": True, "success": True,
"results": transformed, "results": transformed,
"pagination": { "pagination": {
"current_page": (int(params.get("offset", 0)) // max(int(params.get("limit", 20)), 1)) + 1, "current_page": (current_offset // per_page) + 1,
"per_page": params.get("limit", 20), "per_page": per_page,
"has_next": len(transformed) >= int(params.get("limit", 20)), "has_next": total_results >= per_page,
}, },
} }
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
@ -88,20 +91,41 @@ def _fetch_giphy(endpoint, params):
response.status = 502 response.status = 502
return {"success": False, "error": error_msg} return {"success": False, "error": error_msg}
def register_routes(app): def register_routes(app):
@app.route("/api/gifs/trending", method="GET") @app.route("/api/gifs/trending", method="GET")
def gifs_trending(): def gifs_trending():
try:
logger.debug(f"Trending request: {dict(request.query)}") logger.debug(f"Trending request: {dict(request.query)}")
params = _build_params(request.query) params = _build_params(request.query)
return _fetch_giphy("trending", params) answ = _fetch_giphy("trending", params)
serialized_answ = json.dumps(answ)
redis_server.set('trending', serialized_answ, ex=360)
return json.loads(serialized_answ)
except Exception as e:
logger.exception("Error in trending route")
response.status = 500
return {"success": False, "error": str(e)}
@app.route("/api/gifs/search", method="GET") @app.route("/api/gifs/search", method="GET")
def gifs_search(): def gifs_search():
try:
logger.debug(f"Search request: {dict(request.query)}") logger.debug(f"Search request: {dict(request.query)}")
q = request.query.get("q", "") q = request.query.get("q", "")
if not q: if not q:
response.status = 400 response.status = 400
return {"success": False, "error": "Missing query"} return {"success": False, "error": "Missing query parameter 'q'"}
params = _build_params(request.query, extra={"q": q}) params = _build_params(request.query, extra={"q": q})
return _fetch_giphy("search", params) cache_key = f"search:{q.lower().strip()}"
# Проверка кеша
cached = redis_server.get(cache_key)
if cached:
return json.loads(cached)
# Если нет кеша, делаем запрос
answ = _fetch_giphy("search", params)
serialized_answ = json.dumps(answ)
redis_server.set(cache_key, serialized_answ, ex=360)
return answ
except Exception as e:
logger.exception("Error in search route")
response.status = 500
return {"success": False, "error": str(e)}