aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 986b7f13daaa59ddcdae8f4eb8fe7bebda8b6434 (plain)
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
#![feature(duration_constructors)]
pub mod embed;
pub mod error;
pub mod info;
pub mod state;
use embed::*;
use info::*;

use markup::Render;
use rocket::{
    catch, catchers,
    fairing::AdHoc,
    get,
    http::{ContentType, Header, Status},
    response::{self, Responder},
    routes,
    shield::{self, Shield},
    Request, Response,
};
use state::{AdInfo, Config, Logic};
use std::{io::Cursor, net::IpAddr};

#[rocket::main]
async fn main() {
    env_logger::init_from_env("LOG");

    let config = std::env::args()
        .nth(1)
        .expect("first arg needs to be the config");
    let config = rocket::tokio::fs::read_to_string(config)
        .await
        .expect("could not read config");
    let mut config: Config = toml::from_str(config.as_str()).expect("config invalid");

    for entry in config.ad_dir.read_dir().expect("cannot read ad directory") {
        if let Ok(entry) = entry {
            if entry
                .path()
                .file_name()
                .unwrap()
                .to_str()
                .unwrap()
                .ends_with(".toml")
            {
                let path = entry.path();
                let imname = path.file_stem().unwrap().to_str().unwrap();
                let basename = imname.split_once(".").unwrap().0;
                let info: AdInfo = toml::from_str(
                    &rocket::tokio::fs::read_to_string(entry.path())
                        .await
                        .unwrap(),
                )
                .unwrap();
                config.ads.insert(
                    basename.to_string(),
                    AdInfo {
                        image: imname.into(),
                        ..info
                    },
                );
            }
        }
    }

    let state = Logic::new(config);

    let _ = rocket::build()
        .configure(rocket::Config {
            port: state.config.port,
            ..Default::default()
        })
        .attach(Shield::default().disable::<shield::Frame>())
        .attach(AdHoc::on_response("set server header", |_req, res| {
            res.set_header(Header::new("server", "meta adservices"));
            Box::pin(async {})
        }))
        .manage(state)
        .mount("/", routes![r_index, r_embed, r_style, r_image, r_iptest])
        .register("/", catchers![r_catch])
        .launch()
        .await
        .unwrap();
}

#[get("/myip")]
fn r_iptest(addr: IpAddr) -> String {
    format!("{addr}")
}

pub struct Template<T>(pub T);
impl<'r, T: Render> Responder<'r, 'static> for Template<T> {
    fn respond_to(self, _req: &'r Request<'_>) -> response::Result<'static> {
        let mut out = String::new();
        self.0.render(&mut out).unwrap();
        Response::build()
            .header(ContentType::HTML)
            .streamed_body(Cursor::new(out))
            .ok()
    }
}

#[catch(default)]
pub fn r_catch<'a>(status: Status, _request: &Request) -> String {
    format!("{status}; This ad is likely misconfigured. Server could also be broken...")
}