我正在开发一个带有 FSM 的电报机器人。它应该是用于订购披萨的聊天机器人。对话应该是这样的:
- 你想要什么样的披萨?大或小?
- 伟大的
- 你将如何付款?
- 用现金
- 你想要一个大披萨,现金付款吗?
- 是的
- 谢谢你的订单
我有这个代码:
僵尸软件
import telebot
import config
import FSM
from telebot import types
bot = telebot.TeleBot(config.TOKEN)
fsm = FSM.TelegramBot()
@bot.message_handler(commands=['start'])
def welcome(message):
#keyboard
markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
item1 = types.KeyboardButton("Заказать пиццу")
item2 = types.KeyboardButton("Посмотреть меню")
markup.add(item1, item2)
bot.send_message(message.chat.id,
"Добро пожаловать, {0.first_name}!\nЯ - <b>{1.first_name}</b> бот, я помогу вам "
"сделать заказ.".format(
message.from_user, bot.get_me()),
parse_mode='html', reply_markup=markup)
@bot.message_handler(content_types=['text'])
@bot.message_handler(func=lambda message: fsm.state == 'asleep')
def order_pizza(message):
bot.send_message(message.chat.id, 'Какую вы хотите пиццу? Большую или маленькую?')
fsm.asked_for_payment_method(message.text)
@bot.message_handler(content_types=['text'])
@bot.message_handler(func=lambda message: fsm.state == 'size_selected')
def choose_size(message):
bot.send_message(message.chat.id, 'Как вы будете платить?')
fsm.asked_for_payment_method(message.text)
@bot.message_handler(content_types=['text'])
@bot.message_handler(func=lambda message: fsm.state == 'payment_selected')
def choose_size(message):
bot.send_message(message.chat.id, 'Какой вкус вы хотите?')
fsm.asked_for_flavour(message.text)
@bot.message_handler(content_types=['text'])
@bot.message_handler(func=lambda message: fsm.state == 'flavour_selected')
def choose_size(message):
markup = types.InlineKeyboardMarkup(row_width=2)
item1 = types.InlineKeyboardButton("Да", callback_data='yes')
item2 = types.InlineKeyboardButton("Нет ", callback_data='no')
markup.add(item1, item2)
bot.send_message(message.chat.id, f'Вы хотите {fsm.size} пиццу {fsm.flavour}, оплата - {fsm.pay_method} ?', reply_markup=markup)
@bot.callback_query_handler(func=lambda call: True)
def callback_inline(call):
try:
if call.message:
if call.data == 'yes':
bot.send_message(call.message.chat.id, 'Спасибо за заказ')
fsm.confirmed()
# show alert
bot.answer_callback_query(callback_query_id=call.id, show_alert=True,
text="Заказ оформлен")
elif call.data == 'no':
markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
item1 = types.KeyboardButton("Заказать пиццу")
item2 = types.KeyboardButton("Посмотреть меню")
markup.add(item1, item2)
bot.send_message(call.message.chat.id, 'Бывает ', reply_markup=markup)
fsm.confirmed()
# remove inline buttons
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=f'Вы хотите {fsm.size} пицца {fsm.flavour}, оплата - {fsm.pay_method} ?',
reply_markup=None)
except Exception as e:
print(repr(e))
# RUN
bot.polling(none_stop=True)
而这个有限状态机的代码。我用过pytransitions/transitions
FSM.py
from transitions import Machine, State
class telegram_bot_state(object):
states = ['asleep',
'size_selected',
'payment_selected',
'flavour_selected']
transitions = [
{'trigger': 'asked_size', 'source': 'asleep', 'dest': 'size_selected', 'after': 'update_size'},
{'trigger': 'asked_for_payment_method', 'source': 'size_selected', 'dest': 'payment_selected', 'after': 'update_payment'},
{'trigger': 'asked_for_flavour', 'source': 'payment_selected', 'dest': 'flavour_selected','after': 'update_flavour'},
{'trigger': 'confirmed', 'source': 'flavour_selected', 'dest': 'asleep'}, ]
def __init__(self):
self.size = ''
self.pay_method = ''
self.flavour = ''
self.machine = Machine(model=self, states=TelegramBot.states, transitions=TelegramBot.transitions, initial='asleep')
def update_size(self, msg):
self.size = msg
print(f'размер задан: {self.size}')
def update_payment(self, msg):
self.pay_method = msg
print(f'способ оплаты задан: {self.pay_method}')
def update_flavour(self, msg):
self.flavour = msg
print(f'Вкус пиццы задан: {self.flavour}')
但问题是它只是贯穿所有内容,而不是等待用户的回答。只需发送所有的questin。
ps如果写错了,我很抱歉这是我的第一个问题。