sys/sysmod/http/
index.rs

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