smol bot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use axum::{
    extract::Path,
    http::{header::*, StatusCode},
    response::{AppendHeaders, Html},
    routing::get,
    Router, Server as AxumServer,
};

use std::{net::SocketAddr, sync::LazyLock, time::SystemTime};
const COMPILED_AT: LazyLock<SystemTime> = LazyLock::new(SystemTime::now);
// LazyLock::new(|| edg::r! { || -> std::time::SystemTime { std::time::SystemTime::now() }});
static COMPILED: LazyLock<String> = LazyLock::new(|| httpdate::fmt_http_date(*COMPILED_AT));

fn no_bytes(map: HeaderMap) -> (StatusCode, Option<&'static [u8]>) {
    if let Some(x) = map.get("if-modified-since")
        && let Ok(x) = x.to_str()
        && let Ok(x) = httpdate::parse_http_date(x)
        && x < *COMPILED_AT
    {
        (StatusCode::NOT_MODIFIED, Some(&[]))
    } else {
        (StatusCode::OK, None)
    }
}

macro_rules! html {
    ($file:expr) => {
        get(|_map: HeaderMap| async {
            println!("a wild visitor approaches");
            #[cfg(debug_assertions)]
            return Html(std::fs::read(concat!("html-src/", stringify!($file), ".html")).unwrap());
            #[cfg(not(debug_assertions))]
            {
                let (code, bytes) = no_bytes(_map);
                (
                    code,
                    Html(bytes.unwrap_or(include_bytes!(concat!(
                        "../html/",
                        stringify!($file),
                        ".html"
                    )))),
                )
            }
        })
    };
}

macro_rules! png {
    ($file:expr) => {
        get(|map: HeaderMap| async {
            let (code, bytes) = no_bytes(map);
            let bytes = bytes.unwrap_or(include_bytes!(concat!(
                "../html/",
                stringify!($file),
                ".png"
            )));

            (
                code,
                (
                    AppendHeaders([(CONTENT_TYPE, "image/png"), (LAST_MODIFIED, &*COMPILED)]),
                    bytes,
                ),
            )
        })
    };
}

pub struct Server;
impl Server {
    pub async fn spawn(addr: SocketAddr) {
        let router = Router::new()
            .route("/", html!(index))
            .route("/fail.png", png!(fail))
            .route("/bg.png", png!(bg))
            .route("/border.png", png!(border))
            .route("/border-active.png", png!(border_active))
            .route("/border-hover.png", png!(border_hover))
            .route("/favicon.ico", png!(favicon))
            .route(
                "/default.woff",
                get(|| async {
                    (
                        [(CONTENT_TYPE, "font/woff")],
                        include_bytes!("../html-src/default.woff"),
                    )
                }),
            )
            .route(
                "/index.js",
                get(|| async {
                    (
                        [(CONTENT_TYPE, "application/javascript")],
                        if cfg!(debug_assertions) {
                            std::fs::read_to_string("html-src/index.js").unwrap().leak()
                        } else {
                            include_str!("../html-src/index.js")
                        },
                    )
                }),
            )
            .route(
                "/files",
                get(|| async {
                    serde_json::to_string(
                        &crate::bot::search::files()
                            .map(|(x, _)| {
                                x.with_extension("")
                                    .file_name()
                                    .unwrap()
                                    .to_string_lossy()
                                    .into_owned()
                            })
                            .collect::<Vec<_>>(),
                    )
                    .unwrap()
                }),
            )
            .route(
                "/blame/:file",
                get(|Path(file): Path<String>| async move {
                    (
                        StatusCode::OK,
                        crate::bot::ownership::whos(
                            925674713429184564,
                            match u64::from_str_radix(file.trim_end_matches(".msch"), 16) {
                                Ok(x) => x,
                                Err(_) => return (StatusCode::NOT_FOUND, "".into()),
                            },
                        )
                        .await,
                    )
                }),
            )
            .route(
                "/files/:file",
                get(|Path(file): Path<String>| async move {
                    match crate::bot::search::files().map(|(x, _)| x).find(|x| {
                        x.with_extension("").file_name().unwrap().to_string_lossy() == file
                    }) {
                        Some(x) => (StatusCode::OK, std::fs::read(x).unwrap()),
                        None => (StatusCode::NOT_FOUND, vec![]),
                    }
                }),
            );
        tokio::spawn(async move {
            AxumServer::bind(&addr)
                .serve(router.into_make_service())
                .await
                .unwrap();
        });
    }
}