mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-19 06:12:24 +02:00
New options for downloading into folders over web-ui.
This commit is contained in:
+24
-5
@@ -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
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user