FreshPixels commited on
Commit
53237d0
Β·
verified Β·
1 Parent(s): db464cd

Delete bot_modules

Browse files
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
-