mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-24 09:16:12 +01:00
update dialogue_bot example
This commit is contained in:
parent
b10288f751
commit
50f37cf43b
9 changed files with 94 additions and 125 deletions
|
@ -7,7 +7,9 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
teloxide = { path = "../../", features = ["frunk", "macros", "auto-send"] }
|
teloxide = { path = "../../", features = ["frunk", "macros", "auto-send", "sqlite-storage"] }
|
||||||
|
anyhow = "1.0.52"
|
||||||
|
serde = "1"
|
||||||
|
|
||||||
futures = "0.3.5"
|
futures = "0.3.5"
|
||||||
tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] }
|
tokio = { version = "1.3.0", features = ["rt-multi-thread", "macros"] }
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
mod states;
|
|
||||||
|
|
||||||
use crate::dialogue::states::{
|
|
||||||
ReceiveAgeState, ReceiveFullNameState, ReceiveLocationState, StartState,
|
|
||||||
};
|
|
||||||
use derive_more::From;
|
|
||||||
use teloxide::macros::Transition;
|
|
||||||
|
|
||||||
#[derive(Transition, Clone, From)]
|
|
||||||
pub enum Dialogue {
|
|
||||||
Start(StartState),
|
|
||||||
ReceiveFullName(ReceiveFullNameState),
|
|
||||||
ReceiveAge(ReceiveAgeState),
|
|
||||||
ReceiveLocation(ReceiveLocationState),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Dialogue {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Start(StartState)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
mod receive_age;
|
|
||||||
mod receive_full_name;
|
|
||||||
mod receive_location;
|
|
||||||
mod start;
|
|
||||||
|
|
||||||
pub use receive_age::ReceiveAgeState;
|
|
||||||
pub use receive_full_name::ReceiveFullNameState;
|
|
||||||
pub use receive_location::ReceiveLocationState;
|
|
||||||
pub use start::StartState;
|
|
|
@ -1,25 +0,0 @@
|
||||||
use crate::dialogue::{states::receive_location::ReceiveLocationState, Dialogue};
|
|
||||||
use teloxide::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Generic)]
|
|
||||||
pub struct ReceiveAgeState {
|
|
||||||
pub full_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[teloxide(subtransition)]
|
|
||||||
async fn receive_age_state(
|
|
||||||
state: ReceiveAgeState,
|
|
||||||
cx: TransitionIn<AutoSend<Bot>>,
|
|
||||||
ans: String,
|
|
||||||
) -> TransitionOut<Dialogue> {
|
|
||||||
match ans.parse::<u8>() {
|
|
||||||
Ok(ans) => {
|
|
||||||
cx.answer("What's your location?").await?;
|
|
||||||
next(ReceiveLocationState::up(state, ans))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
cx.answer("Send me a number.").await?;
|
|
||||||
next(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
use crate::dialogue::{states::receive_age::ReceiveAgeState, Dialogue};
|
|
||||||
use teloxide::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Generic)]
|
|
||||||
pub struct ReceiveFullNameState;
|
|
||||||
|
|
||||||
#[teloxide(subtransition)]
|
|
||||||
async fn receive_full_name(
|
|
||||||
state: ReceiveFullNameState,
|
|
||||||
cx: TransitionIn<AutoSend<Bot>>,
|
|
||||||
ans: String,
|
|
||||||
) -> TransitionOut<Dialogue> {
|
|
||||||
cx.answer("How old are you?").await?;
|
|
||||||
next(ReceiveAgeState::up(state, ans))
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
use crate::dialogue::Dialogue;
|
|
||||||
use teloxide::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Generic)]
|
|
||||||
pub struct ReceiveLocationState {
|
|
||||||
pub full_name: String,
|
|
||||||
pub age: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[teloxide(subtransition)]
|
|
||||||
async fn receive_location(
|
|
||||||
state: ReceiveLocationState,
|
|
||||||
cx: TransitionIn<AutoSend<Bot>>,
|
|
||||||
ans: String,
|
|
||||||
) -> TransitionOut<Dialogue> {
|
|
||||||
cx.answer(format!("Full name: {}\nAge: {}\nLocation: {}", state.full_name, state.age, ans))
|
|
||||||
.await?;
|
|
||||||
exit()
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
use crate::dialogue::{states::ReceiveFullNameState, Dialogue};
|
|
||||||
use teloxide::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct StartState;
|
|
||||||
|
|
||||||
#[teloxide(subtransition)]
|
|
||||||
async fn start(
|
|
||||||
_state: StartState,
|
|
||||||
cx: TransitionIn<AutoSend<Bot>>,
|
|
||||||
_ans: String,
|
|
||||||
) -> TransitionOut<Dialogue> {
|
|
||||||
cx.answer("Let's start! What's your full name?").await?;
|
|
||||||
next(ReceiveFullNameState)
|
|
||||||
}
|
|
|
@ -13,17 +13,30 @@
|
||||||
// Age: 223
|
// Age: 223
|
||||||
// Location: Middle-earth
|
// Location: Middle-earth
|
||||||
// ```
|
// ```
|
||||||
|
use crate::state::State;
|
||||||
|
use teloxide::{
|
||||||
|
dispatching2::dialogue::{serializer::Json, SqliteStorage},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
#![allow(clippy::trivial_regex)]
|
// FIXME: naming
|
||||||
#![allow(dead_code)]
|
type MyBot = AutoSend<Bot>;
|
||||||
|
type Store = SqliteStorage<Json>;
|
||||||
|
type BotDialogue = Dialogue<State, Store>;
|
||||||
|
|
||||||
#[macro_use]
|
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
||||||
extern crate frunk;
|
pub enum State {
|
||||||
|
Start,
|
||||||
|
ReceiveFullName,
|
||||||
|
ReceiveAge { full_name: String },
|
||||||
|
ReceiveLocation { full_name: String, age: u8 },
|
||||||
|
}
|
||||||
|
|
||||||
mod dialogue;
|
impl Default for State {
|
||||||
|
fn default() -> Self {
|
||||||
use crate::dialogue::Dialogue;
|
Self::Start
|
||||||
use teloxide::prelude::*;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -35,22 +48,80 @@ async fn run() {
|
||||||
log::info!("Starting dialogue_bot...");
|
log::info!("Starting dialogue_bot...");
|
||||||
|
|
||||||
let bot = Bot::from_env().auto_send();
|
let bot = Bot::from_env().auto_send();
|
||||||
|
let storage = SqliteStorage::open("db.sqlite", Json).await.unwrap();
|
||||||
|
|
||||||
teloxide::dialogues_repl(bot, |message, dialogue| async move {
|
Dispatcher::new(bot)
|
||||||
handle_message(message, dialogue).await.expect("Something wrong with the bot!")
|
.dependencies(dptree::deps![storage])
|
||||||
|
.messages_handler(|h| {
|
||||||
|
h.add_dialogue::<Message, Store, State>().branch(dptree::endpoint(handle_message))
|
||||||
})
|
})
|
||||||
|
.dispatch()
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_message(
|
async fn handle_message(bot: MyBot, mes: Message, dialogue: BotDialogue) -> anyhow::Result<()> {
|
||||||
cx: UpdateWithCx<AutoSend<Bot>, Message>,
|
match mes.text().map(ToOwned::to_owned) {
|
||||||
dialogue: Dialogue,
|
|
||||||
) -> TransitionOut<Dialogue> {
|
|
||||||
match cx.update.text().map(ToOwned::to_owned) {
|
|
||||||
None => {
|
None => {
|
||||||
cx.answer("Send me a text message.").await?;
|
bot.send_message(mes.chat_id(), "Send me a text message.").await?;
|
||||||
next(dialogue)
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(ans) => dialogue.react(cx, ans).await,
|
Some(_) => match dialogue.current_state_or_default().await? {
|
||||||
|
State::Start => handle_start(bot, mes, dialogue).await,
|
||||||
|
State::ReceiveFullName => handle_receive_full_name(bot, mes, dialogue).await,
|
||||||
|
State::ReceiveAge { full_name } => {
|
||||||
|
handle_receive_age(bot, mes, dialogue, full_name).await
|
||||||
|
}
|
||||||
|
State::ReceiveLocation { full_name, age } => {
|
||||||
|
handle_receive_location(bot, mes, dialogue, full_name, age).await
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_start(bot: MyBot, mes: Message, dialogue: BotDialogue) -> anyhow::Result<()> {
|
||||||
|
bot.send_message(mes.chat_id(), "Let's start! What's your full name?").await?;
|
||||||
|
dialogue.next(State::ReceiveFullName).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_receive_full_name(
|
||||||
|
bot: MyBot,
|
||||||
|
mes: Message,
|
||||||
|
dialogue: BotDialogue,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
bot.send_message(mes.chat_id(), "How old are you?").await?;
|
||||||
|
dialogue.next(State::ReceiveAge { full_name: mes.text().unwrap().into() }).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_receive_age(
|
||||||
|
bot: MyBot,
|
||||||
|
mes: Message,
|
||||||
|
dialogue: BotDialogue,
|
||||||
|
full_name: String,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
match mes.text().unwrap().parse::<u8>() {
|
||||||
|
Ok(age) => {
|
||||||
|
bot.send_message(mes.chat_id(), "What's your location?").await?;
|
||||||
|
dialogue.next(State::ReceiveLocation { full_name, age }).await?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
bot.send_message(mes.chat_id(), "Send me a number.").await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_receive_location(
|
||||||
|
bot: MyBot,
|
||||||
|
mes: Message,
|
||||||
|
dialogue: BotDialogue,
|
||||||
|
full_name: String,
|
||||||
|
age: u8,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let location = mes.text().unwrap();
|
||||||
|
let message = format!("Full name: {}\nAge: {}\nLocation: {}", full_name, age, location);
|
||||||
|
bot.send_message(mes.chat_id(), message).await?;
|
||||||
|
dialogue.exit().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
0
examples/dialogue_bot/src/state.rs
Normal file
0
examples/dialogue_bot/src/state.rs
Normal file
Loading…
Add table
Reference in a new issue