diff --git a/Cargo.lock b/Cargo.lock index f633f2c58..901cdfc46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2581,6 +2581,8 @@ name = "shared" version = "0.1.0" dependencies = [ "bitflags 2.9.1", + "rand", + "regex", "serde", ] diff --git a/backend/src/api/api_utils.rs b/backend/src/api/api_utils.rs index e655ea58f..ee759d3a8 100644 --- a/backend/src/api/api_utils.rs +++ b/backend/src/api/api_utils.rs @@ -17,12 +17,11 @@ use crate::model::{ConfigInput, ConfigTarget, InputFetchMethod, TargetType}; use shared::model::{PlaylistEntry, PlaylistItemType, XtreamCluster}; use crate::tools::atomic_once_flag::AtomicOnceFlag; use crate::tools::lru_cache::LRUResourceCache; -use crate::utils::{DASH_EXT, HLS_EXT}; -use crate::utils::default_grace_period_millis; +use shared::utils::{DASH_EXT, HLS_EXT}; +use shared::utils::{default_grace_period_millis, human_readable_byte_size}; use crate::utils::create_new_file_for_write; use crate::utils::request; use crate::utils::request::{extract_extension_from_url, replace_url_extension, sanitize_sensitive_info}; -use crate::utils::human_readable_byte_size; use crate::utils::{debug_if_enabled, trace_if_enabled}; use crate::{BUILD_TIMESTAMP}; use axum::body::Body; diff --git a/backend/src/api/endpoints/download_api.rs b/backend/src/api/endpoints/download_api.rs index f3c074d5f..8561581b3 100644 --- a/backend/src/api/endpoints/download_api.rs +++ b/backend/src/api/endpoints/download_api.rs @@ -12,6 +12,7 @@ use std::ops::Deref; use std::sync::Arc; use std::{fs}; use axum::response::IntoResponse; +use shared::utils::bytes_to_megabytes; use crate::tuliprox_error::to_io_error; use crate::utils::request::create_client; @@ -39,7 +40,7 @@ async fn download_file(active: Arc>>, client: &reqwe Err(err) => return Err(format!("Error while writing to file: {file_path_str} {err}")) } } else { - let megabytes = request::bytes_to_megabytes(downloaded); + let megabytes = bytes_to_megabytes(downloaded); info!("Downloaded {file_path_str}, filesize: {megabytes}MB"); active.write().await.as_mut().unwrap().size = downloaded; return Ok(()); diff --git a/backend/src/api/endpoints/hls_api.rs b/backend/src/api/endpoints/hls_api.rs index a3e82c5f8..f72fc470f 100644 --- a/backend/src/api/endpoints/hls_api.rs +++ b/backend/src/api/endpoints/hls_api.rs @@ -6,7 +6,7 @@ use crate::model::{ProxyUserCredentials, UserConnectionPermission}; use crate::model::ConfigInput; use shared::model::{PlaylistItemType, XtreamCluster}; use crate::processing::parser::hls::{get_hls_session_token_and_url_from_token, rewrite_hls, RewriteHlsProps}; -use crate::utils::HLS_EXT; +use shared::utils::HLS_EXT; use crate::utils::request; use crate::utils::request::{is_hls_url, replace_url_extension, sanitize_sensitive_info}; use axum::response::IntoResponse; diff --git a/backend/src/api/endpoints/m3u_api.rs b/backend/src/api/endpoints/m3u_api.rs index 20561c444..111ac420d 100644 --- a/backend/src/api/endpoints/m3u_api.rs +++ b/backend/src/api/endpoints/m3u_api.rs @@ -10,7 +10,7 @@ use shared::model::{FieldGetAccessor, PlaylistEntry, PlaylistItemType, XtreamClu 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}; -use crate::utils::HLS_EXT; +use shared::utils::HLS_EXT; use axum::http::{HeaderMap, StatusCode}; use axum::response::IntoResponse; use bytes::Bytes; diff --git a/backend/src/api/endpoints/web_index.rs b/backend/src/api/endpoints/web_index.rs index fe25740af..74bc8a5b8 100644 --- a/backend/src/api/endpoints/web_index.rs +++ b/backend/src/api/endpoints/web_index.rs @@ -8,7 +8,7 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::sync::{Arc}; use tower::Service; -use crate::utils::CONSTANTS; +use shared::utils::CONSTANTS; fn no_web_auth_token() -> impl axum::response::IntoResponse + Send { axum::Json(HashMap::from([("token", "authorized")])).into_response() diff --git a/backend/src/api/endpoints/xtream_api.rs b/backend/src/api/endpoints/xtream_api.rs index 4e6d470ae..4a5f710c1 100644 --- a/backend/src/api/endpoints/xtream_api.rs +++ b/backend/src/api/endpoints/xtream_api.rs @@ -24,7 +24,7 @@ use crate::utils::get_u32_from_serde_value; use crate::utils::request::{extract_extension_from_url, sanitize_sensitive_info}; use crate::utils::trace_if_enabled; use crate::utils::xtream::create_vod_info_from_item; -use crate::utils::HLS_EXT; +use shared::utils::HLS_EXT; use crate::utils::{request, xtream}; use crate::auth::Fingerprint; use axum::http::{HeaderMap, StatusCode}; diff --git a/backend/src/api/model/active_provider_manager.rs b/backend/src/api/model/active_provider_manager.rs index 63313c7cd..f87dcf9cf 100644 --- a/backend/src/api/model/active_provider_manager.rs +++ b/backend/src/api/model/active_provider_manager.rs @@ -6,7 +6,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use tokio::sync::{Mutex, RwLock}; use crate::api::model::provider_config::{ProviderConfig, ProviderConfigWrapper}; -use crate::utils::{default_grace_period_millis, default_grace_period_timeout_secs}; +use shared::utils::{default_grace_period_millis, default_grace_period_timeout_secs}; pub struct ProviderConnectionGuard { // manager: Arc, diff --git a/backend/src/api/model/active_user_manager.rs b/backend/src/api/model/active_user_manager.rs index 08822138c..942ad277f 100644 --- a/backend/src/api/model/active_user_manager.rs +++ b/backend/src/api/model/active_user_manager.rs @@ -1,7 +1,7 @@ use crate::model::Config; use crate::model::{ProxyUserCredentials, UserConnectionPermission}; use crate::utils::request::sanitize_sensitive_info; -use crate::utils::{current_time_secs, default_grace_period_millis, default_grace_period_timeout_secs}; +use shared::utils::{current_time_secs, default_grace_period_millis, default_grace_period_timeout_secs}; use jsonwebtoken::get_current_timestamp; use log::{debug, info}; use std::collections::HashMap; diff --git a/backend/src/api/model/download.rs b/backend/src/api/model/download.rs index 47beb38be..36862f959 100644 --- a/backend/src/api/model/download.rs +++ b/backend/src/api/model/download.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::model::{VideoDownloadConfig}; use crate::utils::hash_string_as_hex; -use crate::utils::{CONSTANTS, FILENAME_TRIM_PATTERNS}; +use shared::utils::{CONSTANTS, FILENAME_TRIM_PATTERNS}; /// File-Download information. #[derive(Clone)] diff --git a/backend/src/api/model/model_utils.rs b/backend/src/api/model/model_utils.rs index cfe5e7be1..f865e496a 100644 --- a/backend/src/api/model/model_utils.rs +++ b/backend/src/api/model/model_utils.rs @@ -2,7 +2,7 @@ use reqwest::{StatusCode}; use std::collections::{HashSet}; use std::str::FromStr; use reqwest::header::HeaderMap; -use crate::utils::{filter_response_header}; +use shared::utils::{filter_response_header}; pub fn get_response_headers(headers: &HeaderMap) -> Vec<(String, String)> { let mut response_headers: Vec<(String, String)> = headers.iter() diff --git a/backend/src/api/model/streams/provider_stream_factory.rs b/backend/src/api/model/streams/provider_stream_factory.rs index 606bcf7f3..77498a45d 100644 --- a/backend/src/api/model/streams/provider_stream_factory.rs +++ b/backend/src/api/model/streams/provider_stream_factory.rs @@ -10,7 +10,8 @@ use shared::model::PlaylistItemType; use crate::model::{Config, DEFAULT_USER_AGENT}; use crate::tools::atomic_once_flag::AtomicOnceFlag; use crate::utils::request::{classify_content_type, get_request_headers, sanitize_sensitive_info, MimeCategory}; -use crate::utils::{debug_if_enabled, filter_request_header}; +use crate::utils::{debug_if_enabled}; +use shared::utils::{filter_request_header}; use futures::stream::{self}; use futures::{StreamExt, TryStreamExt}; use log::{debug, log_enabled, warn}; diff --git a/backend/src/api/model/xtream.rs b/backend/src/api/model/xtream.rs index 2bda9f843..fc5e0e508 100644 --- a/backend/src/api/model/xtream.rs +++ b/backend/src/api/model/xtream.rs @@ -1,7 +1,7 @@ use crate::model::{ApiProxyServerInfo, ProxyUserCredentials, ProxyUserStatus}; use chrono::{Duration, Local}; use serde::{Deserialize, Serialize}; -use crate::utils::CONSTANTS; +use shared::utils::CONSTANTS; #[derive(Serialize, Deserialize, Clone)] pub struct XtreamUserInfoResponse { diff --git a/backend/src/foundation/filter.rs b/backend/src/foundation/filter.rs index 951900e2c..37383fe9a 100644 --- a/backend/src/foundation/filter.rs +++ b/backend/src/foundation/filter.rs @@ -13,7 +13,7 @@ use crate::model::{PlaylistItem, ItemField}; use crate::tools::directed_graph::DirectedGraph; use crate::tuliprox_error::{create_tuliprox_error_result, info_err}; use crate::tuliprox_error::{TuliproxError, TuliproxErrorKind}; -use crate::utils::CONSTANTS; +use shared::utils::CONSTANTS; pub fn get_field_value(pli: &PlaylistItem, field: ItemField) -> String { let header = &pli.header; diff --git a/backend/src/foundation/mapper.rs b/backend/src/foundation/mapper.rs index 4df41dd2c..ac536bb9f 100644 --- a/backend/src/foundation/mapper.rs +++ b/backend/src/foundation/mapper.rs @@ -3,7 +3,7 @@ use crate::foundation::filter::{PatternTemplate, TemplateValue, ValueAccessor}; use crate::foundation::mapper::EvalResult::{AnyValue, Failure, Named, Number, Undefined, Value}; use crate::tuliprox_error::{create_tuliprox_error_result, info_err, TuliproxError, TuliproxErrorKind}; -use crate::utils::Capitalize; +use shared::utils::Capitalize; use log::{debug, trace}; use pest::iterators::{Pair, Pairs}; use pest::Parser; diff --git a/backend/src/model/config.rs b/backend/src/model/config.rs index f8cbe6347..750c80e03 100644 --- a/backend/src/model/config.rs +++ b/backend/src/model/config.rs @@ -15,8 +15,7 @@ use rand::Rng; use crate::model::{ApiProxyConfig, ApiProxyServerInfo, Mappings, ProxyUserCredentials, SourcesConfig}; use crate::model::{ConfigInput, ConfigInputOptions, ConfigTarget, HdHomeRunConfig, IpCheckConfig, LogConfig, MessagingConfig, ProxyConfig, TargetOutput, VideoConfig, WebUiConfig}; use crate::tuliprox_error::{create_tuliprox_error_result, TuliproxError, TuliproxErrorKind}; -use crate::utils::{default_connect_timeout_secs, default_grace_period_millis, default_grace_period_timeout_secs}; -use crate::utils::{parse_to_kbps}; +use shared::utils::{parse_to_kbps, default_connect_timeout_secs, default_grace_period_millis, default_grace_period_timeout_secs}; const STREAM_QUEUE_SIZE: usize = 1024; // mpsc channel holding messages. with 8192byte chunks and 2Mbit/s approx 8MB diff --git a/backend/src/model/config_api_proxy.rs b/backend/src/model/config_api_proxy.rs index c3f5ebfcf..f25f31f73 100644 --- a/backend/src/model/config_api_proxy.rs +++ b/backend/src/model/config_api_proxy.rs @@ -2,7 +2,8 @@ use crate::api::model::app_state::AppState; use crate::tuliprox_error::{create_tuliprox_error_result, info_err, TuliproxError, TuliproxErrorKind}; use crate::model::{Config}; use crate::repository::user_repository::{backup_api_user_db_file, get_api_user_db_path, load_api_user, merge_api_user}; -use crate::utils::{default_as_true, save_api_proxy}; +use crate::utils::{save_api_proxy}; +use shared::utils::{default_as_true}; use chrono::Local; use enum_iterator::Sequence; use log::debug; diff --git a/backend/src/model/config_cache.rs b/backend/src/model/config_cache.rs index 6bc52b256..829e3f940 100644 --- a/backend/src/model/config_cache.rs +++ b/backend/src/model/config_cache.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use log::error; use path_clean::PathClean; use crate::tuliprox_error::{info_err, TuliproxError, TuliproxErrorKind}; -use crate::utils::parse_size_base_2; +use shared::utils::parse_size_base_2; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)] #[serde(deny_unknown_fields)] diff --git a/backend/src/model/config_epg.rs b/backend/src/model/config_epg.rs index b6e2c3560..e4a0677c7 100644 --- a/backend/src/model/config_epg.rs +++ b/backend/src/model/config_epg.rs @@ -1,5 +1,5 @@ use crate::tuliprox_error::{create_tuliprox_error_result, info_err, TuliproxError, TuliproxErrorKind}; -use crate::utils::CONSTANTS; +use shared::utils::CONSTANTS; use log::warn; use regex::Regex; diff --git a/backend/src/model/config_input.rs b/backend/src/model/config_input.rs index 8fec6f5e2..5291c66d1 100644 --- a/backend/src/model/config_input.rs +++ b/backend/src/model/config_input.rs @@ -1,7 +1,7 @@ use crate::tuliprox_error::{create_tuliprox_error_result, handle_tuliprox_error_result_list, info_err, TuliproxError, TuliproxErrorKind}; use crate::model::{EpgConfig}; -use crate::utils::default_as_true; -use crate::utils::get_trimmed_string; +use shared::utils::default_as_true; +use shared::utils::get_trimmed_string; use crate::utils::request::{get_base_url_from_str, get_credentials_from_url, get_credentials_from_url_str, sanitize_sensitive_info}; use enum_iterator::Sequence; use log::{debug}; diff --git a/backend/src/model/config_log.rs b/backend/src/model/config_log.rs index 8860363e3..556fe6bc2 100644 --- a/backend/src/model/config_log.rs +++ b/backend/src/model/config_log.rs @@ -1,5 +1,5 @@ -use crate::utils::default_as_true; +use shared::utils::default_as_true; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)] #[serde(deny_unknown_fields)] diff --git a/backend/src/model/config_source.rs b/backend/src/model/config_source.rs index 5a7ae12df..e7ab5639b 100644 --- a/backend/src/model/config_source.rs +++ b/backend/src/model/config_source.rs @@ -3,7 +3,7 @@ use crate::foundation::filter::{prepare_templates, PatternTemplate}; use crate::tuliprox_error::{TuliproxError, TuliproxErrorKind, handle_tuliprox_error_result_list, create_tuliprox_error_result}; use crate::model::{ConfigInput, ProcessTargets}; use crate::model::config_target::ConfigTarget; -use crate::utils::default_as_default; +use shared::utils::default_as_default; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[serde(deny_unknown_fields)] diff --git a/backend/src/model/config_target.rs b/backend/src/model/config_target.rs index dd5c40eb8..6a999d85e 100644 --- a/backend/src/model/config_target.rs +++ b/backend/src/model/config_target.rs @@ -5,7 +5,7 @@ use crate::model::mapping::Mapping; use crate::model::processing_order::ProcessingOrder; use crate::model::trakt::TraktConfig; use crate::tuliprox_error::{create_tuliprox_error_result, handle_tuliprox_error_result_list, info_err, TuliproxError, TuliproxErrorKind}; -use crate::utils::{default_as_default, default_as_true, default_resolve_delay_secs}; +use shared::utils::{default_as_default, default_as_true, default_resolve_delay_secs}; use arc_swap::ArcSwapOption; use enum_iterator::Sequence; use shared::model::ClusterFlags; diff --git a/backend/src/model/config_web_auth.rs b/backend/src/model/config_web_auth.rs index 4ef61aec4..a1a424035 100644 --- a/backend/src/model/config_web_auth.rs +++ b/backend/src/model/config_web_auth.rs @@ -1,4 +1,4 @@ -use crate::utils::default_as_true; +use shared::utils::default_as_true; use std::fs::File; use std::io::BufRead; use std::path::PathBuf; diff --git a/backend/src/model/config_webui.rs b/backend/src/model/config_webui.rs index b3d4f1909..425e4a051 100644 --- a/backend/src/model/config_webui.rs +++ b/backend/src/model/config_webui.rs @@ -1,4 +1,4 @@ -use crate::utils::default_as_true; +use shared::utils::default_as_true; use crate::tuliprox_error::{TuliproxError, TuliproxErrorKind}; use crate::model::WebAuthConfig; diff --git a/backend/src/model/xtream.rs b/backend/src/model/xtream.rs index 0a46a3372..bfcd5fd73 100644 --- a/backend/src/model/xtream.rs +++ b/backend/src/model/xtream.rs @@ -3,7 +3,8 @@ use crate::model::{Config, ConfigTarget, XtreamTargetOutput}; use crate::model::{PlaylistItem,XtreamPlaylistItem}; use crate::model::serde_utils::{deserialize_as_option_rc_string, deserialize_as_rc_string, deserialize_as_string_array, deserialize_number_from_string}; use crate::model::xtream_const; -use crate::utils::{get_non_empty_str, opt_string_or_number_u32, string_default_on_null, string_or_number_f64, string_or_number_u32}; +use crate::utils::{opt_string_or_number_u32, string_default_on_null, string_or_number_f64, string_or_number_u32}; +use shared::utils::{get_non_empty_str}; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use std::collections::HashMap; diff --git a/backend/src/processing/parser/hls.rs b/backend/src/processing/parser/hls.rs index b92618170..dc7111cb6 100644 --- a/backend/src/processing/parser/hls.rs +++ b/backend/src/processing/parser/hls.rs @@ -1,5 +1,5 @@ use crate::model::ProxyUserCredentials; -use crate::utils::{CONSTANTS, HLS_PREFIX}; +use shared::utils::{CONSTANTS, HLS_PREFIX}; use crate::utils::{deobfuscate_text, obfuscate_text}; use std::str; diff --git a/backend/src/processing/parser/m3u.rs b/backend/src/processing/parser/m3u.rs index 2b2d0b339..70b8d7981 100644 --- a/backend/src/processing/parser/m3u.rs +++ b/backend/src/processing/parser/m3u.rs @@ -2,7 +2,23 @@ use std::borrow::BorrowMut; use shared::model::{PlaylistItemType, XtreamCluster}; use crate::model::{Config, ConfigInput}; use crate::model::{PlaylistGroup, PlaylistItem, PlaylistItemHeader}; -use crate::utils::{extract_id_from_url, get_title_group}; +use crate::utils::{extract_id_from_url}; + + +// other implementations like calculating text_distance on all titles took too much time +// we keep it now as simple as possible and less memory intensive. +fn get_title_group(text: &str) -> String { + let alphabetic_only: String = text.chars().map(|c| if c.is_alphanumeric() { c } else { ' ' }).collect(); + let parts = alphabetic_only.split_whitespace(); + let mut combination = String::new(); + for p in parts { + combination = format!("{combination} {p}").trim().to_string(); + if combination.len() > 2 { + return combination; + } + } + text.to_string() +} #[inline] fn token_value(stack: &mut String, it: &mut std::str::Chars) -> String { diff --git a/backend/src/processing/parser/xmltv.rs b/backend/src/processing/parser/xmltv.rs index 47419f9b8..c3b6ef5f3 100644 --- a/backend/src/processing/parser/xmltv.rs +++ b/backend/src/processing/parser/xmltv.rs @@ -2,7 +2,7 @@ use crate::model::{Epg, TVGuide, XmlTag, XmlTagIcon, EPG_ATTRIB_CHANNEL, EPG_ATT use crate::model::{EpgNamePrefix, EpgSmartMatchConfig, PersistedEpgSource}; use crate::processing::processor::epg::EpgIdCache; use crate::utils::compressed_file_reader::CompressedFileReader; -use crate::utils::CONSTANTS; +use shared::utils::CONSTANTS; use deunicode::deunicode; use quick_xml::events::{BytesStart, BytesText, Event}; use quick_xml::Reader; diff --git a/backend/src/processing/processor/playlist.rs b/backend/src/processing/processor/playlist.rs index 26bd1cd67..802614342 100644 --- a/backend/src/processing/processor/playlist.rs +++ b/backend/src/processing/processor/playlist.rs @@ -22,7 +22,7 @@ use crate::processing::processor::trakt::process_trakt_categories_for_target; use crate::repository::playlist_repository::persist_playlist; use crate::tuliprox_error::{get_errors_notify_message, notify_err, TuliproxError, TuliproxErrorKind}; use crate::utils::debug_if_enabled; -use crate::utils::default_as_default; +use shared::utils::default_as_default; use deunicode::deunicode; use log::{debug, error, info, log_enabled, trace, warn, Level}; use std::time::Instant; diff --git a/backend/src/processing/processor/trakt.rs b/backend/src/processing/processor/trakt.rs index 97d37fa61..bfcf0170e 100644 --- a/backend/src/processing/processor/trakt.rs +++ b/backend/src/processing/processor/trakt.rs @@ -3,10 +3,11 @@ use crate::model::{ConfigTarget, PlaylistGroup, PlaylistItem}; use shared::model::{FieldGetAccessor, FieldSetAccessor, XtreamCluster}; use crate::model::{TraktConfig, TraktContentType, TraktListConfig, TraktListItem, TraktMatchItem, TraktMatchResult}; use crate::tuliprox_error::TuliproxError; -use crate::utils::trakt::client::TraktClient; +use crate::utils::trakt::TraktClient; use crate::utils::trakt::extract_year_from_title; use crate::utils::trakt::normalize_title_for_matching; -use crate::utils::{get_u32_from_serde_value, CONSTANTS}; +use crate::utils::{get_u32_from_serde_value}; +use shared::utils::{CONSTANTS}; use crate::utils::{trace_if_enabled, with}; use log::{debug, info, trace, warn}; use std::sync::Arc; diff --git a/backend/src/repository/strm_repository.rs b/backend/src/repository/strm_repository.rs index 2db20989e..f40fcd394 100644 --- a/backend/src/repository/strm_repository.rs +++ b/backend/src/repository/strm_repository.rs @@ -9,7 +9,8 @@ use crate::repository::bplustree::BPlusTree; use crate::repository::storage::{ensure_target_storage_path, get_input_storage_path}; use crate::repository::storage_const; use crate::repository::xtream_repository::{xtream_get_record_file_path, InputVodInfoRecord}; -use crate::utils::{hash_bytes, ExportStyleConfig, CONSTANTS}; +use crate::utils::{hash_bytes}; +use shared::utils::{ExportStyleConfig, CONSTANTS}; use crate::utils::FileReadGuard; use crate::utils::request::extract_extension_from_url; use chrono::Datelike; diff --git a/backend/src/tools/lru_cache.rs b/backend/src/tools/lru_cache.rs index 5d1002c69..449abece5 100644 --- a/backend/src/tools/lru_cache.rs +++ b/backend/src/tools/lru_cache.rs @@ -1,5 +1,5 @@ use crate::utils::{hash_string_as_hex, traverse_dir}; -use crate::utils::human_readable_byte_size; +use shared::utils::human_readable_byte_size; use log::{debug, error, info, trace}; use std::collections::{HashMap, VecDeque}; use std::fs; diff --git a/backend/src/utils/file/config_reader.rs b/backend/src/utils/file/config_reader.rs index b4cb5ee05..8e1cee9f8 100644 --- a/backend/src/utils/file/config_reader.rs +++ b/backend/src/utils/file/config_reader.rs @@ -4,7 +4,7 @@ use crate::tuliprox_error::{create_tuliprox_error, info_err, to_io_error, Tulip use crate::utils::{open_file, EnvResolvingReader}; use crate::utils::{file_reader}; use crate::utils::sys_utils::exit; -use crate::utils::CONSTANTS; +use shared::utils::CONSTANTS; use chrono::Local; use log::{error, info, warn}; use serde::Serialize; diff --git a/backend/src/utils/file/file_utils.rs b/backend/src/utils/file/file_utils.rs index b48de93d4..0e9ac14fc 100644 --- a/backend/src/utils/file/file_utils.rs +++ b/backend/src/utils/file/file_utils.rs @@ -7,7 +7,7 @@ use std::{env, fs}; use crate::tuliprox_error::str_to_io_error; use crate::utils::debug_if_enabled; -use crate::utils::{API_PROXY_FILE, CONFIG_FILE, CONFIG_PATH, MAPPING_FILE, SOURCE_FILE, USER_FILE}; +use shared::utils::{API_PROXY_FILE, CONFIG_FILE, CONFIG_PATH, MAPPING_FILE, SOURCE_FILE, USER_FILE}; use log::{debug, error}; use path_clean::PathClean; diff --git a/backend/src/utils/mod.rs b/backend/src/utils/mod.rs index c00abeaae..8d5c730bf 100644 --- a/backend/src/utils/mod.rs +++ b/backend/src/utils/mod.rs @@ -1,6 +1,4 @@ -mod string_utils; mod json_utils; -mod size_utils; mod sys_utils; mod hash_utils; mod compression; @@ -8,7 +6,6 @@ mod file; mod network; mod bincode_utils; mod crypto_utils; -mod constants; mod step_measure; pub mod logging; pub mod trakt; @@ -59,9 +56,7 @@ pub use debug_if_enabled; pub use trace_if_enabled; pub use with; -pub use self::string_utils::*; pub use self::json_utils::*; -pub use self::size_utils::*; pub use self::sys_utils::*; pub use self::hash_utils::*; pub use self::compression::*; @@ -69,5 +64,4 @@ pub use self::file::*; pub use self::network::*; pub use self::bincode_utils::*; pub use self::crypto_utils::*; -pub use self::constants::*; pub use self::step_measure::*; diff --git a/backend/src/utils/network/request.rs b/backend/src/utils/network/request.rs index f99e4b7ae..73bab66ed 100644 --- a/backend/src/utils/network/request.rs +++ b/backend/src/utils/network/request.rs @@ -22,13 +22,10 @@ use crate::model::{ConfigInput, InputFetchMethod}; use crate::repository::storage::{get_input_storage_path}; use crate::repository::storage_const; use crate::utils::compression::compression_utils::{is_deflate, is_gzip}; -use crate::utils::{debug_if_enabled, filter_request_header, short_hash}; +use crate::utils::{debug_if_enabled, short_hash}; +use shared::utils::{filter_request_header}; use crate::utils::{get_file_path, persist_file}; -use crate::utils::{CONSTANTS, DASH_EXT, DASH_EXT_FRAGMENT, DASH_EXT_QUERY, ENCODING_DEFLATE, ENCODING_GZIP, HLS_EXT, HLS_EXT_FRAGMENT, HLS_EXT_QUERY}; - -pub const fn bytes_to_megabytes(bytes: u64) -> u64 { - bytes / 1_048_576 -} +use shared::utils::{CONSTANTS, DASH_EXT, DASH_EXT_FRAGMENT, DASH_EXT_QUERY, ENCODING_DEFLATE, ENCODING_GZIP, HLS_EXT, HLS_EXT_FRAGMENT, HLS_EXT_QUERY}; pub async fn get_input_epg_content_as_file(client: Arc, input: &ConfigInput, working_dir: &str, url_str: &str, persist_filepath: Option) -> Result { debug_if_enabled!("getting input epg content working_dir: {}, url: {}", working_dir, sanitize_sensitive_info(url_str)); diff --git a/backend/src/utils/sys_utils.rs b/backend/src/utils/sys_utils.rs index e6b4a7fe4..a683a4f5c 100644 --- a/backend/src/utils/sys_utils.rs +++ b/backend/src/utils/sys_utils.rs @@ -7,7 +7,7 @@ macro_rules! exit { } pub use exit; #[cfg(target_os = "linux")] -use crate::utils::CONSTANTS; +use shared::utils::CONSTANTS; #[cfg(target_os = "linux")] fn get_memory_usage_linux() -> std::io::Result { diff --git a/backend/src/utils/trakt/mod.rs b/backend/src/utils/trakt/mod.rs index fb51ced11..41db3b443 100644 --- a/backend/src/utils/trakt/mod.rs +++ b/backend/src/utils/trakt/mod.rs @@ -1,9 +1,12 @@ // Common utilities for Trakt functionality -pub mod client; -pub mod errors; +mod client; +mod errors; + +pub use self::client::*; +pub use self::errors::*; use deunicode::deunicode; -use crate::utils::CONSTANTS; +use shared::utils::CONSTANTS; /// Normalize title for matching - optimized version with reduced allocations pub fn normalize_title_for_matching(title: &str) -> String { diff --git a/shared/Cargo.toml b/shared/Cargo.toml index eb50051cd..2433de59e 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" [dependencies] bitflags = "2.9.1" serde = { version = "1.0.219", features = ["derive"] } +rand = "0.9.1" +regex = "1.11.1" diff --git a/backend/src/utils/constants.rs b/shared/src/utils/constants.rs similarity index 100% rename from backend/src/utils/constants.rs rename to shared/src/utils/constants.rs diff --git a/shared/src/utils/mod.rs b/shared/src/utils/mod.rs index 4dc975585..c02c842ed 100644 --- a/shared/src/utils/mod.rs +++ b/shared/src/utils/mod.rs @@ -1,5 +1,11 @@ mod default_utils; mod time_utils; +mod string_utils; +mod size_utils; +mod constants; pub use self::default_utils::*; pub use self::time_utils::*; +pub use self::string_utils::*; +pub use self::size_utils::*; +pub use self::constants::*; diff --git a/backend/src/utils/size_utils.rs b/shared/src/utils/size_utils.rs similarity index 97% rename from backend/src/utils/size_utils.rs rename to shared/src/utils/size_utils.rs index 3b4e3efb9..5e8d39d26 100644 --- a/backend/src/utils/size_utils.rs +++ b/shared/src/utils/size_utils.rs @@ -1,5 +1,10 @@ use std::str::FromStr; +# [inline] +pub const fn bytes_to_megabytes(bytes: u64) -> u64 { + bytes / 1_048_576 +} + // pub fn parse_size_base_10(size_str: &str) -> Result { // let units = [ // ("KB", 1_000u64), // Kilobytes (Base 10) diff --git a/backend/src/utils/string_utils.rs b/shared/src/utils/string_utils.rs similarity index 72% rename from backend/src/utils/string_utils.rs rename to shared/src/utils/string_utils.rs index 4d97af63c..c866c0e6b 100644 --- a/backend/src/utils/string_utils.rs +++ b/shared/src/utils/string_utils.rs @@ -1,20 +1,5 @@ use rand::Rng; -// other implementations like calculating text_distance on all titles took too much time -// we keep it now as simple as possible and less memory intensive. -pub fn get_title_group(text: &str) -> String { - let alphabetic_only: String = text.chars().map(|c| if c.is_alphanumeric() { c } else { ' ' }).collect(); - let parts = alphabetic_only.split_whitespace(); - let mut combination = String::new(); - for p in parts { - combination = format!("{combination} {p}").trim().to_string(); - if combination.len() > 2 { - return combination; - } - } - text.to_string() -} - pub trait Capitalize { fn capitalize(&self) -> String; } @@ -70,7 +55,7 @@ pub fn get_non_empty_str<'a>(first: &'a str, second: &'a str, third: &'a str) -> #[cfg(test)] mod test { use std::collections::HashSet; - use crate::utils::{generate_random_string, Capitalize}; + use super::generate_random_string; #[test] fn test_generate_random_string() {