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("Бот остановлен")