sys/sysmod/http/
index.rs

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    // unlock
43    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}