Put the world path in the configuration file
[valheim_web.git] / backend / src / main.rs
1
2 extern crate listenfd;
3 extern crate askama;
4
5 // use futures::sink::With;
6 use listenfd::ListenFd;
7 use actix_files as fs;
8 use actix_web::{ get, web, Responder, middleware, App, HttpServer };
9 use askama::Template;
10
11 use std::{ sync::Mutex, env::args, fs::File, io::prelude::* };
12 use ron::{ de::from_reader, ser::{ to_string_pretty, PrettyConfig } };
13 use serde::{ Deserialize, Serialize };
14
15 mod consts;
16 mod tests;
17 mod valheim_controller;
18
19 #[derive(Template)]
20 #[template(path = "main.html")]
21 struct MainTemplate {
22 text_status: String,
23 memory: String,
24 load_average: String,
25 uptime: String,
26 world_size: String
27 }
28
29 const VALUE_UNKNOWN: &str = "-";
30
31 #[get("/")]
32 async fn main_page(config_shared: web::Data<Mutex<Config>>) -> impl Responder {
33 let config = config_shared.lock().unwrap();
34
35 match valheim_controller::get_valheim_executable_information(&config.world_path) {
36 Some(info) =>
37 MainTemplate {
38 text_status: String::from("Valheim server is up and running :)"),
39 memory: info.format_memory(),
40 load_average: info.format_load_average(),
41 uptime: info.format_uptime(),
42 world_size: info.format_world_size()
43 },
44 None => {
45 let value_unknown = String::from(VALUE_UNKNOWN);
46 MainTemplate { text_status: String::from("Valheim server is down :("), memory: value_unknown.clone(), load_average: value_unknown.clone(), uptime: value_unknown.clone(), world_size: value_unknown.clone() }
47 }
48 }
49 }
50
51 #[derive(Debug, Deserialize, Serialize)]
52 struct Config {
53 port: u16,
54 #[serde(default = "empty_string")]
55 world_path: String,
56 }
57
58 fn empty_string() -> String { "".to_string() }
59
60 impl Config {
61 fn default() -> Self {
62 Config { port: 8082, world_path: String::from("") }
63 }
64 }
65
66 fn get_exe_name() -> String {
67 let first_arg = std::env::args().next().unwrap();
68 let sep: &[_] = &['\\', '/'];
69 first_arg[first_arg.rfind(sep).unwrap()+1..].to_string()
70 }
71
72 fn load_config() -> Config {
73 // unwrap_or_else(|_| panic!("Failed to open configuration file {}", consts::FILE_CONF));
74 match File::open(consts::FILE_CONF) {
75 Ok(file) => from_reader(file).unwrap_or_else(|_| panic!("Failed to open configuration file {}", consts::FILE_CONF)),
76 Err(_) => {
77 let mut file = File::create(consts::FILE_CONF) .unwrap();
78 let default_config = Config::default();
79 file.write_all(to_string_pretty(&default_config, PrettyConfig::new()).unwrap().as_bytes()).unwrap(); // We do not use 'to_writer' because it can't pretty format the output.
80 default_config
81 }
82 }
83 }
84
85 #[actix_rt::main]
86 async fn main() -> std::io::Result<()> {
87 let config = load_config();
88 let port = config.port;
89
90 if process_args(&config) { return Ok(()) }
91
92 println!("Starting Valheim Admin as web server...");
93
94 println!("Configuration: {:?}", config);
95
96 let config_shared = web::Data::new(Mutex::new(config));
97
98 let mut listenfd = ListenFd::from_env();
99 let mut server =
100 HttpServer::new(
101 move || {
102 App::new()
103 .app_data(config_shared.clone())
104 .wrap(middleware::Compress::default())
105 .wrap(middleware::Logger::default())
106 .service(main_page)
107 .service(fs::Files::new("/static", "static").show_files_listing())
108 }
109 );
110
111 server =
112 if let Some(l) = listenfd.take_tcp_listener(0).unwrap() {
113 server.listen(l).unwrap()
114 } else {
115 server.bind(&format!("0.0.0.0:{}", port)).unwrap()
116 };
117
118 server.run().await
119 }
120
121 fn process_args(config: &Config) -> bool {
122 fn print_usage() {
123 println!("Usage:");
124 println!(" {} [--help] [--status]", get_exe_name());
125 }
126
127 let args: Vec<String> = args().collect();
128
129 if args.iter().any(|arg| arg == "--help") {
130 print_usage();
131 return true
132 } else if args.iter().any(|arg| arg == "--status") {
133 println!("{:?}", valheim_controller::get_valheim_executable_information(&config.world_path));
134 return true
135 }
136
137 false
138 }