Skip to main content

hvz/
main.rs

1use std::env;
2
3use actix_cors::Cors;
4use actix_web::{App, HttpResponse, HttpServer, Responder, get, middleware};
5use diesel::{Connection, MysqlConnection};
6use diesel_migrations::{EmbeddedMigrations, MigrationHarness};
7use dotenv::dotenv;
8use log::info;
9
10pub mod admin;
11pub mod endpoints;
12use endpoints::{
13    admin::revive_zombie,
14    admin::{
15        corpsify, cure_zombie, feed_player, feed_players, get_all_players, get_logs, inject_sql,
16        kill_all_not_at_checkpoint, player_at_checkpoint, player_count, recover_password,
17        revive_human,
18    },
19    interactions::{get_interactions, leaderboard, zombie_tree},
20    notifications::{send_notification, subscribe, unsubscribe},
21    player::{
22        change_password, delete_player, edit_player, get_other_player, get_pfp, get_player,
23        get_users, login, logout, new_player, pfp, set_pfp,
24    },
25    zombie::{hunt, next_feeding, starvation},
26};
27
28pub mod groupchat;
29pub mod interactions;
30pub mod messages;
31pub mod notifications;
32pub mod player;
33pub mod schema;
34pub mod settings;
35pub mod time;
36use settings::UPLOAD_PATH;
37pub mod token;
38pub mod zombie;
39use zombie::Zombie;
40
41use crate::{
42    endpoints::{
43        admin::{zombies_add_day, zombify}, player::{get_username, remove_pfp}, settings::{
44            get_checkpoint, get_edition, get_maintenance, set_checkpoint, set_maintenance, start_edition, stop_edition,
45        },
46    }, settings::Settings,
47};
48
49/// Embedded migrations for the application.
50pub const MIGRATIONS: EmbeddedMigrations = diesel_migrations::embed_migrations!("migrations");
51
52/// Runs the pending database migrations.
53fn run_migration(conn: &mut MysqlConnection) {
54    conn.run_pending_migrations(MIGRATIONS).unwrap();
55}
56
57/// Main entry point for the application.
58///
59/// This function initializes the server and routes for the application.
60///
61/// It spawns the zombie death monitor as a background task that runs until the program terminates.
62///
63/// It also creates the necessary directories for file uploads.
64#[actix_web::main]
65async fn main() -> std::io::Result<()> {
66    log4rs::init_file("log4rs.yaml", Default::default()).unwrap();
67    info!("Application started");
68    // Spawn the zombie death monitor as a background task that runs until the program terminates.
69    actix_rt::spawn(async {
70        Zombie::monitor_zombie_death().await;
71    });
72    async_fs::create_dir_all(UPLOAD_PATH).await?;
73    Settings::init_settings().await?;
74
75    let host = env::var("API_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
76    let port = 8080;
77    HttpServer::new(|| {
78        let cors = Cors::default()
79            .allow_any_origin()
80            .allow_any_method()
81            .allow_any_header()
82            .max_age(3600);
83        App::new()
84            .wrap(cors)
85            .wrap(middleware::Logger::default())
86            .service(health_check)
87            .service(zombify)
88            .service(corpsify)
89            .service(cure_zombie)
90            .service(feed_player)
91            .service(feed_players)
92            .service(zombies_add_day)
93            .service(get_all_players)
94            .service(get_logs)
95            .service(inject_sql)
96            .service(kill_all_not_at_checkpoint)
97            .service(player_at_checkpoint)
98            .service(player_count)
99            .service(recover_password)
100            .service(revive_human)
101            .service(revive_zombie)
102            .service(change_password)
103            .service(delete_player)
104            .service(edit_player)
105            .service(get_pfp)
106            .service(remove_pfp)
107            .service(get_other_player)
108            .service(get_username)
109            .service(pfp)
110            .service(get_player)
111            .service(get_users)
112            .service(login)
113            .service(logout)
114            .service(new_player)
115            .service(set_pfp)
116            .service(hunt)
117            .service(next_feeding)
118            .service(starvation)
119            .service(get_interactions)
120            .service(leaderboard)
121            .service(zombie_tree)
122            .service(get_edition)
123            .service(start_edition)
124            .service(stop_edition)
125            .service(get_maintenance)
126            .service(set_maintenance)
127            .service(get_checkpoint)
128            .service(set_checkpoint)
129            .service(subscribe)
130            .service(unsubscribe)
131            .service(send_notification)
132    })
133    .bind((host, port))?
134    .run()
135    .await
136}
137
138/// Performs a health check on the base url of the API.
139#[get("/")]
140pub async fn health_check() -> impl Responder {
141    HttpResponse::Ok().body("API online")
142}
143
144/// This function establishes a connection to the MySQL database.
145///
146/// Note that the connection has to be set in a configuration file called `.env`, with the following format:
147///
148/// ```sh
149/// DATABASE_URL=mysql://username:password@localhost/database_name
150/// ```
151///
152/// # Returns
153/// A `MysqlConnection` object representing the connection to the database.
154///
155/// # Usage
156/// This function is used to establish a connection to the MySQL database. It is usually called with:
157///
158/// ```
159/// let connection = &mut establish_connection();
160/// ```
161pub fn establish_connection() -> MysqlConnection {
162    info!("Retrieving database URL from .env file");
163
164    dotenv().ok();
165
166    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
167
168    MysqlConnection::establish(&database_url)
169        .unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
170}
171
172/// Retrieves the VAPID keys from environment variables.
173///
174/// # Returns
175/// A `Result` containing a tuple of the VAPID private key, public key, and email.
176///
177/// # Usage
178/// This function is used to retrieve the VAPID keys from environment variables. It is usually called with:
179///
180/// ```
181/// let (vapid_private_key, vapid_public_key, vapid_email) = vapid_keys().unwrap();
182/// ```
183pub fn vapid_keys() -> Result<(String, String, String), String> {
184    let vapid_private_key =
185        std::env::var("VAPID_PRIVATE_KEY").expect("VAPID private key is missing.");
186    let vapid_public_key = std::env::var("VAPID_PUBLIC_KEY").expect("VAPID public key is missing.");
187    let vapid_email = std::env::var("VAPID_EMAIL").expect("VAPID email is missing.");
188
189    Ok((vapid_private_key, vapid_public_key, vapid_email))
190}