Files
tuliprox/src/api/main_api.rs
T

127 lines
3.9 KiB
Rust
Raw Normal View History

2021-10-07 20:11:54 +02:00
use std::path::PathBuf;
use std::str::FromStr;
2023-09-26 19:41:02 +02:00
use std::time::Duration;
2021-10-07 20:11:54 +02:00
use actix_cors::Cors;
use actix_files::NamedFile;
use actix_web::{App, get, HttpRequest, HttpResponse, HttpServer, web};
use actix_web::middleware::Logger;
2023-09-26 19:53:45 +02:00
use actix_web::web::Data;
use chrono::Local;
use cron::Schedule;
use log::error;
2021-10-07 20:11:54 +02:00
2023-10-08 19:54:59 +02:00
use crate::{exit, playlist_processor};
use crate::api::model_api::{AppState, PlaylistRequest, ServerConfig};
use crate::api::xtream_player_api::xtream_player_api;
use crate::download::get_m3u_playlist;
use crate::model::config::{Config, ConfigInput, InputType, ProcessTargets};
2021-10-07 20:11:54 +02:00
#[get("/")]
async fn index(
_req: HttpRequest,
_app_state: web::Data<AppState>,
) -> std::io::Result<NamedFile> {
let path: PathBuf = [_app_state.config.api.web_root.clone(), String::from("index.html")].iter().collect();
2023-05-03 17:46:39 +02:00
NamedFile::open(path)
2021-10-07 20:11:54 +02:00
}
pub(crate) async fn playlist(
req: web::Json<PlaylistRequest>,
_app_state: web::Data<AppState>,
) -> HttpResponse {
2023-03-19 17:16:05 +01:00
// TODO refactor this
let input = ConfigInput {
id: 0,
2023-03-19 17:16:05 +01:00
input_type: InputType::M3u,
headers: Default::default(),
url: String::from(&req.url),
username: None,
password: None,
persist: None,
2023-03-19 17:16:05 +01:00
prefix: None,
suffix: None,
enabled: true,
};
2023-10-08 19:54:59 +02:00
let result = get_m3u_playlist(&_app_state.config, &input, &_app_state.config.working_dir);
2021-10-07 20:11:54 +02:00
HttpResponse::Ok().json(result)
}
pub(crate) async fn config(
_app_state: web::Data<AppState>,
) -> HttpResponse {
let sources: Vec<String> = _app_state.config.sources.iter()
.flat_map(|t| t.inputs.iter())
.map(|i| i.url.clone()).collect();
2021-10-07 20:11:54 +02:00
let result = ServerConfig {
sources
};
HttpResponse::Ok().json(result)
}
#[actix_web::main]
2023-10-08 19:54:59 +02:00
pub(crate) async fn start_server(cfg: Config, targets: ProcessTargets) -> futures::io::Result<()> {
2021-10-07 20:11:54 +02:00
let host = cfg.api.host.clone();
let port = cfg.api.port;
let web_dir = cfg.api.web_root.clone();
2021-10-15 16:59:20 +02:00
let web_dir_path = PathBuf::from(&web_dir);
if !web_dir_path.exists() || !web_dir_path.is_dir() {
2023-10-08 19:54:59 +02:00
exit!("web_root does not exists or is not an directory: {:?}", &web_dir_path);
2021-10-15 16:59:20 +02:00
}
2021-10-07 20:11:54 +02:00
let schedule = cfg.schedule.clone();
2023-09-26 19:41:02 +02:00
2023-09-26 19:53:45 +02:00
let shared_data = web::Data::new(AppState {
config: cfg,
targets,
});
2023-09-26 19:41:02 +02:00
// Scheduler
if let Some(expression) = schedule {
2023-09-26 19:53:45 +02:00
let cloned_data = shared_data.clone();
2023-09-26 19:41:02 +02:00
actix_rt::spawn(async move {
2023-09-26 19:53:45 +02:00
start_scheduler(&expression, cloned_data).await
2023-09-26 19:41:02 +02:00
});
}
// Web Server
2021-10-07 20:11:54 +02:00
HttpServer::new(move || App::new()
.wrap(Logger::default())
2021-10-07 20:11:54 +02:00
.wrap(Cors::default()
.supports_credentials()
.allow_any_origin()
.allowed_methods(vec!["GET", "POST", "OPTIONS", "HEAD"])
.allow_any_header()
.max_age(3600)
)
.app_data(shared_data.clone())
.service(
web::scope("/api/v1")
.route("/playlist", web::post().to(playlist))
.route("/config", web::get().to(config))
).service(xtream_player_api)
2021-10-07 20:11:54 +02:00
.service(index)
.service(actix_files::Files::new("/", web_dir.clone()))
)
.bind(format!("{}:{}", host, port))?
.run().await
//
// .service(actix_files::Files::new("/static", ".").show_files_listing())
2023-09-26 19:41:02 +02:00
}
2023-10-11 14:33:17 +02:00
async fn start_scheduler(expression: &str, data: Data<AppState>) -> ! {
2023-09-26 19:41:02 +02:00
let schedule = Schedule::from_str(expression).unwrap();
let offset = *Local::now().offset();
loop {
let mut upcoming = schedule.upcoming(offset).take(1);
actix_rt::time::sleep(Duration::from_millis(500)).await;
let local = &Local::now();
if let Some(datetime) = upcoming.next() {
if datetime.timestamp() <= local.timestamp() {
2023-10-11 14:33:17 +02:00
playlist_processor::process_sources((data.config).clone(), &data.targets);
2023-09-26 19:41:02 +02:00
}
}
}
2021-10-07 20:11:54 +02:00
}