Small extension for pyTelegramBotAPI library for building interactive forms in Telegram bots.
Project description
TelebotForms
Small extension for pyTelegramBotAPI library for building interactive forms in Telegram bots.
Contents
Installation
$ pip install TBForms
Demo
Demo for Example
- default mode:
- step-by-step mode:
Quickstart
from tb_forms import TelebotForms, BaseForm, fields
from telebot import TeleBot
bot = TeleBot("your_token")
tbf = TelebotForms(bot)
class TestRegisterForm(BaseForm):
update_name = "submit_register_form"
form_title = "TBF Test Register Form"
name = fields.StrField("Name", "Enter your name:")
group_number = fields.NumberField(
"Group number", "Select your group number:", only_int=True, key_mode=True, input_range=(1, 10))
sex = fields.ChooseField("Sex", "Select your sex:", answer_list=["male", "female"])
date_of_birth = fields.DateTimeField("Date of Birth", "Select your date of birth: ",
only_date=True, current_year_only=False, years_range=80)
photo = fields.MediaField(
"Photo", "Enter your photo:",
valid_types=['photo'], required=False, error_message="Error. You can only send a photo")
freeze_mode = True
close_form_but = False
submit_button_text = "Register"
@bot.message_handler(commands=['start'])
def start_update(message):
tbf.send_form(message.chat.id, TestRegisterForm())
@tbf.form_submit_event("submit_register_form")
def submit_register_update(call, form_data):
print(form_data) # Completed form data
bot.send_message(call.message.chat.id, "Successful registration")
Docs
TelebotForms
Init
Args | Required? | Default | Type | Description |
---|---|---|---|---|
bot | Yes | telebot.TeleBot | pyTelegramBotAPI bot object | |
fsm | No | tb_forms.ffsm.MemoryFSM | tb_forms.ffsm.FSM | TBForms FSM object |
Settings
tbf = TelebotForms(bot)
# Global icon for a missing value field
tbf.GLOBAL_MISSING_VALUE_ICON: str = "💢"
# Global icon for a field with data
tbf.GLOBAL_EDIT_ICON: str = "✏️"
''' Global cancel form button text
Type: Union[Str,Callable] '''
tbf.GLOBAL_CANCEL_BUTTON_TEXT = "Cancel"
# Callable example
tbf.GLOBAL_CANCEL_BUTTON_TEXT = lambda user_id: "Cancel"
# Global submit form button text
tbf.GLOBAL_SUBMIT_BUTTON_TEXT: str = "Submit"
# Global close button in form
tbf.GLOBAL_CLOSE_FORM_BUT: bool = True
''' Global form freeze mode.
If True, prohibits any action prior to submitting or canceling the form. '''
tbf.GLOBAL_FREEZE_MODE: bool = True
''' Global freeze mode alart text.
If freeze_mode is True, sends this text after any action.
Type: Union[Str,Callable] '''
tbf.GLOBAL_STOP_FREEZE_TEXT = "Cancel or submit the form first before proceeding further"
''' Global invalide input error text.
Type: Union[Str,Callable] '''
tbf.GLOBAL_INVALID_INPUT_TEXT = "Error. Invalide input!"
Methods
Send forms
- send_form - Send form to chat
Args | Required? | Default | Type | Description |
---|---|---|---|---|
chat_id | Yes | int | Chat id for send form | |
form | Yes | tb_forms.BaseForm | TbfForms Form object | |
step_by_step | No | None | bool | Step-by-Step form mode. The data will be requested one by one without returning to the state of the form |
auto_submit | No | None | bool | If true the form will automatically submit when the last field has a value. If this parameter is True, chat_id: int will be passed to the function that will receive the completed form object instead of the CallbackQuery object ⚠️ |
Handle form
- form_submit_event - handle submit form event
Args | Required? | Default | Type | Description |
---|---|---|---|---|
update_name | Yes | str | update_name of form to handle |
@tbf.form_submit_event("update_name")
def submit_update(call,form_data):
pass
- form_cancel_event - handle cancel form event
Args | Required? | Default | Type | Description |
---|---|---|---|---|
update_name | Yes | str | update_name of form to handle |
@tbf.form_cancel_event("update_name")
def cancel_form_update(call,form_data):
pass
- form_event - handle all form event
Args | Required? | Default | Type | Description |
---|---|---|---|---|
update_name | Yes | str | update_name of form to handle | |
action | Yes | list | handle events type |
@tbf.form_event("update_name",action=["submit","cancel"])
def form_event_update(call,form_data):
print(form_data.update_action) # event action type
BaseForm
Parameters
Args | Required? | Default | Type | Description |
---|---|---|---|---|
update_name | Yes | str | update name for handle event | |
MISSING_VALUE_ICON | No | "💢" | str | Icon for a missing value field |
EDIT_ICON | No | "✏️" | str | Icon for a field with data |
freeze_mode | No | False | bool | Form freeze mode. If True, prohibits any action prior to submitting or canceling the form. |
close_form_but | No | False | bool | Show close form button |
submit_button_text | No | "Submit" | str | Form submit button text |
cancel_button_text | No | "Cancel" | str | Cancel form\input button text |
input_not_valid | No | "Invalid input..." | str | Invalide input default error message text |
form_global_error_message | No | str | Global form default error message text | |
form_valid_error | No | "Error! You may have filled in some of the fields incorrectly. ⚠️" | str | Form default pre-submit validation error message text |
back_text | No | "🔙" | str | Back button text |
default_step_by_step | No | False | bool | Step-by-Step form mode. The data will be requested one by one without returning to the state of the form. It's better to use send_form parameter instead of defining this param ❗️ |
step_by_step_skip_text | No | "➡️" | str | Skip button text for optional field in step-by-step mode |
default_auto_submit | No | False | bool | Auto-submit form mode. If true the form will automatically submit when the last field has a value. It's better to use send_form parameter instead of defining this param ❗️. If this parameter is True, chat_id: int will be passed to the function that will receive the completed form object instead of the CallbackQuery object ⚠️ |
Fields
from tb_forms import fields
StrField
Simple input text
-> str
Args | Required? | Default | Type | Description |
---|---|---|---|---|
title | Yes | str | Field button title in form | |
input_text | Yes | str | Input message text | |
required | No | True | bool | required for submit? |
default_value | No | str | Default field value | |
validators | No | List[Callable | tb_forms.validators.Validator ] | Default field value | |
error_message | No | str | Validation error message text |
MediaField
Telegram Media input field
-> tb_forms.tbf_types.MediaData
Args | Required? | Default | Type | Description |
---|---|---|---|---|
title | Yes | str | Field button title in form | |
input_text | Yes | str | Input message text | |
required | No | True | bool | required for submit? |
validators | No | List[Callable | tb_forms.validators.Validator ] | Default field value | |
error_message | No | str | Validation error message text | |
valid_types | No | All | List[str] | Aviable content_type for input |
caption_required | No | False | bool | Required caption with media |
only_text_aviable | No | False | bool | Aviable only text message |
NumberField
Input int or float value
-> Union[int, float]
Args | Required? | Default | Type | Description |
---|---|---|---|---|
title | Yes | str | Field button title in form | |
input_text | Yes | str | Input message text | |
required | No | True | bool | required for submit? |
validators | No | List[Callable | tb_forms.validators.Validator ] | Default field value | |
error_message | No | str | Validation error message text | |
only_text_aviable | No | False | bool | Input only int value |
key_mode | No | False | bool | Input value from inline keyboard |
input_range | No | (1,99) | tuple | key_mode input range |
BooleanField
True\False input
-> bool
Args | Required? | Default | Type | Description |
---|---|---|---|---|
title | Yes | str | Field button title in form | |
input_text | Yes | str | Input message text | |
required | No | True | bool | required for submit? |
default_value | No | str | Default field value | |
validators | No | List[Callable | tb_forms.validators.Validator ] | Default field value | |
error_message | No | str | Validation error message text |
ChooseField
Select input from list of values
-> List[str]
Args | Required? | Default | Type | Description |
---|---|---|---|---|
title | Yes | str | Field button title in form | |
input_text | Yes | str | Input message text | |
required | No | True | bool | required for submit? |
default_value | No | str | Default field value | |
validators | No | List[Callable | tb_forms.validators.Validator ] | Default field value | |
error_message | No | str | Validation error message text | |
answer_list | Yes | [] | list | Values for select |
multiple | No | False | bool | Aviable multiple select |
answer_mapping | No | dict | Dictionary for replace return selected value |
DateTimeField
Select datetime object
-> Union[datetime, time, date]
Args | Required? | Default | Type | Description |
---|---|---|---|---|
title | Yes | str | Field button title in form | |
input_text | Yes | str | Input message text | |
required | No | True | bool | required for submit? |
default_value | No | Union[datetime, date, time] | Default field value | |
validators | No | List[Callable | tb_forms.validators.Validator ] | Default field value | |
error_message | No | str | Validation error message text | |
only_time | No | None | bool | Input time only |
only_date | No | None | bool | Input date only |
custom_month_names | No | None | List[str] | List with custom names for months. Must be 12 elements long! |
years_range | No | 20 | int | Range of years to select from current in descending order |
current_year_only | No | True | bool | If True, the year selection will be skipped and the value will be the current year. |
seconds_input | No | False | bool | Request seconds |
month_names_lang_code | No | "EN" | str | Language code for month names. By default, English ("EN"), "RU" - in Russian, and "UA" - Ukrainian are also available. |
custom_hours_icon_text | No | "🕐" | str | Icon for the button for selecting the time (hours) next to the number |
Advanced
Pre-submit validation
Form validation before submitting
How it works?
You must override the function
def form_validator(self, call, form_data) -> Union[bool, str]
The form will be submitted only if the function returns True, if the function returns Str, this will be the error text, and the default error will be used if the function returns False
Example
class TestRegisterForm(BaseForm):
update_name = "submit_register_form"
form_title = "TBF Test Register Form"
name = fields.StrField("Name", "Enter your name:")
age = fields.NumberField("Age", "Select your age:", only_int=True, key_mode=True)
sex = fields.ChooseField("Sex", "Select your sex:", answer_list=["male", "female"])
photo = fields.MediaField(
"Photo", "Enter your photo:",
valid_types=['photo'], required=False, error_message="Error. You can only send a photo")
freeze_mode = True
close_form_but = False
submit_button_text = "Register"
def form_validator(self, call, form_data):
if form_data.age < 18:
return "You must be at least 18 years old to use the bot"
return True
Fields work
Add new field
class TestRegisterForm(BaseForm):
update_name = "submit_register_form"
form_title = "TBF Test Register Form"
name = fields.StrField("Name", "Enter your name:")
age = fields.NumberField("Age", "Select your age:", only_int=True, key_mode=True)
sex = fields.ChooseField("Sex", "Select your sex:", answer_list=["male", "female"])
photo = fields.MediaField(
"Photo", "Enter your photo:",
valid_types=['photo'], required=False, error_message="Error. You can only send a photo")
freeze_mode = True
close_form_but = False
submit_button_text = "Register"
form = TestRegisterForm()
new_field = {"terms": fields.BooleanField("Terms of use", "Accept terms of use:")}
form.field_from_dict(new_field)
Field visibility
class TestRegisterForm(BaseForm):
update_name = "submit_register_form"
form_title = "TBF Test Register Form"
name = fields.StrField("Name", "Enter your name:")
age = fields.NumberField("Age", "Select your age:", only_int=True, key_mode=True)
sex = fields.ChooseField("Sex", "Select your sex:", answer_list=["male", "female"])
photo = fields.MediaField(
"Photo", "Enter your photo:",
valid_types=['photo'], required=False, error_message="Error. You can only send a photo")
terms = fields.BooleanField("Terms of use", "Accept terms of use:")
freeze_mode = True
close_form_but = False
submit_button_text = "Register"
form = TestRegisterForm()
# Hide Field
form.hide_field("terms")
# Show Field
form.show_field("terms")
Pre-submit events
Events when using the form before cancel/submit
How it works?
You must override the function
def event_listener(self, event: tb_form.FormEvent, form_data)
This is how you can receive all events inside the form. In the Form Event object, you can get the type of the event.
FormEvent aviable types
- field_input - event after input any field. "event_data" is Field object.
- field_input_invalid - event after invalid input any field. "event_data" is Field object.
Example
class TestRegisterForm(BaseForm):
update_name = "submit_register_form"
form_title = "TBF Test Register Form"
name = fields.StrField("Name", "Enter your name:")
age = fields.NumberField("Age", "Select your age:", only_int=True, key_mode=True)
sex = fields.ChooseField("Sex", "Select your sex:", answer_list=["male", "female"])
photo = fields.MediaField(
"Photo", "Enter your photo:",
valid_types=['photo'], required=False, error_message="Error. You can only send a photo")
terms = fields.BooleanField("Terms of use", "Accept terms of use:")
self.hide_field("terms")
freeze_mode = True
close_form_but = False
submit_button_text = "Register"
def event_listener(self, event: tb_form.FormEvent, form_data):
if event.event_type == "field_input":
# Show terms field only for 18+ age input
if event.event_data.name_in_form == "age":
if form_data.age >= 18:
self.hide_field("terms")
else:
self.show_field("terms")
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
File details
Details for the file TBForms-0.9.16-py3-none-any.whl
.
File metadata
- Download URL: TBForms-0.9.16-py3-none-any.whl
- Upload date:
- Size: 24.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.8.16
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 862caafca50b8d67a8ddc813a38c7da0ff32fc0f8af2aed1c2704a1760024f53 |
|
MD5 | cf03c75cd65e44b941bfb19d23b01d49 |
|
BLAKE2b-256 | 2ac3076cdcd7f621160728ca18e4eab9b71f1c3c1d4b77732ae8587720efcdb4 |