main.rs 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. use actix_web::{HttpServer, web, App, middleware};
  2. use actix_cors::Cors;
  3. use http_error::HttpError;
  4. use sqlx::PgPool;
  5. use std::{env, sync::OnceLock};
  6. mod http_error;
  7. mod routes;
  8. mod controllers;
  9. mod models;
  10. mod logic;
  11. mod auth;
  12. static JWT_SECRET: OnceLock<String> = OnceLock::new();
  13. static STRIPE_KEY: OnceLock<String> = OnceLock::new();
  14. static TOKEN_PACK_PRICE: OnceLock<i32> = OnceLock::new();
  15. static TOKENS_PER_PACK: OnceLock<i32> = OnceLock::new();
  16. static STRIPE_WEBHOOK_SECRET: OnceLock<String> = OnceLock::new();
  17. static DEEPINFRA_TOKEN: OnceLock<String> = OnceLock::new();
  18. #[actix_web::main]
  19. async fn main() -> std::io::Result<()> {
  20. //Environment variables
  21. dotenvy::from_filename(".env").expect("Failed to load .env file");
  22. let port: u16 = env_var("PORT");
  23. let app_env: String = env_var("APP_ENV");
  24. let database_url: String = env_var("DATABASE_URL");
  25. JWT_SECRET.set(env_var("JWT_SECRET")).expect("Failed to set JWT");
  26. STRIPE_KEY.set(env_var("STRIPE_KEY")).expect("Failed to set Stripe key");
  27. TOKEN_PACK_PRICE.set(env_var("TOKEN_PACK_PRICE")).expect("Failed to set token pack price");
  28. TOKENS_PER_PACK.set(env_var("TOKENS_PER_PACK")).expect("Failed to set tokens per pack");
  29. STRIPE_WEBHOOK_SECRET.set(env_var("STRIPE_WEBHOOK_SECRET")).expect("Failed to set stripe webhook secret");
  30. DEEPINFRA_TOKEN.set(env_var("DEEPINFRA_TOKEN")).expect("Failed to set DeepInfra token");
  31. //Database
  32. let pool = PgPool::connect(&database_url)
  33. .await
  34. .expect("Failed to start Postgres");
  35. //Server
  36. HttpServer::new(move || {
  37. let cors = if app_env == "development" {
  38. Cors::default()
  39. .allowed_origin("http://localhost:5173")
  40. .allowed_methods(vec!["GET", "POST", "PUT", "PATCH", "DELETE"])
  41. .allow_any_header()
  42. .supports_credentials()
  43. } else {
  44. Cors::default()
  45. .allowed_origin_fn(|origin, _req| {
  46. let bytes = origin.as_bytes();
  47. bytes == b"http://localhost:5173" || bytes == b"https://chatrpg.leemorgan.dev"
  48. })
  49. .allowed_methods(vec!["GET", "POST", "PUT", "PATCH", "DELETE"])
  50. .allow_any_header()
  51. .supports_credentials()
  52. };
  53. App::new()
  54. .wrap(middleware::Compress::default())
  55. .wrap(cors)
  56. .app_data(
  57. web::JsonConfig::default().error_handler(|err, _req| {
  58. HttpError::JsonDeserializationError(err.to_string()).into()
  59. })
  60. )
  61. .app_data(web::Data::new(pool.clone()))
  62. .configure(routes::other::config)
  63. .configure(routes::user::config)
  64. .configure(routes::webhook::config)
  65. .configure(routes::game::game::config)
  66. .configure(routes::game::character::config)
  67. .configure(routes::game::session::config)
  68. .configure(routes::game::turn::config)
  69. })
  70. .bind(("0.0.0.0", port))
  71. .expect("Failed to bind to port")
  72. .run()
  73. .await
  74. .expect("Failed to start server");
  75. Ok(())
  76. }
  77. fn env_var<T: std::str::FromStr>(key: &str) -> T
  78. where
  79. T::Err: std::fmt::Debug,
  80. {
  81. env::var(key)
  82. .unwrap_or_else(|_| panic!("Environment variable {} not set", key))
  83. .parse()
  84. .unwrap_or_else(|_| panic!("{} could not be parsed", key))
  85. }