Как решить проблему с ботом ВК? Python
Есть бот в ВК, который парсит данные с сайта и отправляет их человеку.
Вот пример кода:
def main():
file = open('token.ini', 'r')
token = file.read()
token = str(token.strip())
file.close()
vk_session = vk_api.VkApi(token=token, api_version=5.103)
longpoll = VkLongPoll(vk_session)
vk = vk_session.get_api()
for event in longpoll.listen():
if event.type == VkEventType.MESSAGE_NEW and event.to_me and event.text:
if event.from_user:
if event.text.lower() == 'начать':
vk.messages.send(
user_id=event.user_id,
message='Приветствую тебя, друг! Перед тобой появились кнопки для управления ботом воспользуйся ими!',
random_id=0,
keyboard=keyboard
)
elif event.text.lower() == 'в меню':
vk.messages.send(
user_id=event.user_id,
message='Вы попали в меню!',
random_id=0,
keyboard=keyboard
)
elif event.text.lower() == 'получить данные':
event_user_id = event.user_id
get_info
else:
vk.messages.send(
user_id=event.user_id,
message='Я не понял твоей команды. Для начала работы с ботом напишите Начать.',
random_id=0
)
get_info отправляет пользователю картинку, так-же пример кода:
vk.messages.send(
user_id=event_user_id,
attachment=','.join(attachments),
random_id=0,
message=''
)
attachments это список с приложенными картинками формата [photo{owner_id}_{photo_id},и так далее]
И если написать боту "получить данные" все вроде в порядке, но после отправки картинки он 4 раза флудит текстом из else: в функции main как это исправить?
Ответы (3 шт):
Я не уверен в своих словах, но всё же напишу предположения.
Используйте метод из vk_api utils.get_random_id или генерируйте random_id, а не используйте 0.
Отключите в настройках LongPoll 'Исходящее сообщение'. Настройка -> Работа с API -> LongPoll API -> Типы событий.
Вы вызываете функцию get_info по ссылке без скобок в конце, что значит вы выполняете ее как процедуру, не отдавая на вход никаких параметров, и запускаете в отдельном процессе. Насколько мне известно, оно не захватывает данные из пространства функции, из которой была вызвана, а также не бросает ошибок, поскольку выполняется в другом процессе параллельно.
Я попытался воссоздать вашу программу и протестировать. С вашей проблемой я не столкнулся, но функция get_info очевидно не работала. После того, как я передал функции все необходимые для работы аргументы, она заработала без ошибок. Получив изображения, я мог продолжать дальше пользоваться ботом без каких-либо проблем.
def get_info(vk, event_user_id):
vk.messages.send(
user_id=event_user_id,
attachment=','.join("photoSOMEUID_SOMEMID"),
random_id=0,
message='test'
)
...
#in main():
...
elif event.text.lower() == 'получить данные':
event_user_id = event.user_id
get_info(vk, event.user_id)
...
Получив полный код, разобрался с проблемой. Дабы сохранить в тайне назначение решения, опишу логику ошибки, не вдаваясь в подробности реализации конкретного примера. Предыдущий мой ответ тоже актуален, но описывает ошибку иного рода, которая тоже может критично повлиять на работу бота, так что создал второй ответ.
В реализации функции get_info присутствует чтение сообщений от пользователя и их обработка. Посредством клавиатуры и просто сообщений. Клавиатура, собственно, и отправляет сообщение с текстом кнопки.
def get_info(...):
vk.messages.send(
user_id=event_user_id,
message='Выберите ...',
random_id=utils.get_random_id(),
keyboard=keyboard_name
)
for event in longpoll.listen():
... #Обработка сообщений от пользователя
Сообщения ловятся благодаря методу VKLongPoll.listen() из vk_api. Работает он следующим образом:
Каждое сообщение пользователя возвращается в виде генератора с помощью ключевого слова yield. Когда вы вводите longpoll.listen(), у вас создается, грубо говоря, постоянно обновляемый итератор, по которому вы и идете, ловя сообщения:
for event in longpoll.listen()
Из github vk_api:
def listen(self):
while True:
for event in self.check():
yield event
Так вот:
После того, как функция get_info() обрабатывает 4 ваших сообщения, они добавляются не только в итератор внутри функции, но и в ваш родительский итератор в функции main().
В итоге, итерируя на уровне main(), бот читает команды, предназначенные для обработки в функции get_info, и конечно же, не понимает их, ведь они описывают получаемые данные в get_info. Эти команды не выглядят, как что-то из ['Начать', 'в меню', 'получить данные'], поэтому для каждой из этих команд мы переходим в else и пишем, что команда нам непонятна.
На вашем месте, я бы продумал сначала структуру решения, прежде чем приступать к реализации, чтобы проблем с решением подобных оплошностей потом не возникало. Как человек не знакомый с vk_api, могу предложить костыльное решение:
Пусть get_info() возвращает как значение с ключевым словом return количество сообщений, которое было отправлено пользователем боту от входа в функцию до, собственно, ключевого слова return. Внутри main() первой же строкой заведите переменную msgCounter = 0 и используйте эту функцию следующим образом:
msgCounter = get_info()
Перед обработкой команд ['Начать', 'в меню', 'получить данные'] напишите:
while msgCounter:
msgCounter -= 1
continue
Это решит вашу проблему.