async def choice_cat(message):
CATs = cur.execute(f'SELECT name FROM cathlete WHERE id = "{message.from_user.id}"').fetchall()
for fds in range(len(CATs)):
astt = ReplyKeyboardMarkup(resize_keyboard=True).add(KeyboardButton(f"CATs[{fds}]"))
Код, конечно, жесть. По пунктам:
1. НИКОГДА не генерируй SQL запрос через форматирование строк. Легко словить ошибку, а если очень не повезёт -
SQL-инъекцию. Используй
подстановку параметров (ссылка для sqlite, если у тебя другая БД - ищи доки на неё).
2. Как насчёт проверить, а вернула ли БД хоть что-то? Это не гарантируется. Всегда ожидай подставы.
3. Зачем итерироваться по индексу списка, если ты индекс не используешь? Почему не итерироваться по самому списку? И да, это абсолютные основы питона, которые НАДО знать задолго до того, как браться за ботов.
4. Зачем ты создаёшь новую клавиатуру на каждой итерации цикла? Тут уже даже не знания языка, тут простая логика. Создал клавиатуру, добавил кнопку - на следующей итерации выбросил старую клавиатуру, создал новую добавил другую кнопку. Ну бессмыслица же! Создай клавиатуру один раз, до цикла, и добавляй кнопки к ней.
5. Ну тот факт, что ты не посылаешь сообщение, к которому будет прикреплена клавиатура (а сама по себе она не бывает!), это уже мелочи. Видимо, не дошёл ещё до этого этапа.
kbd = ReplyKeyboardMarkup(resize_keyboard=True)
btns = cur.execute(f'SELECT name FROM cathlete WHERE id = ?', (message.from_user.id,)).fetchall()
# btns - список списков.
if not btns:
# кнопки не предусмотрены, как-то даём пользователю знать об этом
return # если это фатально, останавливаемся тут
# иначе создаём какое-то значение btns по умолчанию и продолжаем
# тут уж сам решай
# делаем клавиатуру
for btn in btns:
kbd.add(KeyboardButton(btn[0]))
# ну и отправляем её вместе с сообщением