mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
EOL of Py3.9 (#1726)
Some checks failed
Tests / tests (macos-latest, 3.10) (push) Has been cancelled
Tests / tests (macos-latest, 3.11) (push) Has been cancelled
Tests / tests (macos-latest, 3.12) (push) Has been cancelled
Tests / tests (macos-latest, 3.13) (push) Has been cancelled
Tests / tests (ubuntu-latest, 3.10) (push) Has been cancelled
Tests / tests (ubuntu-latest, 3.11) (push) Has been cancelled
Tests / tests (ubuntu-latest, 3.12) (push) Has been cancelled
Tests / tests (ubuntu-latest, 3.13) (push) Has been cancelled
Tests / tests (windows-latest, 3.10) (push) Has been cancelled
Tests / tests (windows-latest, 3.11) (push) Has been cancelled
Tests / tests (windows-latest, 3.12) (push) Has been cancelled
Tests / tests (windows-latest, 3.13) (push) Has been cancelled
Tests / pypy-tests (macos-latest, pypy3.10) (push) Has been cancelled
Tests / pypy-tests (macos-latest, pypy3.11) (push) Has been cancelled
Tests / pypy-tests (ubuntu-latest, pypy3.10) (push) Has been cancelled
Tests / pypy-tests (ubuntu-latest, pypy3.11) (push) Has been cancelled
Some checks failed
Tests / tests (macos-latest, 3.10) (push) Has been cancelled
Tests / tests (macos-latest, 3.11) (push) Has been cancelled
Tests / tests (macos-latest, 3.12) (push) Has been cancelled
Tests / tests (macos-latest, 3.13) (push) Has been cancelled
Tests / tests (ubuntu-latest, 3.10) (push) Has been cancelled
Tests / tests (ubuntu-latest, 3.11) (push) Has been cancelled
Tests / tests (ubuntu-latest, 3.12) (push) Has been cancelled
Tests / tests (ubuntu-latest, 3.13) (push) Has been cancelled
Tests / tests (windows-latest, 3.10) (push) Has been cancelled
Tests / tests (windows-latest, 3.11) (push) Has been cancelled
Tests / tests (windows-latest, 3.12) (push) Has been cancelled
Tests / tests (windows-latest, 3.13) (push) Has been cancelled
Tests / pypy-tests (macos-latest, pypy3.10) (push) Has been cancelled
Tests / pypy-tests (macos-latest, pypy3.11) (push) Has been cancelled
Tests / pypy-tests (ubuntu-latest, pypy3.10) (push) Has been cancelled
Tests / pypy-tests (ubuntu-latest, pypy3.11) (push) Has been cancelled
* Drop py3.9 and pypy3.9 Add pypy3.11 (testing) into `tests.yml` Remove py3.9 from matrix in `tests.yml` Refactor not auto-gen code to be compatible with py3.10+, droping ugly 3.9 annotation. Replace some `from typing` imports to `from collections.abc`, due to deprecation Add `from __future__ import annotations` and `if TYPE_CHECKING:` where possible Add some `noqa` to calm down Ruff in some places, if Ruff will be used as default linting+formatting tool in future Replace some relative imports to absolute Sort `__all__` tuples in `__init__.py` and some other `.py` files Sort `__slots__` tuples in classes Split raises into `msg` and `raise` (`EM101`, `EM102`) to not duplicate error message in the traceback Add `Self` from `typing_extenstion` where possible Resolve typing problem in `aiogram/filters/command.py:18` Concatenate nested `if` statements Convert `HandlerContainer` into a dataclass in `aiogram/fsm/scene.py` Bump tests docker-compose.yml `redis:6-alpine` -> `redis:8-alpine` Bump tests docker-compose.yml `mongo:7.0.6` -> `mongo:8.0.14` Bump pre-commit-config `black==24.4.2` -> `black==25.9.0` Bump pre-commit-config `ruff==0.5.1` -> `ruff==0.13.3` Update Makefile lint for ruff to show fixes Add `make outdated` into Makefile Use `pathlib` instead of `os.path` Bump `redis[hiredis]>=5.0.1,<5.3.0` -> `redis[hiredis]>=6.2.0,<7` Bump `cryptography>=43.0.0` -> `cryptography>=46.0.0` due to security reasons Bump `pytz~=2023.3` -> `pytz~=2025.2` Bump `pycryptodomex~=3.19.0` -> `pycryptodomex~=3.23.0` due to security reasons Bump linting and formatting tools * Add `1726.removal.rst` * Update aiogram/utils/dataclass.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update aiogram/filters/callback_data.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update 1726.removal.rst * Remove `outdated` from Makefile * Add `__slots__` to `HandlerContainer` * Remove unused imports * Add `@dataclass` with `slots=True` to `HandlerContainer` --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
ab32296d07
commit
df7b16d5b3
94 changed files with 1383 additions and 1215 deletions
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Dict, Optional, Union
|
||||
from typing import Any
|
||||
|
||||
from aiogram import Router
|
||||
from aiogram.filters import Filter
|
||||
|
|
@ -8,7 +8,7 @@ router = Router(name=__name__)
|
|||
|
||||
|
||||
class HelloFilter(Filter):
|
||||
def __init__(self, name: Optional[str] = None) -> None:
|
||||
def __init__(self, name: str | None = None) -> None:
|
||||
self.name = name
|
||||
|
||||
async def __call__(
|
||||
|
|
@ -16,7 +16,7 @@ class HelloFilter(Filter):
|
|||
message: Message,
|
||||
event_from_user: User,
|
||||
# Filters also can accept keyword parameters like in handlers
|
||||
) -> Union[bool, Dict[str, Any]]:
|
||||
) -> bool | dict[str, Any]:
|
||||
if message.text.casefold() == "hello":
|
||||
# Returning a dictionary that will update the context data
|
||||
return {"name": event_from_user.mention_html(name=self.name)}
|
||||
|
|
@ -25,6 +25,7 @@ class HelloFilter(Filter):
|
|||
|
||||
@router.message(HelloFilter())
|
||||
async def my_handler(
|
||||
message: Message, name: str # Now we can accept "name" as named parameter
|
||||
message: Message,
|
||||
name: str, # Now we can accept "name" as named parameter
|
||||
) -> Any:
|
||||
return message.answer("Hello, {name}!".format(name=name))
|
||||
return message.answer(f"Hello, {name}!")
|
||||
|
|
|
|||
|
|
@ -75,11 +75,13 @@ async def handle_set_age(message: types.Message, command: CommandObject) -> None
|
|||
# To get the command arguments you can use `command.args` property.
|
||||
age = command.args
|
||||
if not age:
|
||||
raise InvalidAge("No age provided. Please provide your age as a command argument.")
|
||||
msg = "No age provided. Please provide your age as a command argument."
|
||||
raise InvalidAge(msg)
|
||||
|
||||
# If the age is invalid, raise an exception.
|
||||
if not age.isdigit():
|
||||
raise InvalidAge("Age should be a number")
|
||||
msg = "Age should be a number"
|
||||
raise InvalidAge(msg)
|
||||
|
||||
# If the age is valid, send a message to the user.
|
||||
age = int(age)
|
||||
|
|
@ -95,7 +97,8 @@ async def handle_set_name(message: types.Message, command: CommandObject) -> Non
|
|||
# To get the command arguments you can use `command.args` property.
|
||||
name = command.args
|
||||
if not name:
|
||||
raise InvalidName("Invalid name. Please provide your name as a command argument.")
|
||||
msg = "Invalid name. Please provide your name as a command argument."
|
||||
raise InvalidName(msg)
|
||||
|
||||
# If the name is valid, send a message to the user.
|
||||
await message.reply(text=f"Your name is {name}")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import asyncio
|
|||
import logging
|
||||
import sys
|
||||
from os import getenv
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
from aiogram import Bot, Dispatcher, F, Router, html
|
||||
from aiogram.client.default import DefaultBotProperties
|
||||
|
|
@ -66,7 +66,7 @@ async def process_name(message: Message, state: FSMContext) -> None:
|
|||
[
|
||||
KeyboardButton(text="Yes"),
|
||||
KeyboardButton(text="No"),
|
||||
]
|
||||
],
|
||||
],
|
||||
resize_keyboard=True,
|
||||
),
|
||||
|
|
@ -106,13 +106,13 @@ async def process_language(message: Message, state: FSMContext) -> None:
|
|||
|
||||
if message.text.casefold() == "python":
|
||||
await message.reply(
|
||||
"Python, you say? That's the language that makes my circuits light up! 😉"
|
||||
"Python, you say? That's the language that makes my circuits light up! 😉",
|
||||
)
|
||||
|
||||
await show_summary(message=message, data=data)
|
||||
|
||||
|
||||
async def show_summary(message: Message, data: Dict[str, Any], positive: bool = True) -> None:
|
||||
async def show_summary(message: Message, data: dict[str, Any], positive: bool = True) -> None:
|
||||
name = data["name"]
|
||||
language = data.get("language", "<something unexpected>")
|
||||
text = f"I'll keep in mind that, {html.quote(name)}, "
|
||||
|
|
@ -124,7 +124,7 @@ async def show_summary(message: Message, data: Dict[str, Any], positive: bool =
|
|||
await message.answer(text=text, reply_markup=ReplyKeyboardRemove())
|
||||
|
||||
|
||||
async def main():
|
||||
async def main() -> None:
|
||||
# Initialize Bot instance with default bot properties which will be passed to all API calls
|
||||
bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
import sys
|
||||
from os import getenv
|
||||
from typing import Any, Dict, Union
|
||||
from typing import Any
|
||||
|
||||
from aiohttp import web
|
||||
from finite_state_machine import form_router
|
||||
|
|
@ -34,7 +34,7 @@ REDIS_DSN = "redis://127.0.0.1:6479"
|
|||
OTHER_BOTS_URL = f"{BASE_URL}{OTHER_BOTS_PATH}"
|
||||
|
||||
|
||||
def is_bot_token(value: str) -> Union[bool, Dict[str, Any]]:
|
||||
def is_bot_token(value: str) -> bool | dict[str, Any]:
|
||||
try:
|
||||
validate_token(value)
|
||||
except TokenValidationError:
|
||||
|
|
@ -54,11 +54,11 @@ async def command_add_bot(message: Message, command: CommandObject, bot: Bot) ->
|
|||
return await message.answer(f"Bot @{bot_user.username} successful added")
|
||||
|
||||
|
||||
async def on_startup(dispatcher: Dispatcher, bot: Bot):
|
||||
async def on_startup(dispatcher: Dispatcher, bot: Bot) -> None:
|
||||
await bot.set_webhook(f"{BASE_URL}{MAIN_BOT_PATH}")
|
||||
|
||||
|
||||
def main():
|
||||
def main() -> None:
|
||||
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
|
||||
session = AiohttpSession()
|
||||
bot_settings = {"session": session, "parse_mode": ParseMode.HTML}
|
||||
|
|
|
|||
|
|
@ -14,4 +14,4 @@ class MyFilter(Filter):
|
|||
|
||||
|
||||
@router.message(MyFilter("hello"))
|
||||
async def my_handler(message: Message): ...
|
||||
async def my_handler(message: Message) -> None: ...
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ quiz_router.message.register(QuizScene.as_handler(), Command("quiz"))
|
|||
|
||||
|
||||
@quiz_router.message(Command("start"))
|
||||
async def command_start(message: Message, scenes: ScenesManager):
|
||||
async def command_start(message: Message, scenes: ScenesManager) -> None:
|
||||
await scenes.close()
|
||||
await message.answer(
|
||||
"Hi! This is a quiz bot. To start the quiz, use the /quiz command.",
|
||||
|
|
@ -271,7 +271,7 @@ async def command_start(message: Message, scenes: ScenesManager):
|
|||
)
|
||||
|
||||
|
||||
def create_dispatcher():
|
||||
def create_dispatcher() -> Dispatcher:
|
||||
# Event isolation is needed to correctly handle fast user responses
|
||||
dispatcher = Dispatcher(
|
||||
events_isolation=SimpleEventIsolation(),
|
||||
|
|
@ -288,7 +288,7 @@ def create_dispatcher():
|
|||
return dispatcher
|
||||
|
||||
|
||||
async def main():
|
||||
async def main() -> None:
|
||||
dp = create_dispatcher()
|
||||
bot = Bot(token=TOKEN)
|
||||
await dp.start_polling(bot)
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ class CancellableScene(Scene):
|
|||
"""
|
||||
|
||||
@on.message(F.text.casefold() == BUTTON_CANCEL.text.casefold(), after=After.exit())
|
||||
async def handle_cancel(self, message: Message):
|
||||
async def handle_cancel(self, message: Message) -> None:
|
||||
await message.answer("Cancelled.", reply_markup=ReplyKeyboardRemove())
|
||||
|
||||
@on.message(F.text.casefold() == BUTTON_BACK.text.casefold(), after=After.back())
|
||||
async def handle_back(self, message: Message):
|
||||
async def handle_back(self, message: Message) -> None:
|
||||
await message.answer("Back.")
|
||||
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ class LanguageScene(CancellableScene, state="language"):
|
|||
"""
|
||||
|
||||
@on.message.enter()
|
||||
async def on_enter(self, message: Message):
|
||||
async def on_enter(self, message: Message) -> None:
|
||||
await message.answer(
|
||||
"What language do you prefer?",
|
||||
reply_markup=ReplyKeyboardMarkup(
|
||||
|
|
@ -58,14 +58,14 @@ class LanguageScene(CancellableScene, state="language"):
|
|||
)
|
||||
|
||||
@on.message(F.text.casefold() == "python", after=After.exit())
|
||||
async def process_python(self, message: Message):
|
||||
async def process_python(self, message: Message) -> None:
|
||||
await message.answer(
|
||||
"Python, you say? That's the language that makes my circuits light up! 😉"
|
||||
"Python, you say? That's the language that makes my circuits light up! 😉",
|
||||
)
|
||||
await self.input_language(message)
|
||||
|
||||
@on.message(after=After.exit())
|
||||
async def input_language(self, message: Message):
|
||||
async def input_language(self, message: Message) -> None:
|
||||
data: FSMData = await self.wizard.get_data()
|
||||
await self.show_results(message, language=message.text, **data)
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ class LikeBotsScene(CancellableScene, state="like_bots"):
|
|||
"""
|
||||
|
||||
@on.message.enter()
|
||||
async def on_enter(self, message: Message):
|
||||
async def on_enter(self, message: Message) -> None:
|
||||
await message.answer(
|
||||
"Did you like to write bots?",
|
||||
reply_markup=ReplyKeyboardMarkup(
|
||||
|
|
@ -96,18 +96,18 @@ class LikeBotsScene(CancellableScene, state="like_bots"):
|
|||
)
|
||||
|
||||
@on.message(F.text.casefold() == "yes", after=After.goto(LanguageScene))
|
||||
async def process_like_write_bots(self, message: Message):
|
||||
async def process_like_write_bots(self, message: Message) -> None:
|
||||
await message.reply("Cool! I'm too!")
|
||||
|
||||
@on.message(F.text.casefold() == "no", after=After.exit())
|
||||
async def process_dont_like_write_bots(self, message: Message):
|
||||
async def process_dont_like_write_bots(self, message: Message) -> None:
|
||||
await message.answer(
|
||||
"Not bad not terrible.\nSee you soon.",
|
||||
reply_markup=ReplyKeyboardRemove(),
|
||||
)
|
||||
|
||||
@on.message()
|
||||
async def input_like_bots(self, message: Message):
|
||||
async def input_like_bots(self, message: Message) -> None:
|
||||
await message.answer("I don't understand you :(")
|
||||
|
||||
|
||||
|
|
@ -117,25 +117,25 @@ class NameScene(CancellableScene, state="name"):
|
|||
"""
|
||||
|
||||
@on.message.enter() # Marker for handler that should be called when a user enters the scene.
|
||||
async def on_enter(self, message: Message):
|
||||
async def on_enter(self, message: Message) -> None:
|
||||
await message.answer(
|
||||
"Hi there! What's your name?",
|
||||
reply_markup=ReplyKeyboardMarkup(keyboard=[[BUTTON_CANCEL]], resize_keyboard=True),
|
||||
)
|
||||
|
||||
@on.callback_query.enter() # different types of updates that start the scene also supported.
|
||||
async def on_enter_callback(self, callback_query: CallbackQuery):
|
||||
async def on_enter_callback(self, callback_query: CallbackQuery) -> None:
|
||||
await callback_query.answer()
|
||||
await self.on_enter(callback_query.message)
|
||||
|
||||
@on.message.leave() # Marker for handler that should be called when a user leaves the scene.
|
||||
async def on_leave(self, message: Message):
|
||||
async def on_leave(self, message: Message) -> None:
|
||||
data: FSMData = await self.wizard.get_data()
|
||||
name = data.get("name", "Anonymous")
|
||||
await message.answer(f"Nice to meet you, {html.quote(name)}!")
|
||||
|
||||
@on.message(after=After.goto(LikeBotsScene))
|
||||
async def input_name(self, message: Message):
|
||||
async def input_name(self, message: Message) -> None:
|
||||
await self.wizard.update_data(name=message.text)
|
||||
|
||||
|
||||
|
|
@ -154,22 +154,22 @@ class DefaultScene(
|
|||
start_demo = on.message(F.text.casefold() == "demo", after=After.goto(NameScene))
|
||||
|
||||
@on.message(Command("demo"))
|
||||
async def demo(self, message: Message):
|
||||
async def demo(self, message: Message) -> None:
|
||||
await message.answer(
|
||||
"Demo started",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
inline_keyboard=[[InlineKeyboardButton(text="Go to form", callback_data="start")]]
|
||||
inline_keyboard=[[InlineKeyboardButton(text="Go to form", callback_data="start")]],
|
||||
),
|
||||
)
|
||||
|
||||
@on.callback_query(F.data == "start", after=After.goto(NameScene))
|
||||
async def demo_callback(self, callback_query: CallbackQuery):
|
||||
async def demo_callback(self, callback_query: CallbackQuery) -> None:
|
||||
await callback_query.answer(cache_time=0)
|
||||
await callback_query.message.delete_reply_markup()
|
||||
|
||||
@on.message.enter() # Mark that this handler should be called when a user enters the scene.
|
||||
@on.message()
|
||||
async def default_handler(self, message: Message):
|
||||
async def default_handler(self, message: Message) -> None:
|
||||
await message.answer(
|
||||
"Start demo?\nYou can also start demo via command /demo",
|
||||
reply_markup=ReplyKeyboardMarkup(
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ async def command_start_handler(message: Message) -> None:
|
|||
await message.answer(
|
||||
f"Hello, {hbold(message.from_user.full_name)}!",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
inline_keyboard=[[InlineKeyboardButton(text="Tap me, bro", callback_data="*")]]
|
||||
inline_keyboard=[[InlineKeyboardButton(text="Tap me, bro", callback_data="*")]],
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ async def chat_member_update(chat_member: ChatMemberUpdated, bot: Bot) -> None:
|
|||
await bot.send_message(
|
||||
chat_member.chat.id,
|
||||
f"Member {hcode(chat_member.from_user.id)} was changed "
|
||||
+ f"from {chat_member.old_chat_member.status} to {chat_member.new_chat_member.status}",
|
||||
f"from {chat_member.old_chat_member.status} to {chat_member.new_chat_member.status}",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ my_router = Router()
|
|||
|
||||
|
||||
@my_router.message(CommandStart())
|
||||
async def command_start(message: Message, bot: Bot, base_url: str):
|
||||
async def command_start(message: Message, bot: Bot, base_url: str) -> None:
|
||||
await bot.set_chat_menu_button(
|
||||
chat_id=message.chat.id,
|
||||
menu_button=MenuButtonWebApp(text="Open Menu", web_app=WebAppInfo(url=f"{base_url}/demo")),
|
||||
|
|
@ -21,28 +21,29 @@ async def command_start(message: Message, bot: Bot, base_url: str):
|
|||
|
||||
|
||||
@my_router.message(Command("webview"))
|
||||
async def command_webview(message: Message, base_url: str):
|
||||
async def command_webview(message: Message, base_url: str) -> None:
|
||||
await message.answer(
|
||||
"Good. Now you can try to send it via Webview",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
inline_keyboard=[
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
text="Open Webview", web_app=WebAppInfo(url=f"{base_url}/demo")
|
||||
)
|
||||
]
|
||||
]
|
||||
text="Open Webview",
|
||||
web_app=WebAppInfo(url=f"{base_url}/demo"),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@my_router.message(~F.message.via_bot) # Echo to all messages except messages via bot
|
||||
async def echo_all(message: Message, base_url: str):
|
||||
async def echo_all(message: Message, base_url: str) -> None:
|
||||
await message.answer(
|
||||
"Test webview",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
inline_keyboard=[
|
||||
[InlineKeyboardButton(text="Open", web_app=WebAppInfo(url=f"{base_url}/demo"))]
|
||||
]
|
||||
[InlineKeyboardButton(text="Open", web_app=WebAppInfo(url=f"{base_url}/demo"))],
|
||||
],
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ TOKEN = getenv("BOT_TOKEN")
|
|||
APP_BASE_URL = getenv("APP_BASE_URL")
|
||||
|
||||
|
||||
async def on_startup(bot: Bot, base_url: str):
|
||||
async def on_startup(bot: Bot, base_url: str) -> None:
|
||||
await bot.set_webhook(f"{base_url}/webhook")
|
||||
await bot.set_chat_menu_button(
|
||||
menu_button=MenuButtonWebApp(text="Open Menu", web_app=WebAppInfo(url=f"{base_url}/demo"))
|
||||
menu_button=MenuButtonWebApp(text="Open Menu", web_app=WebAppInfo(url=f"{base_url}/demo")),
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
def main() -> None:
|
||||
bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
dispatcher = Dispatcher()
|
||||
dispatcher["base_url"] = APP_BASE_URL
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from aiohttp.web_fileresponse import FileResponse
|
||||
from aiohttp.web_request import Request
|
||||
from aiohttp.web_response import json_response
|
||||
|
||||
from aiogram import Bot
|
||||
from aiogram.types import (
|
||||
InlineKeyboardButton,
|
||||
InlineKeyboardMarkup,
|
||||
|
|
@ -14,12 +15,18 @@ from aiogram.types import (
|
|||
)
|
||||
from aiogram.utils.web_app import check_webapp_signature, safe_parse_webapp_init_data
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from aiohttp.web_request import Request
|
||||
from aiohttp.web_response import Response
|
||||
|
||||
async def demo_handler(request: Request):
|
||||
from aiogram import Bot
|
||||
|
||||
|
||||
async def demo_handler(request: Request) -> FileResponse:
|
||||
return FileResponse(Path(__file__).parent.resolve() / "demo.html")
|
||||
|
||||
|
||||
async def check_data_handler(request: Request):
|
||||
async def check_data_handler(request: Request) -> Response:
|
||||
bot: Bot = request.app["bot"]
|
||||
|
||||
data = await request.post()
|
||||
|
|
@ -28,7 +35,7 @@ async def check_data_handler(request: Request):
|
|||
return json_response({"ok": False, "err": "Unauthorized"}, status=401)
|
||||
|
||||
|
||||
async def send_message_handler(request: Request):
|
||||
async def send_message_handler(request: Request) -> Response:
|
||||
bot: Bot = request.app["bot"]
|
||||
data = await request.post()
|
||||
try:
|
||||
|
|
@ -44,11 +51,11 @@ async def send_message_handler(request: Request):
|
|||
InlineKeyboardButton(
|
||||
text="Open",
|
||||
web_app=WebAppInfo(
|
||||
url=str(request.url.with_scheme("https").with_path("demo"))
|
||||
url=str(request.url.with_scheme("https").with_path("demo")),
|
||||
),
|
||||
)
|
||||
]
|
||||
]
|
||||
),
|
||||
],
|
||||
],
|
||||
)
|
||||
await bot.answer_web_app_query(
|
||||
web_app_query_id=web_app_init_data.query_id,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ def create_parser() -> ArgumentParser:
|
|||
return parser
|
||||
|
||||
|
||||
async def main():
|
||||
async def main() -> None:
|
||||
parser = create_parser()
|
||||
ns = parser.parse_args()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue