main.rs 3.0 KB

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