Spaces:
Runtime error
Runtime error
Delete bot_modules
Browse files- bot_modules/__init__.py +0 -2
- bot_modules/network_patch.py +0 -83
- bot_modules/utils.py +0 -126
bot_modules/__init__.py
DELETED
|
@@ -1,2 +0,0 @@
|
|
| 1 |
-
# bot_modules package
|
| 2 |
-
|
|
|
|
|
|
|
|
|
bot_modules/network_patch.py
DELETED
|
@@ -1,83 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
ΠΠ»ΠΎΠΊ 0: ΠΠ»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ ΡΠ΅ΡΠ΅Π²ΡΠ΅ ΠΏΠ°ΡΡΠΈ Π΄Π»Ρ HF Spaces.
|
| 3 |
-
|
| 4 |
-
Π Π΅ΡΠ°Π΅Ρ 3 ΠΈΠ½ΡΡΠ°ΡΡΡΡΠΊΡΡΡΠ½ΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ:
|
| 5 |
-
1. ΠΡΡΡΡΡΡΠ²ΠΈΠ΅ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΡ
CA-ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΠ² β SSL-ΠΎΡΠΈΠ±ΠΊΠΈ ΠΏΡΠΈ HTTPS-Π·Π°ΠΏΡΠΎΡΠ°Ρ
|
| 6 |
-
2. ΠΠΎΡΠΏΠΎΡΠ°ΡΠΈΠ²Π½ΡΠ΅ ΠΏΡΠΎΠΊΡΠΈ Π² env β aiohttp ΠΈΡ
ΠΈΠ³Π½ΠΎΡΠΈΡΡΠ΅Ρ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ
|
| 7 |
-
3. ΠΠ»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ° api.telegram.org Π² Π Π€ β aiogram Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ
|
| 8 |
-
|
| 9 |
-
ΠΠ°ΡΡΠΈ ΠΏΡΠΈΠΌΠ΅Π½ΡΡΡΡΡ ΠΊΠ°ΠΊ side-effect ΠΏΡΠΈ ΠΈΠΌΠΏΠΎΡΡΠ΅ ΠΌΠΎΠ΄ΡΠ»Ρ.
|
| 10 |
-
ΠΠΌΠΏΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ ΠΠ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π»ΡΠ±ΡΡ
aiohttp-ΡΠ΅ΡΡΠΈΠΉ (aiogram, YooKassa, etc.).
|
| 11 |
-
|
| 12 |
-
ΠΠΠΠΠΠΠΠ: Monkey-patching β ΡΡΠΎ ΠΊΡΠ°ΠΉΠ½ΡΡ ΠΌΠ΅ΡΠ°. ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΠΎΠΌΡ,
|
| 13 |
-
ΡΡΠΎ HF Spaces Π½Π΅ ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΡ
CA-ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΠ², Π° aiogram
|
| 14 |
-
Π½Π΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ²Π½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ SSL-ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π΄Π»Ρ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΡ
Π·Π°ΠΏΡΠΎΡΠΎΠ².
|
| 15 |
-
"""
|
| 16 |
-
import os
|
| 17 |
-
import ssl
|
| 18 |
-
import logging
|
| 19 |
-
|
| 20 |
-
import certifi
|
| 21 |
-
import aiohttp
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 25 |
-
# SSL-ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π΄Π»Ρ Π²Π½Π΅ΡΠ½ΠΈΡ
HTTPS-Π·Π°ΠΏΡΠΎΡΠΎΠ² (OpenAI, Telegram API)
|
| 26 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 27 |
-
# ΠΠ ΠΏΠΎΠ΄ΠΌΠ΅Π½ΡΠ΅ΠΌ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ ssl._create_default_https_context β ΡΡΠΎ Π»ΠΎΠΌΠ°Π΅Ρ PostgreSQL
|
| 28 |
-
custom_ssl = ssl.create_default_context(cafile=certifi.where())
|
| 29 |
-
custom_ssl.check_hostname = True
|
| 30 |
-
custom_ssl.verify_mode = ssl.CERT_REQUIRED
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 34 |
-
# ΠΠ°ΡΡ 1: TCPConnector β certifi SSL Π΄Π»Ρ Π²ΡΠ΅Ρ
HTTPS-ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ
|
| 35 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 36 |
-
# HF Spaces Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΡ
CA-ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΠ².
|
| 37 |
-
# ΠΠ΅Π· ΡΡΠΎΠ³ΠΎ ΠΏΠ°ΡΡΠ° Π²ΡΠ΅ HTTPS-Π·Π°ΠΏΡΠΎΡΡ ΠΏΠ°Π΄Π°ΡΡ Ρ SSLCertVerificationError.
|
| 38 |
-
# Π£ΡΠ»ΠΎΠ²ΠΈΠ΅ `ssl is not False` ΡΠΎΡ
ΡΠ°Π½ΡΠ΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΡΠ²Π½ΠΎ ΠΎΡΠΊΠ»ΡΡΠΈΡΡ SSL
|
| 39 |
-
# Π΄Π»Ρ HTTP-Π·Π°ΠΏΡΠΎΡΠΎΠ² (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΊ Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΠΌ ΡΠ΅ΡΠ²ΠΈΡΠ°ΠΌ).
|
| 40 |
-
_orig_tcp_init = aiohttp.TCPConnector.__init__
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
def _patched_tcp_init(self, *args, **kwargs):
|
| 44 |
-
if kwargs.get('ssl') is not False:
|
| 45 |
-
kwargs['ssl'] = custom_ssl
|
| 46 |
-
_orig_tcp_init(self, *args, **kwargs)
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
aiohttp.TCPConnector.__init__ = _patched_tcp_init
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 53 |
-
# ΠΠ°ΡΡ 2: ClientSession β trust_env Π΄Π»Ρ ΠΏΡΠΎΠΊΡΠΈ ΠΈΠ· ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ
|
| 54 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 55 |
-
# HF Spaces ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΎΠΊΡΠΈΡΠΎΠ²Π°ΡΡ ΡΡΠ°ΡΠΈΠΊ ΡΠ΅ΡΠ΅Π· HTTP_PROXY/HTTPS_PROXY.
|
| 56 |
-
# ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ aiohttp ΠΈΠ³Π½ΠΎΡΠΈΡΡΠ΅Ρ ΡΡΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅.
|
| 57 |
-
# trust_env=True Π·Π°ΡΡΠ°Π²Π»ΡΠ΅Ρ aiohttp ΡΠΈΡΠ°ΡΡ ΠΏΡΠΎΠΊΡΠΈ ΠΈΠ· env.
|
| 58 |
-
_orig_session_init = aiohttp.ClientSession.__init__
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
def _patched_session_init(self, *args, **kwargs):
|
| 62 |
-
kwargs['trust_env'] = True
|
| 63 |
-
_orig_session_init(self, *args, **kwargs)
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
aiohttp.ClientSession.__init__ = _patched_session_init
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
# ΠΠ°ΡΡ 3: _request β ΠΏΠ΅ΡΠ΅Π°Π΄ΡΠ΅ΡΠ°ΡΠΈΡ ΠΠ‘Π₯ΠΠΠ―Π©ΠΠ₯ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΊ api.telegram.org ΡΠ΅ΡΠ΅Π· ΠΏΡΠΎΠΊΡΠΈ
|
| 70 |
-
# ΠΠΠΠΠ: ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΠΌΠ΅ΡΠΎΠ΄ ΠΈ Ρ
ΠΎΡΡ, ΡΡΠΎΠ±Ρ Π½Π΅ ΡΠ»ΠΎΠΌΠ°ΡΡ Π²Ρ
ΠΎΠ΄ΡΡΠΈΠ΅ webhook-Π·Π°ΠΏΡΠΎΡΡ ΠΊ Π½Π°ΡΠ΅ΠΌΡ ΡΠ΅ΡΠ²Π΅ΡΡ
|
| 71 |
-
_orig_request = aiohttp.ClientSession._request
|
| 72 |
-
async def _patched_request(self, method, url, *args, **kwargs):
|
| 73 |
-
proxy_server = os.getenv("TELEGRAM_API_SERVER")
|
| 74 |
-
# ΠΠ°ΡΠΈΡΠ°: ΠΏΠ°ΡΡΠΈΠΌ ΡΠΎΠ»ΡΠΊΠΎ ΠΈΡΡ
ΠΎΠ΄ΡΡΠΈΠ΅ POST/GET ΠΊ Telegram API ΠΎΡ ΠΈΠΌΠ΅Π½ΠΈ Π±ΠΎΡΠ°
|
| 75 |
-
if proxy_server and isinstance(url, (str, aiohttp.client.URL)) and "api.telegram.org" in str(url) and str(method).upper() in ("POST", "GET"):
|
| 76 |
-
clean_proxy = proxy_server.strip().rstrip('/')
|
| 77 |
-
# Π£Π±Π΅ΠΆΠ΄Π°Π΅ΠΌΡΡ, ΡΡΠΎ ΡΡΠΎ Π½Π΅ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠΉ ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡ Π½Π°ΡΠ΅Π³ΠΎ ΡΠ΅ΡΠ²Π΅ΡΠ°
|
| 78 |
-
if "bot" in str(url):
|
| 79 |
-
str_url = str(url).replace("https://api.telegram.org", clean_proxy)
|
| 80 |
-
logging.info(f"π Π£ΠΌΠ½Π°Ρ ΠΏΠ΅ΡΠ΅Π°Π΄ΡΠ΅ΡΠ°ΡΠΈΡ Π·Π°ΠΏΡΠΎΡΠ° aiogram ΡΠ΅ΡΠ΅Π· ΠΏΡΠΎΠΊΡΠΈ β‘οΈ {str_url[:80]}...")
|
| 81 |
-
url = str_url
|
| 82 |
-
return await _orig_request(self, method, url, *args, **kwargs)
|
| 83 |
-
aiohttp.ClientSession._request = _patched_request
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bot_modules/utils.py
DELETED
|
@@ -1,126 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Π£ΡΠΈΠ»ΠΈΡΡ: Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ, Π·Π°ΡΠΈΡΠ° ΠΎΡ ΡΠΏΠ°ΠΌΠ°, ΡΠ°Π½ΠΈΡΠΈΠ·Π°ΡΠΈΡ, ΡΠΎΠ½ΠΎΠ²ΡΠ΅ Π·Π°Π΄Π°ΡΠΈ.
|
| 3 |
-
|
| 4 |
-
Π‘ΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΏΠ΅ΡΠ΅ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ, Π½Π΅ ΠΏΡΠΈΠ²ΡΠ·Π°Π½Π½ΡΠ΅ ΠΊ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠΉ
|
| 5 |
-
Π΄ΠΎΠΌΠ΅Π½Π½ΠΎΠΉ ΠΎΠ±Π»Π°ΡΡΠΈ (ΠΠ, AI, Ρ
Π΅Π½Π΄Π»Π΅ΡΡ). ΠΡΠ΅ ΡΡΡΠ½ΠΎΡΡΠΈ β ΡΠΈΡΡΠ°Ρ Π»ΠΎΠ³ΠΈΠΊΠ°
|
| 6 |
-
Π±Π΅Π· ΠΏΠΎΠ±ΠΎΡΠ½ΡΡ
ΡΡΡΠ΅ΠΊΡΠΎΠ² ΠΏΡΠΈ ΠΈΠΌΠΏΠΎΡΡΠ΅.
|
| 7 |
-
"""
|
| 8 |
-
import asyncio
|
| 9 |
-
import logging
|
| 10 |
-
import re
|
| 11 |
-
from datetime import date
|
| 12 |
-
from typing import Dict
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 16 |
-
# USER LOCK MANAGER (Thread-safe, Π±Π΅Π· ΡΡΠ΅ΡΠΊΠΈ ΠΏΠ°ΠΌΡΡΠΈ)
|
| 17 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 18 |
-
class UserLockManager:
|
| 19 |
-
"""ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΉ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΎΠΊ per-user Ρ Π°ΡΠΎΠΌΠ°ΡΠ½ΡΠΌ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ΠΌ Π»ΠΎΠΊΠ°.
|
| 20 |
-
|
| 21 |
-
ΠΠΈΠ·Π½Π΅Ρ-ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ: ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ°Π΅Ρ Race Condition ΠΏΡΠΈ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎΠΉ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ
|
| 22 |
-
Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΎΠ² ΠΎΠ΄Π½ΠΈΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΌ. ΠΠ»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ Π»ΠΎΠΊ Π·Π°ΡΠΈΡΠ°Π΅Ρ dict _locks
|
| 23 |
-
ΠΎΡ ΠΎΠ΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π΄Π²ΡΡ
asyncio.Lock Π΄Π»Ρ ΠΎΠ΄Π½ΠΎΠ³ΠΎ user_id.
|
| 24 |
-
"""
|
| 25 |
-
def __init__(self):
|
| 26 |
-
self._locks: Dict[int, asyncio.Lock] = {}
|
| 27 |
-
self._global_lock = asyncio.Lock()
|
| 28 |
-
|
| 29 |
-
async def get(self, user_id: int) -> asyncio.Lock:
|
| 30 |
-
"""ΠΡΠΎΠΌΠ°ΡΠ½ΠΎ ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ ΠΈΠ»ΠΈ ΡΠΎΠ·Π΄Π°ΡΡ asyncio.Lock Π΄Π»Ρ user_id.
|
| 31 |
-
|
| 32 |
-
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ _global_lock Π΄Π»Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ race condition ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ.
|
| 33 |
-
ΠΡΠ΅ Π²ΡΠ·ΠΎΠ²Ρ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ await: lock = await user_lock_manager.get(user_id)
|
| 34 |
-
"""
|
| 35 |
-
async with self._global_lock:
|
| 36 |
-
if user_id not in self._locks:
|
| 37 |
-
self._locks[user_id] = asyncio.Lock()
|
| 38 |
-
return self._locks[user_id]
|
| 39 |
-
|
| 40 |
-
async def release(self, user_id: int):
|
| 41 |
-
"""ΠΡΠΈΡΡΠΊΠ° Π»ΠΎΠΊΠ° ΠΈΠ· ΠΏΠ°ΠΌΡΡΠΈ Π’ΠΠΠ¬ΠΠ Π΅ΡΠ»ΠΈ ΠΎΠ½ Π½Π΅ Π·Π°Ρ
Π²Π°ΡΠ΅Π½.
|
| 42 |
-
ΠΡΠ·ΡΠ²Π°ΡΡ ΡΡΡΠΎΠ³ΠΎ ΠΠΠ‘ΠΠ Π²ΡΡ
ΠΎΠ΄Π° ΠΈΠ· async with lock."""
|
| 43 |
-
async with self._global_lock:
|
| 44 |
-
if user_id in self._locks and not self._locks[user_id].locked():
|
| 45 |
-
del self._locks[user_id]
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 49 |
-
# GLOBAL SPAM PROTECTOR (Free-tier daily limit)
|
| 50 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 51 |
-
class GlobalSpamProtector:
|
| 52 |
-
"""ΠΠ»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ Π΄Π½Π΅Π²Π½ΠΎΠΉ Π»ΠΈΠΌΠΈΡ Π½Π° Π±Π΅ΡΠΏΠ»Π°ΡΠ½ΡΠ΅ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ.
|
| 53 |
-
|
| 54 |
-
ΠΠΈΠ·Π½Π΅Ρ-ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ: Π·Π°ΡΠΈΡΠ° ΠΎΡ API-Π°Π±ΡΠ·Π° ΠΈ Π±ΠΎΡΠΎΠ², ΡΠ½ΠΈΠΆΠ°Π΅Ρ TCO Π½Π° OpenAI-ΡΠΎΠΊΠ΅Π½Ρ.
|
| 55 |
-
ΠΡΠΈ ΠΏΡΠ΅Π²ΡΡΠ΅Π½ΠΈΠΈ Π»ΠΈΠΌΠΈΡΠ° β graceful degradation Ρ ΠΏΠΎΠ½ΡΡΠ½ΡΠΌ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ΠΌ ΡΠ·Π΅ΡΡ.
|
| 56 |
-
"""
|
| 57 |
-
def __init__(self, daily_limit: int = 1000):
|
| 58 |
-
self.daily_limit = daily_limit
|
| 59 |
-
self.current_count = 0
|
| 60 |
-
self.current_date = date.today()
|
| 61 |
-
|
| 62 |
-
def can_generate(self) -> bool:
|
| 63 |
-
today = date.today()
|
| 64 |
-
if today != self.current_date:
|
| 65 |
-
self.current_date = today
|
| 66 |
-
self.current_count = 0
|
| 67 |
-
|
| 68 |
-
if self.current_count >= self.daily_limit:
|
| 69 |
-
return False
|
| 70 |
-
|
| 71 |
-
self.current_count += 1
|
| 72 |
-
return True
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 76 |
-
# OPENAI SEMAPHORE (ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠ½ΡΡ
Π·Π°ΠΏΡΠΎΡΠΎΠ²)
|
| 77 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 78 |
-
# ΠΠ»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ ΡΠ΅ΠΌΠ°ΡΠΎΡ Π΄Π»Ρ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠ½ΡΡ
Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΊ OpenAI API.
|
| 79 |
-
# ΠΠΈΠ·Π½Π΅Ρ-ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ: Π·Π°ΡΠΈΡΠ° ΠΎΡ cascading failure ΠΏΡΠΈ Π²ΡΠΏΠ»Π΅ΡΠΊΠ°Ρ
Π½Π°Π³ΡΡΠ·ΠΊΠΈ,
|
| 80 |
-
# ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ°Π΅Ρ ΠΈΡΡΠ΅ΡΠΏΠ°Π½ΠΈΠ΅ Π»ΠΈΠΌΠΈΡΠΎΠ² RPM ΠΈ connection pool httpx.
|
| 81 |
-
openai_semaphore = asyncio.Semaphore(10)
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 85 |
-
# MEMORY SYSTEM HELPERS (Sanitize)
|
| 86 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 87 |
-
def _sanitize_memory_key(key: str) -> str:
|
| 88 |
-
"""Strict snake_case sanitize: ΡΠΎΠ»ΡΠΊΠΎ a-z, 0-9, _."""
|
| 89 |
-
if not key:
|
| 90 |
-
return ""
|
| 91 |
-
key = key.lower().strip()
|
| 92 |
-
sanitized = re.sub(r'[^a-z0-9_]', '_', key)
|
| 93 |
-
sanitized = re.sub(r'_+', '_', sanitized)
|
| 94 |
-
sanitized = sanitized.strip('_')
|
| 95 |
-
return sanitized[:50]
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
def _sanitize_memory_value(value: str) -> str:
|
| 99 |
-
"""Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ ΡΠΏΡΠ°Π²Π»ΡΡΡΠΈΡ
ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² ΠΈ truncation Π΄ΠΎ 200 ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ²."""
|
| 100 |
-
if not value:
|
| 101 |
-
return ""
|
| 102 |
-
value = value.strip()
|
| 103 |
-
value = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '', value)
|
| 104 |
-
return value[:200]
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 108 |
-
# SAFE BACKGROUND TASK (ΠΎΠ±ΡΡΡΠΊΠ° Π΄Π»Ρ asyncio.create_task)
|
| 109 |
-
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 110 |
-
def safe_background_task(coro, name: str = "background_task"):
|
| 111 |
-
"""ΠΠ±ΡΡΡΠΊΠ° Π΄Π»Ρ asyncio.create_task Ρ Π³Π°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΌ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ.
|
| 112 |
-
|
| 113 |
-
ΠΠΈΠ·Π½Π΅Ρ-ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ: ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ°Π΅Ρ silent failures ΡΠΎΠ½ΠΎΠ²ΡΡ
Π·Π°Π΄Π°Ρ
|
| 114 |
-
(memory extraction, cleanup), ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈΠ½Π°ΡΠ΅ ΡΠ΅ΡΡΠ»ΠΈ Π±Ρ traceback.
|
| 115 |
-
"""
|
| 116 |
-
task = asyncio.create_task(coro)
|
| 117 |
-
def _on_task_done(t):
|
| 118 |
-
try:
|
| 119 |
-
t.result()
|
| 120 |
-
except asyncio.CancelledError:
|
| 121 |
-
pass
|
| 122 |
-
except Exception as e:
|
| 123 |
-
logging.error(f"β [Background Task '{name}'] ΠΠ΅ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Π½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅: {e}", exc_info=True)
|
| 124 |
-
task.add_done_callback(_on_task_done)
|
| 125 |
-
return task
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|