Skip to content

Instantly share code, notes, and snippets.

@loRes228
Last active February 1, 2025 16:15
Show Gist options
  • Save loRes228/bab79de8ec0c61b59801e20f18513c08 to your computer and use it in GitHub Desktop.
Save loRes228/bab79de8ec0c61b59801e20f18513c08 to your computer and use it in GitHub Desktop.
from __future__ import annotations
from typing import TYPE_CHECKING
from aiogram.enums import MessageEntityType
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
if TYPE_CHECKING:
from aiogram.types import Message, MessageEntity
MAX_BUTTONS_PER_ROW = 8
MAX_ROWS = 100
class TooManyButtonsInRowError(Exception):
pass
class TooManyRowsError(Exception):
pass
class NoTextLinkEntitiesError(Exception):
pass
def parse_buttons(message: Message) -> InlineKeyboardMarkup:
if not message.text:
raise ValueError
if not message.entities:
raise NoTextLinkEntitiesError
entities = filter_text_link_entities(entities=message.entities)
if not entities:
raise NoTextLinkEntitiesError
return parse_rows(entities=entities, text=message.text)
def filter_text_link_entities(entities: list[MessageEntity]) -> list[MessageEntity]:
return [entity for entity in entities if entity.type == MessageEntityType.TEXT_LINK]
def parse_rows(entities: list[MessageEntity], text: str) -> InlineKeyboardMarkup:
rows = []
lines = text.splitlines()
for line in lines:
row = parse_row(entities=entities, text=text, line=line)
if len(row) > MAX_BUTTONS_PER_ROW:
raise TooManyButtonsInRowError
if row:
rows.append(row)
if len(rows) > MAX_ROWS:
raise TooManyRowsError
return InlineKeyboardMarkup(inline_keyboard=rows)
def parse_row(entities: list[MessageEntity], text: str, line: str) -> list[InlineKeyboardButton]:
return [
create_button(entity=entity, text=text)
for entity in entities
if is_entity_in_line(entity=entity, text=text, line=line)
]
def is_entity_in_line(entity: MessageEntity, text: str, line: str) -> bool:
entity_start = entity.offset
entity_end = entity_start + entity.length
line_start = text.index(line)
line_end = line_start + len(line)
return entity_start >= line_start and entity_end <= line_end
def create_button(entity: MessageEntity, text: str) -> InlineKeyboardButton:
text = text[entity.offset : entity.offset + entity.length]
return InlineKeyboardButton(text=text, url=entity.url)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment