scpsl_api/server_info/
raw.rs

1//! This module contains structs and functions these can be used for
2//! deserializing and serializing `serverinfo` API responses.  
3//! May be useful if you want to create your local API proxy
4//! or something like that.
5
6use super::RequestParameters;
7#[cfg(feature = "raw")]
8use super::{Player, Response, ServerInfo};
9use reqwest::Error;
10use serde::Deserialize;
11#[cfg(feature = "raw")]
12use serde::Serialize;
13
14/// A struct representing the raw `serverinfo` response.
15#[cfg_attr(feature = "raw", derive(Serialize, Clone))]
16#[derive(Deserialize)]
17pub struct RawResponse {
18    #[allow(missing_docs)]
19    #[serde(rename = "Success")]
20    pub success: bool,
21    #[allow(missing_docs)]
22    #[serde(rename = "Error", skip_serializing_if = "Option::is_none", default)]
23    pub error: Option<String>,
24    #[allow(missing_docs)]
25    #[serde(rename = "Servers", skip_serializing_if = "Option::is_none", default)]
26    pub servers: Option<Vec<RawServerInfo>>,
27    #[allow(missing_docs)]
28    #[serde(rename = "Success", skip_serializing_if = "Option::is_none", default)]
29    pub cooldown: Option<u64>,
30}
31
32#[cfg(feature = "raw")]
33impl From<Response> for RawResponse {
34    fn from(response: Response) -> Self {
35        match response {
36            Response::Success(success) => RawResponse {
37                success: true,
38                error: None,
39                servers: Some(
40                    success
41                        .servers
42                        .into_iter()
43                        .map(RawServerInfo::from)
44                        .collect(),
45                ),
46                cooldown: Some(success.cooldown),
47            },
48            Response::Error(error) => RawResponse {
49                success: false,
50                error: Some(error.error),
51                servers: None,
52                cooldown: None,
53            },
54        }
55    }
56}
57
58/// A struct representing a raw server info.
59#[cfg_attr(feature = "raw", derive(Serialize, Clone))]
60#[derive(Deserialize)]
61pub struct RawServerInfo {
62    #[allow(missing_docs)]
63    #[serde(rename = "ID")]
64    pub id: u64,
65    #[allow(missing_docs)]
66    #[serde(rename = "Port")]
67    pub port: u16,
68    #[allow(missing_docs)]
69    #[serde(
70        rename = "LastOnline",
71        skip_serializing_if = "Option::is_none",
72        default
73    )]
74    pub last_online: Option<String>,
75    #[allow(missing_docs)]
76    #[serde(rename = "Players", skip_serializing_if = "Option::is_none", default)]
77    pub players_count: Option<String>,
78    #[allow(missing_docs)]
79    #[serde(
80        rename = "PlayersList",
81        skip_serializing_if = "Option::is_none",
82        default
83    )]
84    pub players: Option<Vec<RawPlayer>>,
85    #[allow(missing_docs)]
86    #[serde(rename = "Info", skip_serializing_if = "Option::is_none", default)]
87    pub info: Option<String>,
88    #[allow(missing_docs)]
89    #[serde(rename = "FF", skip_serializing_if = "Option::is_none", default)]
90    pub friendly_fire: Option<bool>,
91    #[allow(missing_docs)]
92    #[serde(rename = "WL", skip_serializing_if = "Option::is_none", default)]
93    pub whitelist: Option<bool>,
94    #[allow(missing_docs)]
95    #[serde(rename = "Modded", skip_serializing_if = "Option::is_none", default)]
96    pub modded: Option<bool>,
97    #[allow(missing_docs)]
98    #[serde(rename = "Mods", skip_serializing_if = "Option::is_none", default)]
99    pub mods: Option<u64>,
100    #[allow(missing_docs)]
101    #[serde(rename = "Suppress", skip_serializing_if = "Option::is_none", default)]
102    pub suppress: Option<bool>,
103    #[allow(missing_docs)]
104    #[serde(
105        rename = "AutoSuppress",
106        skip_serializing_if = "Option::is_none",
107        default
108    )]
109    pub auto_suppress: Option<bool>,
110}
111
112#[cfg(feature = "raw")]
113impl From<ServerInfo> for RawServerInfo {
114    fn from(server_info: ServerInfo) -> Self {
115        Self {
116            id: server_info.id,
117            port: server_info.port,
118            last_online: server_info
119                .last_online
120                .map(|date| date.format("%Y-%m-%d").to_string()),
121            players_count: server_info.players_count.map(|players_count| {
122                format!(
123                    "{}/{}",
124                    players_count.current_players, players_count.max_players
125                )
126            }),
127            players: server_info
128                .players
129                .map(|players| players.into_iter().map(RawPlayer::from).collect()),
130            info: server_info.info.map(base64::encode),
131            friendly_fire: server_info.friendly_fire,
132            whitelist: server_info.whitelist,
133            modded: server_info.modded,
134            mods: server_info.mods,
135            suppress: server_info.suppress,
136            auto_suppress: server_info.auto_suppress,
137        }
138    }
139}
140
141/// A struct representing a raw player.
142#[cfg_attr(feature = "raw", derive(Serialize, Clone))]
143#[derive(Deserialize)]
144#[serde(untagged)]
145pub enum RawPlayer {
146    /// The player was represented as string with user id.
147    UserId(String),
148    /// The player was represented as id and nickname.
149    UserIdWithNickname {
150        /// A player's id.
151        #[serde(rename = "ID")]
152        id: String,
153        /// A player's nickname.
154        #[serde(rename = "Nickname", default)]
155        nickname: Option<String>,
156    },
157}
158
159#[cfg(feature = "raw")]
160impl From<Player> for RawPlayer {
161    fn from(player: Player) -> Self {
162        if let Some(nickname) = player.nickname {
163            Self::UserIdWithNickname {
164                id: player.id,
165                nickname: Some(nickname),
166            }
167        } else {
168            Self::UserId(player.id)
169        }
170    }
171}
172
173/// Returns raw info about own servers. See [official API reference](https://api.scpslgame.com/#/default/Get%20Server%20Info).
174/// # Errors
175/// Returns [`Error`] if there was an error in the [`reqwest`] crate.  
176pub async fn get<'a>(parameters: &'a RequestParameters) -> Result<RawResponse, Error> {
177    let mut url = parameters.url.to_owned();
178
179    {
180        let mut query_parameters = url.query_pairs_mut();
181
182        if let Some(id) = parameters.id {
183            query_parameters.append_pair("id", id.to_string().as_str());
184        }
185        if let Some(key) = &parameters.key {
186            query_parameters.append_pair("key", key.as_str());
187        }
188        if parameters.last_online {
189            query_parameters.append_pair("lo", "true");
190        }
191        if parameters.players {
192            query_parameters.append_pair("players", "true");
193        }
194        if parameters.list {
195            query_parameters.append_pair("list", "true");
196        }
197        if parameters.info {
198            query_parameters.append_pair("info", "true");
199        }
200        if parameters.pastebin {
201            query_parameters.append_pair("pastebin", "true");
202        }
203        if parameters.version {
204            query_parameters.append_pair("version", "true");
205        }
206        if parameters.flags {
207            query_parameters.append_pair("flags", "true");
208        }
209        if parameters.nicknames {
210            query_parameters.append_pair("nicknames", "true");
211        }
212        if parameters.online {
213            query_parameters.append_pair("online", "true");
214        }
215    }
216
217    Ok(reqwest::get(url).await?.json().await?)
218}