Coder Social home page Coder Social logo

trixis / aiogram3-form Goto Github PK

View Code? Open in Web Editor NEW
7.0 1.0 0.0 123 KB

A library for creating forms in aiogram3

License: MIT License

Python 100.00%
aiogram aiogram-bot aiogram3 chatbot chatbots form forms telegram telegram-bot telegram-bot-api telegram-bots

aiogram3-form's Introduction

aiogram3-form

A library for creating forms in aiogram3

pip install aiogram3-form

What is a form?

Form is a set of fields that you want your user to fill in. Forms are defined as classses derived from aiogram3_form.Form and contain fields with annotated types and aiogram3_form.FormField values. You should not inherit your form class from your another form class. (so no deep inheritance).

When you start your form with .start() method, your bot will ask a user input values one by one until the end. Filling in the last field of a form means "submitting" it.

Forms use default aiogram FSM.

Minimal example

import asyncio

from aiogram import Bot, Dispatcher, F, Router
from aiogram3_form import Form, FormField
from aiogram.fsm.context import FSMContext

bot = Bot(token="YOUR_TOKEN")
dispatcher = Dispatcher()
router = Router()
dispatcher.include_router(router)


class NameForm(Form):
    first_name: str = FormField(enter_message_text="Enter your first name please")
    second_name: str = FormField(
        enter_message_text="Enter your second name please",
        filter=(F.text.len() > 10) & F.text,
    )
    age: int = FormField(enter_message_text="Enter age as integer")


@NameForm.submit(router=router)
async def name_form_submit_handler(form: NameForm):
    # handle form submitted data
    # also supports aiogram standart DI (e. g. middlewares, filter data, etc)
    # you can do anything you want in here
    await form.answer(f"{form.first_name} {form.second_name} of age {form.age}")


@router.message(F.text == "/form")
async def form_handler(_, state: FSMContext):
    await NameForm.start(bot, state)  # start your form


asyncio.run(dispatcher.start_polling(bot))

Keyboards

You can use any type of keyboard in your form, but only reply keyboards are actually useful. (cause forms only accept messages as input, so no callback queries)

FRUITS = ("Orange", "Apple", "Banana")

fruits_markup = (
    ReplyKeyboardBuilder().add(*(KeyboardButton(text=f) for f in FRUITS)).as_markup()
)


class FruitForm(Form):
    fruit: str = FormField(
        enter_message_text="Pick your favorite fruit",
        filter=F.text.in_(FRUITS) & F.text,
        reply_markup=fruits_markup,
    )

Form filters

Default filters are built in for types: str (checks for mesasge text and returns it), int (tries to convert message text to int), float, datetime.date, datetime.datetime, aiogram.types.PhotoSize, aiogram.types.Document, aiogram.types.Message

Supported form filter kinds: sync function, async function, aiogram magic filter.

If your filter is a function (sync or async), it should take aiogram.types.Message as the first argument and return False, if it does not pass. If a filter passed, it should return the value you want in your form data.

Magic filters return None on failure, so it's a special case that is handled differently.

If your filter fails and error_message_text is provided in FormField call, an error message will be sent with the provided text.

def sync_fruit_form_filter(message: types.Message) -> str:
    if message.text not in FRUITS:
        return False

    return message.text


async def async_fruit_form_filter(
    message: types.Message,
): ...  # some async fruit filtering


class FruitForm(Form):
    fruit: str = FormField(
        enter_message_text="Pick your favorite fruit",
        filter=sync_fruit_form_filter,  # you can pass an async filter here as well
        reply_markup=fruits_markup,
        error_message_text="Thats an invalid fruit",
    )

Enter callback

Enter callbacks enable you to write your own enter functions for form fields

async def enter_fruit_callback(chat_id: int, user_id: int, data: dict[str, Any]):
    # do whatever you want in here
    print(f"user {user_id} has just entered the fruit callback in chat {chat_id}!")

    return await bot.send_message(
        chat_id, "Hey, pick your favorite fruit please", reply_markup=fruits_markup
    )


class FruitForm(Form):
    fruit: str = FormField(
        enter_callback=enter_fruit_callback,
        filter=sync_fruit_form_filter,
        error_message_text="Thats an invalid fruit",
    )

aiogram3-form's People

Contributors

trixis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.