Bot for VKontakte MDB (school project and project for the All-Russian competition of design works)

Hello, Habr! I want to tell you about my research project, in which I created a game bot for VKontakte.





Ahtung!

I am not a professional developer, I am an ordinary ninth grader who sometimes loves to code in completely different languages. Here I am just talking about my project and my experience of participating in a design competition.





This article is not a step-by-step guide on creating a bot for VKontakte - there are enough of them both on Habré and beyond.





What kind of project?

, ( ~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 .





, , , , , , ( ). .





- , . , , .





P.S

I am open to criticism in the comments, a special thank you for it, because it is criticism, maybe even very harsh, maybe even with a minified article, that will help me develop as a developer and creator of articles on Habré.





Bot on GitHub








All Articles