1use super::HttpConfig;
2use super::{github, line_hook, tmp, 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 cfg.service(tmp::index_get);
32 }
33 }
34}
35
36#[actix_web::get("/")]
37async fn index_get(state: web::Data<IndexState>, ctrl: web::Data<Control>) -> impl Responder {
38 let counter = state.access_counter.fetch_add(1, Ordering::Relaxed) + 1;
39
40 let sysinfo = ctrl.sysmods().sysinfo.lock().await;
41 let started = sysinfo.started;
42 let op_time = Local::now() - sysinfo.started;
43 drop(sysinfo);
45
46 let day = op_time.num_days();
47 let hour = op_time.num_hours() - op_time.num_days() * 24;
48 let min = op_time.num_minutes() - op_time.num_hours() * 60;
49 let sec = op_time.num_seconds() - op_time.num_minutes() * 60;
50 let ms = op_time.num_milliseconds() - op_time.num_seconds() * 1000;
51 let info_list = [
52 format!("Started: {}", started.format("%F %T %:z")),
53 format!("Operated for: {day} days, {hour:02}:{min:02}:{sec:02}.{ms:03}"),
54 ];
55
56 let info_str = info_list
57 .iter()
58 .map(|s| format!(" <li>{s}</li>"))
59 .collect::<Vec<_>>()
60 .join("\n");
61
62 let ver_str = verinfo::version_info_vec()
63 .iter()
64 .map(|s| format!(" <li>{s}</li>"))
65 .collect::<Vec<_>>()
66 .join("\n");
67
68 let body = format!(
69 r#"<!DOCTYPE html>
70<html lang="en">
71 <head>
72 <title>House Management System Web Interface</title>
73 </head>
74 <body>
75 <h1>House Management System Web Interface</h1>
76 <h2>System Available</h2>
77 <ul>
78{info_str}
79 </ul>
80 <p>Access count: {counter}</p>
81
82 <hr>
83
84 <ul>
85{ver_str}
86 </ul>
87 </body>
88</html>
89"#
90 );
91
92 HttpResponse::Ok()
93 .content_type(ContentType::html())
94 .body(body)
95}