summaryrefslogtreecommitdiff
path: root/src/macro_processor/deadlinks.rs
blob: f8bf352793e4c0311ba80ed44e1952365b0ad043 (plain) (blame)
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
use crate::macro_processor::error::SMPError;
use crate::macro_processor::macro_processor::MacroProcessorWarning;
use crate::macro_processor::MacroProcessor;
use core::cell::OnceCell;
use std::collections::HashMap;

static mut LINK_CACHE: OnceCell<HashMap<String, (bool, i32, String)>> = OnceCell::new();

/// Warn on dead link
pub fn smp_builtin_wodl(
    smp: &mut MacroProcessor,
    macro_name: &str,
    args: &mut [String],
) -> Result<String, SMPError> {
    if args.len() != 1 {
        smp.warnings
            .push(MacroProcessorWarning::from_macro_invocation(
                macro_name,
                args,
                format!("Wrong number of arguments, expected 1"),
            ));
        return Ok(macro_name.to_string());
    }

    let link_cache: &mut HashMap<String, (bool, i32, String)>;
    unsafe {
        let _ = LINK_CACHE.get_or_init(|| HashMap::new());
        link_cache = LINK_CACHE.get_mut().expect("Init of OnceCell failed!");
    }

    let link_info = match link_cache.get(&args[0]) {
        Some(working_link) => working_link.clone(),
        None => {
            let response = match minreq::get(&args[0]).send() {
                Ok(s) => s,
                Err(e) => {
                    smp.warnings
                        .push(MacroProcessorWarning::from_macro_invocation(
                            macro_name,
                            args,
                            format!("Dead link {:#?} ({:#?})!", args[0], e),
                        ));
                    return Ok(args[0].to_string());
                }
            };
            let working_link = response.status_code == 200 && response.reason_phrase == "OK";
            let info = (working_link, response.status_code, response.reason_phrase);
            link_cache.insert(String::from(&args[0]), info.clone());
            info
        }
    };
    if !link_info.0 {
        smp.warnings
            .push(MacroProcessorWarning::from_macro_invocation(
                macro_name,
                args,
                format!(
                    "Dead link {:#?} ({} {})!",
                    args[0], link_info.1, link_info.2
                ),
            ));
    }
    Ok(args[0].to_string())
}