From 6d2b4b6346c84f2e055a238b139800ba086539f3 Mon Sep 17 00:00:00 2001 From: Faynot Date: Sat, 28 Mar 2026 20:59:54 +0300 Subject: [PATCH] feat: bot start, database --- .gitignore | 2 ++ bot.py | 70 ++++++++++++++++++++++++++------------------- database.py | 29 +++++++++++++++++++ main.py => kwork.py | 0 4 files changed, 71 insertions(+), 30 deletions(-) create mode 100644 database.py rename main.py => kwork.py (100%) diff --git a/.gitignore b/.gitignore index 4c49bd7..4a1c781 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .env +*.db +/__pycache__ diff --git a/bot.py b/bot.py index d6db686..c64ff55 100644 --- a/bot.py +++ b/bot.py @@ -7,52 +7,62 @@ from aiogram import Bot, Dispatcher, html from aiogram.client.default import DefaultBotProperties from aiogram.enums import ParseMode from aiogram.filters import CommandStart -from aiogram.types import Message +from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton from dotenv import load_dotenv +from aiogram import F +from aiogram.fsm.context import FSMContext +from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder +from database import Database load_dotenv() - -# Bot token can be obtained via https://t.me/BotFather TOKEN = getenv("BOT_TOKEN") - -# All handlers should be attached to the Router (or Dispatcher) - dp = Dispatcher() +db = Database("users.db") + +async def on_startup(): + await db.create_tables() + print("db 200") @dp.message(CommandStart()) async def command_start_handler(message: Message) -> None: - """ - This handler receives messages with `/start` command - """ - # Most event objects have aliases for API methods that can be called in events' context - # For example if you want to answer to incoming message you can use `message.answer(...)` alias - # and the target chat will be passed to :ref:`aiogram.methods.send_message.SendMessage` - # method automatically or call API method directly via - # Bot instance: `bot.send_message(chat_id=message.chat.id, ...)` - await message.answer(f"Hello, {html.bold(message.from_user.full_name)}!") + builder = InlineKeyboardBuilder() + builder.row(InlineKeyboardButton(text="✅ Подписаться", callback_data="subscribe")) + builder.row(InlineKeyboardButton(text="📄 Читать оферту", url="https://telegra.ph/Polzovatelskoe-soglashenie-i-Oferta-qwork-parse-bot-03-28")) + text = ( + "👋 Привет! Я твой персональный агент по Kwork.\n\n" + "🔍 Я мониторю биржу 24/7 и мгновенно присылаю тебе свежие заказы.\n\n" + "⚠️ Нажимая кнопку «Подписаться», вы принимаете условия " + "публичной оферты." + ) -@dp.message() -async def echo_handler(message: Message) -> None: - """ - Handler will forward receive a message back to the sender + await message.answer( + text, + reply_markup=builder.as_markup(), + parse_mode="HTML", + disable_web_page_preview=True + ) - By default, message handler will handle all message types (like a text, photo, sticker etc.) - """ - try: - # Send a copy of the received message - await message.send_copy(chat_id=message.chat.id) - except TypeError: - # But not all the types is supported to be copied so need to handle it - await message.answer("Nice try!") +@dp.callback_query(F.data == "subscribe") +async def subscribe_handler(callback: CallbackQuery): + user_id = callback.from_user.id + print("User ID:", user_id) + await db.add_user(user_id) + + users = await db.get_all() + print("All users in DB:", users) + + await callback.message.edit_text( + "✅ Вы успешно подписались на уведомления!", + parse_mode="HTML" + ) + await callback.answer("Подписка активирована!") async def main() -> None: - # Initialize Bot instance with default bot properties which will be passed to all API calls bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) - - # And the run events dispatching + dp.startup.register(on_startup) await dp.start_polling(bot) diff --git a/database.py b/database.py new file mode 100644 index 0000000..149e53a --- /dev/null +++ b/database.py @@ -0,0 +1,29 @@ +import aiosqlite + +class Database: + def __init__(self, db_path: str): + self.db_path = db_path + + async def create_tables(self): + async with aiosqlite.connect(self.db_path) as db: + await db.execute(""" + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY, + user_id INTEGER UNIQUE + ) + """) + await db.commit() + + async def add_user(self, user_id: int): + async with aiosqlite.connect(self.db_path) as db: + await db.execute( + "INSERT OR IGNORE INTO users (user_id) VALUES (?)", + (user_id,) + ) + await db.commit() + + async def get_all(self): + async with aiosqlite.connect(self.db_path) as db: + async with db.execute("SELECT * FROM users") as cursor: + rows = await cursor.fetchall() + return rows diff --git a/main.py b/kwork.py similarity index 100% rename from main.py rename to kwork.py