Oops, push the examples too

This commit is contained in:
Temirkhan Myrzamadi 2021-03-06 03:24:10 +06:00 committed by Eric S. Londres
parent 539bc6763b
commit d52382e271
16 changed files with 92 additions and 66 deletions

View file

@ -1,6 +1,8 @@
use std::str::FromStr;
use std::{convert::TryInto, str::FromStr};
use teloxide::{prelude::*, types::ChatPermissions, utils::command::BotCommand};
use teloxide::{prelude::*, utils::command::BotCommand};
use teloxide::core::types::ChatPermissions;
// Derive BotCommand to parse text with a command into this enumeration.
//
@ -60,20 +62,19 @@ fn calc_restrict_time(time: u32, unit: UnitOfTime) -> u32 {
}
}
type Cx = UpdateWithCx<Message>;
type Cx = UpdateWithCx<AutoSend<Bot>, Message>;
// Mute a user with a replied message.
async fn mute_user(cx: &Cx, time: u32) -> ResponseResult<()> {
match cx.update.reply_to_message() {
Some(msg1) => {
cx.bot
cx.requester
.restrict_chat_member(
cx.update.chat_id(),
msg1.from().expect("Must be MessageKind::Common").id,
ChatPermissions::default(),
)
.until_date(cx.update.date + time as i32)
.send()
.until_date((cx.update.date + time as i32).try_into().unwrap())
.await?;
}
None => {
@ -88,7 +89,10 @@ async fn kick_user(cx: &Cx) -> ResponseResult<()> {
match cx.update.reply_to_message() {
Some(mes) => {
// bot.unban_chat_member can also kicks a user from a group chat.
cx.bot.unban_chat_member(cx.update.chat_id(), mes.from().unwrap().id).send().await?;
cx.requester
.unban_chat_member(cx.update.chat_id(), mes.from().unwrap().id)
.send()
.await?;
}
None => {
cx.reply_to("Use this command in reply to another message").send().await?;
@ -101,13 +105,12 @@ async fn kick_user(cx: &Cx) -> ResponseResult<()> {
async fn ban_user(cx: &Cx, time: u32) -> ResponseResult<()> {
match cx.update.reply_to_message() {
Some(message) => {
cx.bot
cx.requester
.kick_chat_member(
cx.update.chat_id(),
message.from().expect("Must be MessageKind::Common").id,
)
.until_date(cx.update.date + time as i32)
.send()
.until_date((cx.update.date + time as i32).try_into().unwrap())
.await?;
}
None => {
@ -117,7 +120,7 @@ async fn ban_user(cx: &Cx, time: u32) -> ResponseResult<()> {
Ok(())
}
async fn action(cx: UpdateWithCx<Message>, command: Command) -> ResponseResult<()> {
async fn action(cx: Cx, command: Command) -> ResponseResult<()> {
match command {
Command::Help => cx.answer(Command::descriptions()).send().await.map(|_| ())?,
Command::Kick => kick_user(&cx).await?,
@ -137,7 +140,7 @@ async fn run() {
teloxide::enable_logging!();
log::info!("Starting admin_bot...");
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
let bot_name: String = panic!("Your bot's name here");
teloxide::commands_repl(bot, bot_name, action).await;

View file

@ -10,16 +10,16 @@ pub struct ReceiveAgeState {
#[teloxide(subtransition)]
async fn receive_age_state(
state: ReceiveAgeState,
cx: TransitionIn,
cx: TransitionIn<AutoSend<Bot>>,
ans: String,
) -> TransitionOut<Dialogue> {
match ans.parse::<u8>() {
Ok(ans) => {
cx.answer_str("What's your location?").await?;
cx.answer("What's your location?").await?;
next(ReceiveLocationState::up(state, ans))
}
_ => {
cx.answer_str("Send me a number.").await?;
cx.answer("Send me a number.").await?;
next(state)
}
}

View file

@ -8,9 +8,9 @@ pub struct ReceiveFullNameState;
#[teloxide(subtransition)]
async fn receive_full_name(
state: ReceiveFullNameState,
cx: TransitionIn,
cx: TransitionIn<AutoSend<Bot>>,
ans: String,
) -> TransitionOut<Dialogue> {
cx.answer_str("How old are you?").await?;
cx.answer("How old are you?").await?;
next(ReceiveAgeState::up(state, ans))
}

View file

@ -11,10 +11,10 @@ pub struct ReceiveLocationState {
#[teloxide(subtransition)]
async fn receive_location(
state: ReceiveLocationState,
cx: TransitionIn,
cx: TransitionIn<AutoSend<Bot>>,
ans: String,
) -> TransitionOut<Dialogue> {
cx.answer_str(format!("Full name: {}\nAge: {}\nLocation: {}", state.full_name, state.age, ans))
cx.answer(format!("Full name: {}\nAge: {}\nLocation: {}", state.full_name, state.age, ans))
.await?;
exit()
}

View file

@ -5,7 +5,11 @@ use teloxide_macros::teloxide;
pub struct StartState;
#[teloxide(subtransition)]
async fn start(_state: StartState, cx: TransitionIn, _ans: String) -> TransitionOut<Dialogue> {
cx.answer_str("Let's start! What's your full name?").await?;
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)
}

View file

@ -34,7 +34,7 @@ async fn run() {
teloxide::enable_logging!();
log::info!("Starting dialogue_bot...");
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
teloxide::dialogues_repl(bot, |message, dialogue| async move {
handle_message(message, dialogue).await.expect("Something wrong with the bot!")
@ -42,10 +42,13 @@ async fn run() {
.await;
}
async fn handle_message(cx: UpdateWithCx<Message>, dialogue: Dialogue) -> TransitionOut<Dialogue> {
async fn handle_message(
cx: UpdateWithCx<AutoSend<Bot>, Message>,
dialogue: Dialogue,
) -> TransitionOut<Dialogue> {
match cx.update.text_owned() {
None => {
cx.answer_str("Send me a text message.").await?;
cx.answer("Send me a text message.").await?;
next(dialogue)
}
Some(ans) => dialogue.react(cx, ans).await,

View file

@ -11,10 +11,10 @@ async fn run() {
teloxide::enable_logging!();
log::info!("Starting dices_bot...");
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
teloxide::repl(bot, |message| async move {
message.answer_dice().send().await?;
message.answer_dice().await?;
respond(())
})
.await;

View file

@ -19,7 +19,7 @@ async fn handle_rejection(error: warp::Rejection) -> Result<impl warp::Reply, In
Ok(StatusCode::INTERNAL_SERVER_ERROR)
}
pub async fn webhook<'a>(bot: Bot) -> impl update_listeners::UpdateListener<Infallible> {
pub async fn webhook<'a>(bot: AutoSend<Bot>) -> impl update_listeners::UpdateListener<Infallible> {
// Heroku defines auto defines a port value
let teloxide_token = env::var("TELOXIDE_TOKEN").expect("TELOXIDE_TOKEN env variable missing");
let port: u16 = env::var("PORT")
@ -31,7 +31,7 @@ pub async fn webhook<'a>(bot: Bot) -> impl update_listeners::UpdateListener<Infa
let path = format!("bot{}", teloxide_token);
let url = format!("https://{}/{}", host, path);
bot.set_webhook(url).send().await.expect("Cannot setup a webhook");
bot.set_webhook(url).await.expect("Cannot setup a webhook");
let (tx, rx) = mpsc::unbounded_channel();
@ -71,14 +71,14 @@ async fn run() {
teloxide::enable_logging!();
log::info!("Starting heroku_ping_pong_bot...");
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
let cloned_bot = bot.clone();
teloxide::repl_with_listener(
bot,
|message| async move {
message.answer_str("pong").await?;
ResponseResult::<()>::Ok(())
message.answer("pong").await?;
respond(())
},
webhook(cloned_bot).await,
)

View file

@ -19,11 +19,10 @@ async fn handle_rejection(error: warp::Rejection) -> Result<impl warp::Reply, In
Ok(StatusCode::INTERNAL_SERVER_ERROR)
}
pub async fn webhook<'a>(bot: Bot) -> impl update_listeners::UpdateListener<Infallible> {
pub async fn webhook<'a>(bot: AutoSend<Bot>) -> impl update_listeners::UpdateListener<Infallible> {
// You might want to specify a self-signed certificate via .certificate
// method on SetWebhook.
bot.set_webhook("Your HTTPS ngrok URL here. Get it by 'ngrok http 80'")
.send()
.await
.expect("Cannot setup a webhook");
@ -53,14 +52,14 @@ async fn run() {
teloxide::enable_logging!();
log::info!("Starting ngrok_ping_pong_bot...");
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
let cloned_bot = bot.clone();
teloxide::repl_with_listener(
bot,
|message| async move {
message.answer_str("pong").await?;
ResponseResult::<()>::Ok(())
message.answer("pong").await?;
respond(())
},
webhook(cloned_bot).await,
)

View file

@ -22,7 +22,7 @@ enum Error {
StorageError(#[from] StorageError),
}
type In = DialogueWithCx<Message, Dialogue, StorageError>;
type In = DialogueWithCx<AutoSend<Bot>, Message, Dialogue, StorageError>;
#[tokio::main]
async fn main() {
@ -30,7 +30,7 @@ async fn main() {
}
async fn run() {
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
Dispatcher::new(bot)
.messages_handler(DialogueDispatcher::with_storage(
|DialogueWithCx { cx, dialogue }: In| async move {
@ -47,10 +47,13 @@ async fn run() {
.await;
}
async fn handle_message(cx: UpdateWithCx<Message>, dialogue: Dialogue) -> TransitionOut<Dialogue> {
async fn handle_message(
cx: UpdateWithCx<AutoSend<Bot>, Message>,
dialogue: Dialogue,
) -> TransitionOut<Dialogue> {
match cx.update.text_owned() {
None => {
cx.answer_str("Send me a text message.").await?;
cx.answer("Send me a text message.").await?;
next(dialogue)
}
Some(ans) => dialogue.react(cx, ans).await,

View file

@ -4,12 +4,16 @@ use teloxide_macros::teloxide;
use super::states::*;
#[teloxide(subtransition)]
async fn start(state: StartState, cx: TransitionIn, ans: String) -> TransitionOut<Dialogue> {
async fn start(
state: StartState,
cx: TransitionIn<AutoSend<Bot>>,
ans: String,
) -> TransitionOut<Dialogue> {
if let Ok(number) = ans.parse() {
cx.answer_str(format!("Remembered number {}. Now use /get or /reset", number)).await?;
cx.answer(format!("Remembered number {}. Now use /get or /reset", number)).await?;
next(HaveNumberState { number })
} else {
cx.answer_str("Please, send me a number").await?;
cx.answer("Please, send me a number").await?;
next(state)
}
}
@ -17,19 +21,19 @@ async fn start(state: StartState, cx: TransitionIn, ans: String) -> TransitionOu
#[teloxide(subtransition)]
async fn have_number(
state: HaveNumberState,
cx: TransitionIn,
cx: TransitionIn<AutoSend<Bot>>,
ans: String,
) -> TransitionOut<Dialogue> {
let num = state.number;
if ans.starts_with("/get") {
cx.answer_str(format!("Here is your number: {}", num)).await?;
cx.answer(format!("Here is your number: {}", num)).await?;
next(state)
} else if ans.starts_with("/reset") {
cx.answer_str("Resetted number").await?;
cx.answer("Resetted number").await?;
next(StartState)
} else {
cx.answer_str("Please, send /get or /reset").await?;
cx.answer("Please, send /get or /reset").await?;
next(state)
}
}

View file

@ -10,5 +10,6 @@ edition = "2018"
log = "0.4.8"
pretty_env_logger = "0.4.0"
tokio = { version = "0.2.11", features = ["rt-threaded", "macros"] }
tokio-stream = "0.1.3"
teloxide = { path = "../../" }
lazy_static = "1.4.0"

View file

@ -4,6 +4,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
use lazy_static::lazy_static;
use teloxide::prelude::*;
use tokio_stream::wrappers::UnboundedReceiverStream;
lazy_static! {
static ref MESSAGES_TOTAL: AtomicU64 = AtomicU64::new(0);
@ -18,15 +19,15 @@ async fn run() {
teloxide::enable_logging!();
log::info!("Starting shared_state_bot...");
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
Dispatcher::new(bot)
.messages_handler(|rx: DispatcherHandlerRx<Message>| {
rx.for_each_concurrent(None, |message| async move {
.messages_handler(|rx: DispatcherHandlerRx<AutoSend<Bot>, Message>| {
UnboundedReceiverStream::new(rx).for_each_concurrent(None, |message| async move {
let previous = MESSAGES_TOTAL.fetch_add(1, Ordering::Relaxed);
message
.answer_str(format!("I received {} messages in total.", previous))
.answer(format!("I received {} messages in total.", previous))
.await
.log_on_error()
.await;

View file

@ -11,14 +11,14 @@ enum Command {
UsernameAndAge { username: String, age: u8 },
}
async fn answer(cx: UpdateWithCx<Message>, command: Command) -> ResponseResult<()> {
async fn answer(cx: UpdateWithCx<AutoSend<Bot>, Message>, command: Command) -> ResponseResult<()> {
match command {
Command::Help => cx.answer(Command::descriptions()).send().await?,
Command::Username(username) => {
cx.answer_str(format!("Your username is @{}.", username)).await?
cx.answer(format!("Your username is @{}.", username)).await?
}
Command::UsernameAndAge { username, age } => {
cx.answer_str(format!("Your username is @{} and age is {}.", username, age)).await?
cx.answer(format!("Your username is @{} and age is {}.", username, age)).await?
}
};
@ -34,7 +34,7 @@ async fn run() {
teloxide::enable_logging!();
log::info!("Starting simple_commands_bot...");
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
let bot_name: String = panic!("Your bot's name here");
teloxide::commands_repl(bot, bot_name, answer).await;

View file

@ -22,12 +22,15 @@ enum Error {
StorageError(#[from] StorageError),
}
type In = DialogueWithCx<Message, Dialogue, StorageError>;
type In = DialogueWithCx<AutoSend<Bot>, Message, Dialogue, StorageError>;
async fn handle_message(cx: UpdateWithCx<Message>, dialogue: Dialogue) -> TransitionOut<Dialogue> {
async fn handle_message(
cx: UpdateWithCx<AutoSend<Bot>, Message>,
dialogue: Dialogue,
) -> TransitionOut<Dialogue> {
match cx.update.text_owned() {
None => {
cx.answer_str("Send me a text message.").await?;
cx.answer("Send me a text message.").await?;
next(dialogue)
}
Some(ans) => dialogue.react(cx, ans).await,
@ -36,7 +39,8 @@ async fn handle_message(cx: UpdateWithCx<Message>, dialogue: Dialogue) -> Transi
#[tokio::main]
async fn main() {
let bot = Bot::from_env();
let bot = Bot::from_env().auto_send();
Dispatcher::new(bot)
.messages_handler(DialogueDispatcher::with_storage(
|DialogueWithCx { cx, dialogue }: In| async move {

View file

@ -4,12 +4,16 @@ use teloxide_macros::teloxide;
use super::states::*;
#[teloxide(subtransition)]
async fn start(state: StartState, cx: TransitionIn, ans: String) -> TransitionOut<Dialogue> {
async fn start(
state: StartState,
cx: TransitionIn<AutoSend<Bot>>,
ans: String,
) -> TransitionOut<Dialogue> {
if let Ok(number) = ans.parse() {
cx.answer_str(format!("Remembered number {}. Now use /get or /reset", number)).await?;
cx.answer(format!("Remembered number {}. Now use /get or /reset", number)).await?;
next(HaveNumberState { number })
} else {
cx.answer_str("Please, send me a number").await?;
cx.answer("Please, send me a number").await?;
next(state)
}
}
@ -17,19 +21,19 @@ async fn start(state: StartState, cx: TransitionIn, ans: String) -> TransitionOu
#[teloxide(subtransition)]
async fn have_number(
state: HaveNumberState,
cx: TransitionIn,
cx: TransitionIn<AutoSend<Bot>>,
ans: String,
) -> TransitionOut<Dialogue> {
let num = state.number;
if ans.starts_with("/get") {
cx.answer_str(format!("Here is your number: {}", num)).await?;
cx.answer(format!("Here is your number: {}", num)).await?;
next(state)
} else if ans.starts_with("/reset") {
cx.answer_str("Resetted number").await?;
cx.answer("Resetted number").await?;
next(StartState)
} else {
cx.answer_str("Please, send /get or /reset").await?;
cx.answer("Please, send /get or /reset").await?;
next(state)
}
}