Бот для ВКонтакте MDB (школьный проект и проект для Всероссийского конкурса проектных работ)

Привет, Хабр! Хочу вам рассказать о своём исследовательском проекте, в котором я создал игрового ботеца для ВКонтакте.

Ахтунг!

Я не являюсь профессиональным разработчиком, я обычный девятиклассник, любящий иногда покодить на совершенно разных языках. Здесь я просто рассказываю о своём проекте и опыте участия в конкурсе проектных работ.

Эта статья не является пошаговым руководством по созданию бота для ВКонтакте - их достаточно и на Хабре, и за его пределами.

Что за проект?

Я, как администратор немаленькой беседы во ВКонтакте (на тот момент это было ~670 человек), столкнулся с проблемой ужасной активности. Ну серьёзно, человек много, а не пишет никто, очень много незаинтересованных молчунов, которые лишь цифру создают для беседы. Подавляющее большинство пользователей из тех 670 человек просто входили и не появлялись в списке сообщений ни разу.

Чтобы решить эту проблему, я решил попробовать написать своего бота с некоторыми игровыми механиками. Сразу хочу оговориться, что пусть и код писал я сам, мне два раза проводил код ревью мой замечательный приятель, поэтому, пусть сам проект, сама задумка довольно простая, - это не помешало мне набраться опыта от более продвинутого в кодинге человека.

С ботом и своей темой я отправился прямиком на конкурс "Большие вызовы", съездил в лагерь, где с экспертами (а с одним из них мы общаемся до сих пор) я допиливал презентацию, чутка сменил цель, всё подкорректировал, успешно защитился. Сейчас меня ждёт только последний тур заключительного этапа, но это уже совсем другая история.

Что же за системы есть в боте?

В общем и целом, по сути я вдохновлялся другим ботом, в которого любил играть продолжительное время (и закончил только потому, что они его отрубили и делают сейчас игру в приложении ВК).

У меня бот намного проще, но подошёл для проекта в школе и для проекта в конкурсе. Основными характеристиками пользователя являются игровая валюта и опыт. Фактически, всё сводится к фарму опыта и денег ради фарма опыта и денег. За опыт можно устроиться на работу, каждая последующая работа будет давать всё больше денег в 24 часа (без фарма, получение зарплаты только командой раз в сутки), в свою очередь за деньги можно купить машину получше, которая будет давать больший множитель к опыту. Опыт даётся за каждое сообщение кроме команд посимвольно, затем умножается на множитель от автомобиля. Это самое основное, чего я стал требовать от бота. Также есть выдача предупреждений (максимальное их количество - 4).

Да, такого бота я делал около 6 месяцев, постоянно что-то изменяя, добавляя и удаляя.

Давай о реализации уже!

Делал я бота на языке программирования Python с использованием асинхронной библиотеки для написания ботов vkbottle. Работает на CallBack API, в качестве сервера использую aiohttp.

Во входном файле bot.py происходит инициализация сервера, прописаны все роуты (их всего 4 и они очень маленькие), к основному боту добавляются blueprint'ы, о которых пойдёт речь позже.

import pathlib

import aiohttp
import aiohttp_jinja2
import jinja2
from aiohttp import web

import utils.consts
from config import SECRET, WEBHOOK_ACCEPT, CONFIRMATION_TOKEN
from routes import actions, admin_realize, global_admin_realize, users_realize, economic_realize
from utils.db_methods import init_database
from middlewares import ExpMiddleware # dead import for include middleware

INDEX_DIR = str(pathlib.Path(__file__).resolve().parent) + '/index_page'

utils.consts.BOT.loop.run_until_complete(init_database())
utils.consts.BOT.set_blueprints(
    actions.bp, admin_realize.bp, global_admin_realize.bp,
    users_realize.bp, economic_realize.bp
)

APP = aiohttp.web.Application()
ROUTES = aiohttp.web.RouteTableDef()

if not WEBHOOK_ACCEPT:
    aiohttp_jinja2.setup(APP, loader=jinja2.FileSystemLoader(str(INDEX_DIR)))
    APP.router.add_static('/static/',
                          path=str('./index_page/'),
                          name='static')


@ROUTES.get("/")
@aiohttp_jinja2.template('index.html')
async def hello(request):
    """Root site response"""
    return {}


@ROUTES.get("/when_update")
@aiohttp_jinja2.template('whenupdate.html')
async def whenupdate(request):
    """When update site response"""
    return {}

Все конфиги хранятся в config.py, точнее, там инициализируются константы. Сами значения хранятся в файле .env и с помощью библиотеки dotenv берутся из виртуального окружения по ключу.

import os

from dotenv import load_dotenv

dotenv_path = os.path.join(os.path.dirname(__file__), '.env')
if os.path.exists(dotenv_path):
    load_dotenv(dotenv_path)

# Loading token from .env
ACCESS_TOKEN = os.getenv("ACCESS_TOKEN")
SECRET = os.getenv("SECRET")
USER_ACCESS_TOKEN = os.getenv("USER_ACCESS_TOKEN")
WEBHOOK_ACCEPT = bool(int(os.getenv("WEBHOOK_ACCEPT", 0)))
CONFIRMATION_TOKEN = os.getenv("CONFIRMATION_TOKEN")
NEW_START = bool(int(os.getenv("NEW_START", 0)))
ADMINS_IN_CONV = list(map(int, os.getenv("ADMINS_IN_CONV").split(',')))

Теперь о том, где хранятся все обработчики команд.

Я их разделил логически на 5 видов: обработчик событий (пользователь вошел в беседу), обработчик сообщений для всех (например, команда /profile), для администраторов беседы (например, /пред чтобы выдать предупреждение пользователю), для администраторов и модераторов бота (например, /бд добавить, чтобы добавить, как ни странно, новый экземпляр какой-то модельки, например, создать новую машину, не взаимодействуя напрямую с БД), и реализация системы экономики (купить или продать машину, поступить на работу и пр.).

Всё это хранится в пяти разных файлах в папке routes:

Вот пример команды покупки машины:

@bp.on.message_handler(AccessForAllRule(), Registered(), text="/купить_машину <c_id>")
async def buy_car(message: Message, user: User, c_id: str = None):
    if c_id.isdigit():
        c_id = int(c_id)
        car = await Car.get(id=c_id)

        buy_car_user_status = status_on_buy_car(user, car)

        if buy_car_user_status == BuyCarUserStatuses.APPROVED:
            chat = await Conversation.get(peer_id=message.peer_id)
            await User.get(user_id=message.from_id, chat=chat).update(
                coins=user.coins - car.cost, car=car
            )

            await message(f"Машина {car} куплена!")
        elif buy_car_user_status == BuyCarUserStatuses.NOT_ENOUGH_MONEY:
            await message("У тебя недостаточно денег!")
        elif buy_car_user_status == BuyCarUserStatuses.NOT_ENOUGH_EXP:
            await message("У тебя недостаточно опыта!")
        else:
            await message("У тебя уже есть машина!")
    else:
        await message("Введите цифру-ID машины!")

Все обработчики в пределах одного файла объединяются blueprint'ом, а все "чертежи" подключаются к боту во входном файле.

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

Все подобные функции хранятся в отдельно в папке utils в файле main.py. В этой же папке лежат файлы с константами, функциями для работы с БД, правила и ошибки, которые функции могут raise'ить иногда.

def status_on_buy_car(user: User, car: Car) -> BuyCarUserStatuses:
    if user.coins >= car.cost and user.exp >= car.exp_need and user.car is None:
        return BuyCarUserStatuses.APPROVED
    elif user.coins < car.cost:
        return BuyCarUserStatuses.NOT_ENOUGH_MONEY
    elif user.exp < car.exp_need:
        return BuyCarUserStatuses.NOT_ENOUGH_EXP
    else:
        return BuyCarUserStatuses.NOW_HAVE_CAR

В качестве ОРМки я использую Tortoise ORM, потому что асинхронно (а смысл в асинхронности фреймворка, если вся работа с БД синхронная?), потому что удобно лично для меня.

Что по итогу?

По итогу я имею бота, который некоторое время работал у меня в беседе, с помощью которого я показал небольшой прирост количества сообщений. В него иногда игрались, люди даже зарабатывали опыт общением и покупали себе имущество, но эффект, на самом деле, заметен не так сильно, так что это больше просто для развлечения, чем реально для поднятия активности с 0 до миллиона сообщений в секунду.

Конечно, в беседе, где бот был, наблюдалось больше сообщений, чем в беседе, где его не было, было больше активности (пусть и не сильно). Это я и записал в вывод.

В результате я получил небольшой научно-исследовательский проект, целью которого было исследовать возможность с помощью бота с игровой механикой повышения активности в беседах. Цель полностью выполнена, это частично возможно, но нужно пробовать различные подходы к решению поставленной проблемы.

Постскриптум

Я открыт к критике в комментариях, за неё отдельное спасибо, ведь именно критика, может даже очень жёсткая, может даже с заминусованной статьёй поможет развиваться мне как разработчику и создателю статей на Хабре.

Бот на GitHub

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 10

    +1
    А вам там всем на «всероссийском конкурсе проектных работ» в обязательном порядке надо написать статью на хабр, или что?
      +1
      Нет, просто было интересно поделиться опытом создания бота для выполнения конкретной задачи, тем более что изначально я его делал чисто для себя и беседы ВК, потом всё завертелось-закрутилось и решили с учителем отдать проект на конкурс.
      Вот про то, насколько хорошо бот с определённой целью справляется — я и написал на Хабр, не сильно делая акцент в самой статье на конкурс, пару раз лишь его упомянув =]
        +1

        Вынужден не согласиться с вашим мнением.

        Безусловно, основываясь на конкурсе проектов не напишешь какой-то невероятной научной статьи, но этого ведь не предполагалось, человек просто поделился своим опытом, ничего плохого не вижу)

        +3

        Сначала потянулся к минусу, но потом вчитался -- написано хорошо, читать приятно.

        Очень не хватило подробностей про самого бота -- как именно люди в него играют, как это устроено, чтобы не мешать тем, кто не играет, как это оживило собственно беседу...

          0
          Большое спасибо за отзыв. Всегда рад критике со стороны, особенно когда она исходит от человека, который гораздо опытнее меня в конкретной сфере =)
          В статье я хотел рассказать (и, собственно, рассказал) про реализацию в части кода, но соглашусь — надо было раскрыть механики, которые есть в боте, поглубже.
          На самом деле, как я и написал в выводе, активность в беседе увеличилась, но не сильно.
          Механики довольно простые: есть опыт, который даётся за сообщения, есть игровая валюта. Есть работы и машины. Каждая последующая работа даёт в 24 часа больше денег, но требует больше опыта для поступления. Машины нужны как множитель опыта (опыт рассчитывается относительно количества символов без пробелов, и это всё умноженное на множитель машины, если таковая имеется). Каждая последующая машина будет требовать больше денег.
          Фарм ради фарма, по сути (но не так ли во многих играх? конечно, сравнение от слова совсем не уместно, но в той же GTA 5 Online: нужно больше денег. Зачем? Чтобы купить бизнес. Зачем? Чтобы было больше денег. Конечно там есть куда их тратить, чисто для развлечения, но по сути: копим ради того, чтобы копить еще больше. Во многих играх, где есть деньги и способы их пассивного заработка, часть геймплея сводится к «фарму ради фарма»).
          То же самое и у меня, пока что. Идеи: сделать рандомные пакости игрокам, такие как ограбления с потерей большого количества денег, поломка машин, внезапные увольнения с работы с возможностью восстановления только через некоторое время, ну и прочее, чтобы играть было не так нудно и чтобы в итоге вся игра не сводилась к чистому ожиданию денег.
          Вы задали хороший вопрос, над которым я даже не задумывался: как не мешать тем, кто не играет. Внезапно. Я обязательно подумаю над этим.
          Юзеры просто пишут команды, чтобы играть. Вот и всё. Сейчас это устроено просто на обычных командах.
            +1

            Насколько полезны сообщения в рамках беседы, которые стали писать молчуны ради игры?

              0
              Часть сообщений, которые писали «молчуны», были просто команды боту, но чтобы заработать опыт надо было еще и писать обычные сообщения. Увы, я запретил флудить символами и буковками, так что другого выбора, кроме как просто общаться, нет.
              При этом важно, чтобы в беседе была какая-то атмосфера, что ли. Надо чтобы в целом человеку было интересно в беседе.
              «Молчуны» просто общались на житейские, такие, бытовые темы. Как дела, чем занимаетесь, а потом уже некоторые вовлекались в какие-то споры и обсуждения.
              И есть два типа «молчунов»: которые входят в беседу и забывают о ней и которые заходят в беседу чисто для R\O. Бот создавался для второго типа, их хотя бы иногда пару раз можно увидеть в беседе, можно позвать их и им не будет неинтересно, в отличие от первого типа, которые просто на беседе фармят сообщения.
          +1

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

          Отдельный респект за VKBottle, сам увлекаюсь этим фреймворком, рад, что о нем пишут)

            0
            Но он допустил ошибку, данный фреймворк работает на longpoll api, разве нет?
              0

              Там можно и на лонгполле писать бота, и на коллбэк апи, ошибки никакой нет =}

          Only users with full accounts can post comments. Log in, please.