ВК-бот для напоминаний

Материал из Поле цифровой дидактики

Цель проекта:

Разработка автоматизированного бота для социальной сети ВКонтакте, способного принимать текстовые команды от пользователей, планировать задачи и отправлять уведомления в заданное время с использованием VK API.

Задачи:

  1. Изучить документацию VK API для работы с сообщениями сообществ.
  2. Реализовать механизм аутентификации через токен доступа.
  3. Организовать хранение данных о задачах в локальной базе данных (SQLite).
  4. Реализовать парсинг естественного языка для распознавания времени напоминания.
  5. Настроить асинхронную работу планировщика задач.


Область знаний

Программирование на Python, Разработка чат-ботов, Работа с API, Веб-технологии


Среда разработки

vk_api, Python, Bot Long Poll, requests

Шаги разработки:


Логика работы бота:

Шаг 1. Создание группы. Получение API. Подключение бота

Шаг 2. Создание файлов и кода

import os
import time
import sqlite3
import threading
import re
from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType
from vk_api import VkApi
from dotenv import load_dotenv

load_dotenv()

TOKEN = os.getenv('VK_TOKEN')
GROUP_ID = int(os.getenv('VK_GROUP_ID'))

# ... (функции init_db, parse_time, send_message оставь как были) ...
def init_db():
    conn = sqlite3.connect('database.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS reminders 
                 (id INTEGER PRIMARY KEY, user_id INTEGER, text TEXT, execute_at INTEGER, is_sent INTEGER)''')
    conn.commit()
    conn.close()

def parse_time(text):
    pattern = r"через\s+(\d+)\s*(минут|мин|часов|час)"
    match = re.search(pattern, text.lower())
    if match:
        value = int(match.group(1))
        unit = match.group(2)
        now = int(time.time())
        add_sec = value * 60 if unit in ['минут', 'мин'] else value * 3600
        return now + add_sec
    return None

def send_message(vk, user_id, message):
    vk.messages.send(peer_id=user_id, message=message, random_id=0)

def scheduler_worker(vk):
    while True:
        time.sleep(5)
        conn = sqlite3.connect('database.db')
        c = conn.cursor()
        now = int(time.time())
        c.execute("SELECT id, user_id, text FROM reminders WHERE execute_at <= ? AND is_sent = 0", (now,))
        tasks = c.fetchall()
        for task in tasks:
            task_id, user_id, text = task
            try:
                print(f"📤 Отправка: {text}")
                send_message(vk, user_id, f"⏰ Напоминание: {text}")
                c.execute("UPDATE reminders SET is_sent = 1 WHERE id = ?", (task_id,))
                conn.commit()
            except Exception as e:
                print(f"❌ Ошибка: {e}")
        conn.close()

def main():
    init_db()
    vk_session = VkApi(token=TOKEN)
    vk = vk_session.get_api()
    longpoll = VkBotLongPoll(vk_session, GROUP_ID)
    
    threading.Thread(target=scheduler_worker, args=(vk,), daemon=True).start()
    print("✅ Бот запущен...")
    
    for event in longpoll.listen():
        print(f"⚡ СОБЫТИЕ: {event.type}") # <<< Показывает ЛЮБОЕ событие
        
        if event.type == VkBotEventType.MESSAGE_NEW:
            print(f"📩 НОВОЕ СООБЩЕНИЕ!") # <<< Показывает именно сообщение
            try:
                message = event.object.message
                text = message['text']
                user_id = message['from_id']
                peer_id = message['peer_id']
                
                print(f"👤 От: {user_id} | Текст: {text}")
                
                execute_at = parse_time(text)
                if execute_at:
                    conn = sqlite3.connect('database.db')
                    c = conn.cursor()
                    c.execute("INSERT INTO reminders (user_id, text, execute_at, is_sent) VALUES (?, ?, ?, 0)", 
                              (user_id, text, execute_at))
                    conn.commit()
                    conn.close()
                    send_message(vk, peer_id, "✅ Напоминание установлено!")
            except Exception as e:
                print(f"❌ Ошибка обработки: {e}")
                import traceback
                traceback.print_exc()

if __name__ == '__main__':
    main()

Шаг 3. Проверка работы бота