#![warn(unused_extern_crates)] #![allow(non_snake_case)] use std::{env, thread}; use diesel::{ SqliteConnection, r2d2::{self, ConnectionManager}, }; use dotenvy::dotenv; use ntex::web; use ntex_files as fs; mod api; mod db; mod models; mod providers; mod proxies; mod proxy; mod schema; mod status; mod util; mod videos; type DbPool = r2d2::Pool>; // #[macro_use(c)] // extern crate cute; #[ntex::main] async fn main() -> std::io::Result<()> { // std::env::set_var("RUST_BACKTRACE", "1"); dotenv().ok(); // Enable request logging if std::env::var("RUST_LOG").is_err() { unsafe { std::env::set_var("RUST_LOG", "warn"); } } env_logger::init(); // You need this to actually see logs crate::flow_debug!( "startup begin rust_log={} debug_compiled={}", std::env::var("RUST_LOG").unwrap_or_else(|_| "unset".to_string()), cfg!(feature = "debug") ); // set up database connection pool let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL"); let manager = ConnectionManager::::new(connspec.clone()); let pool = r2d2::Pool::builder() .build(manager) .expect("Failed to create pool."); crate::flow_debug!( "database pool ready database_url={}", crate::util::flow_debug::preview(&connspec, 96) ); let mut requester = util::requester::Requester::new(); let proxy_enabled = env::var("PROXY").unwrap_or("0".to_string()) != "0".to_string(); requester.set_proxy(proxy_enabled); crate::flow_debug!("requester initialized proxy_enabled={}", proxy_enabled); let cache: util::cache::VideoCache = crate::util::cache::VideoCache::new() .max_size(100_000) .to_owned(); crate::flow_debug!("video cache initialized max_size=100000"); let _ = providers::configure_runtime_validation(pool.clone(), cache.clone(), requester.clone()); thread::spawn(move || { crate::flow_debug!("provider init thread spawned"); // Create a tiny runtime just for these async tasks let rt = tokio::runtime::Builder::new_current_thread() .enable_all() .build() .expect("build tokio runtime"); rt.block_on(async move { crate::flow_debug!("provider init begin"); providers::init_providers_now(); crate::flow_debug!("provider init complete"); }); }); crate::flow_debug!("http server binding addr=0.0.0.0:18080 workers=8"); web::HttpServer::new(move || { web::App::new() .state(pool.clone()) .state(cache.clone()) .state(requester.clone()) .wrap(web::middleware::Logger::default()) .service(web::scope("/api").configure(api::config)) .service(web::scope("/proxy").configure(proxy::config)) .service( web::resource("/").route(web::get().to(|req: web::HttpRequest| async move { let host = match std::env::var("DOMAIN") { Ok(d) => d, Err(_) => req.connection_info().host().to_string(), }; let source_forward_header = format!("hottub://source?url={}", host); web::HttpResponse::Found() .header("Location", source_forward_header) .finish() })), ) .service(fs::Files::new("/", "static").index_file("index.html")) }) .workers(8) // .bind_openssl(("0.0.0.0", 18080), builder)? .bind(("0.0.0.0", 18080))? .run() .await }