Hi all,
I'm building a Telegram bot with teloxide which uses a simple hashmap as in-memory storage to keep track of the URL given via the bot.
Despite my bets efforts the dependency injection lib is raising a trait bound error and I cannot trace the source of the issue.
The code of the bot:
extern crate dotenv;
mod storage;
use dotenv::dotenv;
use reqwest::Url;
use teloxide::utils::command::BotCommands;
use std::collections::HashMap;
use std::error::Error;
use std::sync::RwLock;
use teloxide::prelude::*;
type HandlerResult = Result<(), Box<dyn std::error::Error + Send + Sync>>;
#[derive(Debug, Clone)]
pub enum DownloadStatus {
Pending,
Downloading,
Finished,
Failed,
}
#[derive(Clone)]
pub struct Download {
pub url: Url,
pub status: DownloadStatus,
}
#[derive(Clone)]
pub struct DownloadStorage {
downloads: HashMap<Url, Download>,
}
impl DownloadStorage {
pub fn new() -> Self {
Self {
downloads: HashMap::new(),
}
}
pub fn list(&self) -> Vec<&Download> {
self.downloads.values().collect()
}
}
#[derive(BotCommands, Clone)]
#[command(
rename_rule = "lowercase",
description = "These commands are supported:"
)]
pub enum Command {
#[command(description = "show download statuses.")]
List,
}
#[tokio::main]
async fn main() {
dotenv().ok();
pretty_env_logger::init();
log::info!("Starting bot...");
let bot = Bot::from_env();
let storage = RwLock::new(DownloadStorage::new());
let handler = Update::filter_message().endpoint(handler);
Dispatcher::builder(bot, handler)
.dependencies(dptree::deps![storage])
.enable_ctrlc_handler()
.build()
.dispatch()
.await;
log::info!("Closing bot... Goodbye!");
}
pub async fn handler(bot: Bot, msg: Message, storage: RwLock<DownloadStorage>) -> HandlerResult {
let text = match msg.text() {
Some(text) => text.trim(),
None => return Ok(()),
};
let command = Command::parse(text, "bot");
match command {
Ok(Command::List) => {
list(bot, msg, storage).await;
}
Err(e) => {
log::error!("Error parsing command: {}", e);
}
};
Ok(())
}
pub async fn list(bot: Bot, msg: Message, storage: RwLock<DownloadStorage>) -> HandlerResult {
log::info!("Sending list of dowloading statuses");
let locked_storage = storage.read().unwrap();
let items = locked_storage.list();
let content = items
.iter()
.map(|item| item.url.as_str())
.collect::<Vec<&str>>()
.join("\n");
bot.send_message(msg.chat.id, content).await;
Ok(())
}
and the error raised at compile time:
error[E0277]: the trait bound `fn(teloxide::Bot, teloxide::prelude::Message, Arc<std::sync::RwLock<DownloadStorage>>) -> impl Future<Output = Result<(), Box<(dyn std::error::Error + Send + Sync + 'static)>>> {handler}: Injectable<DependencyMap, _, _>` is not satisfied
--> src/main.rs:24:53
|
24 | let handler = Update::filter_message().endpoint(handler);
| -------- ^^^^^^^ the trait `Injectable<DependencyMap, _, _>` is not implemented for fn item `fn(Bot, Message, Arc<RwLock<DownloadStorage>>) -> impl Future<Output = Result<(), Box<...>>> {handler}`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Injectable<Input, Output, FnArgs>`:
`Asyncify<Func>` implements `Injectable<Input, Output, ()>`
`Asyncify<Func>` implements `Injectable<Input, Output, (A, B)>`
`Asyncify<Func>` implements `Injectable<Input, Output, (A, B, C)>`
`Asyncify<Func>` implements `Injectable<Input, Output, (A, B, C, D)>`
`Asyncify<Func>` implements `Injectable<Input, Output, (A, B, C, D, E)>`
`Asyncify<Func>` implements `Injectable<Input, Output, (A, B, C, D, E, F)>`
`Asyncify<Func>` implements `Injectable<Input, Output, (A, B, C, D, E, F, G)>`
`Asyncify<Func>` implements `Injectable<Input, Output, (A, B, C, D, E, F, G, H)>`
and 2 others
note: required by a bound in `teloxide::dptree::handler::methods::<impl Handler<'a, Input, Output, Descr>>::endpoint`
--> /Users/danieleesposti/.cargo/registry/src/index.crates.io-6f17d22bba15001f/dptree-0.3.0/src/handler/methods.rs:108:12
|
106 | pub fn endpoint<F, FnArgs>(self, f: F) -> Handler<'a, Input, Output, Descr>
| -------- required by a bound in this associated function
107 | where
108 | F: Injectable<Input, Output, FnArgs> + Send + Sync + 'a,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `teloxide::dptree::handler::methods::<impl Handler<'a, Input, Output, Descr>>::endpoint`
Can anyone help me to find the issue please?