mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-17 04:09:03 +02:00
Le serveur Dart (bin/) est remplacé par un serveur Rust (server/) : tokio + axum, reqwest/rustls, SQLite embarqué via rusqlite. Même API, mêmes routes et mêmes réponses : le front Flutter ne change pas. La base de production est reprise telle quelle : schéma, migrations et formats de dates (DateTime.toIso8601String de Dart) sont reproduits à l'identique, les sessions et hachages existants restent valides. Comportement conservé : cascade de routage, anti-SSRF, logs masqués, rate limits, transcodage HLS/turbo.ts avec repli GPU, quotas fournisseur, enregistrements (reprise, relances, fusion), season passes, EPG, logos de repli, arrêt gracieux sur SIGTERM. Tests Dart portés (132 tests Rust) ; la CI exécute fmt, test et clippy -D warnings, l'image Docker compile le serveur dans un étage rust:1.98.1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
2.2 KiB
Rust
66 lines
2.2 KiB
Rust
//! État partagé du serveur.
|
|
|
|
use crate::api::epg::EpgApi;
|
|
use crate::api::proxy::ProxyHandler;
|
|
use crate::api::streaming::Streaming;
|
|
use crate::db::AppDatabase;
|
|
use crate::http::Req;
|
|
use crate::models::PlaylistConfig;
|
|
use crate::server::RateLimiter;
|
|
use crate::services::cleanup::CleanupService;
|
|
use crate::services::logo_catalog::LogoCatalog;
|
|
use crate::services::recording_scheduler::RecordingScheduler;
|
|
use std::collections::HashMap;
|
|
use std::sync::Arc;
|
|
|
|
pub struct AppState {
|
|
pub db: Arc<AppDatabase>,
|
|
pub web_path: String,
|
|
/// Points d'entrée réécrits avec `?v=<empreinte>` (asset_versioning).
|
|
pub versioned: HashMap<String, String>,
|
|
/// Client HTTP qui suit les redirections.
|
|
pub http: reqwest::Client,
|
|
/// Client HTTP sans suivi des redirections (revalidées à la main).
|
|
pub http_manual: reqwest::Client,
|
|
pub scheduler: Arc<RecordingScheduler>,
|
|
pub streaming: Arc<Streaming>,
|
|
pub proxy: ProxyHandler,
|
|
pub epg: EpgApi,
|
|
pub logo_catalog: Arc<LogoCatalog>,
|
|
pub cleanup: Arc<CleanupService>,
|
|
pub rate_limit: RateLimiter,
|
|
pub login_rate_limit: RateLimiter,
|
|
pub allowed_origin: Option<String>,
|
|
pub trusted_proxies: Vec<String>,
|
|
}
|
|
|
|
impl AppState {
|
|
/// Playlist Xtream de la requête : la première playlist de l'utilisateur
|
|
/// authentifié ; à défaut (proxy, streaming), celle du premier
|
|
/// utilisateur de la base.
|
|
pub fn get_playlist(&self, req: &Req) -> Option<PlaylistConfig> {
|
|
let playlist = match &req.user {
|
|
Some(user) => self.db.get_playlists(&user.id).into_iter().next(),
|
|
None => {
|
|
let users = self.db.get_all_users();
|
|
users
|
|
.first()
|
|
.and_then(|u| self.db.get_playlists(&u.id).into_iter().next())
|
|
}
|
|
};
|
|
match playlist {
|
|
Some(p) => Some(PlaylistConfig {
|
|
dns: p.server_url,
|
|
username: p.username,
|
|
password: p.password,
|
|
}),
|
|
None => {
|
|
println!("[getPlaylist] WARNING: No playlist found, returning null");
|
|
None
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub type SharedState = Arc<AppState>;
|