use std::time::{SystemTime, UNIX_EPOCH};
use tokio::task::JoinHandle;
use crate::error::Result;
pub mod fs;
pub mod http;
pub mod network;
pub mod platform;
pub mod subtitle;
pub mod validation;
pub use fs::*;
pub use network::{retry, url_expiry};
pub use platform::Platform;
pub use subtitle::subtitle_converter::convert_subtitle;
pub use subtitle::subtitle_validator::{ValidationResult, is_format_compatible, validate_subtitle};
pub use url_expiry::{ExpiryConfig, UrlStatus, check_download_error, should_refresh_url};
pub fn to_owned(vec: Vec<impl AsRef<str>>) -> Vec<String> {
vec.into_iter().map(|s| s.as_ref().to_owned()).collect()
}
pub fn find_executable(name: impl AsRef<str>) -> String {
let platform = Platform::detect();
let name_str = name.as_ref();
match platform {
Platform::Windows => format!("{}.exe", name_str),
_ => name_str.to_string(),
}
}
pub async fn await_two<T: std::fmt::Debug>(
first: JoinHandle<Result<T>>,
second: JoinHandle<Result<T>>,
) -> Result<(T, T)> {
tracing::debug!("⚙️ Awaiting two futures");
let (first_result, second_result) = tokio::try_join!(first, second)?;
let first = first_result?;
let second = second_result?;
tracing::debug!("✅ Both futures completed successfully");
Ok((first, second))
}
pub async fn await_all<T, I>(handles: I) -> Result<Vec<T>>
where
I: IntoIterator<Item = JoinHandle<Result<T>>> + std::fmt::Debug,
T: Send + 'static,
{
tracing::debug!("⚙️ Awaiting multiple futures");
let results = futures_util::future::try_join_all(handles).await?;
let result_vec: Result<Vec<T>> = results.into_iter().collect();
if let Ok(ref vec) = result_vec {
tracing::debug!(completed_count = vec.len(), "✅ All futures completed successfully");
}
result_vec
}
pub fn current_timestamp() -> i64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs() as i64
}
pub fn is_expired(cached_at: i64, ttl: u64) -> bool {
let now = current_timestamp();
(now - cached_at) > ttl as i64
}