summary refs log tree commit diff
path: root/src/config.rs
blob: 27911ea94385e6155d8b82334fd8b82eff6fa3ca (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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::collections::HashMap;

use regex::{Regex, RegexBuilder};
use serde::{Deserialize, Deserializer, de::Error};

#[derive(Deserialize)]
pub enum AutoProxyScope {
    Global,
    Server,
    Channel
}

#[derive(Deserialize, Clone)]
pub enum PresenceMode {
    Online,
    Busy,
    Idle,
    Invisible,
}

#[derive(Deserialize, Clone)]
#[serde(tag = "mode", rename_all = "lowercase")]
pub enum AutoproxyConfig {
    Member {
        name: MemberName
    },
    Latch {
        scope: AutoproxyLatchScope,
        timeout_seconds: u32,
        presence_indicator: bool
    }
}

#[derive(Deserialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum AutoproxyLatchScope {
    Global,
    Server
}

#[derive(Deserialize, Clone)]
pub struct PluralkitConfig {
    #[serde(deserialize_with = "parse_regex")]
    pub message_pattern: Regex,
    pub api_token: String,
}

#[derive(Deserialize, Clone)]
pub struct System {
    pub reference_user_id: String,
    pub members: Vec<Member>,
    #[serde(default = "default_forward_pings")]
    pub forward_pings: bool,
    pub autoproxy: Option<AutoproxyConfig>,
    pub pluralkit: Option<PluralkitConfig>,
}

fn default_forward_pings() -> bool {
    false
}

pub type MemberName = String;

#[derive(Deserialize, Clone)]
pub struct Member {
    pub name: MemberName,
    #[serde(deserialize_with = "parse_regex")]
    pub message_pattern: Regex,
    pub discord_token: String,
    pub presence: Option<PresenceMode>,
    pub status: Option<String>,
}

#[derive(Deserialize)]
pub struct Config {
    #[serde(flatten)]
    pub systems: HashMap<String, System>
}

impl Config {
    pub fn load(config_contents: String) -> Config {
        let config : Config = toml::from_str(config_contents.as_str()).unwrap();

        config.systems.iter().for_each(|config_system| {
            let (system_name, system) = config_system;
            if let Some(autoproxy) = &system.autoproxy {
                if let AutoproxyConfig::Member { name } = autoproxy {
                    let member_matches = system.members.iter().all(|member| {
                        member.name == *name
                    });

                    if !member_matches {
                        panic!("System {} autoproxy member {} does not match a known member name", system_name, name);
                    }
                }
            }
        });

        return config
    }
}

fn parse_regex<'de, D: Deserializer<'de>> (deserializer: D) -> Result<Regex, D::Error> {
    let mut pattern = String::deserialize(deserializer)?;

    if !pattern.starts_with("^") {
        pattern.insert(0, '^');
    }

    if !pattern.ends_with("$") {
        pattern.push('$');
    }

    RegexBuilder::new(&pattern)
        .multi_line(true)
        .case_insensitive(true)
        .build()
        .map_err(|e| D::Error::custom(e))
}