diff --git a/bot.py b/bot.py index fe9056c..6da2506 100644 --- a/bot.py +++ b/bot.py @@ -1,5 +1,6 @@ import os import asyncio +import sqlite3 from functools import wraps from dotenv import load_dotenv from aiogram import Bot, Dispatcher, types @@ -57,10 +58,10 @@ async def cmd_start(message: Message): ]) await message.answer( "🌑 *МракоЗвон*\n\n" - "📥 Отправь номер телефона — сохраню.\n" - "🃏 Отправь QR-код бонусной карты — привяжу.\n" - "📎 Отправь номер + QR вместе — свяжу их.\n\n" - "🎲 /get — случайный номер из базы\n" + "📞 Отправь номер телефона — сохраню.\n" + "🃏 Отправь QR-код бонусной карты — сохраню.\n" + "🔗 Отправь номер + QR вместе — свяжу их.\n\n" + "🎲 /get — случайная запись из базы\n" "📊 /stats — статистика\n" "🗑 /del <номер> — удалить номер\n\n" "🌐 Кнопка ниже — веб-морда", @@ -80,6 +81,7 @@ async def cmd_get(message: Message): record_type = record['type'] phone = record.get('phone') qr_code = record.get('qr_code') + qr_data = record.get('qr_data') if record_type == 'both' and qr_code: await message.answer_photo( @@ -93,9 +95,10 @@ async def cmd_get(message: Message): parse_mode="Markdown" ) elif record_type == 'qr' and qr_code: + short_data = qr_data[:50] + '...' if qr_data and len(qr_data) > 50 else (qr_data or '—') await message.answer_photo( photo=qr_code, - caption=f"🎲 *МракоЗвон*\n🃏 Бонусная карта\n🔄 Использована: {record['usage_count']} раз", + caption=f"🎲 *МракоЗвон*\n🃏 Бонусная карта\n📝 Данные: `{short_data}`\n🔄 Использована: {record['usage_count']} раз", parse_mode="Markdown" ) @@ -103,15 +106,18 @@ async def cmd_get(message: Message): @dp.message(Command("stats")) @allowed_only async def cmd_stats(message: Message): - all_nums = db.get_all_numbers() - total = len(all_nums) - used_total = sum(n["usage_count"] for n in all_nums) - with_card = sum(1 for n in all_nums if n.get("bonus_card")) + records = db.get_all_records() + total = len(records) + phones = sum(1 for r in records if r['type'] in ('phone', 'both')) + qrs = sum(1 for r in records if r['type'] in ('qr', 'both')) + both = sum(1 for r in records if r['type'] == 'both') + await message.answer( f"📊 *Статистика МракоЗвона*\n\n" - f"📞 Всего номеров: {total}\n" - f"🃏 Из них с бонусными картами: {with_card}\n" - f"🔄 Всего использований: {used_total}", + f"📝 Всего записей: {total}\n" + f"📞 Из них номеров: {phones}\n" + f"🃏 Из них карт: {qrs}\n" + f"🔗 Связок номер+карта: {both}", parse_mode="Markdown" ) @@ -129,10 +135,11 @@ async def cmd_delete_number(message: Message): await message.answer("⚠️ Некорректный формат номера") return - all_nums = db.get_all_numbers() - for num in all_nums: - if num["phone"] == normalized: - db.delete_number(num["id"]) + # Ищем запись с таким номером + records = db.get_all_records() + for record in records: + if record.get('phone') == normalized: + db.delete_record(record['id']) await message.answer(f"✅ Номер {normalized} удалён") return @@ -212,7 +219,7 @@ async def cmd_whitelist(message: Message): await message.answer(text, parse_mode="Markdown") -# ========== ОБРАБОТЧИК СООБЩЕНИЙ (НОМЕРА + QR) ========== +# ========== ОБРАБОТЧИК СООБЩЕНИЙ ========== @dp.message() @allowed_only async def handle_message(message: Message): @@ -235,17 +242,15 @@ async def handle_message(message: Message): # 3. Определяем тип записи и сохраняем if phone and qr_raw_data: - # Тип: номер + QR db.add_record('both', phone=phone, qr_code=qr_image, qr_data=qr_raw_data) await message.answer(f"✅ Сохранено: номер `{phone}` + бонусная карта", parse_mode="Markdown") elif phone: - # Тип: только номер db.add_record('phone', phone=phone) await message.answer(f"✅ Сохранён номер: `{phone}`", parse_mode="Markdown") elif qr_raw_data: - # Тип: только QR db.add_record('qr', qr_code=qr_image, qr_data=qr_raw_data) - await message.answer(f"🃏 Сохранена бонусная карта: `{qr_raw_data[:50]}...`", parse_mode="Markdown") + short_data = qr_raw_data[:50] + '...' if len(qr_raw_data) > 50 else qr_raw_data + await message.answer(f"🃏 Сохранена бонусная карта: `{short_data}`", parse_mode="Markdown") else: await message.answer("⚠️ Не распознано. Отправь номер, QR-код или оба вместе.") @@ -254,21 +259,45 @@ async def handle_message(message: Message): routes = web.RouteTableDef() +@routes.get("/get_webapp") +async def serve_webapp(request): + try: + with open("web_app.html", "r", encoding="utf-8") as f: + html = f.read() + return web.Response(text=html, content_type="text/html") + except FileNotFoundError: + return web.Response(text="web_app.html not found", status=404) + + @routes.get("/get_records") async def get_records(request): records = db.get_all_records() - return web.json_response({"records": records}) + # Убираем qr_code из списка для экономии (будем подгружать отдельно) + safe_records = [] + for r in records: + safe_records.append({ + "id": r["id"], + "type": r["type"], + "phone": r.get("phone"), + "qr_data": r.get("qr_data"), + "created_at": r["created_at"], + "used_at": r.get("used_at"), + "usage_count": r["usage_count"] + }) + return web.json_response({"records": safe_records}) + @routes.get("/get_qr_code/{record_id}") async def get_qr_code(request): record_id = int(request.match_info.get('record_id', 0)) - with sqlite3.connect(DB_NAME) as conn: + with sqlite3.connect(db.DB_NAME) as conn: conn.row_factory = sqlite3.Row result = conn.execute("SELECT qr_code FROM records WHERE id = ?", (record_id,)).fetchone() if result and result['qr_code']: return web.json_response({"qr_code": result['qr_code']}) return web.json_response({"qr_code": None}) + @routes.post("/delete_record") async def delete_record(request): data = await request.json() @@ -276,17 +305,6 @@ async def delete_record(request): return web.json_response({"status": "ok"}) -@routes.get("/get_bonus_card/{record_id}") -async def get_bonus_card(request): - record_id = int(request.match_info.get('record_id', 0)) - bonus_card = db.get_bonus_card(record_id) - - if bonus_card: - return web.json_response({"bonus_card": bonus_card}) - - return web.json_response({"bonus_card": None}) - - async def start_webapp(): app = web.Application() app.add_routes(routes)