как я могу сохранить следующий текст в боте telegram, используя python - PullRequest
0 голосов
/ 19 апреля 2020

Я хочу, чтобы бот определенным образом обрабатывал команду "/ add". Я хотел бы сохранить три ввода от пользователя (заголовок, текст, комментарии)

@bot.message_handler(commands=['add'])
def add_to_database(message):
    msg = bot.reply_to(message, """\
We are glad that you are helping us to grow please provide us with the following:-
title of article (the head of the article)
""")

проблема в том, что когда пользователь отправляет "/ добавить", он становится переменной сообщения для функции, и поэтому я хочу обновить эту переменную до следующего сообщения, которое будет отправлено пользователем, я попытался что-то вроде

title = updater.message.text

Я хочу, чтобы пользователь отправил заголовок статьи, и это становится переменной заголовка Далее мы просим статью и сохраняем ее в другом значении в виде обычного текста и т. д.

Но я получил ошибку, такую ​​как

    title = updater.message.text
AttributeError: 'Updater' object has no attribute 'message'

1 Ответ

0 голосов
/ 19 апреля 2020

Это минимальный пример, который использует ConversationHandler для получения title, text и comments в отдельных сообщениях

Вы начинаете разговор с помощью команды /add.

Функция add() отправляет пользователю сообщение с информацией о том, что делать, и возвращает значение TITLE, информирующее бота о том, что следующее сообщение должно получить функцию get_title().

Функция get_title() получает текст и сохраняет его в глобальном словаре как title, и возвращает значение TEXT, чтобы сообщить боту, что следующее сообщение должно получить функцию get_text().

Функция get_text() получает текст и сохраняет его в глобальный словарь как text, и он возвращает значение COMMENTS, чтобы сообщить боту, что следующее сообщение должно получить функцию get_comments().

Функция get_comments() получает текст и сохраняет его в глобальном словаре как comments , и он отображает все данные из словаря (но он может сохранить его в базе данных). Он возвращает ConversationHandler.END, чтобы сообщить боту, что это конец разговора. Он может вернуть COMMENTS, чтобы получить больше комментариев, но он должен будет оставить комментарии в виде списка в словаре. И потребуется некоторая команда, чтобы прекратить получать комментарии, а затем сохранить все данные.


На основе примера кода разговорbot.py из документации


from telegram.ext import Updater, CommandHandler, ConversationHandler, MessageHandler, Filters

TOKEN = 'YOUR_TOKEN'

updater = Updater(token=TOKEN, use_context=True)
dispatcher = updater.dispatcher

# --- structure for data ---

data = {'title': "", 'text': "", 'comments': ""}

# --- states use in conversation ---

TITLE = 1
TEXT = 2
COMMENTS = 3

# --- functions use in conversation ---

# Command Handler which starts conversation
def add(update, context):
    global data # to assign new dictionary to external/global variable

    # create new empty dictionary
    data = {'title': "", 'text': "", 'comments': ""}

    update.message.reply_text("add title, text, comments in separated messages\n\nnow write title")

    # next state in conversation 
    return TITLE

def get_title(update, context):
    data['title'] = update.message.text

    update.message.reply_text(f"title: {update.message.text}\n\nnow write text")

    # next state in conversation 
    return TEXT

def get_text(update, context):
    data['text'] = update.message.text

    update.message.reply_text(f"text: {update.message.text}\n\nnow write comments")

    # next state in conversation 
    return COMMENTS

def get_comments(update, context):
    data['comments'] = update.message.text

    update.message.reply_text(f"comments: {update.message.text}")

    msg = """I got all data

title: {}
text: {}
comments: {}""".format(data['title'], data['text'], data['comments'])

    update.message.reply_text(msg)

    # end of conversation
    return ConversationHandler.END

def cancel(update, context):

    update.message.reply_text('canceled')

    # end of conversation
    return ConversationHandler.END

# --- create conversation ---

my_conversation_handler = ConversationHandler(
   entry_points=[CommandHandler('add', add)],
   states={
       TITLE: [
           CommandHandler('cancel', cancel),  # has to be before MessageHandler to catch `/cancel` as command, not as `title`
           MessageHandler(Filters.text, get_title)
       ],
       TEXT: [
           CommandHandler('cancel', cancel),  # has to be before MessageHandler to catch `/cancel` as command, not as `text`
           MessageHandler(Filters.text, get_text)
       ],
       COMMENTS: [
           CommandHandler('cancel', cancel),  # has to be before MessageHandler to catch `/cancel` as command, not as `comments`
           MessageHandler(Filters.text, get_comments)
       ],
   },
   fallbacks=[CommandHandler('cancel', cancel)]
)                

dispatcher.add_handler(my_conversation_handler)

# --- run bot ---

updater.start_polling()
print('Running... [Press Ctrl+C to stop]')
updater.idle()
print('Stoping...')
updater.stop()      

РЕДАКТИРОВАТЬ: что-то похожее с telebot. Я использую глобальную переменную state и message_handler, который перехватывает неизвестные сообщения

import telebot 

TOKEN = 'TOKEN'

bot = telebot.TeleBot(TOKEN)

#print(bot.get_me())

# --- structure for data ---

data = {'title': "", 'text': "", 'comments': ""}

# --- states use in conversation ---

state = None

TITLE = 1
TEXT = 2
COMMENTS = 3

@bot.message_handler(commands=['add'])
def test(message):
    global state
    global data

    data = {'title': "", 'text': "", 'comments': ""}

    bot.send_message(message.chat.id, 'add title, text, comments in separated messages\n\nnow write title')

    state = TITLE

@bot.message_handler()
def unknown(message):
    global state

    if state == TITLE:
        data['title'] = message.text
        bot.send_message(message.chat.id, f"title: {message.text}\n\nnow write text")
        state = TEXT
    elif state == TEXT:
        data['text'] = message.text
        bot.send_message(message.chat.id, f"text: {message.text}\n\nnow write comments")
        state = COMMENTS
    elif state == COMMENTS:
        data['comments'] = message.text
        bot.send_message(message.chat.id, f"comments: {message.text}")
        msg = """I got all data

title: {}
text: {}
comments: {}""".format(data['title'], data['text'], data['comments'])

        bot.send_message(message.chat.id, msg)
        state = None
    #else:
    #    print('unknown message')
    #    bot.send_message(msg.chat.id, 'unknown message')

@bot.message_handler(commands=['cancel'])
def test(message):
    global state

    bot.send_message(message.chat.id, 'canceled')

    state = None

bot.polling()

РЕДАКТИРОВАТЬ: более простая версия

import telebot 

TOKEN = 'TOKEN'

bot = telebot.TeleBot(TOKEN)

# --- structure for data ---

data = {'title': "", 'text': "", 'comments': ""}

# --- states use in conversation ---

bot.state = None # create own value `.state` in `bot` - so I don't have to use `global state`. Similar way I could create and use `bot.data`

TITLE = 1
TEXT = 2
COMMENTS = 3

@bot.message_handler(commands=['add'])
def test(message):
    global data

    data = {'title': "", 'text': "", 'comments': ""}

    bot.send_message(message.chat.id, 'add title, text, comments in separated messages\n\nnow write title')
    bot.state = TITLE

# it has to be before functions which check `bot.state`
@bot.message_handler(commands=['cancel'])
def test(message):
    bot.send_message(message.chat.id, 'canceled')
    bot.state = None

@bot.message_handler(func=lambda msg:bot.state==TITLE)
def get_title(message):

    data['title'] = message.text

    bot.send_message(message.chat.id, f"title: {message.text}\n\nnow write text")
    bot.state = TEXT

@bot.message_handler(func=lambda msg:bot.state==TEXT)
def get_title(message):

    data['text'] = message.text

    bot.send_message(message.chat.id, f"text: {message.text}\n\nnow write comments")
    bot.state = COMMENTS

@bot.message_handler(func=lambda msg:bot.state==COMMENTS)
def get_title(message):

    data['comments'] = message.text

    bot.send_message(message.chat.id, f"comments: {message.text}")
    msg = """I got all data

title: {}
text: {}
comments: {}""".format(data['title'], data['text'], data['comments'])
    bot.send_message(message.chat.id, msg)
    bot.state = None

bot.polling()
...