mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-02 14:02:22 +02:00
Feature/staged input and path improvements (#632)
* No template file not found error message * Setup wizard improvmenets * path improvements * staged input fix * path improvements * Provider dns resolved ips now writing to a file instead of source.yml * Playlist update hard kill after 1h * matadata update tmdb fix * Web UI fixes * GeoIp update schedule * batch:// prefix for aliases
This commit is contained in:
@@ -7,6 +7,14 @@ use std::{
|
||||
|
||||
pub const DEFAULT_HOME_ENV_VAR: &str = "TULIPROX_HOME";
|
||||
pub const DEFAULT_WEB_ROOT_ENV_VAR: &str = "TULIPROX_WEB_ROOT";
|
||||
pub const DEFAULT_USER_AGENT: &str = "VLC/3.0.16 LibVLC/3.0.16";
|
||||
pub const DEFAULT_BACKUP_DIR: &str = "backup";
|
||||
pub const DEFAULT_CACHE_DIR: &str = "cache";
|
||||
pub const DEFAULT_STORAGE_TEMP_DIR: &str = "tmp";
|
||||
pub const DEFAULT_USER_CONFIG_DIR: &str = "user_config";
|
||||
pub const DEFAULT_DOWNLOAD_DIR: &str = "downloads";
|
||||
pub const DEFAULT_CUSTOM_STREAM_RESPONSE_PATH: &str = "resources";
|
||||
pub const DNS_RESOLVED_FILE: &str = "provider_dns_resolved.json";
|
||||
pub const USER_FILE: &str = "user.txt";
|
||||
pub const CONFIG_PATH: &str = "config";
|
||||
pub const CONFIG_FILE: &str = "config.yml";
|
||||
@@ -15,7 +23,7 @@ pub const MAPPING_FILE: &str = "mapping.yml";
|
||||
pub const TEMPLATE_FILE: &str = "template.yml";
|
||||
pub const API_PROXY_FILE: &str = "api-proxy.yml";
|
||||
pub const DEFAULT_WEB_DIR: &str = "web";
|
||||
pub const DEFAULT_WORKING_DIR: &str = "data";
|
||||
pub const DEFAULT_STORAGE_DIR: &str = "data"; // TODO rename to storage and use data for config, storage, ...
|
||||
pub const DEFAULT_PORT: u16 = 8901;
|
||||
pub const ENCODING_GZIP: &str = "gzip";
|
||||
pub const ENCODING_DEFLATE: &str = "deflate";
|
||||
@@ -31,6 +39,8 @@ pub const HLS_EXT_FRAGMENT: &str = ".m3u8#";
|
||||
pub const DASH_EXT_QUERY: &str = ".mpd?";
|
||||
pub const DASH_EXT_FRAGMENT: &str = ".mpd#";
|
||||
|
||||
pub const DEFAULT_EPISODE_PATTERN: &str = r".*(?P<episode>[Ss]\d{1,2}(.*?)[Ee]\d{1,2}).*";
|
||||
|
||||
pub const FILENAME_TRIM_PATTERNS: &[char] = &['.', '-', '_'];
|
||||
|
||||
const SUPPORTED_RESPONSE_HEADERS: &[&str] = &[
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
use crate::model::{ConfigTargetOptions, LibraryMetadataFormat, ProcessingOrder};
|
||||
use crate::{
|
||||
model::{ConfigTargetOptions, LibraryMetadataFormat, MetadataUpdateConfigDto, ProcessingOrder, VideoConfigDto},
|
||||
utils::{
|
||||
CONFIG_PATH, DEFAULT_BACKUP_DIR, DEFAULT_CACHE_DIR, DEFAULT_CUSTOM_STREAM_RESPONSE_PATH, DEFAULT_DOWNLOAD_DIR,
|
||||
DEFAULT_EPISODE_PATTERN, DEFAULT_STORAGE_DIR, DEFAULT_USER_AGENT, DEFAULT_USER_CONFIG_DIR, DEFAULT_WEB_DIR,
|
||||
MAPPING_FILE, TEMPLATE_FILE, USER_FILE,
|
||||
},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub const fn is_zero_u16(v: &u16) -> bool { *v == 0 }
|
||||
@@ -218,6 +225,112 @@ pub fn is_default_metadata_ffprobe_live_probe_size(v: &String) -> bool {
|
||||
*v == default_metadata_ffprobe_live_probe_size()
|
||||
}
|
||||
|
||||
pub fn get_default_web_root() -> String { DEFAULT_WEB_DIR.to_string() }
|
||||
pub fn is_blank_or_default_web_root(value: &str) -> bool {
|
||||
let normalized = value.trim().replace('\\', "/");
|
||||
if normalized.is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let normalized = normalized.trim_end_matches('/');
|
||||
normalized.trim_start_matches("./") == DEFAULT_WEB_DIR
|
||||
}
|
||||
|
||||
pub fn is_default_dir_path(value: &str, default_dir: &str) -> bool {
|
||||
let normalized = value.trim().replace('\\', "/");
|
||||
let normalized = normalized.trim_end_matches('/');
|
||||
let normalized = normalized.trim_start_matches("./");
|
||||
let default_dir = default_dir.trim().replace('\\', "/");
|
||||
let default_dir = default_dir.trim_end_matches('/');
|
||||
normalized == default_dir
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_download_dir(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || is_default_dir_path(value, DEFAULT_DOWNLOAD_DIR))
|
||||
}
|
||||
pub fn default_download_dir() -> Option<String> { Some(DEFAULT_DOWNLOAD_DIR.to_string()) }
|
||||
|
||||
pub fn default_episode_pattern() -> Option<String> { Some(DEFAULT_EPISODE_PATTERN.to_string()) }
|
||||
|
||||
pub fn is_blank_or_default_episode_pattern(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || value.trim() == DEFAULT_EPISODE_PATTERN)
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_cache_dir(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || is_default_dir_path(value, DEFAULT_CACHE_DIR))
|
||||
}
|
||||
|
||||
pub fn default_default_user_agent() -> Option<String> { Some(DEFAULT_USER_AGENT.to_string()) }
|
||||
pub fn default_main_storage_dir() -> Option<String> { Some(DEFAULT_STORAGE_DIR.to_string()) }
|
||||
pub fn default_main_backup_dir() -> Option<String> { Some(DEFAULT_BACKUP_DIR.to_string()) }
|
||||
pub fn default_main_user_config_dir() -> Option<String> { Some(DEFAULT_USER_CONFIG_DIR.to_string()) }
|
||||
pub fn default_main_mapping_path() -> Option<String> { Some(format!("./{CONFIG_PATH}/{MAPPING_FILE}")) }
|
||||
pub fn default_main_template_path() -> Option<String> { Some(format!("./{CONFIG_PATH}/{TEMPLATE_FILE}")) }
|
||||
pub fn default_custom_stream_response_path() -> Option<String> { Some(DEFAULT_CUSTOM_STREAM_RESPONSE_PATH.to_string()) }
|
||||
pub fn default_user_file_path() -> Option<String> { Some(format!("./{CONFIG_PATH}/{USER_FILE}")) }
|
||||
fn is_default_config_file_path(value: &str, file_name: &str) -> bool {
|
||||
let normalized = value.trim().replace('\\', "/");
|
||||
let normalized = normalized.trim_start_matches("./");
|
||||
normalized == file_name
|
||||
|| normalized.rsplit_once('/').is_some_and(|(dir, file)| dir == CONFIG_PATH && file == file_name)
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_custom_stream_response_path(path: &Option<String>) -> bool {
|
||||
path.as_ref()
|
||||
.is_none_or(|value| value.trim().is_empty() || is_default_dir_path(value, DEFAULT_CUSTOM_STREAM_RESPONSE_PATH))
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_mapping_path(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || is_default_config_file_path(value, MAPPING_FILE))
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_template_path(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || is_default_config_file_path(value, TEMPLATE_FILE))
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_storage_dir(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || is_default_dir_path(value, DEFAULT_STORAGE_DIR))
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_backup_dir(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || is_default_dir_path(value, DEFAULT_BACKUP_DIR))
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_user_config_dir(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || is_default_dir_path(value, DEFAULT_USER_CONFIG_DIR))
|
||||
}
|
||||
|
||||
pub fn is_blank_or_default_user_file_path(path: &Option<String>) -> bool {
|
||||
path.as_ref().is_none_or(|value| value.trim().is_empty() || is_default_config_file_path(value, USER_FILE))
|
||||
}
|
||||
|
||||
pub fn normalize_optional_dir(path: &Option<String>, default_dir: &str) -> Option<String> {
|
||||
path.as_ref().and_then(|value| {
|
||||
if value.trim().is_empty() || is_default_dir_path(value, default_dir) {
|
||||
None
|
||||
} else {
|
||||
Some(value.clone())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn normalize_optional_config_file_path(path: &Option<String>, default_file_name: &str) -> Option<String> {
|
||||
path.as_ref().and_then(|value| {
|
||||
if value.trim().is_empty() || is_default_config_file_path(value, default_file_name) {
|
||||
None
|
||||
} else {
|
||||
Some(value.clone())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_none_or_empty_video(video: &Option<VideoConfigDto>) -> bool {
|
||||
video.as_ref().is_none_or(VideoConfigDto::is_empty)
|
||||
}
|
||||
pub fn is_none_or_empty_metadata_update(metadata_update: &Option<MetadataUpdateConfigDto>) -> bool {
|
||||
metadata_update.as_ref().is_none_or(MetadataUpdateConfigDto::is_empty)
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// HDHomerun Device Defaults
|
||||
//////////////////////////////
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::{borrow::Cow, sync::atomic::Ordering};
|
||||
use url::Url;
|
||||
|
||||
pub const PROVIDER_SCHEME_PREFIX: &str = "provider://";
|
||||
pub const BATCH_SCHEME_PREFIX: &str = "batch://";
|
||||
|
||||
pub const CONTENT_TYPE_JSON: &str = "application/json";
|
||||
pub const CONTENT_TYPE_CBOR: &str = "application/cbor";
|
||||
|
||||
Reference in New Issue
Block a user