From 28b9e3b163f604257cf5fa250ab0fc41473b45f8 Mon Sep 17 00:00:00 2001 From: vrubelroman Date: Fri, 12 Dec 2025 11:25:25 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20=D1=81=D0=BE=D0=BE=D0=B1?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broadcast.py | 207 +++++++++++++++++++++ instagram-downloader/instagram_cookies.txt | 6 +- 2 files changed, 210 insertions(+), 3 deletions(-) create mode 100755 broadcast.py diff --git a/broadcast.py b/broadcast.py new file mode 100755 index 0000000..f4f31ad --- /dev/null +++ b/broadcast.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python3 +""" +Скрипт для рассылки сообщений всем пользователям бота. + +Использование: + python broadcast.py "Текст сообщения" + python broadcast.py --html "Жирный текст" + python broadcast.py --file message.txt +""" +import os +import sys +import sqlite3 +import argparse +from pathlib import Path + +# Загружаем переменные окружения из .env если есть +def load_env_file(): + env_file = Path(__file__).resolve().parent / '.env' + if env_file.exists(): + with open(env_file, 'r') as f: + for line in f: + line = line.strip() + if line and not line.startswith('#') and '=' in line: + key, value = line.split('=', 1) + os.environ.setdefault(key.strip(), value.strip()) + +load_env_file() + +import requests +import time + +# Настройки +BASE_DIR = Path(__file__).resolve().parent +DB_FILE = BASE_DIR / 'data' / 'bot.db' +TELEGRAM_BOT_TOKEN = os.getenv('TELEGRAM_BOT_TOKEN') + + +def get_telegram_api_url(): + return f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}" + + +def get_all_users() -> list[tuple[int, str, str]]: + """Получает всех пользователей из базы данных""" + if not DB_FILE.exists(): + print(f"❌ База данных не найдена: {DB_FILE}") + sys.exit(1) + + conn = sqlite3.connect(str(DB_FILE)) + cursor = conn.cursor() + cursor.execute('SELECT chat_id, username, locale FROM users') + users = cursor.fetchall() + conn.close() + return users + + +def send_message(chat_id: int, text: str, parse_mode: str = None) -> bool: + """Отправляет сообщение пользователю""" + payload = { + "chat_id": chat_id, + "text": text, + } + if parse_mode: + payload["parse_mode"] = parse_mode + + try: + response = requests.post( + f"{get_telegram_api_url()}/sendMessage", + json=payload, + timeout=30 + ) + + if response.status_code == 200: + return True + else: + result = response.json() + error = result.get('description', 'Unknown error') + # Пользователь заблокировал бота или удалил чат + if 'blocked' in error.lower() or 'chat not found' in error.lower(): + return False + print(f" ⚠️ {chat_id}: {error}") + return False + except Exception as e: + print(f" ❌ {chat_id}: {e}") + return False + + +def broadcast(text: str, parse_mode: str = None): + """Рассылает сообщение всем пользователям""" + users = get_all_users() + + if not users: + print("❌ Нет пользователей в базе данных") + return + + print(f"📤 Начинаю рассылку для {len(users)} пользователей...") + print(f"📝 Сообщение:\n{text[:100]}{'...' if len(text) > 100 else ''}\n") + + success = 0 + failed = 0 + + for chat_id, username, locale in users: + result = send_message(chat_id, text, parse_mode) + if result: + success += 1 + print(f" ✅ {chat_id} (@{username or 'no_username'})") + else: + failed += 1 + + # Небольшая задержка чтобы не превысить лимиты Telegram + time.sleep(0.05) + + print(f"\n📊 Результат:") + print(f" ✅ Успешно: {success}") + print(f" ❌ Ошибок: {failed}") + print(f" 📨 Всего: {len(users)}") + + +def main(): + parser = argparse.ArgumentParser( + description='Рассылка сообщений всем пользователям бота', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Примеры: + python broadcast.py "Привет! Это важное сообщение." + python broadcast.py --html "Важно! Новая функция добавлена." + python broadcast.py --file announcement.txt + python broadcast.py --file announcement.txt --html + """ + ) + + parser.add_argument( + 'message', + nargs='?', + help='Текст сообщения для рассылки' + ) + parser.add_argument( + '--html', + action='store_true', + help='Использовать HTML-разметку в сообщении' + ) + parser.add_argument( + '--file', '-f', + type=str, + help='Файл с текстом сообщения' + ) + parser.add_argument( + '--list', '-l', + action='store_true', + help='Показать список пользователей без отправки' + ) + parser.add_argument( + '--yes', '-y', + action='store_true', + help='Пропустить подтверждение' + ) + + args = parser.parse_args() + + # Проверяем токен + if not TELEGRAM_BOT_TOKEN: + print("❌ TELEGRAM_BOT_TOKEN не установлен!") + print(" Установите переменную окружения или создайте .env файл") + sys.exit(1) + + # Показать список пользователей + if args.list: + users = get_all_users() + print(f"👥 Всего пользователей: {len(users)}\n") + for chat_id, username, locale in users: + print(f" {chat_id:>12} | @{username or 'no_username':<20} | {locale}") + sys.exit(0) + + # Получаем текст сообщения + if args.file: + file_path = Path(args.file) + if not file_path.exists(): + print(f"❌ Файл не найден: {args.file}") + sys.exit(1) + text = file_path.read_text(encoding='utf-8') + elif args.message: + text = args.message + else: + parser.print_help() + sys.exit(1) + + if not text.strip(): + print("❌ Сообщение не может быть пустым") + sys.exit(1) + + # Подтверждение + users = get_all_users() + print(f"⚠️ Вы собираетесь отправить сообщение {len(users)} пользователям.") + + if not args.yes: + confirm = input("Продолжить? (y/N): ").strip().lower() + if confirm != 'y': + print("❌ Отменено") + sys.exit(0) + + # Отправляем + parse_mode = 'HTML' if args.html else None + broadcast(text, parse_mode) + + +if __name__ == '__main__': + main() + diff --git a/instagram-downloader/instagram_cookies.txt b/instagram-downloader/instagram_cookies.txt index e3a156f..8fae77f 100644 --- a/instagram-downloader/instagram_cookies.txt +++ b/instagram-downloader/instagram_cookies.txt @@ -38,15 +38,15 @@ rusoska.com FALSE / FALSE 1799795493 userToken a01e24c3-c94f-4a4e-b11b-751b72046 .bongacams.com TRUE / FALSE 1796771469 ls01 %7B%22th_type%22%3A%22live%22%2C%22display%22%3A%22medium%22%7D .mozilla.org TRUE / FALSE 1799925684 _ga_B9CY1C9VBC GS2.1.s1765365263$o1$g1$t1765365684$j60$l0$h0 .mozilla.org TRUE / FALSE 1799925263 _ga GA1.2.1451822324.1765365263 -.instagram.com TRUE / TRUE 1800085241 csrftoken CnChQ6nTz8cfm_U7q2ur9w +.instagram.com TRUE / TRUE 1800087827 csrftoken CnChQ6nTz8cfm_U7q2ur9w .instagram.com TRUE / TRUE 1799925292 datr LFY5aVDEvvzQRTypNm_NZ0d3 .instagram.com TRUE / TRUE 1796901312 ig_did B0879634-89D6-4098-9B3E-958B6BC00183 .instagram.com TRUE / TRUE 1765970112 dpr 2 .instagram.com TRUE / TRUE 1799925293 mid aTlWLAAEAAEBRoS_PfrA_i5UP0w1 .instagram.com TRUE / TRUE 1766008776 wd 1920x944 .instagram.com TRUE / TRUE 1796939890 sessionid 42059678244%3AD0GdfKmaFZWqXp%3A10%3AAYgpCODjycI3EWMR6G5Uh6kXjroGZ6pb1IRJmXGX3g -.instagram.com TRUE / TRUE 1773301241 ds_user_id 42059678244 -.instagram.com TRUE / TRUE 0 rur "LDC\05442059678244\0541797061240:01fe985ff74de9ed73460fbffd0fb6620fd751ad0a7ff4257430368aa35e2866cf4f184a" +.instagram.com TRUE / TRUE 1773303827 ds_user_id 42059678244 +.instagram.com TRUE / TRUE 0 rur "LDC\05442059678244\0541797063826:01fe4af62175a80bcbb48930ff03aa6c92740a54197d1ba96c088c3e257156b522f8ba94" addons.mozilla.org FALSE / TRUE 0 taarId 4dffa50e49cca797bb48f2f4f11803c251746ad45af1fef3ba1ad37379a24fea .facebook.com TRUE / TRUE 1799963979 datr S-05aRMEAJEaLLwYCMb4y3JM .facebook.com TRUE / TRUE 1766008781 wd 1920x944