1use std::str::FromStr;
2
3use jsonrpsee::core::client::ClientT;
4use jsonrpsee::rpc_params;
5use jsonrpsee::ws_client::{HeaderMap, HeaderValue, WsClient, WsClientBuilder};
6use serde::{Deserialize, Serialize};
7
8#[derive(Serialize, Deserialize, Debug)]
9pub struct UntypedGameRule {
10 value: String,
11 key: String,
12}
13
14#[derive(Serialize, Deserialize, Debug)]
15pub struct IncomingIPBan {
16 reason: String,
17 expires: String,
18 ip: String,
19 source: String,
20 player: Player,
21}
22
23#[derive(Serialize, Deserialize, Debug)]
24pub struct SystemMessage {
25 receiveing_players: Vec<Player>,
26 overlay: bool,
27 message: Message,
28}
29
30#[derive(Serialize, Deserialize, Debug)]
31pub struct KickPlayer {
32 player: Player,
33 message: Message,
34}
35
36#[derive(Serialize, Deserialize, Debug)]
37pub struct IPBan {
38 reason: String,
39 expires: String,
40 ip: String,
41 source: String,
42}
43
44#[derive(Serialize, Deserialize, Debug)]
45pub struct TypedGameRule {
46 r#type: String,
47 value: String,
48 key: String,
49}
50
51#[derive(Serialize, Deserialize, Debug)]
52pub struct UserBan {
53 reason: String,
54 expires: Option<String>,
55 source: Option<String>,
56 player: Player,
57}
58
59impl UserBan {
60 pub fn new(player_name: &str, reason: &str) -> Self {
62 UserBan {
63 reason: reason.to_string(),
64 expires: None,
65 source: None,
66 player: player_name.parse().unwrap(),
67 }
68 }
69}
70
71#[derive(Serialize, Deserialize, Debug)]
72pub struct Message {
73 translatable: String,
74 translatable_params: Vec<String>,
75 literal: String,
76}
77
78#[derive(Serialize, Deserialize, Debug)]
79pub struct Version {
80 protocol: i64,
81 name: String,
82}
83
84#[derive(Serialize, Deserialize, Debug)]
85pub struct ServerState {
86 players: Vec<Player>,
87 started: bool,
88 version: Version,
89}
90
91#[derive(Serialize, Deserialize, Debug)]
92pub struct Operator {
93 permission_level: i64,
94 bypasses_player_limit: bool,
95 player: Player,
96}
97
98#[derive(Serialize, Deserialize, Debug)]
99pub struct Player {
100 pub name: String,
101 pub id: Option<String>,
102}
103
104impl FromStr for Player {
105 type Err = Error;
106 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 Ok(Player {
109 name: s.to_string(),
110 id: None,
111 })
112 }
113}
114
115#[derive(Debug)]
116pub struct Error;
117
118impl std::fmt::Display for Error {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 write!(f, "MinecraftRpcError")
121 }
122}
123
124impl std::error::Error for Error {}
125
126pub trait ClientTrait {
127 fn allowlist_get(
131 &self,
132 ) -> impl std::future::Future<Output = anyhow::Result<Vec<Player>>> + Send;
133 fn allowlist_set(
134 &self,
135 players: &[Player],
136 ) -> impl std::future::Future<Output = anyhow::Result<Vec<Player>>> + Send;
137 fn allowlist_add(
138 &self,
139 players: &[Player],
140 ) -> impl std::future::Future<Output = anyhow::Result<Vec<Player>>> + Send;
141 fn allowlist_remove(
142 &self,
143 players: &[Player],
144 ) -> impl std::future::Future<Output = anyhow::Result<Vec<Player>>> + Send;
145 fn allowlist_clear(
146 &self,
147 ) -> impl std::future::Future<Output = anyhow::Result<Vec<Player>>> + Send;
148
149 fn bans_get(&self) -> impl std::future::Future<Output = anyhow::Result<Vec<UserBan>>> + Send;
153 fn bans_set(
154 &self,
155 bans: &[UserBan],
156 ) -> impl std::future::Future<Output = anyhow::Result<Vec<UserBan>>> + Send;
157 fn bans_add(
158 &self,
159 bans: &[UserBan],
160 ) -> impl std::future::Future<Output = anyhow::Result<Vec<UserBan>>> + Send;
161 fn bans_remove(
162 &self,
163 players: &[Player],
164 ) -> impl std::future::Future<Output = anyhow::Result<Vec<UserBan>>> + Send;
165 fn bans_clear(&self) -> impl std::future::Future<Output = anyhow::Result<Vec<UserBan>>> + Send;
166}
167
168struct Client {
169 ws_client: WsClient,
170}
171
172pub async fn new_client(url: &str, secret: &str) -> anyhow::Result<impl ClientTrait> {
173 let mut headers = HeaderMap::new();
174 headers.insert(
175 "Authorization",
176 HeaderValue::from_str(&format!("Bearer {secret}"))?,
177 );
178 let client = WsClientBuilder::new()
179 .set_headers(headers)
180 .build(url)
181 .await?;
182 Ok(Client { ws_client: client })
183}
184
185impl ClientTrait for Client {
186 async fn allowlist_get(&self) -> anyhow::Result<Vec<Player>> {
190 let players: Vec<Player> = self
191 .ws_client
192 .request("minecraft:allowlist", rpc_params![])
193 .await?;
194 Ok(players)
195 }
196 async fn allowlist_set(&self, players: &[Player]) -> anyhow::Result<Vec<Player>> {
197 let players: Vec<Player> = self
198 .ws_client
199 .request("minecraft:allowlist/set", rpc_params![players])
200 .await?;
201 Ok(players)
202 }
203 async fn allowlist_add(&self, players: &[Player]) -> anyhow::Result<Vec<Player>> {
204 let players: Vec<Player> = self
205 .ws_client
206 .request("minecraft:allowlist/add", rpc_params![players])
207 .await?;
208 Ok(players)
209 }
210 async fn allowlist_remove(&self, players: &[Player]) -> anyhow::Result<Vec<Player>> {
211 let players: Vec<Player> = self
212 .ws_client
213 .request("minecraft:allowlist/remove", rpc_params![players])
214 .await?;
215 Ok(players)
216 }
217 async fn allowlist_clear(&self) -> anyhow::Result<Vec<Player>> {
218 let players: Vec<Player> = self
219 .ws_client
220 .request("minecraft:allowlist/clear", rpc_params![])
221 .await?;
222 Ok(players)
223 }
224
225 async fn bans_get(&self) -> anyhow::Result<Vec<UserBan>> {
229 let bans: Vec<UserBan> = self
230 .ws_client
231 .request("minecraft:bans", rpc_params![])
232 .await?;
233 Ok(bans)
234 }
235 async fn bans_set(&self, bans: &[UserBan]) -> anyhow::Result<Vec<UserBan>> {
236 let bans: Vec<UserBan> = self
237 .ws_client
238 .request("minecraft:bans/set", rpc_params![bans])
239 .await?;
240 Ok(bans)
241 }
242 async fn bans_add(&self, bans: &[UserBan]) -> anyhow::Result<Vec<UserBan>> {
243 let bans: Vec<UserBan> = self
244 .ws_client
245 .request("minecraft:bans/add", rpc_params![bans])
246 .await?;
247 Ok(bans)
248 }
249 async fn bans_remove(&self, players: &[Player]) -> anyhow::Result<Vec<UserBan>> {
250 let bans: Vec<UserBan> = self
251 .ws_client
252 .request("minecraft:bans/remove", rpc_params![players])
253 .await?;
254 Ok(bans)
255 }
256 async fn bans_clear(&self) -> anyhow::Result<Vec<UserBan>> {
257 let bans: Vec<UserBan> = self
258 .ws_client
259 .request("minecraft:bans/clear", rpc_params![])
260 .await?;
261 Ok(bans)
262 }
263}