f14592ead05ce4eb8f242cc399e9036911c4bfff
[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, Responder, middleware, App, HttpServer, web::Query };
9 use askama::Template;
10
11 use std::{ /*sync::Mutex, */fs::File, env::args, 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 #[derive(Deserialize)]
30 pub struct Request {
31 m: Option<String>
32 }
33
34 const VALUE_UNKNOWN: &str = "-";
35
36 #[get("/")]
37 async fn main_page(/*key_shared: web::Data<Mutex<String>>,*/ query: Query<Request>) -> impl Responder {
38 //let key = key_shared.lock().unwrap();
39
40 match valheim_controller::get_valheim_executable_information() {
41 Some(info) =>
42 MainTemplate {
43 text_status: String::from("Valheim server is up and running :)"),
44 memory: info.format_memory(),
45 load_average: info.format_load_average(),
46 uptime: info.format_uptime(),
47 world_size: info.format_world_size()
48 },
49 None => {
50 let value_unknown = String::from(VALUE_UNKNOWN);
51 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() }
52 }
53 }
54
55 /*
56
57 let m =
58 if valheim_controller::is_valheim_running() { String::from("Valheim server is up and running") } else { String::from("Valheim server is down :(") };
59
60 MainTemplate { sentence: m }
61 */
62 }
63
64 #[derive(Debug, Deserialize, Serialize)]
65 struct Config {
66 port: u16
67 }
68
69 const DEFAULT_CONFIG: Config = Config { port: 8082 };
70
71 fn get_exe_name() -> String {
72 let first_arg = std::env::args().next().unwrap();
73 let sep: &[_] = &['\\', '/'];
74 first_arg[first_arg.rfind(sep).unwrap()+1..].to_string()
75 }
76
77 fn load_config() -> Config {
78 // unwrap_or_else(|_| panic!("Failed to open configuration file {}", consts::FILE_CONF));
79 match File::open(consts::FILE_CONF) {
80 Ok(file) => from_reader(file).unwrap_or_else(|_| panic!("Failed to open configuration file {}", consts::FILE_CONF)),
81 Err(_) => {
82 let mut file = File::create(consts::FILE_CONF) .unwrap();
83 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.
84 DEFAULT_CONFIG
85 }
86 }
87 }
88
89 #[actix_rt::main]
90 async fn main() -> std::io::Result<()> {
91
92 if process_args() { return Ok(()) }
93
94 println!("Starting Valheim Admin as web server...");
95
96 let config = load_config();
97
98 println!("Configuration: {:?}", config);
99
100 let mut listenfd = ListenFd::from_env();
101 let mut server =
102 HttpServer::new(
103 move || {
104 App::new()
105 // .app_data(key_shared.clone())
106 .wrap(middleware::Compress::default())
107 .wrap(middleware::Logger::default())
108 .service(main_page)
109 .service(fs::Files::new("/static", "static").show_files_listing())
110 }
111 );
112
113 server =
114 if let Some(l) = listenfd.take_tcp_listener(0).unwrap() {
115 server.listen(l).unwrap()
116 } else {
117 server.bind(&format!("0.0.0.0:{}", config.port)).unwrap()
118 };
119
120 server.run().await
121 }
122
123 fn process_args() -> bool {
124 fn print_usage() {
125 println!("Usage:");
126 println!(" {} [--help] [--status]", get_exe_name());
127 }
128
129 let args: Vec<String> = args().collect();
130
131 if args.iter().any(|arg| arg == "--help") {
132 print_usage();
133 return true
134 } else if args.iter().any(|arg| arg == "--status") {
135 println!("{:?}", valheim_controller::get_valheim_executable_information());
136 return true
137 }
138
139 false
140 }