refactor requirements and rss_generator: replace direct get_chat calls with cached_get_chat for improved performance and update requirements.txt to uncomment Kurigram
This commit is contained in:
+2
-2
@@ -1,8 +1,8 @@
|
||||
fastapi==0.115.8
|
||||
uvicorn==0.34.0
|
||||
python-multipart==0.0.20
|
||||
#Kurigram
|
||||
git+https://github.com/KurimuzonAkuma/pyrogram.git@dev#egg=Kurigram
|
||||
Kurigram
|
||||
#git+https://github.com/KurimuzonAkuma/pyrogram.git@dev#egg=Kurigram
|
||||
TgCrypto
|
||||
uvloop
|
||||
pillow==11.1.0
|
||||
|
||||
+8
-4
@@ -333,10 +333,12 @@ async def generate_channel_rss(channel: str | int,
|
||||
|
||||
channel_info_start_time = time.time()
|
||||
try:
|
||||
from tg_cache import cached_get_chat
|
||||
|
||||
channel = post_parser.channel_name_prepare(channel)
|
||||
channel_info = await post_parser.client.get_chat(channel)
|
||||
channel_info = await cached_get_chat(post_parser.client, channel)
|
||||
channel_title = channel_info.title or f"Telegram: {channel}"
|
||||
channel_username = post_parser.get_channel_username(channel_info)
|
||||
channel_username = channel_info.username or (str(channel_info.id) if channel_info.id and str(channel_info.id).startswith('-100') else None)
|
||||
if not channel_username:
|
||||
# Use prepared channel (which could be int) for error feed if username fails
|
||||
logger.warning(f"Could not get username for channel {channel}, using identifier for error feed.")
|
||||
@@ -468,10 +470,12 @@ async def generate_channel_html(channel: str | int,
|
||||
|
||||
channel_info_start_time = time.time()
|
||||
try:
|
||||
from tg_cache import cached_get_chat
|
||||
|
||||
channel = post_parser.channel_name_prepare(channel)
|
||||
logger.debug(f"Prepared channel identifier for HTML: {channel} (type: {type(channel)})") # Log prepared channel
|
||||
channel_info = await post_parser.client.get_chat(channel)
|
||||
channel_username = post_parser.get_channel_username(channel_info)
|
||||
channel_info = await cached_get_chat(post_parser.client, channel)
|
||||
channel_username = channel_info.username or (str(channel_info.id) if channel_info.id and str(channel_info.id).startswith('-100') else None)
|
||||
if not channel_username:
|
||||
logger.warning(f"Could not get username for channel {channel} in HTML generation, returning error feed structure (as string). NOTE: This should ideally return HTML error page.")
|
||||
# For HTML, returning an error feed string might not be ideal. Consider returning a dedicated HTML error page.
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import json
|
||||
import pickle
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Optional, Union
|
||||
from pyrogram import Client
|
||||
from pyrogram.types import Chat, Message
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Путь к директории кеша
|
||||
CACHE_DIR = os.path.join('data', 'tgcache')
|
||||
|
||||
def _get_cache_file_path(channel_id: Union[str, int]) -> str:
|
||||
"""Возвращает путь к файлу кеша для канала"""
|
||||
if not os.path.exists(CACHE_DIR):
|
||||
os.makedirs(CACHE_DIR, exist_ok=True)
|
||||
logger.debug(f"cache_dir_created: path {CACHE_DIR}")
|
||||
# Преобразуем в строку для унификации
|
||||
channel_id_str = str(channel_id)
|
||||
# Заменяем потенциально проблемные символы
|
||||
safe_filename = channel_id_str.replace('/', '_').replace('\\', '_')
|
||||
return os.path.join(CACHE_DIR, f"{safe_filename}.cache")
|
||||
|
||||
def _save_to_cache(channel_id: Union[str, int], chat_data: Chat) -> None:
|
||||
"""Сохраняет данные чата в кеш"""
|
||||
try:
|
||||
cache_file = _get_cache_file_path(channel_id)
|
||||
|
||||
# Создаем метаданные кеша
|
||||
cache_data = {
|
||||
'timestamp': time.time(),
|
||||
'chat_data': pickle.dumps(chat_data)
|
||||
}
|
||||
|
||||
with open(cache_file, 'wb') as f:
|
||||
pickle.dump(cache_data, f)
|
||||
|
||||
logger.debug(f"chat_cache_saved: channel {channel_id}, file {cache_file}")
|
||||
except Exception as e:
|
||||
logger.error(f"cache_save_error: channel {channel_id}, error {str(e)}")
|
||||
|
||||
def _get_from_cache(channel_id: Union[str, int], max_age_seconds: int = 86400) -> Optional[Chat]:
|
||||
"""
|
||||
Получает данные чата из кеша если они не старше указанного возраста
|
||||
|
||||
Args:
|
||||
channel_id: ID или username канала
|
||||
max_age_seconds: Максимальный возраст кеша в секундах (по умолчанию 1 день)
|
||||
|
||||
Returns:
|
||||
Chat объект или None если кеш не найден или устарел
|
||||
"""
|
||||
try:
|
||||
cache_file = _get_cache_file_path(channel_id)
|
||||
|
||||
if not os.path.exists(cache_file):
|
||||
logger.debug(f"chat_cache_miss: channel {channel_id}, cache file not found")
|
||||
return None
|
||||
|
||||
with open(cache_file, 'rb') as f:
|
||||
cache_data = pickle.load(f)
|
||||
|
||||
# Проверяем возраст кеша
|
||||
cache_age = time.time() - cache_data['timestamp']
|
||||
if cache_age > max_age_seconds:
|
||||
logger.debug(f"chat_cache_expired: channel {channel_id}, age {cache_age:.1f}s > max {max_age_seconds}s")
|
||||
return None
|
||||
|
||||
# Восстанавливаем объект Chat из пикла
|
||||
chat_data = pickle.loads(cache_data['chat_data'])
|
||||
logger.debug(f"chat_cache_hit: channel {channel_id}, age {cache_age:.1f}s")
|
||||
return chat_data
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"cache_read_error: channel {channel_id}, error {str(e)}")
|
||||
# В случае ошибки чтения кеша лучше вернуть None и запросить свежие данные
|
||||
return None
|
||||
|
||||
def adapt_chat_for_get_username(chat: Chat) -> Chat:
|
||||
"""
|
||||
Адаптирует объект Chat для использования в методе get_channel_username
|
||||
|
||||
Метод get_channel_username ожидает объект Message, но использует только его атрибут chat,
|
||||
поэтому мы можем передать сам объект Chat без обертки
|
||||
"""
|
||||
return chat
|
||||
|
||||
async def cached_get_chat(client: Client, channel_id: Union[str, int], cache_ttl: int = 86400) -> Chat:
|
||||
"""
|
||||
Получает информацию о чате с кешированием.
|
||||
|
||||
Args:
|
||||
client: Pyrogram клиент
|
||||
channel_id: ID или username канала
|
||||
cache_ttl: Время жизни кеша в секундах (по умолчанию 1 день)
|
||||
|
||||
Returns:
|
||||
Chat объект, как и оригинальный client.get_chat()
|
||||
"""
|
||||
# Пробуем получить из кеша
|
||||
cached_chat = _get_from_cache(channel_id, cache_ttl)
|
||||
|
||||
if cached_chat is not None:
|
||||
return cached_chat
|
||||
|
||||
# Если в кеше нет или кеш устарел, запрашиваем через API
|
||||
try:
|
||||
logger.debug(f"chat_cache_request: fetching fresh data for channel {channel_id}")
|
||||
chat_data = await client.get_chat(channel_id)
|
||||
|
||||
# Сохраняем в кеш
|
||||
_save_to_cache(channel_id, chat_data)
|
||||
|
||||
return chat_data
|
||||
except Exception as e:
|
||||
logger.error(f"chat_request_error: channel {channel_id}, error {str(e)}")
|
||||
# Пробрасываем ошибку дальше, как и оригинальный метод
|
||||
raise
|
||||
Reference in New Issue
Block a user