Программа не выходит из стейта VKBottle

from vkbottle.bot import Message
from vkbottle import Keyboard, KeyboardButtonColor, \
                        Text, OpenLink, Bot
from jetorm.utils import hash

from connect import db
from keyboards import admin_keyboard, mailing_keyboard
from states import MailingData, ctx

bp = Bot(token=token)
bp.labeler.vbml_ignore_case = True


@bp.on.private_message(text="/admin")
async def admin_commands_handler(message: Message):
    if db.find_one('users', '`isAdmin` = 1 AND `user_id` = ?', str(message.from_id)):
        admin_name = db.read_one('users', ('first_name',), '`user_id` = ?', str(message.from_id))[0][0]
        await message.answer(f"Здравствуйте, {admin_name}! Вот ваша админ-панель:", keyboard=admin_keyboard)
    else:
        await message.answer("Вы не администратор!")

@bp.on.private_message(payload={"cmd": "create_mailing"})
async def mailing_handler(message: Message):
    if db.find_one('users', '`isAdmin` = 1 AND `user_id` = ?', str(message.from_id)):
        await bp.state_dispenser.set(message.peer_id, MailingData.TEXT)
        return "Введите текст для рассылки:"
    else:
        await message.answer("Вы не администратор!")

@bp.on.private_message(state=MailingData.TEXT)
async def text_handler(message: Message):
    ctx.set("text", message.text)
    await bp.state_dispenser.set(message.peer_id, MailingData.IMAGE)
    await message.answer("Загрузите картинку (необязательно):")

@bp.on.private_message(state=MailingData.IMAGE)
async def image_handler(message: Message):
    ctx.set("image", "")
    try:
        ctx.set("image", message.attachments[0].photo.sizes[-5].url)
    except Exception:
        ctx.delete("image")

    text = ctx.get("text")
    image = ctx.get("image")
    post_id = hash(str(message.from_id))[:10]

    db.insert('mailing', {
            'text': text,
            'image_url': image,
            'user_id': message.from_id,
            'post_id': post_id
        })

    return f"Рассылка готова! ID: {post_id}\nНапишите /post <id>"

@bp.on.private_message(text=["/post <item>", "/post"])
async def post_handler(message: Message, item=None):
    print("="*50)
    print(db.find_one('mailing', '`post_id` = ?', item))
    print("="*50)
    await message.answer(f"{item}")

Проблема в стейтах, когда мне прилетает сообщение, что рассылка готова, я пишу /post id (где id идентификационный номер поста выдаваемый в конце стейта) и стейт снова пишет, что рассылка готова. Вопрос: как выйти из стейта?. Я написал return везде в стейтах.

файл states.py

from vkbottle_types import BaseStateGroup
from vkbottle import CtxStorage

ctx = CtxStorage()

class MailingData(BaseStateGroup):
    TEXT = 0
    IMAGE = 1

Ответы (1 шт):

Автор решения: 0xmeow

У вас в image_handler обрабатывается, когда state=MailingData.IMAGE, а внутри вы state не меняете. И он снова обрабатывается, поскольку state остался прежним и стоит раньше post_handler.

Есть два решения:

  1. Изменять state внутри image_handler.
  2. Изменить порядок хендлеров.

Можно использовать одновременно оба решения.

→ Ссылка