diff --git a/backend/src/api/api_utils.rs b/backend/src/api/api_utils.rs index 41668eeb5..4df0cd9c2 100644 --- a/backend/src/api/api_utils.rs +++ b/backend/src/api/api_utils.rs @@ -12,9 +12,9 @@ use crate::api::model::streams::provider_stream_factory::{create_provider_stream use crate::api::model::streams::shared_stream_manager::SharedStreamManager; use crate::api::model::streams::throttled_stream::ThrottledStream; use crate::auth::Claims; -use crate::model::{ConfigTarget, ProxyUserCredentials, UserConnectionPermission}; +use crate::model::{ConfigTarget, ProxyUserCredentials}; use crate::model::{ConfigInput, InputFetchMethod}; -use shared::model::{PlaylistEntry, PlaylistItemType, TargetType, XtreamCluster}; +use shared::model::{PlaylistEntry, PlaylistItemType, TargetType, UserConnectionPermission, XtreamCluster}; use crate::tools::atomic_once_flag::AtomicOnceFlag; use crate::tools::lru_cache::LRUResourceCache; use shared::utils::{DASH_EXT, HLS_EXT}; diff --git a/backend/src/api/endpoints/api_playlist_utils.rs b/backend/src/api/endpoints/api_playlist_utils.rs index 53f78e3c1..26045c598 100644 --- a/backend/src/api/endpoints/api_playlist_utils.rs +++ b/backend/src/api/endpoints/api_playlist_utils.rs @@ -1,6 +1,6 @@ -use crate::model::{Config, ConfigInput, ConfigTarget, InputType, TargetType}; +use crate::model::{Config, ConfigInput, ConfigTarget, InputType}; use crate::model::{M3uPlaylistItem, PlaylistGroup}; -use shared::model::{PlaylistItemType, XtreamCluster}; +use shared::model::{PlaylistItemType, TargetType, XtreamCluster}; use crate::repository::{m3u_repository, xtream_repository}; use crate::utils::{m3u, xtream}; use axum::response::IntoResponse; diff --git a/backend/src/api/endpoints/hdhomerun_api.rs b/backend/src/api/endpoints/hdhomerun_api.rs index 4db41ce9e..784f27a9e 100644 --- a/backend/src/api/endpoints/hdhomerun_api.rs +++ b/backend/src/api/endpoints/hdhomerun_api.rs @@ -1,9 +1,9 @@ use crate::api::model::app_state::HdHomerunAppState; use crate::auth::AuthBasic; -use crate::model::ProxyUserCredentials; -use crate::model::{Config, ConfigTarget, TargetType}; +use crate::model::{ConfigTarget, ProxyUserCredentials}; +use crate::model::{Config}; use crate::model::{M3uPlaylistItem, XtreamPlaylistItem}; -use shared::model::{PlaylistItemType, XtreamCluster}; +use shared::model::{PlaylistItemType, TargetType, XtreamCluster}; use crate::processing::parser::xtream::get_xtream_url; use crate::repository::m3u_playlist_iterator::M3uPlaylistIterator; use crate::repository::xtream_playlist_iterator::XtreamPlaylistIterator; diff --git a/backend/src/api/endpoints/hls_api.rs b/backend/src/api/endpoints/hls_api.rs index f72fc470f..da5748d5f 100644 --- a/backend/src/api/endpoints/hls_api.rs +++ b/backend/src/api/endpoints/hls_api.rs @@ -2,9 +2,9 @@ use crate::api::api_utils::{force_provider_stream_response, get_stream_alternati use crate::api::api_utils::{try_option_bad_request}; use crate::api::model::app_state::AppState; use crate::api::model::streams::provider_stream::{create_custom_video_stream_response, CustomVideoStreamType}; -use crate::model::{ProxyUserCredentials, UserConnectionPermission}; +use crate::model::{ProxyUserCredentials}; use crate::model::ConfigInput; -use shared::model::{PlaylistItemType, XtreamCluster}; +use shared::model::{PlaylistItemType, UserConnectionPermission, XtreamCluster}; use crate::processing::parser::hls::{get_hls_session_token_and_url_from_token, rewrite_hls, RewriteHlsProps}; use shared::utils::HLS_EXT; use crate::utils::request; diff --git a/backend/src/api/endpoints/m3u_api.rs b/backend/src/api/endpoints/m3u_api.rs index 111ac420d..ddc166740 100644 --- a/backend/src/api/endpoints/m3u_api.rs +++ b/backend/src/api/endpoints/m3u_api.rs @@ -4,9 +4,7 @@ use crate::api::endpoints::xtream_api::{ApiStreamContext, ApiStreamRequest}; use crate::api::model::app_state::AppState; use crate::api::model::request::UserApiRequest; use crate::api::model::streams::provider_stream::{create_custom_video_stream_response, CustomVideoStreamType}; -use crate::model::TargetType; -use crate::model::UserConnectionPermission; -use shared::model::{FieldGetAccessor, PlaylistEntry, PlaylistItemType, XtreamCluster}; +use shared::model::{FieldGetAccessor, PlaylistEntry, PlaylistItemType, TargetType, UserConnectionPermission, XtreamCluster}; use crate::repository::m3u_repository::{m3u_get_item_for_stream_id, m3u_load_rewrite_playlist}; use crate::repository::storage_const; use crate::utils::request::{extract_extension_from_url, sanitize_sensitive_info}; diff --git a/backend/src/api/endpoints/user_api.rs b/backend/src/api/endpoints/user_api.rs index b14147013..7c355be47 100644 --- a/backend/src/api/endpoints/user_api.rs +++ b/backend/src/api/endpoints/user_api.rs @@ -1,8 +1,8 @@ use crate::api::api_utils::{get_user_target_by_username, get_username_from_auth_header}; use crate::api::model::app_state::AppState; use crate::auth::validator_user; -use crate::model::{Config, ConfigTarget, TargetType}; -use shared::model::XtreamCluster; +use crate::model::{Config, ConfigTarget}; +use shared::model::{TargetType, XtreamCluster}; use crate::model::PlaylistBouquetDto; use crate::model::PlaylistXtreamCategory; use crate::repository::user_repository::{load_user_bouquet_as_json, save_user_bouquet}; diff --git a/backend/src/api/endpoints/v1_api.rs b/backend/src/api/endpoints/v1_api.rs index f9c7e417b..25684b3d1 100644 --- a/backend/src/api/endpoints/v1_api.rs +++ b/backend/src/api/endpoints/v1_api.rs @@ -7,9 +7,9 @@ use crate::api::model::request::{PlaylistRequest, PlaylistRequestType}; use crate::auth::create_access_token; use crate::auth::validator_admin; use shared::error::TuliproxError; -use crate::model::StatusCheck; +use crate::model::{ConfigTarget, StatusCheck}; use crate::model::XtreamPlaylistItem; -use crate::model::{Config, ConfigDto, ConfigInput, ConfigInputOptions, ConfigSource, ConfigTarget, InputType}; +use crate::model::{Config, ConfigDto, ConfigInput, ConfigInputOptions, ConfigSource, InputType}; use crate::model::{ApiProxyConfig, ApiProxyServerInfo, ProxyUserCredentials, TargetUser}; use crate::processing::processor::playlist; use crate::repository::user_repository::store_api_user; diff --git a/backend/src/api/endpoints/xmltv_api.rs b/backend/src/api/endpoints/xmltv_api.rs index b661a4d34..937125274 100644 --- a/backend/src/api/endpoints/xmltv_api.rs +++ b/backend/src/api/endpoints/xmltv_api.rs @@ -12,8 +12,8 @@ use std::sync::Arc; use crate::api::api_utils::{get_user_target, serve_file}; use crate::api::model::app_state::AppState; use crate::api::model::request::UserApiRequest; -use crate::model::ProxyUserCredentials; -use crate::model::{Config, ConfigTarget, TargetOutput}; +use crate::model::{ConfigTarget, ProxyUserCredentials, TargetOutput}; +use crate::model::{Config}; use crate::repository::m3u_repository::m3u_get_epg_file_path; use crate::repository::storage::get_target_storage_path; use crate::repository::xtream_repository::{xtream_get_epg_file_path, xtream_get_storage_path}; diff --git a/backend/src/api/endpoints/xtream_api.rs b/backend/src/api/endpoints/xtream_api.rs index b1107e8c1..1b1f5202f 100644 --- a/backend/src/api/endpoints/xtream_api.rs +++ b/backend/src/api/endpoints/xtream_api.rs @@ -9,10 +9,9 @@ use crate::api::model::app_state::AppState; use crate::api::model::request::UserApiRequest; use crate::api::model::streams::provider_stream::{create_custom_video_stream_response, CustomVideoStreamType}; use crate::api::model::xtream::XtreamAuthorizationResponse; -use crate::model::TargetType; -use crate::model::{get_backdrop_path_value, XtreamPlaylistItem}; -use crate::model::{Config, ConfigInput, ConfigTarget}; -use crate::model::{ProxyType, ProxyUserCredentials, UserConnectionPermission}; +use crate::model::{get_backdrop_path_value, ConfigTarget, XtreamPlaylistItem}; +use crate::model::{Config, ConfigInput}; +use crate::model::{ProxyUserCredentials}; use crate::repository::playlist_repository::get_target_id_mapping; use crate::repository::storage::{get_target_storage_path}; use crate::repository::{storage_const, user_repository, xtream_repository}; @@ -41,7 +40,7 @@ use std::fmt::{Display, Formatter}; use std::path::Path; use std::str::FromStr; use std::sync::Arc; -use shared::model::{PlaylistItemType, XtreamCluster, FieldGetAccessor, PlaylistEntry}; +use shared::model::{PlaylistItemType, XtreamCluster, FieldGetAccessor, PlaylistEntry, TargetType, UserConnectionPermission, ProxyType}; #[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq)] pub enum ApiStreamContext { diff --git a/backend/src/api/model/active_user_manager.rs b/backend/src/api/model/active_user_manager.rs index 942ad277f..35c1ebf60 100644 --- a/backend/src/api/model/active_user_manager.rs +++ b/backend/src/api/model/active_user_manager.rs @@ -1,5 +1,5 @@ use crate::model::Config; -use crate::model::{ProxyUserCredentials, UserConnectionPermission}; +use crate::model::{ProxyUserCredentials}; use crate::utils::request::sanitize_sensitive_info; use shared::utils::{current_time_secs, default_grace_period_millis, default_grace_period_timeout_secs}; use jsonwebtoken::get_current_timestamp; @@ -8,6 +8,7 @@ use std::collections::HashMap; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; use tokio::sync::RwLock; +use shared::model::UserConnectionPermission; const USER_CON_TTL: u64 = 10_800; // 3 hours const USER_SESSION_LIMIT: usize = 50; diff --git a/backend/src/api/model/app_state.rs b/backend/src/api/model/app_state.rs index e9b5ec31f..190274b3f 100644 --- a/backend/src/api/model/app_state.rs +++ b/backend/src/api/model/app_state.rs @@ -1,10 +1,11 @@ use tokio::sync::{Mutex}; use std::sync::Arc; +use shared::model::UserConnectionPermission; use crate::api::model::active_provider_manager::ActiveProviderManager; use crate::api::model::active_user_manager::ActiveUserManager; use crate::api::model::download::DownloadQueue; use crate::api::model::streams::shared_stream_manager::SharedStreamManager; -use crate::model::{Config, UserConnectionPermission, HdHomeRunDeviceConfig}; +use crate::model::{Config, HdHomeRunDeviceConfig}; use crate::tools::lru_cache::LRUResourceCache; #[derive(Clone)] diff --git a/backend/src/api/model/config.rs b/backend/src/api/model/config.rs index 673f5e81f..5fe0597cb 100644 --- a/backend/src/api/model/config.rs +++ b/backend/src/api/model/config.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; use shared::model::ProcessingOrder; -use crate::model::{ApiProxyConfig, ConfigApi, InputType, LogConfig, MessagingConfig, ReverseProxyConfig, ScheduleConfig, VideoConfig, ConfigRename, ConfigSort, ConfigTargetOptions, TargetOutput, WebUiConfig, ProxyConfig, IpCheckConfig}; +use crate::model::{ApiProxyConfig, ConfigApi, InputType, LogConfig, MessagingConfig, ReverseProxyConfig, ScheduleConfig, VideoConfig, ConfigSort, WebUiConfig, ProxyConfig, IpCheckConfig, ConfigTargetOptions, TargetOutput, ConfigRename}; #[derive(Deserialize, Serialize, Debug, Clone)] pub struct ServerInputConfig { diff --git a/backend/src/api/model/xtream.rs b/backend/src/api/model/xtream.rs index fc5e0e508..e9f18ef92 100644 --- a/backend/src/api/model/xtream.rs +++ b/backend/src/api/model/xtream.rs @@ -1,6 +1,7 @@ -use crate::model::{ApiProxyServerInfo, ProxyUserCredentials, ProxyUserStatus}; +use crate::model::{ApiProxyServerInfo, ProxyUserCredentials}; use chrono::{Duration, Local}; use serde::{Deserialize, Serialize}; +use shared::model::ProxyUserStatus; use shared::utils::CONSTANTS; #[derive(Serialize, Deserialize, Clone)] diff --git a/backend/src/processing/processor/trakt.rs b/backend/src/processing/processor/trakt.rs index 7a8cf665e..4f180726a 100644 --- a/backend/src/processing/processor/trakt.rs +++ b/backend/src/processing/processor/trakt.rs @@ -3,9 +3,7 @@ use crate::model::{ConfigTarget, PlaylistGroup, PlaylistItem}; use shared::model::{FieldGetAccessor, FieldSetAccessor, XtreamCluster}; use crate::model::{TraktConfig, TraktContentType, TraktListConfig, TraktListItem, TraktMatchItem, TraktMatchResult}; use shared::error::TuliproxError; -use crate::utils::trakt::TraktClient; -use crate::utils::trakt::extract_year_from_title; -use crate::utils::trakt::normalize_title_for_matching; +use crate::utils::{TraktClient, extract_year_from_title, normalize_title_for_matching}; use crate::utils::{get_u32_from_serde_value}; use shared::utils::{CONSTANTS}; use crate::utils::{trace_if_enabled, with}; diff --git a/backend/src/repository/m3u_playlist_iterator.rs b/backend/src/repository/m3u_playlist_iterator.rs index aafff56ea..6fc40951e 100644 --- a/backend/src/repository/m3u_playlist_iterator.rs +++ b/backend/src/repository/m3u_playlist_iterator.rs @@ -1,9 +1,9 @@ use shared::error::info_err; use shared::error::{TuliproxError, TuliproxErrorKind}; -use crate::model::{ProxyType, ProxyUserCredentials}; -use crate::model::{Config, ConfigTarget, ConfigTargetOptions, TargetType}; +use crate::model::{ProxyUserCredentials}; +use crate::model::{Config, ConfigTarget, ConfigTargetOptions}; use crate::model::{M3uPlaylistItem}; -use shared::model::{PlaylistItemType, XtreamCluster}; +use shared::model::{PlaylistItemType, ProxyType, TargetType, XtreamCluster}; use crate::repository::indexed_document::IndexedDocumentIterator; use crate::repository::m3u_repository::m3u_get_file_paths; use crate::repository::storage::ensure_target_storage_path; diff --git a/backend/src/repository/user_repository.rs b/backend/src/repository/user_repository.rs index b3ab1fc9d..10bc3f095 100644 --- a/backend/src/repository/user_repository.rs +++ b/backend/src/repository/user_repository.rs @@ -1,6 +1,6 @@ -use crate::model::{ProxyType, ProxyUserCredentials, ProxyUserStatus, TargetUser}; -use crate::model::{Config, TargetType}; -use shared::model::XtreamCluster; +use crate::model::{ProxyUserCredentials, TargetUser}; +use crate::model::{Config}; +use shared::model::{ProxyType, ProxyUserStatus, TargetType, XtreamCluster}; use crate::model::{PlaylistBouquetDto, TargetBouquetDto}; use crate::model::PlaylistXtreamCategory; use crate::repository::bplustree::BPlusTree; diff --git a/backend/src/repository/xtream_playlist_iterator.rs b/backend/src/repository/xtream_playlist_iterator.rs index d42a71428..7fbda0bfc 100644 --- a/backend/src/repository/xtream_playlist_iterator.rs +++ b/backend/src/repository/xtream_playlist_iterator.rs @@ -1,10 +1,10 @@ use std::collections::HashSet; use log::error; -use shared::model::XtreamCluster; +use shared::model::{TargetType, XtreamCluster}; use shared::error::info_err; use shared::error::{TuliproxError, TuliproxErrorKind}; use crate::model::{ProxyUserCredentials}; -use crate::model::{Config, ConfigTarget, TargetType}; +use crate::model::{Config, ConfigTarget}; use crate::model::{XtreamPlaylistItem}; use crate::model::XtreamMappingOptions; use crate::repository::indexed_document::{IndexedDocumentIterator}; diff --git a/shared/src/model/config/api_proxy.rs b/shared/src/model/config/api_proxy.rs new file mode 100644 index 000000000..ac69e8244 --- /dev/null +++ b/shared/src/model/config/api_proxy.rs @@ -0,0 +1,30 @@ +use crate::model::{ProxyUserCredentialsDto}; + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct TargetUserDto { + pub target: String, + pub credentials: Vec, +} + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ApiProxyServerInfoDto { + pub name: String, + pub protocol: String, + pub host: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub port: Option, + pub timezone: String, + pub message: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub path: Option, +} + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ApiProxyConfigDto { + pub server: Vec, + pub user: Vec, + #[serde(default)] + pub use_user_db: bool, +} diff --git a/shared/src/model/config/api_user.rs b/shared/src/model/config/api_user.rs new file mode 100644 index 000000000..ae9375a7a --- /dev/null +++ b/shared/src/model/config/api_user.rs @@ -0,0 +1,204 @@ +use crate::utils::default_as_true; +use std::fmt::Display; +use std::str::FromStr; +use enum_iterator::Sequence; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use crate::create_tuliprox_error_result; +use crate::error::{TuliproxError, TuliproxErrorKind}; +use crate::model::{ClusterFlags, PlaylistItemType}; + +#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +pub enum UserConnectionPermission { + Exhausted, + Allowed, + GracePeriod, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ProxyType { + Reverse(Option), + Redirect, +} + +impl Default for ProxyType { + fn default() -> Self { + Self::Redirect + } +} + +impl ProxyType { + const REVERSE: &'static str = "reverse"; + const REDIRECT: &'static str = "redirect"; + + pub fn is_redirect(&self, item_type: PlaylistItemType) -> bool { + match self { + ProxyType::Reverse(Some(flags)) => { + if flags.is_empty() { + return false; + } + if flags.has_cluster(item_type) { + return false; + } + true + }, + ProxyType::Reverse(None) => false, + ProxyType::Redirect => true + } + } + + pub fn is_reverse(&self, item_type: PlaylistItemType) -> bool { + !self.is_redirect(item_type) + } +} + +impl Display for ProxyType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Reverse(force_redirect) => { + if let Some(force) = force_redirect { + write!(f, "{}{force:?}", Self::REVERSE) + } else { + write!(f, "{}", Self::REVERSE) + } + } + Self::Redirect => write!(f, "{}", Self::REDIRECT), + } + } +} + +impl FromStr for ProxyType { + type Err = TuliproxError; + + fn from_str(s: &str) -> Result { + if s == Self::REDIRECT { + return Ok(Self::Redirect); + } + if s == Self::REVERSE { + return Ok(Self::Reverse(None)); + } + + if s.starts_with(Self::REVERSE) { + let suffix = s.strip_prefix(Self::REVERSE).unwrap(); + if let Ok(force_redirect) = ClusterFlags::try_from(suffix) { + if force_redirect.has_full_flags() { + return Ok(ProxyType::Reverse(None)); + } + return Ok(Self::Reverse(Some(force_redirect))); + } + } + + create_tuliprox_error_result!(TuliproxErrorKind::Info, "Unknown ProxyType: {}", s) + } +} + +impl<'de> Deserialize<'de> for ProxyType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let raw: String = Deserialize::deserialize(deserializer)?; + if raw == ProxyType::REDIRECT { + return Ok(ProxyType::Redirect); + } else if raw.starts_with(ProxyType::REVERSE) { + return ProxyType::from_str(raw.as_str()).map_err(serde::de::Error::custom); + } + Err(serde::de::Error::custom("Unknown proxy type")) + } +} + +impl Serialize for ProxyType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + ProxyType::Redirect => serializer.serialize_str(ProxyType::REDIRECT), + ProxyType::Reverse(None) => serializer.serialize_str(ProxyType::REVERSE), + ProxyType::Reverse(Some(ref force_redirect)) => { + serializer.serialize_str(&format!("{}{}", ProxyType::REVERSE, force_redirect)) + }, + } + } +} + +#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize, Sequence, PartialEq, Eq)] +pub enum ProxyUserStatus { + Active, // The account is in good standing and can stream content + Expired, // The account can no longer access content unless it is renewed. + Banned, // The account is temporarily or permanently disabled. Typically used for users who violate terms of service or abuse the system. + Trial, // The account is marked as a trial account. + Disabled, // The account is inactive or deliberately disabled by the administrator. + Pending, +} + + +impl Default for ProxyUserStatus { + fn default() -> Self { + Self::Active + } +} + +impl ProxyUserStatus { + const ACTIVE: &'static str = "Active"; + const EXPIRED: &'static str = "Expired"; + const BANNED: &'static str = "Banned"; + const TRIAL: &'static str = "Trial"; + const DISABLED: &'static str = "Disabled"; + const PENDING: &'static str = "Pending"; +} + +impl Display for ProxyUserStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match self { + Self::Active => Self::ACTIVE, + Self::Expired => Self::EXPIRED, + Self::Banned => Self::BANNED, + Self::Trial => Self::TRIAL, + Self::Disabled => Self::DISABLED, + Self::Pending => Self::PENDING, + }) + } +} + +impl FromStr for ProxyUserStatus { + type Err = TuliproxError; + + fn from_str(s: &str) -> Result { + match s { + Self::ACTIVE => Ok(Self::Active), + Self::EXPIRED => Ok(Self::Expired), + Self::BANNED => Ok(Self::Banned), + Self::TRIAL => Ok(Self::Trial), + Self::DISABLED => Ok(Self::Disabled), + Self::PENDING => Ok(Self::Pending), + _ => create_tuliprox_error_result!(TuliproxErrorKind::Info, "Unknown ProxyUserStatus: {}", s) + } + } +} + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ProxyUserCredentialsDto { + pub username: String, + pub password: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub token: Option, + #[serde(default = "ProxyType::default")] + pub proxy: ProxyType, + #[serde(skip_serializing_if = "Option::is_none")] + pub server: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub epg_timeshift: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub created_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub exp_date: Option, + #[serde(default)] + pub max_connections: u32, + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, + #[serde(default = "default_as_true")] + pub ui_enabled: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub comment: Option, +} diff --git a/shared/src/model/config/mod.rs b/shared/src/model/config/mod.rs index 90d9771ed..952db41ad 100644 --- a/shared/src/model/config/mod.rs +++ b/shared/src/model/config/mod.rs @@ -17,8 +17,13 @@ mod reverse_proxy; mod cache; mod rate_limit; mod proxy; +mod rename; +mod api_proxy; +mod api_user; pub use base::*; +pub use api_proxy::*; +pub use api_user::*; pub use web::*; pub use messaging::*; pub use hdhomerun::*; @@ -37,3 +42,4 @@ pub use rate_limit::*; pub use reverse_proxy::*; pub use proxy::*; pub use trakt::*; +pub use rename::*; diff --git a/shared/src/model/config/rename.rs b/shared/src/model/config/rename.rs new file mode 100644 index 000000000..a22f53f09 --- /dev/null +++ b/shared/src/model/config/rename.rs @@ -0,0 +1,9 @@ +use crate::model::ItemField; + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigRenameDto { + pub field: ItemField, + pub pattern: String, + pub new_name: String, +} \ No newline at end of file diff --git a/shared/src/model/config/source.rs b/shared/src/model/config/source.rs index 2945ef1b4..5ea4f181b 100644 --- a/shared/src/model/config/source.rs +++ b/shared/src/model/config/source.rs @@ -1,4 +1,4 @@ -use crate::model::{ConfigInputDto, ItemField}; +use crate::model::{ConfigInputDto}; use crate::model::config::target::ConfigTargetDto; @@ -17,14 +17,6 @@ pub struct PatternTemplateDto { pub placeholder: String, } -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -#[serde(deny_unknown_fields)] -pub struct ConfigRenameDto { - pub field: ItemField, - pub pattern: String, - pub new_name: String, -} - #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[serde(deny_unknown_fields)] pub struct ConfigSourceDto { diff --git a/shared/src/model/config/target.rs b/shared/src/model/config/target.rs index 2707956a8..1d89c7e5b 100644 --- a/shared/src/model/config/target.rs +++ b/shared/src/model/config/target.rs @@ -1,5 +1,4 @@ -use crate::model::{ClusterFlags, ConfigSortDto, ProcessingOrder, StrmExportStyle, TargetType, TraktConfigDto}; -use crate::model::config::source::ConfigRenameDto; +use crate::model::{ClusterFlags, ConfigRenameDto, ConfigSortDto, ProcessingOrder, StrmExportStyle, TargetType, TraktConfigDto}; use crate::utils::{default_as_true, default_resolve_delay_secs, default_as_default}; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)] #[serde(deny_unknown_fields)]