Добавлено автоматическое обновление Instagram cookies и поддержание сессии
- Автоматическая проверка срока действия cookies каждые 24 часа - Автоматическое обновление cookies за 3 дня до истечения из браузера - Поддержание активности сессии через периодические запросы - Поддержка Chrome, Firefox, Edge, Opera для обновления cookies - Добавлена функция update_instagram_cookies_from_browser() - Добавлена функция check_instagram_cookies_expiry() - Фоновая задача keep_instagram_session_alive() для поддержания сессии - Обновлена документация в README.md - Добавлена переменная INSTAGRAM_AUTO_UPDATE_DAYS в .env.example
This commit is contained in:
parent
ab82f94032
commit
aa5c4cd1e6
3 changed files with 233 additions and 1 deletions
|
|
@ -8,3 +8,6 @@ TELEGRAM_BOT_USERNAME=vrubelVideoDownload_bot
|
|||
# Для локальной разработки: http://localhost:5555
|
||||
# Для продакшена: http://<ip_хоста_с_vk_сервисом>:5555
|
||||
VK_DOWNLOADER_URL=http://localhost:5555
|
||||
|
||||
# Количество дней до истечения cookies, когда начинать автоматическое обновление (по умолчанию: 3)
|
||||
INSTAGRAM_AUTO_UPDATE_DAYS=3
|
||||
|
|
|
|||
|
|
@ -54,7 +54,13 @@ VK_DOWNLOADER_URL=http://localhost:5555
|
|||
2. Сохраните файл как `instagram_cookies.txt` в корне проекта
|
||||
3. Формат: Netscape cookies file
|
||||
|
||||
**Примечание:** Без cookies Instagram может блокировать запросы.
|
||||
**Автоматическое обновление cookies:**
|
||||
- Бот автоматически проверяет срок действия cookies каждые 24 часа
|
||||
- Если cookies истекают через 3 дня (настраивается через `INSTAGRAM_AUTO_UPDATE_DAYS`), бот попытается автоматически обновить их из браузера
|
||||
- Поддерживаются браузеры: Chrome, Firefox, Edge, Opera (по приоритету)
|
||||
- Для автоматического обновления браузер должен быть установлен и доступен
|
||||
|
||||
**Примечание:** Без cookies Instagram может блокировать запросы. При первом запуске или если автоматическое обновление не сработало, обновите cookies вручную.
|
||||
|
||||
### 4. Запуск основного бота
|
||||
|
||||
|
|
|
|||
223
bot.py
223
bot.py
|
|
@ -4,6 +4,8 @@ import json
|
|||
import logging
|
||||
import asyncio
|
||||
import sqlite3
|
||||
import time
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlparse
|
||||
from datetime import datetime
|
||||
|
|
@ -248,6 +250,15 @@ async def download_instagram_video(url: str, chat_id: int, max_retries: int = 3)
|
|||
cookies_file = os.getenv('INSTAGRAM_COOKIES_FILE', 'instagram_cookies.txt')
|
||||
cookies_file_path = Path(cookies_file)
|
||||
|
||||
# Проверяем срок действия cookies перед использованием
|
||||
if cookies_file_path.exists():
|
||||
is_valid, days_left = check_instagram_cookies_expiry()
|
||||
if not is_valid:
|
||||
logger.error("Instagram cookies истекли! Необходимо обновить cookies.")
|
||||
raise Exception("Instagram cookies истекли. Пожалуйста, обновите cookies в файле instagram_cookies.txt")
|
||||
elif days_left < 7:
|
||||
logger.warning(f"Instagram cookies истекают через {days_left} дней. Рекомендуется обновить.")
|
||||
|
||||
# Парсим cookies для получения csrf token (формат Netscape)
|
||||
csrf_token = None
|
||||
sessionid = None
|
||||
|
|
@ -329,6 +340,209 @@ async def download_instagram_video(url: str, chat_id: int, max_retries: int = 3)
|
|||
raise last_error or Exception("Неизвестная ошибка при скачивании с Instagram. Возможно, нужно обновить cookies.")
|
||||
|
||||
|
||||
async def update_instagram_cookies_from_browser(browser: str = 'chrome') -> bool:
|
||||
"""
|
||||
Автоматически обновляет Instagram cookies из браузера
|
||||
Returns: True если успешно, False если ошибка
|
||||
"""
|
||||
cookies_file = os.getenv('INSTAGRAM_COOKIES_FILE', 'instagram_cookies.txt')
|
||||
cookies_file_path = Path(cookies_file)
|
||||
|
||||
try:
|
||||
logger.info(f"Попытка обновления Instagram cookies из браузера {browser}...")
|
||||
|
||||
# Пробуем обновить cookies из браузера
|
||||
loop = asyncio.get_event_loop()
|
||||
result = await loop.run_in_executor(
|
||||
None,
|
||||
lambda: subprocess.run(
|
||||
[
|
||||
'yt-dlp',
|
||||
'--cookies-from-browser', browser,
|
||||
'--cookies', str(cookies_file_path.absolute()),
|
||||
'--no-download',
|
||||
'https://www.instagram.com/'
|
||||
],
|
||||
capture_output=True,
|
||||
timeout=30,
|
||||
text=True
|
||||
)
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
logger.info(f"✅ Instagram cookies успешно обновлены из браузера {browser}")
|
||||
return True
|
||||
else:
|
||||
logger.warning(f"Не удалось обновить cookies из {browser}: {result.stderr[:200]}")
|
||||
return False
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
logger.warning(f"Таймаут при обновлении cookies из {browser}")
|
||||
return False
|
||||
except FileNotFoundError:
|
||||
logger.warning(f"yt-dlp не найден для обновления cookies")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при обновлении cookies из браузера: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def check_instagram_cookies_expiry() -> tuple[bool, int]:
|
||||
"""
|
||||
Проверяет срок действия Instagram cookies
|
||||
Returns: (is_valid, days_until_expiry)
|
||||
"""
|
||||
cookies_file = os.getenv('INSTAGRAM_COOKIES_FILE', 'instagram_cookies.txt')
|
||||
cookies_file_path = Path(cookies_file)
|
||||
|
||||
if not cookies_file_path.exists():
|
||||
return False, 0
|
||||
|
||||
try:
|
||||
current_time = time.time()
|
||||
min_expiry = None
|
||||
|
||||
with open(cookies_file_path, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
parts = line.split('\t')
|
||||
if len(parts) >= 7:
|
||||
domain = parts[0]
|
||||
if 'instagram' in domain.lower():
|
||||
try:
|
||||
expiry = int(parts[4]) # Unix timestamp
|
||||
if min_expiry is None or expiry < min_expiry:
|
||||
min_expiry = expiry
|
||||
except (ValueError, IndexError):
|
||||
continue
|
||||
|
||||
if min_expiry is None:
|
||||
return False, 0
|
||||
|
||||
days_until_expiry = (min_expiry - current_time) / 86400
|
||||
is_valid = min_expiry > current_time
|
||||
|
||||
return is_valid, int(days_until_expiry)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при проверке срока действия cookies: {e}")
|
||||
return False, 0
|
||||
|
||||
|
||||
async def keep_instagram_session_alive():
|
||||
"""Поддерживает сессию Instagram активной через периодические запросы и автоматически обновляет cookies"""
|
||||
cookies_file = os.getenv('INSTAGRAM_COOKIES_FILE', 'instagram_cookies.txt')
|
||||
cookies_file_path = Path(cookies_file)
|
||||
AUTO_UPDATE_DAYS_BEFORE_EXPIRY = int(os.getenv('INSTAGRAM_AUTO_UPDATE_DAYS', '3')) # Обновлять за 3 дня до истечения
|
||||
|
||||
if not cookies_file_path.exists():
|
||||
logger.info("Instagram cookies не найдены, пропускаем поддержание сессии")
|
||||
return
|
||||
|
||||
# Список браузеров для попытки обновления (по приоритету)
|
||||
browsers_to_try = ['chrome', 'firefox', 'edge', 'opera']
|
||||
|
||||
# Проверяем cookies при старте
|
||||
is_valid, days_left = check_instagram_cookies_expiry()
|
||||
if not is_valid:
|
||||
logger.warning("Instagram cookies истекли! Пытаемся автоматически обновить...")
|
||||
# Пытаемся обновить из браузера
|
||||
updated = False
|
||||
for browser in browsers_to_try:
|
||||
if await update_instagram_cookies_from_browser(browser):
|
||||
updated = True
|
||||
break
|
||||
|
||||
if not updated:
|
||||
logger.error("Не удалось автоматически обновить cookies! Необходимо обновить вручную.")
|
||||
return
|
||||
else:
|
||||
# Перепроверяем после обновления
|
||||
is_valid, days_left = check_instagram_cookies_expiry()
|
||||
|
||||
if days_left < AUTO_UPDATE_DAYS_BEFORE_EXPIRY:
|
||||
logger.warning(f"Instagram cookies истекают через {days_left} дней! Пытаемся автоматически обновить...")
|
||||
# Пытаемся обновить заранее
|
||||
for browser in browsers_to_try:
|
||||
if await update_instagram_cookies_from_browser(browser):
|
||||
# Перепроверяем
|
||||
_, days_left = check_instagram_cookies_expiry()
|
||||
logger.info(f"Cookies обновлены! Новый срок: {days_left} дней")
|
||||
break
|
||||
else:
|
||||
logger.info(f"Instagram cookies действительны еще {days_left} дней")
|
||||
|
||||
# Интервал проверки: 24 часа (86400 секунд)
|
||||
check_interval = 86400
|
||||
|
||||
while True:
|
||||
try:
|
||||
await asyncio.sleep(check_interval)
|
||||
|
||||
# Проверяем срок действия перед каждым запросом
|
||||
is_valid, days_left = check_instagram_cookies_expiry()
|
||||
|
||||
# Автоматическое обновление за N дней до истечения
|
||||
if days_left < AUTO_UPDATE_DAYS_BEFORE_EXPIRY and days_left > 0:
|
||||
logger.warning(f"Instagram cookies истекают через {days_left} дней. Автоматическое обновление...")
|
||||
updated = False
|
||||
for browser in browsers_to_try:
|
||||
if await update_instagram_cookies_from_browser(browser):
|
||||
updated = True
|
||||
_, days_left = check_instagram_cookies_expiry()
|
||||
logger.info(f"✅ Cookies обновлены автоматически! Новый срок: {days_left} дней")
|
||||
break
|
||||
|
||||
if not updated:
|
||||
logger.warning("Не удалось автоматически обновить cookies. Попробуйте обновить вручную.")
|
||||
|
||||
if not is_valid:
|
||||
logger.error("Instagram cookies истекли! Пытаемся автоматически обновить...")
|
||||
updated = False
|
||||
for browser in browsers_to_try:
|
||||
if await update_instagram_cookies_from_browser(browser):
|
||||
updated = True
|
||||
is_valid, days_left = check_instagram_cookies_expiry()
|
||||
break
|
||||
|
||||
if not updated:
|
||||
logger.error("Не удалось автоматически обновить cookies! Остановка поддержания сессии.")
|
||||
break
|
||||
|
||||
# Делаем легкий запрос к Instagram для поддержания активности
|
||||
logger.info("Поддерживаем активность сессии Instagram...")
|
||||
try:
|
||||
ydl_opts = {
|
||||
'cookiefile': str(cookies_file_path.absolute()),
|
||||
'quiet': True,
|
||||
'no_warnings': True,
|
||||
'socket_timeout': 10,
|
||||
}
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(
|
||||
None,
|
||||
lambda: yt_dlp.YoutubeDL(ydl_opts).extract_info(
|
||||
'https://www.instagram.com/',
|
||||
download=False
|
||||
)
|
||||
)
|
||||
|
||||
logger.info(f"Сессия Instagram успешно обновлена. Cookies действительны еще {days_left} дней")
|
||||
except Exception as e:
|
||||
logger.warning(f"Не удалось обновить сессию Instagram: {e}")
|
||||
# Продолжаем работу, попробуем в следующий раз
|
||||
|
||||
except asyncio.CancelledError:
|
||||
logger.info("Поддержание сессии Instagram остановлено")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка в задаче поддержания сессии Instagram: {e}")
|
||||
# Ждем перед следующей попыткой
|
||||
await asyncio.sleep(3600) # 1 час
|
||||
|
||||
|
||||
async def download_vk_video(url: str, chat_id: int, max_retries: int = 3) -> str:
|
||||
"""Скачивает видео с VK через внешний сервис"""
|
||||
logger.info(f"VK: отправка запроса на внешний сервис {VK_DOWNLOADER_URL}")
|
||||
|
|
@ -525,6 +739,15 @@ def main():
|
|||
application.add_handler(CommandHandler("start", start_command))
|
||||
application.add_handler(CommandHandler("stat", stat_command))
|
||||
|
||||
# Запускаем фоновую задачу для поддержания сессии Instagram
|
||||
async def post_init(application: Application):
|
||||
"""Выполняется после инициализации приложения"""
|
||||
# Запускаем задачу поддержания сессии Instagram в фоне
|
||||
asyncio.create_task(keep_instagram_session_alive())
|
||||
logger.info("Фоновая задача поддержания сессии Instagram запущена")
|
||||
|
||||
application.post_init = post_init
|
||||
|
||||
# Запускаем бота
|
||||
logger.info("Бот запущен")
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue