New options for downloading into folders over web-ui.

This commit is contained in:
euzu
2023-11-06 12:21:16 +01:00
parent 67703bae8d
commit 075ec974e8
5 changed files with 124 additions and 67 deletions
+24 -5
View File
@@ -10,11 +10,10 @@ use serde_json::json;
use uuid::Uuid;
use crate::api::api_model::{AppState, FileDownloadRequest, PlaylistRequest, ServerConfig, ServerInputConfig, ServerSourceConfig, ServerTargetConfig};
use crate::download::{get_m3u_playlist, get_xtream_playlist};
use crate::model::config::{ConfigInput, InputType, validate_targets};
use crate::model::config::{ConfigInput, InputType, validate_targets, VideoDownloadConfig};
use crate::utils::{bytes_to_megabytes};
use futures::stream::TryStreamExt;
use log::{error, info};
use regex::Regex;
use reqwest::{header, Response};
use reqwest::header::{HeaderName, HeaderValue};
use unidecode::unidecode;
@@ -239,10 +238,9 @@ pub(crate) async fn download_file(
}
match client.get(_url).headers(headers).send().await {
Ok(response) => {
let filename_re = Regex::new(r"[^A-Za-z0-9_.-]").unwrap();
let filename_re = download._re_filename.as_ref().unwrap();
let filename = filename_re.replace_all(&unidecode(&req.filename).replace(' ', "_"), "").to_string();
let file_stem = Path::new(&filename).file_stem().and_then(OsStr::to_str).unwrap_or("");
let file_dir: PathBuf = [download.directory.as_ref().unwrap(), file_stem].iter().collect();
let file_dir = get_download_directory(download, &filename);
match fs::create_dir_all(&file_dir) {
Ok(_) => {
let path = file_dir.join(filename.as_str());
@@ -281,6 +279,27 @@ pub(crate) async fn download_file(
}
}
fn get_download_directory(download: &VideoDownloadConfig, filename: &String) -> PathBuf {
if download.organize_into_directories {
let mut file_stem = Path::new(&filename).file_stem().and_then(OsStr::to_str).unwrap_or("");
if let Some(re) = &download._re_episode_pattern {
if let Some(captures) = re.captures(file_stem) {
if let Some(episode) = captures.name("episode") {
if !episode.as_str().is_empty() {
file_stem = &file_stem[..episode.start()];
}
}
}
}
let re_ending = download._re_remove_filename_ending.as_ref().unwrap();
let dir_name = re_ending.replace(file_stem, "");
let file_dir: PathBuf = [download.directory.as_ref().unwrap(), dir_name.as_ref()].iter().collect();
file_dir
} else {
PathBuf::from(download.directory.as_ref().unwrap())
}
}
pub(crate) fn v1_api_register() -> Scope {
web::scope("/api/v1")
.route("/config", web::get().to(config))
+43 -15
View File
@@ -427,7 +427,15 @@ pub(crate) struct VideoDownloadConfig {
#[serde(default = "default_as_empty_map")]
pub headers: HashMap<String, String>,
pub directory: Option<String>,
#[serde(default = "default_as_false")]
pub organize_into_directories: bool,
pub episode_pattern: Option<String>,
#[serde(skip_serializing, skip_deserializing)]
pub _re_episode_pattern: Option<regex::Regex>,
#[serde(skip_serializing, skip_deserializing)]
pub _re_filename: Option<regex::Regex>,
#[serde(skip_serializing, skip_deserializing)]
pub _re_remove_filename_ending: Option<regex::Regex>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@@ -437,6 +445,33 @@ pub(crate) struct VideoConfig {
pub download: Option<VideoDownloadConfig>,
}
impl VideoConfig {
pub fn prepare(&mut self) -> Result<(), M3uFilterError> {
self.extensions = vec!["mkv".to_string(), "avi".to_string(), "mp4".to_string()];
match &mut self.download {
None => {}
Some(downl) => {
if downl.headers.is_empty() {
downl.headers.borrow_mut().insert("Accept".to_string(), "video/*".to_string());
downl.headers.borrow_mut().insert("User-Agent".to_string(), "AppleTV/tvOS/9.1.1.".to_string());
}
if let Some(episode_pattern) = &downl.episode_pattern {
let re = regex::Regex::new(episode_pattern);
if re.is_err() {
return create_m3u_filter_error_result!(M3uFilterErrorKind::Info, "cant parse regex: {}", episode_pattern);
}
downl._re_episode_pattern = Some(re.unwrap());
}
downl._re_filename = Some(regex::Regex::new(r"[^A-Za-z0-9_.-]").unwrap());
downl._re_remove_filename_ending = Some(regex::Regex::new(r"[_.\s-]$").unwrap());
}
}
Ok(())
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub(crate) struct Config {
#[serde(default = "default_as_zero")]
@@ -568,22 +603,15 @@ impl Config {
self.video = Some(VideoConfig {
extensions: vec!["mkv".to_string(), "avi".to_string(), "mp4".to_string()],
download: None,
})
});
}
Some(video) =>
{
video.extensions = vec!["mkv".to_string(), "avi".to_string(), "mp4".to_string()];
match &mut video.download {
None => {}
Some(downl) => {
if downl.headers.is_empty() {
downl.headers.borrow_mut().insert("Accept".to_string(), "video/*".to_string());
downl.headers.borrow_mut().insert("User-Agent".to_string(), "AppleTV/tvOS/9.1.1.".to_string());
}
}
}
Some(video) => {
match video.prepare() {
Ok(_) => {}
Err(err) => return Err(err)
}
}
},
};
Ok(())
}