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