Telegram-bot: угадай букву

Edward

Новичок
Пользователь
Мар 30, 2024
4
0
1
Написал бота, архитектура из двух файлов bot и game, бот работает до тех пор как дело доходит до начала игры и вылетает ошибка которую я не понимаю "AttributeError: 'Message' object has no attribute 'send_message'. Did you mean: 'pinned_message'?"

Python:
import logging
import telebot

logger = logging.getLogger(__name__)

logging.basicConfig(level=logging.INFO)


bot = telebot.TeleBot('')


@bot.message_handler(commands=['start'])
def start(message):
    bot.send_message(message.chat.id, 'I am online! Я в сети!')

    logger.info(f"Запущен новый чат: {message.chat.id}")


@bot.message_handler(func=lambda message: message.text.lower() == 'hello')
def hello(message):
    bot.send_message(message.chat.id, "Hello! How are you doing today? Would you like to play a game?\n\n"
                                      "Привет! Как у тебя дела сегодня? Не хотите ли поиграть в игру?")


@bot.message_handler(content_types=['text'])
def handle_user_reply(message):
    if message.text.lower().strip() == 'yes':
        bot.send_message(message.chat.id, "Great! Let's play a guessing game.Отлично! Давайте поиграем в угадайку\n\n"
                                          "I will choose a letter between A and Z. Can you guess it in three tries?\n\n"
                                          "Я выберу букву от А до Я. Сможете ли вы угадать ее с трех попыток.")
        bot.register_next_step_handler(message, play_game, message.chat.id, 3)


def play_game(bot, chat_id, num_tries):
    import letter_guess # импортируем файл игры letter_guess
    letter_guess.play_game(bot, chat_id, num_tries)


bot.polling(none_stop=True, interval=0)
файл игры, telebot пайчарм его не импортирует
Код:
import random

def play_game(bot, chat_id, num_tries):
    alphabet = 'abcdefghijklmnopqrstuvwxyz'

    def get_random_letter():
        return random.choice(alphabet)


    def check_input(msg):
        try:
            input_char = msg.text[0].lower()

            if input_char in alphabet:
                return input_char
            else:
                raise ValueError("Please enter a single letter from A to Z.")
        except Exception as e:
            print(f'Caught exeption: {e}')
            return None

    secret_letter = get_random_letter()
    attempts = 0

    while attempts < num_tries:
        attempt_text = f"Attempt #{attempts + 1}: Enter a letter."
        bot.send_message(chat.id, attempt_text) # Используйте chat_id напрямую

        # Предполагается, что msg получен из обработчика сообщений
        response = check_input(msg)
        if response is None:
            continue

        if response == secret_letter:
            win_text = f"Congratulations! You guessed the correct letter: '{secret_letter}'!"
            bot.send_message(chat.id, win_text)
            break

        elif response in alphabet:
            current_index = alphabet.index(response)
            secret_index = alphabet.index(secret_letter)

            if current_index < secret_index:
                feedback_text = f"The correct letter is further right in the alphabet."
            else:
                feedback_text = f"The correct letter is further left in the alphabet."

            bot.send_message(chat.id, feedback_text)

        attempts += 1

    if attempts == num_tries:
        loss_text = f"Sorry, you ran out of tries. The correct letter was: '{secret_letter}'."
        bot.send_message(chat.id, loss_text)
 

PYDEV

Пользователь
Пользователь
Авг 31, 2023
62
15
8
у меня ваш код работает, у вас проблема скорее всего, из за среды разработки. Стоит явно указать аннотацию типов для message
Python:
from telebot import TeleBot
from telebot.types import Message

bot = TeleBot(os.getenv("TESTS_TOKEN_API"))

@bot.message_handler(commands=['start'])
def start(message: Message):
    bot.send_message(message.chat.id, 'I am online! Я в сети!')

    logger.info(f"Запущен новый чат: {message.chat.id}")
и так во всех хендлерах
 
  • Мне нравится
Реакции: Edward

4olshoy_blen

Популярный
Пользователь
Ноя 13, 2022
405
113
43
bot.register_next_step_handler(message, play_game, bot, message.chat.id, 3)
 
  • Мне нравится
Реакции: Edward

Edward

Новичок
Пользователь
Мар 30, 2024
4
0
1
у меня ваш код работает, у вас проблема скорее всего, из за среды разработки. Стоит явно указать аннотацию типов для message
Python:
from telebot import TeleBot
from telebot.types import Message

bot = TeleBot(os.getenv("TESTS_TOKEN_API"))

@bot.message_handler(commands=['start'])
def start(message: Message):
    bot.send_message(message.chat.id, 'I am online! Я в сети!')

    logger.info(f"Запущен новый чат: {message.chat.id}")
и так во всех хендлерах
ничего не помогает, в 29 строке модуля игры так же ошибка, все уже перепробовал и pinned_message вместо send
let_g.play_game(bot, chat_id, num_tries)
File "/home/edvard-user/PycharmProjects/pythonProject/let_g.py", line 29, in play_game
bot.send_message(chat_id, attempt_text) # Используйте chat_id напрямую
^^^^^^^^^^^^^^^^
AttributeError: 'Message' object has no attribute 'send_message'. Did you mean: 'pinned_message'?
 

PYDEV

Пользователь
Пользователь
Авг 31, 2023
62
15
8
я в telebot'е хз как управлять состояниями. и советую переписать проект, где игровая часть и работа бота не будут зависимы друг от друга. что-то вроде:
Python:
import random
from dataclasses import dataclass

@dataclass
class User:
    tries: int

class RandomLetters:
    def __init__(self,
                 letters: list[str],
                 max_tries: int):
        self.letters = letters
        self.max_tries = max_tries
        self.users = {}

    def random_letter(self) -> str:
        return random.choice(self.letters)

    def get_user_tries(self, user: User) -> int:
        return user.tries

    def set_user_tries(self, user: User) -> None:
        user.tries += 1

    def check_user_tries(self, user_id: User) -> bool:
        return user_id.tries <= self.max_tries

    def create_user(self, user_id: int) -> User:
        if user_id not in self.users:
            self.users[user_id] = User(tries=0)
        return self.users[user_id]
Python:
import os
from telebot import TeleBot
from telebot.types import Message

from test import RandomLetters

bot = TeleBot(token=os.getenv("TESTS_TOKEN_API"), parse_mode="HTML")
letters = ["a", "b", "c", "d", "e", "f", "g"]
random_letters = RandomLetters(letters=letters, max_tries=3)

@bot.message_handler(commands=["start"])
def cmd_start(message: Message) -> None:
    bot.send_message(chat_id=message.from_user.id,
                     text=f"Привет, я бот <b>Угадай букву</b>\n"
                          f"Введите команду /random")

@bot.message_handler(commands=["random"])
def cmd_random(message: Message) -> None:
    bot.send_message(chat_id=message.from_user.id,
                     text="Я загадал рандомную букву, угадай её.")

@bot.message_handler(func=lambda message: len(message.text) == 1)
def user_text(message: Message) -> None:
    user = random_letters.create_user(message.from_user.id)
    random_letter = random_letters.random_letter()

    if message.text == random_letter:
        bot.send_message(chat_id=message.from_user.id,
                         text=f"Поздравляю! Ты угадал букву {random_letter}\n"
                              f"Введи команду /game для запуска новой игры.")
        del random_letters.users[message.from_user.id]
    else:
        random_letters.set_user_tries(user)
        if random_letters.check_user_tries(user):
            bot.send_message(chat_id=message.from_user.id,
                             text="Неправильно! Попробуй снова.")
        else:
            bot.send_message(chat_id=message.from_user.id,
                             text="Ты проиграл, все попытки потратил!")
            del random_letters.users[message.from_user.id]

if __name__ == "__main__":
    try:
        bot.infinity_polling(skip_pending=True)
    except KeyboardInterrupt:
        print("Bot stopped!")
наверное можно сделать лучше, но мне лень))
 

Форум IT Специалистов