Skip to content

Commit a71d82a

Browse files
committed
Add optional UUID argument to whitelist add, and don't request UUID for every server category
1 parent 8dbb5f2 commit a71d82a

File tree

2 files changed

+60
-36
lines changed

2 files changed

+60
-36
lines changed

src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ enum Error {
3636
Serenity(#[from] serenity::Error),
3737
#[error("Utf8 Error: {0}")]
3838
Utf8(#[from] std::str::Utf8Error),
39+
#[error("UUID Error: {0}")]
40+
Uuid(#[from] uuid::Error),
3941
#[error("Pterodactyl Error: {0}")]
4042
Pterodactyl(#[from] pterodactyl_api::Error),
4143
#[error("Other Error: {0}")]

src/pterodactyl/whitelist.rs

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use serde::de::value::StrDeserializer;
77
use serde::{Deserialize, Serialize};
88
use std::collections::BTreeSet;
99
use std::future::Future;
10+
use tokio::sync::OnceCell;
1011
use uuid::Uuid;
1112

1213
pub(crate) async fn run(
@@ -27,8 +28,18 @@ pub(crate) async fn run(
2728
print_usage();
2829
return Ok(());
2930
};
30-
whitelist_across_categories(category, |category| whitelist_add(data, player, category))
31-
.await?;
31+
let uuid = args.next().map(Uuid::parse_str).transpose()?;
32+
whitelist_across_categories(category, |category| {
33+
whitelist_add(
34+
data,
35+
player,
36+
category,
37+
uuid.map_or_else(OnceCell::new, |uuid| {
38+
OnceCell::new_with(Some((player.to_owned(), uuid)))
39+
}),
40+
)
41+
})
42+
.await?;
3243
}
3344
"remove" => {
3445
let Some(player) = args.next() else {
@@ -104,6 +115,7 @@ async fn whitelist_add(
104115
data: &ProtobotData,
105116
player_name: &str,
106117
category: PterodactylServerCategory,
118+
name_and_uuid: OnceCell<(String, Uuid)>,
107119
) -> Result<(), crate::Error> {
108120
let Some(mut whitelist) = get_whitelist(data, category).await? else {
109121
return Ok(());
@@ -117,44 +129,54 @@ async fn whitelist_add(
117129
return Ok(());
118130
}
119131

120-
let client = reqwest::Client::builder()
121-
.user_agent(format!("protobot {}", git_version!()))
122-
.build()?;
123-
let response = client
124-
.post("https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname")
125-
.header("Accept", "application/json")
126-
.header("Content-Type", "application/json")
127-
.json(&vec![player_name])
128-
.send()
129-
.await?;
130-
if !response.status().is_success() {
131-
let status = response.status();
132-
error!(
133-
"Failed to request UUID: {}, {}",
134-
status,
135-
response.text().await?
136-
);
137-
return Ok(());
138-
}
132+
let (player_name, player_uuid) = name_and_uuid
133+
.get_or_try_init(|| async {
134+
let client = reqwest::Client::builder()
135+
.user_agent(format!("protobot {}", git_version!()))
136+
.build();
137+
let client = match client {
138+
Ok(client) => client,
139+
Err(err) => return Err::<(String, Uuid), crate::Error>(err.into()),
140+
};
141+
let response = client
142+
.post("https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname")
143+
.header("Accept", "application/json")
144+
.header("Content-Type", "application/json")
145+
.json(&vec![player_name])
146+
.send()
147+
.await?;
139148

140-
#[derive(Deserialize)]
141-
struct MojangPlayer {
142-
id: Uuid,
143-
name: String,
144-
}
149+
if !response.status().is_success() {
150+
let status = response.status();
151+
error!(
152+
"Failed to request UUID: {}, {}",
153+
status,
154+
response.text().await?
155+
);
156+
return Err(crate::Error::Other("failed to request UUID".into()));
157+
}
145158

146-
let mojang_players = response.json::<Vec<MojangPlayer>>().await?;
147-
if mojang_players.len() != 1 {
148-
return Err(crate::Error::Other(
149-
"Mojang server didn't return 1 player when requested".to_owned(),
150-
));
151-
}
152-
let player_uuid = mojang_players[0].id;
153-
let player_name: &str = &mojang_players[0].name;
159+
#[derive(Deserialize)]
160+
struct MojangPlayer {
161+
id: Uuid,
162+
name: String,
163+
}
164+
165+
let mojang_players = response.json::<Vec<MojangPlayer>>().await?;
166+
if mojang_players.len() != 1 {
167+
return Err(crate::Error::Other(
168+
"Mojang server didn't return 1 player when requested".to_owned(),
169+
));
170+
}
171+
172+
let player = mojang_players.into_iter().next().unwrap();
173+
Ok::<(String, Uuid), crate::Error>((player.name, player.id))
174+
})
175+
.await?;
154176

155177
whitelist.push(Player {
156178
name: player_name.to_owned(),
157-
uuid: player_uuid,
179+
uuid: *player_uuid,
158180
});
159181
whitelist.sort_by_key(|player| player.name.to_ascii_lowercase());
160182

@@ -295,7 +317,7 @@ async fn run_command(
295317
}
296318

297319
fn print_usage() {
298-
info!("(whitelist <add|remove> <player> <category|all>) | (whitelist list <category>)");
320+
info!("(whitelist add <player> <category|all> [uuid]) | (whitelist remove <player> <category|all>) | (whitelist list <category>)");
299321
}
300322

301323
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]

0 commit comments

Comments
 (0)