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
49pub const MIGRATIONS: EmbeddedMigrations = diesel_migrations::embed_migrations!("migrations");
51
52fn run_migration(conn: &mut MysqlConnection) {
54 conn.run_pending_migrations(MIGRATIONS).unwrap();
55}
56
57#[actix_web::main]
65async fn main() -> std::io::Result<()> {
66 log4rs::init_file("log4rs.yaml", Default::default()).unwrap();
67 info!("Application started");
68 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#[get("/")]
140pub async fn health_check() -> impl Responder {
141 HttpResponse::Ok().body("API online")
142}
143
144pub 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
172pub 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}