Бот для VK на Python с MySQL за час ч.2

    Предисловие


    Прошу извинения за то, что в первой статье не написал про работу с базой данных, но именно эта часть направлена на работу с MySQL.

    3 часть будет неким дополнением, где мы рассмотрим работу с клавиатурой для бота и на этом цикл статей завершиться.

    Подготовка


    После прошлой статьи на руках мы должны иметь такой код:

    import vk_api
    from vk_api.utils import get_random_id
    from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType
    import pymysql.cursors
    import requests
    
    def get_connection():
        connection = pymysql.connect(host='you_host',
                                     user='you_user',
                                     password='you_password',
                                     db='you_db'
                                     charset='utf8mb4',
                                     cursorclass=pymysql.cursors.DictCursor)
        return connection
    
    <anchor>habracut</anchor>
    vk_session = vk_api.VkApi(token="a6f87v8c9a9sa87a7af9a0f9f9v8a6s6c5b5m6n8bds09asc8d7b87d87bd87n")
    vk = vk_session.get_api()
    longpoll = VkBotLongPoll(vk_session, "637182735")
    #Проверка действий 
    for event in longpoll.listen():
        if event.type == VkBotEventType.MESSAGE_NEW:
            #Проверяем не пустое ли сообщение нам пришло
            if event.obj.text != '': 
                #Проверяем пришло сообщение от пользователя или нет
                if event.from_user:
                    #Отправляем сообщение
                    vk.messages.send(
                            user_id=event.obj.from_id,
                            random_id=get_random_id(),
                            message=event.obj.text)
    

    Создадим бота, который будет возвращать нам результат положительный или отрицательный. Например «Life» и «Dead». Потом заносить его в базу данных и в будущем отправлять этот результат нам.

    Для начала мы должны иметь свою базу данных с уже готовой таблицей.

    Если кто то не умеет создавать таблицы, то вот код, который необходимо вставить будучи в mysql консоли:

    CREATE DATABASE `firstbot`;
    CREATE TABLE `mode`(Id_User INT(11), Mode VARCHAR(6) DEFAULT("NOT"), PRIMARY KEY(Id_User));
    

    На этом каркас нашей таблицы будет готов. Подробнее о создании и изменении таблиц можно найти на офф. сайте(ссылка будет ниже).

    Создадим функцию, которая будет рандомно возвращать Dead или Live:

    #Подключим новый модуль random
    import random
    def random_mode():
        #Получаем рандомное число в районе от 1 до 200
        return random.choice(["Live","Dead"])
    

    Теперь мы должны сделать функцию, которая отправит в базу данных наши значения.

    def add_to_database(function_mode, x):
        #Создаем новую сессию
        connection = getConnection()
        #Будем получать информацию от сюда
        cursor = connection.cursor()
        #Наш запрос
        sql = "INSERT INTO mode (Id_User, Mode) VALUES (%s, %s) ON DUPLICATE KEY UPDATE Mode = %s"
        #Выполняем наш запрос и вставляем свои значения
        cursor.execute(sql, (x, function_mode, function_mode))
        #Делаем коммит 
        connection.commit()
        #Закрываем подключение
        connection.close()
        #Возвращаем результат
        return function_mode
    
    

    Мы создали функцию, которая будет добавлять человека в базу данных или заканчивать свою работу, если он уже там есть. В нашем случае все до ON DUPLICATE KEY UPDATE заносит наши результаты в базу данных. Если в базе данных есть уже колонка с id нашего юзера, то в базу данных не заносится новое значение, а обновляется за что и отвечает ON DUPLICATE KEY UPDATE.

    Но помимо того, что мы заносим значения в базу данных, нам надо их получать. Для этого создадим такую функцию.

    def select_from_database(x):
        connection = get_connection()
        cursor = connection.cursor()
        sql = "SELECT Mode FROM mode WHERE Id_User = %s"
        cursor.execute(sql, (x,))
        #Получаем запрашиваемые данных и заносим их в переменные
        for i in cursor:
            mode_send = i['Mode']
        #Проверяем точно ли есть такая запись
        if cursor.fetchall() == ():
            mode_send = 'Вы еще не пробовали'
        connection.close()
        return mode_send
    

    cursor.fetchall() распаковывает получаемый нами запрос и отображает его. При помощи условия мы проверяем точно ли запись в базе данных есть. Если ее нет, то мы присваиваем ей желаемое значение-предупреждение
    Все что нам осталось это собрать код полностью и добавить пару строк, что бы все работало так как мы хотим.

    if event.obj.text == 'Попытка':
        if event.from_user:
            id_user  = event.obj.from_id
            vk.messages.send(
                                user_id=event.obj.from_id,
                                random_id=get_random_id(),
                                message="Ваш результат: " + add_to_database(random_mode(), id_user))
    if event.obj.text == 'Прошлый результат':
        if event.from_user:
            idUser = event.obj.from_id
            vk.messages.send(
                                user_id=event.obj.from_id,
                                random_id=get_random_id(),
                                message="Ваш последний: " + select_from_database(id_user)
                                
    

    И таким образом мы получим ответ от нашего бота



    Итог


    С помощью проделанной работы мы создали бота умеющего работать с MySQL. На этом его функционал не заканчивается. Он намного шире и больше, а ограничен только вашей фантазией.
    Код не идеале и писал я его только, что бы показать как работает MySQL. Если вы знаете способы лучше, смело применяйте их. Так же приму любую помощь по усовершенствованию текущего кода.

    Полезные ссылки


    Официальная страница PyMySQL
    Официальная страница MySQL
    Документация PyMySQL на русском
    Документация vk_api
    Документая API Вконтакте
    Код самого бота
    Поделиться публикацией

    Комментарии 10

      –1
      Мама, я уже почти программист! Автору спасибо.
        +1
        Если с ботом будут общаться, например, раз в 3 месяца, не будет ли у него отваливаться соединение с базой? А то у меня на php такое возникало, когда с базой общение происходило редко, модифицировал немного скрипт, чтобы проверяло соединение и переподключалось, может быть в python это уже сразу предусмотрено.
        Я недавно на PHP бота писал для своих задачек, но сделал его на нескольких независимых демонах, один слушает longpool и все приходящие сообщения закидывает в цепочку RabbitMQ, второй подписан на цепочку исходящих (кому и что отправить), ну естественно оттуда разгребает отправку так, что исходящие уходят с соблюдением лимита vkapi…
        Ну и третий демон подписан на цепочку входящих и раскладывает ответы на исходящие.
        Думаю в будущем еще пересмотрю архитектуру, ну пока мне всё нравится, когда php-скрипт подписан на цепочку, то callback функция выполняется молниеносно и есть некая параллельность процессов.
          0

          Отваливаться не должен. Точно не скажу. На своём опыте бот работал все время, что был включён. Отсоединялся по логике, только когда пк переводился в режим сна. Если на каком то хосте, то не должен вообще никак. Единственное что pythonanywhere, если программа не работает больше ~3 часов, только он ее отключает

          0

          Статья уровня "я прочитал документацию и смотрите что у меня получилось".


          Код плохой, никакие нормальные современные библиотеки не используются. Нет миграций, никакой нормальной обертки над базой. Хороший пример как писать на python не надо.

            0

            Какие современные библиотеки посоветуешь?

              0
              Минимум: alembic для миграций, для работы с БД — sqlalchemy.
              Чаще всего сейчас такие приложения пишут используя asyncio и aiopg.
                0

                Не везде и не всегда нужна ORM. А aiopg вообще сложно применить для работы с mysql

                  0

                  MySQL можно и нужно заменить на postgresql. Вообще не понимаю необходимости сейчас использовать MySQL, когда postgresql. Только если это старый легаси код.


                  В sqlalchemy orm не обязателен. Там есть прекрасный query builder который намного лучше и гибче.

            0

            Хочу обратить внимание читающих, что писать except без указания исключения (или указывая Exception или BaseException) — очень плохая практика

              0
              Если я исправлю на нужную ошибку, то вопрос отпадет? Понимаю что идея была плохая.

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое