Вопрос или проблема
Я разрабатываю бота для рекомендаций фильмов с использованием библиотеки telebot на Python и библиотеки IMDbPY для получения данных о фильмах. Бот предлагает фильмы на основе выбранных пользователем жанров и диапазонов дат.
Ожидаемое Поведение
Когда пользователь отвечает “Нет” на предложение фильма, бот должен предоставить другую рекомендацию.
Фактическое Поведение
Бот предоставляет только одну рекомендацию и не предлагает другой фильм, когда пользователь отвечает отрицательно.
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
import os
import json
import random
from imdb import Cinemagoer
# Инициализация IMDb и бота
imdb = Cinemagoer()
TELEGRAM_API_TOKEN = os.getenv("TELEGRAM_API_TOKEN")
bot = telebot.TeleBot(TELEGRAM_API_TOKEN, parse_mode=None)
# Структуры данных
user_movie_state = {}
@bot.message_handler(commands=["recommend"])
def recommend_movie(message):
user_id = message.from_user.id
# ... [другой код опущен для краткости]
send_movie_suggestion(message, user_id)
def send_movie_suggestion(message, user_id):
# ... [другой код опущен для краткости]
while True:
current_movie = random.choice(recommended_movies)
movie_id = current_movie.movieID
if movie_id not in user_movie_state[user_id]["suggested_ids"]:
user_movie_state[user_id]["suggested_ids"].add(movie_id)
break
# Ответ пользователю
# ... [другой код опущен для краткости]
markup = InlineKeyboardMarkup()
markup.add(InlineKeyboardButton("Да", callback_data=json.dumps({"action": "happy"})))
markup.add(InlineKeyboardButton("Нет", callback_data=json.dumps({"action": "not_happy"})))
bot.send_message(message.chat.id, "Вы довольны этим предложением?", reply_markup=markup)
@bot.message_handler(func=lambda message: message.text.lower() == "нет")
def handle_no_response(message):
user_id = message.from_user.id
if user_id in user_movie_state:
send_movie_suggestion(message, user_id)
# Отладочные выводы
print(f"[DEBUG] Количество рекомендованных фильмов: {len(recommendations_list)}")
print(f"[DEBUG] Выбранный ID фильма: {movie_id}")
print(f"[DEBUG] Добавленный ID рекомендованного фильма: {movie_id}")
Наблюдаемый Отладочный Вывод.
Количество рекомендованных фильмов: 3
Выбранный ID фильма: 9776008
Добавленный ID рекомендованного фильма: 9776008
Принятые Шаги Для Отладки.
Добавлены отладочные сообщения для записи количества рекомендованных фильмов и ID фильмов, которые предлагаются.
Проверено, что ID фильмов отслеживаются и обновляются правильно в user_movie_state.
Убедился, что обработчик ответов для “Нет” снова вызывает функцию предложения.
Дополнительная Информация.
Ключевая переменная в функции handle_callback_query в настоящее время не используется и отмечена flake8, но я не уверен, связано ли это с проблемой рекомендаций.
Любая помощь или советы по разрешению этой проблемы будут очень полезны!
Реализованные Рекомендации Фильмов: Я создал функцию, которая предлагает фильмы на основе выбранных пользователем жанров и диапазонов дат.
Обработка Отзывов Пользователей: Я добавил кнопки встроенной клавиатуры для обратной связи пользователей (“Да” или “Нет”) по рекомендациям.
Вывод Отладки: Я включил отладочные сообщения для отслеживания количества рекомендованных фильмов и ID предлагаемых фильмов.
Использован цикл while True: Я реализовал цикл, чтобы гарантировать, что фильмы, которые уже были предложены, не предлагались снова.
Проверены suggested_ids: Я подтвердил, что предложенные ID правильно сохраняются, чтобы избежать дубликатов.
Что Я Ожидал.
Я ожидал, что бот будет предлагать новый фильм каждый раз, когда пользователь отвечает “Нет” на предложение.
Я предполагал, что рекомендации будут циклически проходить по доступным фильмам, не повторяясь, пока все варианты не будут показаны.
В идеале я ожидал увидеть правильные отладочные выходные данные, отражающие предложения фильмов и состояние рекомендаций.
Ответ или решение
Чтобы решить проблему с рекоммендательным ботом, который не предлагает новые фильмы при ответе пользователя "Нет", необходимо внести несколько изменений в ваш текущий код. Давайте рассмотрим это шаг за шагом.
Основные проблемы
-
Использование обработчика сообщений вместо callback’ов: Обработчик
handle_no_response
реагирует на текстовые сообщения ("Нет"), однако ваша кнопка, которая предлагает пользователю ответить, использует callback. Это означает, что вы должны использовать обработчик для обработки callback’ов, а не обрабатывать текст. - Повторное предложение фильмов: Ваша текущая логика не обновляет состояние, когда пользователь запрашивает новый фильм. Необходимо обновлять состояние
user_movie_state
и выбирать другой фильм из доступного списка.
Решение
1. Изменение обработчика для "Нет"
Измените обработчик, чтобы он обрабатывал события на основе callback данных. Этот обработчик будет срабатывать, когда пользователь нажимает на кнопку "Нет".
@bot.callback_query_handler(func=lambda call: True)
def handle_callback_query(call):
user_id = call.from_user.id
try:
data = json.loads(call.data)
if data["action"] == "not_happy":
send_movie_suggestion(call.message, user_id)
bot.answer_callback_query(call.id) # Подтверждаем взаимодействие
except Exception as e:
print(f"[ERROR] An error occurred: {e}")
2. Изменение логики send_movie_suggestion
Убедитесь, что логика в функции send_movie_suggestion
обновляет состояние правильно и действительно выбирает новый фильм.
def send_movie_suggestion(message, user_id):
# Проверяем, есть ли у пользователя список предложенных фильмов
if user_id not in user_movie_state:
user_movie_state[user_id] = {"suggested_ids": set()}
current_movie = None
while True:
current_movie = random.choice(recommended_movies)
movie_id = current_movie.movieID
# Проверяем, не был ли фильм уже предложен
if movie_id not in user_movie_state[user_id]["suggested_ids"]:
user_movie_state[user_id]["suggested_ids"].add(movie_id)
break
# Отправляем пользователю рекомендацию
bot.send_message(message.chat.id, f"Как насчет {current_movie.title}?")
markup = InlineKeyboardMarkup()
markup.add(InlineKeyboardButton("Да", callback_data=json.dumps({"action": "happy"})))
markup.add(InlineKeyboardButton("Нет", callback_data=json.dumps({"action": "not_happy"})))
bot.send_message(message.chat.id, "Вам понравилось это предложение?", reply_markup=markup)
3. Удаление ненужных обработчиков
Поскольку мы теперь используем обработчик для callback-ов, вам больше не нужен обработчик для текстового сообщения "Нет". Соответственно, удалите handle_no_response
.
Заключение
Эти изменения помогут вашему боту работать ожидаемым образом, предлагая новые фильмы при ответе пользователя "Нет". Отладочные сообщения, которые вы добавили ранее, также помогут вам убедиться, что бот правильно обрабатывает состояния и выбор фильмов.
Не забывайте тестировать после внесения изменений, чтобы убедиться, что бот работает стабильно.