1use super::HttpConfig;
2use super::{github, line_hook, upload};
3use crate::taskserver::Control;
4use actix_web::{HttpResponse, Responder, http::header::ContentType, web};
5use chrono::Local;
6use std::sync::atomic::{AtomicU32, Ordering};
7
8struct IndexState {
9 access_counter: AtomicU32,
10}
11
12pub(super) fn server_config() -> impl Fn(&mut web::ServiceConfig, &HttpConfig) + Clone {
13 let state = web::Data::new(IndexState {
14 access_counter: Default::default(),
15 });
16
17 move |cfg: &mut web::ServiceConfig, http_config: &HttpConfig| {
18 cfg.app_data(state.clone());
19 cfg.service(index_get);
20 if http_config.upload_enabled {
21 cfg.service(upload::index_get);
22 cfg.service(upload::index_post);
23 }
24 if http_config.ghhook_enabled {
25 cfg.service(github::index_get);
26 cfg.service(github::index_post);
27 }
28 if http_config.line_hook_enabled {
29 cfg.service(line_hook::index_get);
30 cfg.service(line_hook::index_post);
31 }
32 }
33}
34
35#[actix_web::get("/")]
36async fn index_get(state: web::Data<IndexState>, ctrl: web::Data<Control>) -> impl Responder {
37 let counter = state.access_counter.fetch_add(1, Ordering::Relaxed) + 1;
38
39 let sysinfo = ctrl.sysmods().sysinfo.lock().await;
40 let started = sysinfo.started;
41 let op_time = Local::now() - sysinfo.started;
42 drop(sysinfo);
44
45 let day = op_time.num_days();
46 let hour = op_time.num_hours() - op_time.num_days() * 24;
47 let min = op_time.num_minutes() - op_time.num_hours() * 60;
48 let sec = op_time.num_seconds() - op_time.num_minutes() * 60;
49 let ms = op_time.num_milliseconds() - op_time.num_seconds() * 1000;
50 let info_list = [
51 format!("Started: {}", started.format("%F %T %:z")),
52 format!("Operated for: {day} days, {hour:02}:{min:02}:{sec:02}.{ms:03}"),
53 ];
54
55 let info_str = info_list
56 .iter()
57 .map(|s| format!(" <li>{s}</li>"))
58 .collect::<Vec<_>>()
59 .join("\n");
60
61 let ver_str = verinfo::version_info_vec()
62 .iter()
63 .map(|s| format!(" <li>{s}</li>"))
64 .collect::<Vec<_>>()
65 .join("\n");
66
67 let body = format!(
68 r#"<!DOCTYPE html>
69<html lang="en">
70 <head>
71 <title>House Management System Web Interface</title>
72 </head>
73 <body>
74 <h1>House Management System Web Interface</h1>
75 <h2>System Available</h2>
76 <ul>
77{info_str}
78 </ul>
79 <p>Access count: {counter}</p>
80
81 <hr>
82
83 <ul>
84{ver_str}
85 </ul>
86 </body>
87</html>
88"#
89 );
90
91 HttpResponse::Ok()
92 .content_type(ContentType::html())
93 .body(body)
94}