Комментарии 3
def take_position(id_user):
connection = get_connection()
try:
with connection.cursor() as cursor:
sql = "SELECT position FROM user WHERE iduser = %s"
cursor.execute(sql, (id_user))
line = cursor.fetchone()
if line is None:
return_count = 0
else:
return_count = line["position"]
finally:
connection.close()
return return_count
Тут есть одна проблема. Что если достать данные не получится? Тогда return_count
будет не объявлен, на последней строчке код ляжет.
Также if line is None: ... else: ...
можно заменить на return_count = line.get("position", 0)
Честно говоря, не понятен выбор в сторону threads
, ведь есть асинхронность.
Функция processing_message
сильно перегружена. И как быть, если функционал (количество состояний) будет расти? К тому же в таком коде легко будет допустить ошибку (как минимум, из-за того, что состояние выражается через числа).
Ещё мне не понять, почему часть данных находятся в коде (цитаты), а keyboard layout в отдельном файле? К тому же что будет, если вдруг ошибиться в имени файла? (опять ошибка в рантайме)
Желательно бы вообще вынести все credentials (данные от БД, VK API token...) в константы, а ещё лучше вообще вынести их из кода.
Также есть вопрос по поводу обработки сообщений. Почему мы обрабатываем текст таким образом: if message_text == "Цитаты Дурова":
, хотя есть payload
для клавиатур? И что если вдруг текст на кнопках будет одинаков?
А что если вашим ботом будут пользоваться много людей, придётся очень часто отправлять сообщения, но надо помнить, что у VK API есть лимиты на отправку сообщений (борьба со спамом). Также могут произойти всякие проблемы в сети, надо сделать повторную отправку сообщения. Но её нет. (Кстати, вы сначала обновляете состояние, а только потом отправляете сообщение. Что если сообщение не отправится, но состояние обновится?)
Верные замечания, НО здесь базовый код, я не хотел его перегружать проверками.
Я хотел написать статью по максимально простому пути, чтобы был понятен именно принцип.
По поводу асинхронности и longpoll - если только aiovk, но даже если объяснять её - то нужно будет объяснить принцип асинхронности изначально. Я не делал такие проекты с этой библиотекой.
Credentials я не вынес только чтобы не создавать отдельный файл ради трех строк. Так, естественно, правильное замечание.
По поводу сообщений - в статье я упростил код, но в моих проектах всё стоит в цикле. Я стоплю на полсекунды отправку после ошибки и потом повторяю опять:
def send_message(id_user, id_keyboard, message_text):
for i in range(0, 3):
try:
vk.messages.send(
user_id=id_user,
random_id=get_random_id(),
keyboard=open(id_keyboard, 'r', encoding='UTF-8').read(),
message=message_text)
except:
print("Ошибка отправки сообщения у id" + str(id_user))
time.sleep(0.5)
continue
break
Если текст на кнопках будет одинаков, то позиция будет разная.
А про обновление состояния - даже если сообщение не сработает, то повторное сообщение выведет "Непонятная команда" и выведет правильную клавиатуру.
Ах да, я сделал это с мыслью что если пользователь успеет кликнуть на сообщение на новой клавиатуре, а позиция ещё не обновится к этому моменту - будет ошибка.
P.S. Все статьи, которые я читал на хабре с этой темой - нигде так не штудировали код в комментах =)
Худшее решение, которое можно придумать. Зачем использовать vk_api и многопоточность, катода есть асинхронный vkbottle?
Делаем многоуровневого бота для ВК с Long Poll VK API, Python, MySQL и решаем вопрос многопоточности c помощью threading