Added local TBA file downloading

This commit is contained in:
LasterAlex 2024-09-22 16:32:10 +03:00
parent 4f20becee2
commit 2716800a01
No known key found for this signature in database
4 changed files with 44 additions and 4 deletions

View file

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `filter_boost_added` and `filter_reply_to_story` filters to `MessageFilterExt` trait - Add `filter_boost_added` and `filter_reply_to_story` filters to `MessageFilterExt` trait
- Add `filter_mention_command` filter to `HandlerExt` trait ([issue #494](https://github.com/teloxide/teloxide/issues/494)) - Add `filter_mention_command` filter to `HandlerExt` trait ([issue #494](https://github.com/teloxide/teloxide/issues/494))
- Add `filter_business_connection`, `filter_business_message`, `filter_edited_business_message`, and `filter_deleted_business_messages` filters to update filters ([PR 1146](https://github.com/teloxide/teloxide/pull/1146)) - Add `filter_business_connection`, `filter_business_message`, `filter_edited_business_message`, and `filter_deleted_business_messages` filters to update filters ([PR 1146](https://github.com/teloxide/teloxide/pull/1146))
- Add local TBA file downloading support in `crate::net::download`
### Changed ### Changed

View file

@ -1,6 +1,12 @@
use std::path::Path;
use bytes::Bytes; use bytes::Bytes;
use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt}; use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
use tokio::io::AsyncWrite;
use tokio::{
fs::File,
io::{AsyncReadExt, AsyncWrite, AsyncWriteExt},
};
use crate::{ use crate::{
bot::Bot, bot::Bot,
@ -17,9 +23,19 @@ impl Download for Bot {
fn download_file<'dst>( fn download_file<'dst>(
&self, &self,
path: &str, path: &'dst str,
destination: &'dst mut (dyn AsyncWrite + Unpin + Send), destination: &'dst mut (dyn AsyncWrite + Unpin + Send),
) -> Self::Fut<'dst> { ) -> Self::Fut<'dst> {
let is_localhost = match &self.api_url.host_str() {
Some(host) => ["localhost", "127.0.0.1"].contains(host),
None => false,
};
// If path is absolute and api_url contains localhost, it is pretty clear there
// is a local TBA server with --local option, we can just copy the file
if is_localhost && Path::new(&path).is_absolute() {
return copy_file(path, destination).boxed();
}
net::download_file( net::download_file(
&self.client, &self.client,
reqwest::Url::clone(&*self.api_url), reqwest::Url::clone(&*self.api_url),
@ -45,3 +61,23 @@ impl Download for Bot {
.boxed() .boxed()
} }
} }
async fn copy_file<'o, D>(path: &'o str, dst: &'o mut D) -> Result<(), DownloadError>
where
D: ?Sized + AsyncWrite + Unpin,
{
let mut src_file = File::open(path).await?;
let mut buffer = [0; 1024];
loop {
let n = src_file.read(&mut buffer).await?;
if n == 0 {
break;
}
dst.write_all(&buffer[..n]).await?;
}
dst.flush().await?;
Ok(())
}

View file

@ -380,7 +380,7 @@ macro_rules! download_forward {
fn download_file<'dst>( fn download_file<'dst>(
&self, &self,
path: &str, path: &'dst str,
destination: &'dst mut (dyn tokio::io::AsyncWrite destination: &'dst mut (dyn tokio::io::AsyncWrite
+ core::marker::Unpin + core::marker::Unpin
+ core::marker::Send), + core::marker::Send),

View file

@ -28,6 +28,9 @@ pub trait Download {
/// ///
/// `path` can be obtained from [`GetFile`]. /// `path` can be obtained from [`GetFile`].
/// ///
/// If the bot uses a [local bot api](https://github.com/tdlib/telegram-bot-api), this function
/// just copies the file into `destination`.
///
/// To download as a stream of chunks, see [`download_file_stream`]. /// To download as a stream of chunks, see [`download_file_stream`].
/// ///
/// ## Examples /// ## Examples
@ -54,7 +57,7 @@ pub trait Download {
/// [`download_file_stream`]: Self::download_file_stream /// [`download_file_stream`]: Self::download_file_stream
fn download_file<'dst>( fn download_file<'dst>(
&self, &self,
path: &str, path: &'dst str,
destination: &'dst mut (dyn AsyncWrite + Unpin + Send), destination: &'dst mut (dyn AsyncWrite + Unpin + Send),
) -> Self::Fut<'dst>; ) -> Self::Fut<'dst>;