1use std::collections::HashMap;
2
3use cached::proc_macro::cached;
4use config::{Config, File, FileFormat};
5use futures_locks::RwLock;
6use once_cell::sync::Lazy;
7use serde::Deserialize;
8
9static CONFIG_BUILDER: Lazy<RwLock<Config>> = Lazy::new(|| {
10 RwLock::new({
11 let mut builder = Config::builder().add_source(File::from_str(
12 include_str!("../Revolt.toml"),
13 FileFormat::Toml,
14 ));
15
16 if std::env::var("TEST_DB").is_ok() {
17 builder = builder.add_source(File::from_str(
18 include_str!("../Revolt.test.toml"),
19 FileFormat::Toml,
20 ));
21 } else if std::path::Path::new("Revolt.toml").exists() {
22 builder = builder.add_source(File::new("Revolt.toml", FileFormat::Toml));
23 }
24
25 builder.build().unwrap()
26 })
27});
28
29#[derive(Deserialize, Debug, Clone)]
32pub struct Database {
33 pub mongodb: String,
34 pub redis: String,
35}
36
37#[derive(Deserialize, Debug, Clone)]
38pub struct Hosts {
39 pub app: String,
40 pub api: String,
41 pub events: String,
42 pub autumn: String,
43 pub january: String,
44 pub voso_legacy: String,
45 pub voso_legacy_ws: String,
46}
47
48#[derive(Deserialize, Debug, Clone)]
49pub struct ApiRegistration {
50 pub invite_only: bool,
51}
52
53#[derive(Deserialize, Debug, Clone)]
54pub struct ApiSmtp {
55 pub host: String,
56 pub username: String,
57 pub password: String,
58 pub from_address: String,
59}
60
61#[derive(Deserialize, Debug, Clone)]
62pub struct ApiVapid {
63 pub private_key: String,
64 pub public_key: String,
65}
66
67#[derive(Deserialize, Debug, Clone)]
68pub struct ApiFcm {
69 pub api_key: String,
70}
71
72#[derive(Deserialize, Debug, Clone)]
73pub struct ApiSecurityCaptcha {
74 pub hcaptcha_key: String,
75 pub hcaptcha_sitekey: String,
76}
77
78#[derive(Deserialize, Debug, Clone)]
79pub struct ApiSecurity {
80 pub authifier_shield_key: String,
81 pub voso_legacy_token: String,
82 pub captcha: ApiSecurityCaptcha,
83}
84
85#[derive(Deserialize, Debug, Clone)]
86pub struct ApiWorkers {
87 pub max_concurrent_connections: usize,
88}
89
90#[derive(Deserialize, Debug, Clone)]
91pub struct Api {
92 pub staging: bool,
93 pub registration: ApiRegistration,
94 pub smtp: ApiSmtp,
95 pub vapid: ApiVapid,
96 pub fcm: ApiFcm,
97 pub security: ApiSecurity,
98 pub workers: ApiWorkers,
99}
100
101#[derive(Deserialize, Debug, Clone)]
102pub struct FeaturesLimits {
103 pub group_size: usize,
104 pub bots: usize,
105 pub message_length: usize,
106 pub message_replies: usize,
107 pub message_attachments: usize,
108 pub message_embeds: usize,
109 pub message_reactions: usize,
110 pub servers: usize,
111 pub server_emoji: usize,
112 pub server_roles: usize,
113 pub server_channels: usize,
114
115 pub attachment_size: usize,
116 pub avatar_size: usize,
117 pub background_size: usize,
118 pub icon_size: usize,
119 pub banner_size: usize,
120 pub emoji_size: usize,
121}
122
123#[derive(Deserialize, Debug, Clone)]
124pub struct FeaturesLimitsCollection {
125 pub default: FeaturesLimits,
126
127 #[serde(flatten)]
128 pub roles: HashMap<String, FeaturesLimits>,
129}
130
131#[derive(Deserialize, Debug, Clone)]
132pub struct Features {
133 pub limits: FeaturesLimitsCollection,
134}
135
136#[derive(Deserialize, Debug, Clone)]
137pub struct Settings {
138 pub database: Database,
139 pub hosts: Hosts,
140 pub api: Api,
141 pub features: Features,
142}
143
144pub async fn init() {
145 println!(
146 ":: Revolt Configuration ::\n\x1b[32m{:?}\x1b[0m",
147 config().await
148 );
149}
150
151pub async fn read() -> Config {
152 CONFIG_BUILDER.read().await.clone()
153}
154
155#[cached(time = 30)]
156pub async fn config() -> Settings {
157 read().await.try_deserialize::<Settings>().unwrap()
158}
159
160#[cfg(feature = "test")]
161#[cfg(test)]
162mod tests {
163 use crate::init;
164
165 #[async_std::test]
166 async fn it_works() {
167 init().await;
168 }
169}