use tmp file struct instead of paths and manual file deletion
This commit is contained in:
parent
9cc888258f
commit
a85e36f1f2
4 changed files with 47 additions and 56 deletions
|
|
@ -3,12 +3,11 @@ use teloxide::types::InputFile;
|
|||
use tracing::{event, Level};
|
||||
|
||||
use super::types::HandlerResult;
|
||||
use crate::dl::delete_if_exists;
|
||||
use crate::dl::download;
|
||||
|
||||
async fn bot_download(bot: Bot, msg: Message, url: String) -> HandlerResult {
|
||||
let output_path = match download(url.as_str()).await {
|
||||
Ok(path) => path,
|
||||
let output = match download(url.as_str()).await {
|
||||
Ok(file) => file,
|
||||
Err(e) => {
|
||||
event!(Level::ERROR, "{}", e.to_string());
|
||||
bot.send_message(msg.chat.id, e.to_string()).await?;
|
||||
|
|
@ -16,14 +15,8 @@ async fn bot_download(bot: Bot, msg: Message, url: String) -> HandlerResult {
|
|||
}
|
||||
};
|
||||
|
||||
if let Err(e) = bot
|
||||
.send_video(msg.chat.id, InputFile::file(&output_path))
|
||||
.await
|
||||
{
|
||||
delete_if_exists(&output_path);
|
||||
return Err(Box::new(e));
|
||||
}
|
||||
|
||||
bot.send_video(msg.chat.id, InputFile::file(&output.path))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
51
src/dl.rs
51
src/dl.rs
|
|
@ -5,6 +5,7 @@ use tracing::{event, Level};
|
|||
use crate::dl::ffmpeg::FFMpeg;
|
||||
|
||||
use self::spawn::SpawnError;
|
||||
use self::tmpfile::{TmpFile, TmpFileError};
|
||||
use self::yt_dlp::{YtDlp, YtDlpError, YtDlpFormat, YtDlpInfo};
|
||||
|
||||
pub mod ffmpeg;
|
||||
|
|
@ -30,6 +31,14 @@ impl From<YtDlpError> for DownloadError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<TmpFileError> for DownloadError {
|
||||
fn from(value: TmpFileError) -> Self {
|
||||
match value {
|
||||
TmpFileError::MakePathError => DownloadError::MakePathError,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DownloadError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use DownloadError as DE;
|
||||
|
|
@ -76,7 +85,7 @@ pub fn delete_if_exists(path: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
async fn download_fallback(url: &str, info: YtDlpInfo) -> Result<String, DownloadError> {
|
||||
async fn download_fallback(url: &str, info: YtDlpInfo) -> Result<TmpFile, DownloadError> {
|
||||
let av = match info.best_av_format() {
|
||||
Some(av) => av,
|
||||
None => {
|
||||
|
|
@ -95,16 +104,10 @@ async fn download_fallback(url: &str, info: YtDlpInfo) -> Result<String, Downloa
|
|||
}
|
||||
};
|
||||
|
||||
let output_path = make_download_path(&info, None, &av)?;
|
||||
if let Err(e) = YtDlp::download(url, &av.format_id, output_path.as_str()).await {
|
||||
delete_if_exists(&output_path);
|
||||
return Err(DownloadError::Message(e.to_string()));
|
||||
Ok(YtDlp::download(url, &info, &av).await?)
|
||||
}
|
||||
|
||||
Ok(output_path)
|
||||
}
|
||||
|
||||
pub async fn download(url: &str) -> Result<String, DownloadError> {
|
||||
pub async fn download(url: &str) -> Result<TmpFile, DownloadError> {
|
||||
event!(Level::INFO, "url {}", url);
|
||||
|
||||
let info = YtDlp::load_info(url).await?;
|
||||
|
|
@ -117,19 +120,8 @@ pub async fn download(url: &str) -> Result<String, DownloadError> {
|
|||
None => return download_fallback(url, info).await,
|
||||
};
|
||||
|
||||
// TODO: I should wrap those temp files in a impl Drop for defer deletion
|
||||
let video_path = make_download_path(&info, Some("video"), &vf)?;
|
||||
if let Err(e) = YtDlp::download(url, &vf.format_id, video_path.as_str()).await {
|
||||
delete_if_exists(&video_path);
|
||||
return Err(DownloadError::Message(e.to_string()));
|
||||
}
|
||||
|
||||
let audio_path = make_download_path(&info, Some("audio"), &af)?;
|
||||
if let Err(e) = YtDlp::download(url, &af.format_id, audio_path.as_str()).await {
|
||||
delete_if_exists(&video_path);
|
||||
delete_if_exists(&audio_path);
|
||||
return Err(DownloadError::Message(e.to_string()));
|
||||
}
|
||||
let video = YtDlp::download(url, &info, &vf).await?;
|
||||
let audio = YtDlp::download(url, &info, &af).await?;
|
||||
|
||||
let abr = if let Some(abr) = af.abr {
|
||||
FFMpeg::round_mp3_bitrate(abr)
|
||||
|
|
@ -144,8 +136,7 @@ pub async fn download(url: &str) -> Result<String, DownloadError> {
|
|||
192
|
||||
};
|
||||
|
||||
let output_path = make_download_path(&info, None, &vf)?;
|
||||
|
||||
let output = TmpFile::new(format!("{}.{}", &info.id, &vf.ext).as_str())?;
|
||||
event!(
|
||||
Level::INFO,
|
||||
"for {} we joining video {} and audio {}",
|
||||
|
|
@ -154,18 +145,10 @@ pub async fn download(url: &str) -> Result<String, DownloadError> {
|
|||
af.format_id
|
||||
);
|
||||
|
||||
let res = FFMpeg::join_video_audio(
|
||||
video_path.as_str(),
|
||||
audio_path.as_str(),
|
||||
abr,
|
||||
output_path.as_str(),
|
||||
)
|
||||
.await;
|
||||
delete_if_exists(&video_path);
|
||||
delete_if_exists(&audio_path);
|
||||
let res = FFMpeg::join_video_audio(&video.path, &audio.path, abr, &output.path).await;
|
||||
|
||||
match res {
|
||||
Ok(()) => Ok(output_path),
|
||||
Ok(()) => Ok(output),
|
||||
Err(e) => Err(DownloadError::Message(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::fs;
|
|||
use tracing::{event, Level};
|
||||
|
||||
pub enum TmpFileError {
|
||||
MakePathError
|
||||
MakePathError,
|
||||
}
|
||||
|
||||
pub struct TmpFile {
|
||||
|
|
@ -10,7 +10,7 @@ pub struct TmpFile {
|
|||
}
|
||||
|
||||
impl TmpFile {
|
||||
pub fn new(filename: String) -> Result<Self, TmpFileError> {
|
||||
pub fn new(filename: &str) -> Result<Self, TmpFileError> {
|
||||
let path = std::env::temp_dir()
|
||||
.join(filename)
|
||||
.into_os_string()
|
||||
|
|
@ -23,7 +23,7 @@ impl TmpFile {
|
|||
pub fn exists(&self) -> bool {
|
||||
match fs::metadata(&self.path) {
|
||||
Ok(_) => true,
|
||||
Err(_) => false
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ pub enum YtDlpError {
|
|||
ErrorMessage(String), // keep it separate type if we ever plan to parse yt-dlp errors
|
||||
JsonError,
|
||||
NoFormats,
|
||||
MakePathError,
|
||||
NoFilePresent,
|
||||
}
|
||||
// ^(?:ERROR: \[.*\] \S* )(.*$) - regex for matching yt-dlp's youtube errors
|
||||
|
|
@ -213,6 +214,12 @@ impl From<SpawnError> for YtDlpError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<TmpFileError> for YtDlpError {
|
||||
fn from(_value: TmpFileError) -> Self {
|
||||
Self::MakePathError
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for YtDlpError {
|
||||
fn from(_value: serde_json::Error) -> Self {
|
||||
Self::JsonError
|
||||
|
|
@ -227,6 +234,7 @@ impl fmt::Display for YtDlpError {
|
|||
YTE::ErrorMessage(msg) => write!(f, "yt-dlp error - {}", msg),
|
||||
YTE::JsonError => write!(f, "json parsing error"),
|
||||
YTE::NoFormats => write!(f, "no formats were parsed"),
|
||||
YTE::MakePathError => write!(f, "make path error"),
|
||||
YTE::NoFilePresent => write!(f, "downloaded file doesn't exists"),
|
||||
}
|
||||
}
|
||||
|
|
@ -247,7 +255,14 @@ impl YtDlp {
|
|||
Ok(info)
|
||||
}
|
||||
|
||||
pub async fn download(url: &str, format_id: &str, output_path: &str) -> Result<(), YtDlpError> {
|
||||
pub async fn download(
|
||||
url: &str,
|
||||
info: &YtDlpInfo,
|
||||
format: &YtDlpFormat,
|
||||
) -> Result<TmpFile, YtDlpError> {
|
||||
let file =
|
||||
TmpFile::new(format!("{}_{}.{}", info.id, format.format_id, format.ext).as_str())?;
|
||||
|
||||
spawn(
|
||||
"python",
|
||||
&[
|
||||
|
|
@ -255,17 +270,17 @@ impl YtDlp {
|
|||
"yt_dlp",
|
||||
url,
|
||||
"-f",
|
||||
format_id,
|
||||
&format.format_id,
|
||||
"-o",
|
||||
output_path,
|
||||
&file.path,
|
||||
"--force-overwrites",
|
||||
],
|
||||
)
|
||||
.await?;
|
||||
|
||||
match fs::metadata(output_path) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(_) => Err(YtDlpError::NoFilePresent),
|
||||
match file.exists() {
|
||||
true => Ok(file),
|
||||
false => Err(YtDlpError::NoFilePresent),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue