File size: 8,101 Bytes
086d7f5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
import asyncio
import logging
import sqlite3
import os
from datetime import datetime
import pytz
from aiogram import Bot, Dispatcher, types, F
from aiogram.filters import Command
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
# --- НАСТРОЙКИ ---
# Если запускаешь на ПК, можешь временно заменить os.getenv на свой токен в кавычках
TOKEN = os.getenv("BOT_TOKEN") or "8670682692:AAFM0jiSTY7z30O-PKkUZgj8QSpKX-GwHyo"
ADMIN_ID = 1753037099
CHANNEL_ID = "@TWIXER_MUSIC" # Юзернейм канала с @
CHANNEL_URL = "https://t.me/TWIXER_MUSIC"
MOSCOW_TZ = pytz.timezone('Europe/Moscow')
# --- ИНИЦИАЛИЗАЦИЯ БАЗЫ ДАННЫХ ---
def init_db():
conn = sqlite3.connect('database.db')
cur = conn.cursor()
# Таблица пользователей
cur.execute('''CREATE TABLE IF NOT EXISTS users
(user_id INTEGER PRIMARY KEY, username TEXT, received INTEGER, date TEXT)''')
# Таблица настроек (для ID файла и счетчика)
cur.execute('''CREATE TABLE IF NOT EXISTS settings
(key TEXT PRIMARY KEY, value TEXT)''')
# Установка начального счетчика скачиваний
cur.execute("INSERT OR IGNORE INTO settings (key, value) VALUES ('downloads', '0')")
conn.commit()
conn.close()
def get_setting(key):
conn = sqlite3.connect('database.db')
cur = conn.cursor()
cur.execute("SELECT value FROM settings WHERE key=?", (key,))
res = cur.fetchone()
conn.close()
return res[0] if res else None
def update_setting(key, value):
conn = sqlite3.connect('database.db')
cur = conn.cursor()
cur.execute("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)", (key, value))
conn.commit()
conn.close()
def log_user(user_id, username, received):
conn = sqlite3.connect('database.db')
cur = conn.cursor()
now = datetime.now(MOSCOW_TZ).strftime("%d.%m.%Y %H:%M")
cur.execute("INSERT OR REPLACE INTO users VALUES (?, ?, ?, ?)", (user_id, username, received, now))
conn.commit()
conn.close()
def get_all_users():
conn = sqlite3.connect('database.db')
cur = conn.cursor()
cur.execute("SELECT * FROM users")
data = cur.fetchall()
conn.close()
return data
# --- ИНИЦИАЛИЗАЦИЯ БОТА ---
bot = Bot(token=TOKEN)
dp = Dispatcher()
class AdminStates(StatesGroup):
waiting_for_file = State()
# Клавиатура подписки
def get_sub_kb():
return InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="1. Подписаться на TWIXER", url=CHANNEL_URL)],
[InlineKeyboardButton(text="2. Получить Драм Кит", callback_data="check_sub")]
])
# --- ОБРАБОТЧИКИ ---
@dp.message(Command("start"))
async def start_handler(message: types.Message):
await message.answer(
f"Привет, {message.from_user.first_name}!\n"
f"Чтобы получить данный драм кит, нужно быть подписанным на канал TWIXER",
reply_markup=get_sub_kb()
)
@dp.callback_query(F.data == "check_sub")
async def check_sub_callback(callback: types.CallbackQuery):
user_id = callback.from_user.id
try:
# Проверяем статус в канале
chat_member = await bot.get_chat_member(chat_id=CHANNEL_ID, user_id=user_id)
if chat_member.status in ['member', 'administrator', 'creator']:
file_id = get_setting("drum_kit_file_id")
if not file_id:
await callback.message.answer("Админ еще не загрузил файл в бота.")
await callback.answer()
return
# Увеличиваем счетчик
count = int(get_setting("downloads") or 0) + 1
update_setting("downloads", str(count))
# Логируем пользователя
log_user(user_id, callback.from_user.username, 1)
# Отправляем файл
await callback.message.answer_document(
file_id,
caption=f"Драм кит успешно получен!\n\n🔥 Общее количество скачиваний: {count}"
)
await callback.answer("Файл отправлен!")
else:
# Если не подписан
await callback.answer("Вы не подписаны на канал!", show_alert=True)
await callback.message.answer(
"К сожалению вы не подписаны на канал.\n"
"Чтобы получить драм кит, надо быть подписанным на канал!",
reply_markup=get_sub_kb()
)
except Exception as e:
logging.error(e)
await callback.answer("Ошибка! Убедитесь, что бот добавлен в админы канала.", show_alert=True)
# --- АДМИН-КОМАНДЫ ---
@dp.message(Command("admin"))
async def admin_menu(message: types.Message):
if message.from_user.id != ADMIN_ID:
return
text = (
"⚙️ Меню администратора:\n\n"
"/admin - Показать список команд\n"
"/FileDK - Загрузить/изменить файл драм кита\n"
"/Stata - Посмотреть статистику и подписчиков"
)
await message.answer(text)
@dp.message(Command("FileDK"))
async def admin_file_dk(message: types.Message, state: FSMContext):
if message.from_user.id != ADMIN_ID: return
await message.answer("Пришлите файл (документ), который бот будет выдавать пользователям.")
await state.set_state(AdminStates.waiting_for_file)
@dp.message(AdminStates.waiting_for_file, F.document)
async def save_file_id(message: types.Message, state: FSMContext):
file_id = message.document.file_id
update_setting("drum_kit_file_id", file_id)
await message.answer("✅ Файл успешно сохранен! Теперь пользователи будут получать его.")
await state.clear()
@dp.message(Command("Stata"))
async def admin_stata(message: types.Message):
if message.from_user.id != ADMIN_ID: return
users = get_all_users()
if not users:
await message.answer("Статистика пока пуста.")
return
report = "📊 Детальная статистика:\n\n"
for uid, name, received, date in users:
# Проверяем статус подписки в реальном времени
try:
member = await bot.get_chat_member(chat_id=CHANNEL_ID, user_id=uid)
sub_status = "подписан" if member.status in ['member', 'administrator', 'creator'] else "не подписан"
except:
sub_status = "неизвестно (бот заблокирован?)"
rec_status = "получил(-а) файл" if received == 1 else "не получил(-а)"
username = f"@{name}" if name else f"ID: {uid}"
report += f"👤 {username} {sub_status} {rec_status}\n📅 {date}\n\n"
if len(report) > 3800: # Лимит сообщения в ТГ
await message.answer(report)
report = ""
if report:
await message.answer(report)
# --- ЗАПУСК ---
async def main():
init_db()
logging.basicConfig(level=logging.INFO)
print("Бот запущен!")
await dp.start_polling(bot)
if __name__ == "__main__":
try:
asyncio.run(main())
except (KeyboardInterrupt, SystemExit):
logging.info("Бот остановлен")
|