use actix_web::{cookie::Cookie, get, web::Data, App, HttpRequest, HttpResponse, HttpServer, Responder}; use env_logger::Env; use log::*; use dotenv::dotenv; use serde::Deserialize; use services::{gtfs_pull, trip_tracking::{self}}; use templates::ContentTemplate; use std::{fs::File, io::Read, sync::Arc, time::Instant}; use askama::Template; mod services; mod controllers; mod templates; pub struct AppState { gtfs_service: services::gtfs_pull::GtfsPullService, trip_tracking_service: services::trip_tracking::TripTrackingService } #[derive(Deserialize)] struct LocalStateQuery { pub widescreen: Option } pub async fn perform_action(req: HttpRequest, func: F) -> impl Responder where T: Template, F: Fn() -> Fut, Fut: Future>> + 'static { let start_time = Instant::now(); let mut enable_widescreen = true; if let Some(widescreen_set) = req.cookie("widescreen") { enable_widescreen = widescreen_set.value() == "true"; } let query_params = actix_web::web::Query::::from_query(req.query_string()).unwrap(); if let Some(set_widescreen) = query_params.widescreen { enable_widescreen = set_widescreen; } let x = func().await; match x { Ok(mut y) => { y.widescreen = enable_widescreen; y.load_time_ms = Some(start_time.elapsed().as_nanos()); let mut cookie = Cookie::new("widescreen", y.widescreen.to_string()); cookie.set_path("/"); HttpResponse::Ok() .cookie(cookie) .body(y.render().unwrap()) }, Err(_) => { HttpResponse::InternalServerError().body("Error") } } } #[get("/")] async fn get_index(req: HttpRequest) -> impl Responder { perform_action(req, move || async { Ok(templates::ContentTemplate { page_title: None, page_desc: None, content: templates::IndexTemplate {}, load_time_ms: None, widescreen: false }) }).await } #[tokio::main] async fn main() -> ::anyhow::Result<()> { env_logger::init_from_env(Env::default().default_filter_or("septastic_api=info")); dotenv().ok(); let version: &str = option_env!("CARGO_PKG_VERSION").expect("Expected package version"); info!("Starting the SEPTASTIC Server v{} (commit: {})", version, "NONE"); let mut file = File::open("./config.yaml")?; let mut file_contents = String::new(); file.read_to_string(&mut file_contents); let config_file = serde_yaml::from_str::(file_contents.as_str())?; let tt_service = services::trip_tracking::TripTrackingService::new().await; tt_service.start(); let svc = gtfs_pull::GtfsPullService::new(config_file); svc.start(); svc.wait_for_ready(); let state = Arc::new(AppState { gtfs_service: svc, trip_tracking_service: tt_service }); HttpServer::new(move || { App::new() .wrap(actix_cors::Cors::permissive()) .app_data(Data::new(state.clone())) .service(controllers::route::api_get_route) .service(controllers::route::api_get_schedule) .service(controllers::route::get_route) .service(controllers::route::get_routes_json) .service(controllers::route::get_routes_html) .service(controllers::route::get_directions) .service(get_index) .service(actix_files::Files::new("/assets", "./assets")) }) .bind(("0.0.0.0", 8080))? .run() .await?; Ok(()) }