mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 14:35:36 +01:00
Merge pull request #1133 from LasterAlex/add-deep-linking-example
Added deep linking example
This commit is contained in:
commit
c765d1f14c
3 changed files with 191 additions and 6 deletions
55
Cargo.lock
generated
55
Cargo.lock
generated
|
@ -2208,7 +2208,7 @@ checksum = "20f34339676cdcab560c9a82300c4c2581f68b9369aedf0fae86f2ff9565ff3e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "teloxide"
|
name = "teloxide"
|
||||||
version = "0.12.2"
|
version = "0.13.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aquamarine",
|
"aquamarine",
|
||||||
"axum",
|
"axum",
|
||||||
|
@ -2230,8 +2230,8 @@ dependencies = [
|
||||||
"serde_cbor",
|
"serde_cbor",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"teloxide-core",
|
"teloxide-core 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"teloxide-macros",
|
"teloxide-macros 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
|
@ -2243,7 +2243,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "teloxide-core"
|
name = "teloxide-core"
|
||||||
version = "0.9.1"
|
version = "0.10.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.7.20",
|
"aho-corasick 0.7.20",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
|
@ -2277,9 +2277,52 @@ dependencies = [
|
||||||
"xshell",
|
"xshell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "teloxide-core"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4308e2880a535d8c30e494d548af1deb573e1fc06f2574fdd01b8fccf7c801a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"bytes",
|
||||||
|
"chrono",
|
||||||
|
"derive_more",
|
||||||
|
"either",
|
||||||
|
"futures",
|
||||||
|
"log",
|
||||||
|
"mime",
|
||||||
|
"once_cell",
|
||||||
|
"pin-project",
|
||||||
|
"rc-box",
|
||||||
|
"reqwest",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_with",
|
||||||
|
"take_mut",
|
||||||
|
"takecell",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"url",
|
||||||
|
"uuid",
|
||||||
|
"vecrem",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "teloxide-macros"
|
name = "teloxide-macros"
|
||||||
version = "0.7.1"
|
version = "0.8.0"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "teloxide-macros"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e2d33d809c3e7161a9ab18bedddf98821245014f0a78fa4d2c9430b2ec018c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -2752,7 +2795,7 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -194,6 +194,10 @@ required-features = [
|
||||||
"macros",
|
"macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "deep_linking"
|
||||||
|
required-features = ["macros", "ctrlc_handler"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "dialogue"
|
name = "dialogue"
|
||||||
required-features = ["macros", "ctrlc_handler"]
|
required-features = ["macros", "ctrlc_handler"]
|
||||||
|
|
138
crates/teloxide/examples/deep_linking.rs
Normal file
138
crates/teloxide/examples/deep_linking.rs
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
//! This example demonstrates how to use deep linking in Telegram
|
||||||
|
//! by making a simple anonymous message bot.
|
||||||
|
//!
|
||||||
|
//! Deep linking (links like https://t.me/some_bot?start=123456789)
|
||||||
|
//! is handled by telegram in the same way as just sending /start {argument}.
|
||||||
|
//! So, in the StartCommand enum we need to write Start(String)
|
||||||
|
//! to get the argument, just like in command.rs example.
|
||||||
|
//!
|
||||||
|
//! Also, deep linking is only supported with /start command!
|
||||||
|
//! "https://t.me/some_bot?argument=123456789" will not work
|
||||||
|
//!
|
||||||
|
//! https://core.telegram.org/bots/features#deep-linking
|
||||||
|
use dptree::{case, deps};
|
||||||
|
use teloxide::{
|
||||||
|
dispatching::dialogue::{self, InMemStorage},
|
||||||
|
macros::BotCommands,
|
||||||
|
prelude::*,
|
||||||
|
types::{Me, ParseMode},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub type MyDialogue = Dialogue<State, InMemStorage<State>>;
|
||||||
|
pub type HandlerResult = Result<(), Box<dyn std::error::Error + Send + Sync>>;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug, Default)]
|
||||||
|
pub enum State {
|
||||||
|
#[default]
|
||||||
|
Start,
|
||||||
|
WriteToSomeone {
|
||||||
|
id: ChatId,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(BotCommands, Clone, Debug)]
|
||||||
|
#[command(rename_rule = "lowercase")]
|
||||||
|
pub enum StartCommand {
|
||||||
|
Start(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
pretty_env_logger::init();
|
||||||
|
log::info!("Starting deep linking bot...");
|
||||||
|
|
||||||
|
let bot = Bot::from_env();
|
||||||
|
|
||||||
|
let handler = dialogue::enter::<Update, InMemStorage<State>, State, _>()
|
||||||
|
.branch(
|
||||||
|
Update::filter_message()
|
||||||
|
.filter_command::<StartCommand>()
|
||||||
|
.branch(case![StartCommand::Start(start)].endpoint(start)),
|
||||||
|
)
|
||||||
|
.branch(
|
||||||
|
Update::filter_message()
|
||||||
|
.branch(case![State::WriteToSomeone { id }].endpoint(send_message)),
|
||||||
|
);
|
||||||
|
|
||||||
|
Dispatcher::builder(bot, handler)
|
||||||
|
.dependencies(deps![InMemStorage::<State>::new()])
|
||||||
|
.enable_ctrlc_handler()
|
||||||
|
.build()
|
||||||
|
.dispatch()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start(
|
||||||
|
bot: Bot,
|
||||||
|
dialogue: MyDialogue,
|
||||||
|
msg: Message,
|
||||||
|
start: String, // Available from `case![StartCommand::Start(start)]`
|
||||||
|
me: Me,
|
||||||
|
) -> HandlerResult {
|
||||||
|
if start.is_empty() {
|
||||||
|
// This means that it is just a regular link like https://t.me/some_bot, or a /start command
|
||||||
|
bot.send_message(
|
||||||
|
msg.chat.id,
|
||||||
|
format!(
|
||||||
|
"Hello!\n\nThis link allows anyone to message you secretly: {}?start={}",
|
||||||
|
me.tme_url(),
|
||||||
|
msg.chat.id
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
dialogue.exit().await?;
|
||||||
|
} else {
|
||||||
|
// And this means that the link is like this: https://t.me/some_bot?start=123456789,
|
||||||
|
// or a /start 123456789 command
|
||||||
|
match start.parse::<i64>() {
|
||||||
|
Ok(id) => {
|
||||||
|
bot.send_message(msg.chat.id, "Send your message:").await?;
|
||||||
|
dialogue.update(State::WriteToSomeone { id: ChatId(id) }).await?;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
bot.send_message(msg.chat.id, "Bad link!").await?;
|
||||||
|
dialogue.exit().await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_message(
|
||||||
|
bot: Bot,
|
||||||
|
id: ChatId, // Available from `State::WriteToSomeone`
|
||||||
|
msg: Message,
|
||||||
|
dialogue: MyDialogue,
|
||||||
|
me: Me,
|
||||||
|
) -> HandlerResult {
|
||||||
|
match msg.text() {
|
||||||
|
Some(text) => {
|
||||||
|
// Trying to send a message to the user
|
||||||
|
let sent_result = bot
|
||||||
|
.send_message(id, format!("You have a new message!\n\n<i>{text}</i>"))
|
||||||
|
.parse_mode(ParseMode::Html)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// And if no error is returned, success!
|
||||||
|
if sent_result.is_ok() {
|
||||||
|
bot.send_message(
|
||||||
|
msg.chat.id,
|
||||||
|
format!(
|
||||||
|
"Message sent!\n\nYour link is: {}?start={}",
|
||||||
|
me.tme_url(),
|
||||||
|
msg.chat.id
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
bot.send_message(msg.chat.id, "Error sending message! Maybe user blocked the bot?")
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
dialogue.exit().await?;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
bot.send_message(msg.chat.id, "This bot can send only text.").await?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in a new issue