1use crate::raw::*;
2use crate::Result;
3use std::collections::HashMap;
4
5pub type ServerId = u64;
7pub type ServerGroupID = u64;
8pub type ChannelId = u64;
9pub type ClientId = u16;
12pub type ClientDBId = u64;
14pub type ChannelGroupId = u64;
15pub type IconHash = i64;
17
18#[derive(Debug)]
20pub struct ServerGroup {
21 pub sgid: ServerGroupID,
23 pub name: String,
24 pub r#type: i32,
27 pub iconid: IconHash,
28 pub savedb: bool,
30}
31
32impl ServerGroup {
33 pub(crate) fn from_raw(mut data: HashMap<String, Option<String>>) -> Result<Self> {
35 let sgid = int_val_parser(&mut data, "sgid")?;
36 let name = string_val_parser(&mut data, "name")?;
37 let r#type = int_val_parser(&mut data, "type")?;
38 let iconid = int_val_parser(&mut data, "iconid")?;
39 let savedb = bool_val_parser(&mut data, "savedb")?;
40
41 Ok(ServerGroup {
42 sgid,
43 name,
44 r#type,
45 iconid,
46 savedb,
47 })
48 }
49}
50
51#[derive(Debug)]
52pub struct OnlineClient {
53 pub clid: ClientId,
54 pub cid: ChannelId,
55 pub client_database_id: ClientDBId,
56 pub client_nickname: String,
57 pub client_type: i8,
59}
60
61impl OnlineClient {
62 pub(crate) fn from_raw(mut data: HashMap<String, Option<String>>) -> Result<Self> {
63 let clid = int_val_parser(&mut data, "clid")?;
64 let cid = int_val_parser(&mut data, "cid")?;
65 let client_database_id = int_val_parser(&mut data, "client_database_id")?;
66 let client_nickname: String = string_val_parser(&mut data, "client_nickname")?;
67 let client_type = int_val_parser(&mut data, "client_type")?;
68
69 Ok(OnlineClient {
70 clid,
71 cid,
72 client_database_id,
73 client_nickname,
74 client_type,
75 })
76 }
77}
78
79#[derive(Debug)]
80pub struct OnlineClientFull {
81 pub clid: ClientId,
82 pub cid: ChannelId,
83 pub client_database_id: ClientDBId,
84 pub client_nickname: String,
85 pub client_type: i8,
87 pub client_away: bool,
88 pub client_away_message: Option<String>,
89 pub client_flag_talking: bool,
90 pub client_input_muted: bool,
91 pub client_output_muted: bool,
92 pub client_input_hardware: bool,
93 pub client_output_hardware: bool,
94 pub client_talk_power: i32,
95 pub client_is_talker: bool,
96 pub client_is_priority_speaker: bool,
97 pub client_is_recording: bool,
98 pub client_is_channel_commander: bool,
99 pub client_unique_identifier: String,
100 pub client_servergroups: Vec<ServerGroupID>,
101 pub client_channel_group_id: ChannelGroupId,
102 pub client_channel_group_inherited_channel_id: ChannelGroupId,
103 pub client_version: String,
104 pub client_platform: String,
105 pub client_idle_time: i64,
106 pub client_created: i64,
107 pub client_lastconnected: i64,
108 pub client_country: String,
109 pub connection_client_ip: String,
110 pub client_badges: Option<String>, }
112
113impl OnlineClientFull {
114 pub(crate) fn from_raw(mut data: HashMap<String, Option<String>>) -> Result<Self> {
115 let clid = int_val_parser(&mut data, "clid")?;
116 let cid = int_val_parser(&mut data, "cid")?;
117 let client_database_id = int_val_parser(&mut data, "client_database_id")?;
118 let client_nickname: String = string_val_parser(&mut data, "client_nickname")?;
119 let client_type = int_val_parser(&mut data, "client_type")?;
120
121 let client_away = bool_val_parser(&mut data, "client_away")?;
122 let client_away_message = string_val_parser_opt(&mut data, "client_away_message")?;
123 let client_flag_talking = bool_val_parser(&mut data, "client_flag_talking")?;
124 let client_input_muted = bool_val_parser(&mut data, "client_input_muted")?;
125 let client_output_muted = bool_val_parser(&mut data, "client_output_muted")?;
126 let client_input_hardware = bool_val_parser(&mut data, "client_input_hardware")?;
127 let client_output_hardware = bool_val_parser(&mut data, "client_output_hardware")?;
128 let client_talk_power = int_val_parser(&mut data, "client_talk_power")?;
129 let client_is_talker = bool_val_parser(&mut data, "client_is_talker")?;
130 let client_is_priority_speaker = bool_val_parser(&mut data, "client_is_priority_speaker")?;
131 let client_is_recording = bool_val_parser(&mut data, "client_is_recording")?;
132 let client_is_channel_commander =
133 bool_val_parser(&mut data, "client_is_channel_commander")?;
134 let client_unique_identifier = string_val_parser(&mut data, "client_unique_identifier")?;
135 let client_servergroups = int_list_val_parser(&mut data, "client_servergroups")?;
136 let client_channel_group_id = int_val_parser(&mut data, "client_channel_group_id")?;
137 let client_channel_group_inherited_channel_id =
138 int_val_parser(&mut data, "client_channel_group_inherited_channel_id")?;
139 let client_version = string_val_parser(&mut data, "client_version")?;
140 let client_platform = string_val_parser(&mut data, "client_platform")?;
141 let client_idle_time = int_val_parser(&mut data, "client_idle_time")?;
142 let client_created = int_val_parser(&mut data, "client_created")?;
143 let client_lastconnected = int_val_parser(&mut data, "client_lastconnected")?;
144 let client_country = string_val_parser(&mut data, "client_country")?;
145 let connection_client_ip = string_val_parser(&mut data, "connection_client_ip")?;
146 let client_badges = string_val_parser_opt(&mut data, "client_badges")?;
147
148 Ok(OnlineClientFull {
149 clid,
150 cid,
151 client_database_id,
152 client_nickname,
153 client_type,
154 client_away,
155 client_away_message,
156 client_flag_talking,
157 client_input_muted,
158 client_output_muted,
159 client_input_hardware,
160 client_output_hardware,
161 client_talk_power,
162 client_is_talker,
163 client_is_priority_speaker,
164 client_is_recording,
165 client_is_channel_commander,
166 client_unique_identifier,
167 client_servergroups,
168 client_channel_group_id,
169 client_channel_group_inherited_channel_id,
170 client_version,
171 client_platform,
172 client_idle_time,
173 client_created,
174 client_lastconnected,
175 client_country,
176 connection_client_ip,
177 client_badges,
178 })
179 }
180}
181
182#[derive(Debug)]
183pub struct Channel {
184 pub cid: ChannelId,
186 pub pid: ChannelId,
188 pub channel_order: ChannelId,
190 pub channel_name: String,
191 pub total_clients: i32,
192 pub channel_needed_subscribe_power: i32,
193}
194
195impl Channel {
196 pub(crate) fn from_raw(mut data: HashMap<String, Option<String>>) -> Result<Self> {
197 let cid = int_val_parser(&mut data, "cid")?;
198 let pid = int_val_parser(&mut data, "pid")?;
199 let channel_order = int_val_parser(&mut data, "channel_order")?;
200 let channel_name: String = string_val_parser(&mut data, "channel_name")?;
201 let total_clients = int_val_parser(&mut data, "total_clients")?;
202 let channel_needed_subscribe_power =
203 int_val_parser(&mut data, "channel_needed_subscribe_power")?;
204
205 Ok(Channel {
206 cid,
207 pid,
208 channel_order,
209 channel_name,
210 total_clients,
211 channel_needed_subscribe_power,
212 })
213 }
214}
215
216#[derive(Debug)]
217pub struct ChannelFull {
218 pub cid: ChannelId,
220 pub pid: ChannelId,
222 pub channel_order: ChannelId,
224 pub channel_name: String,
225 pub total_clients: i32,
226 pub channel_needed_subscribe_power: i32,
227 pub channel_topic: Option<String>,
228 pub channel_flag_default: bool,
229 pub channel_flag_password: bool,
230 pub channel_flag_permanent: bool,
231 pub channel_flag_semi_permanent: bool,
232 pub channel_codec: i32,
233 pub channel_codec_quality: u8,
234 pub channel_needed_talk_power: i32,
235 pub channel_icon_id: IconHash,
236 pub seconds_empty: i64,
237 pub total_clients_family: i32,
238 pub channel_maxclients: i32,
239 pub channel_maxfamilyclients: i32,
240}
241
242impl ChannelFull {
243 pub(crate) fn from_raw(mut data: HashMap<String, Option<String>>) -> Result<Self> {
244 let cid = int_val_parser(&mut data, "cid")?;
245 let pid = int_val_parser(&mut data, "pid")?;
246 let channel_order = int_val_parser(&mut data, "channel_order")?;
247 let channel_name: String = string_val_parser(&mut data, "channel_name")?;
248 let total_clients = int_val_parser(&mut data, "total_clients")?;
249 let channel_needed_subscribe_power =
250 int_val_parser(&mut data, "channel_needed_subscribe_power")?;
251
252 let channel_topic = string_val_parser_opt(&mut data, "channel_topic")?;
253 let channel_flag_default = bool_val_parser(&mut data, "channel_flag_default")?;
254 let channel_flag_password = bool_val_parser(&mut data, "channel_flag_password")?;
255 let channel_flag_permanent = bool_val_parser(&mut data, "channel_flag_permanent")?;
256 let channel_flag_semi_permanent =
257 bool_val_parser(&mut data, "channel_flag_semi_permanent")?;
258 let channel_codec = int_val_parser(&mut data, "channel_codec")?;
259 let channel_codec_quality = int_val_parser(&mut data, "channel_codec_quality")?;
260 let channel_needed_talk_power = int_val_parser(&mut data, "channel_needed_talk_power")?;
261 let channel_icon_id = int_val_parser(&mut data, "channel_icon_id")?;
262 let seconds_empty = int_val_parser(&mut data, "seconds_empty")?;
263 let total_clients_family = int_val_parser(&mut data, "total_clients_family")?;
264 let channel_maxclients = int_val_parser(&mut data, "channel_maxclients")?;
265 let channel_maxfamilyclients = int_val_parser(&mut data, "channel_maxfamilyclients")?;
266
267 Ok(ChannelFull {
268 cid,
269 pid,
270 channel_order,
271 channel_name,
272 total_clients,
273 channel_needed_subscribe_power,
274 channel_topic,
275 channel_flag_default,
276 channel_flag_password,
277 channel_flag_permanent,
278 channel_flag_semi_permanent,
279 channel_codec,
280 channel_codec_quality,
281 channel_needed_talk_power,
282 channel_icon_id,
283 seconds_empty,
284 total_clients_family,
285 channel_maxclients,
286 channel_maxfamilyclients,
287 })
288 }
289}
290
291#[derive(Debug, Default)]
294pub struct ChannelEdit {
295 pub channel_name: Option<String>,
299 pub channel_life: Option<ChannelLife>,
301 pub pid: Option<ChannelId>,
304 pub channel_order: Option<ChannelId>,
306 pub channel_topic: Option<String>,
307 pub channel_password: Option<String>,
308 pub channel_maxclients: Option<i32>,
309 pub channel_maxfamilyclients: Option<i32>,
310 pub channel_flag_default: bool,
311 pub channel_codec: Option<i32>,
312 pub channel_codec_quality: Option<u8>,
313 pub channel_needed_talk_power: Option<i32>,
314 pub channel_icon_id: Option<IconHash>,
315}
316
317#[derive(Debug)]
319pub enum ChannelLife {
320 Permanent,
322 SemiPermanent,
324 Temporary,
326}
327
328impl ChannelEdit {
329 pub(crate) fn to_raw(&self) -> String {
330 let mut result = String::new();
331
332 if let Some(x) = &self.channel_name {
333 result += &format!(" channel_name={}", &escape_arg(x));
334 }
335 if let Some(x) = &self.channel_life {
336 match x {
337 ChannelLife::Permanent => result += &format!(" channel_flag_permanent={}", 1),
338 ChannelLife::SemiPermanent => {
339 result += &format!(" channel_flag_semi_permanent={}", 1)
340 }
341 ChannelLife::Temporary => result += &format!(" channel_flag_temporary={}", 1),
342 }
343 }
344 if let Some(x) = self.pid {
345 result += &format!(" cpid={}", x);
346 }
347 if let Some(x) = self.channel_order {
348 result += &format!(" channel_order={}", x);
349 }
350 if let Some(x) = &self.channel_topic {
351 result += &format!(" channel_topic={}", &escape_arg(x));
352 }
353 if let Some(x) = &self.channel_password {
354 result += &format!(" channel_password={}", &escape_arg(x));
355 }
356 if let Some(x) = self.channel_maxclients {
357 result += &format!(" channel_maxclients={}", x);
358 }
359 if let Some(x) = self.channel_maxfamilyclients {
360 result += &format!(" channel_maxfamilyclients={}", x);
361 }
362 if self.channel_flag_default {
363 result += &format!(" channel_flag_default={}", 1);
364 }
365 if let Some(x) = self.channel_codec {
366 result += &format!(" channel_codec={}", x);
367 }
368 if let Some(x) = self.channel_codec_quality {
369 result += &format!(" channel_codec_quality={}", x);
370 }
371 if let Some(x) = self.channel_needed_talk_power {
372 result += &format!(" channel_needed_talk_power={}", x);
373 }
374 if let Some(x) = self.channel_icon_id {
375 result += &format!(" channel_icon_id={}", x);
376 }
377
378 result
379 }
380}
381
382impl From<&ChannelFull> for ChannelEdit {
383 fn from(c: &ChannelFull) -> Self {
384 let channel_life;
385 if c.channel_flag_permanent {
386 channel_life = ChannelLife::Permanent;
387 } else if c.channel_flag_semi_permanent {
388 channel_life = ChannelLife::SemiPermanent;
389 } else {
390 channel_life = ChannelLife::Temporary;
391 }
392
393 Self {
394 channel_name: c.channel_name.clone().into(),
395 channel_life: Some(channel_life),
396 pid: c.pid.into(),
397 channel_order: c.channel_order.into(),
398 channel_topic: c.channel_topic.clone(),
399 channel_password: None,
400 channel_maxclients: c.channel_maxclients.into(),
401 channel_maxfamilyclients: c.channel_maxfamilyclients.into(),
402 channel_flag_default: c.channel_flag_default,
403 channel_codec: c.channel_codec.into(),
404 channel_codec_quality: c.channel_codec_quality.into(),
405 channel_needed_talk_power: c.channel_needed_talk_power.into(),
406 channel_icon_id: c.channel_icon_id.into(),
407 }
408 }
409}
410
411impl Default for ChannelLife {
412 fn default() -> Self {
413 Self::Temporary
414 }
415}
416
417#[derive(Debug)]
419pub struct ErrorResponse {
420 pub id: usize,
422 pub msg: String,
424}
425
426impl ErrorResponse {
427 pub fn error_name(&self) -> Option<&'static str> {
430 match self.id {
431 0 => Some("unknown error code"),
432 1 => Some("undefined error"),
433 2 => Some("not implemented"),
434 5 => Some("library time limit reached"),
435 256 => Some("command not found"),
436 257 => Some("unable to bind network port"),
437 258 => Some("no network port available"),
438 512 => Some("invalid clientID"),
439 513 => Some("nickname is already in use"),
440 514 => Some("invalid error code"),
441 515 => Some("max clients protocol limit reached"),
442 516 => Some("invalid client type"),
443 517 => Some("already subscribed"),
444 518 => Some("not logged in"),
445 519 => Some("could not validate client identity"),
446 520 => Some("invalid loginname or password"),
447 521 => Some("too many clones already connected"),
448 522 => Some("client version outdated, please update"),
449 523 => Some("client is online"),
450 524 => Some("client is flooding"),
451 525 => Some("client is modified"),
452 526 => Some("can not verify client at this moment"),
453 527 => Some("client is not permitted to log in"),
454 528 => Some("client is not subscribed to the channel"),
455 768 => Some("invalid channelID"),
456 769 => Some("max channels protocol limit reached"),
457 770 => Some("already member of channel"),
458 771 => Some("channel name is already in use"),
459 772 => Some("channel not empty"),
460 773 => Some("can not delete default channel"),
461 774 => Some("default channel requires permanent"),
462 775 => Some("invalid channel flags"),
463 776 => Some("permanent channel can not be child of non permanent channel"),
464 777 => Some("channel maxclient reached"),
465 778 => Some("channel maxfamily reached"),
466 779 => Some("invalid channel order"),
467 780 => Some("channel does not support filetransfers"),
468 781 => Some("invalid channel password"),
469 782 => Some("channel is private channel"),
470 783 => Some("invalid security hash supplied by client"),
471 1024 => Some("invalid serverID"),
472 1025 => Some("server is running"),
473 1026 => Some("server is shutting down"),
474 1027 => Some("server maxclient reached"),
475 1028 => Some("invalid server password"),
476 1029 => Some("deployment active"),
477 1030 => Some("unable to stop own server in your connection class"),
478 1031 => Some("server is virtual"),
479 1032 => Some("server wrong machineID"),
480 1033 => Some("server is not running"),
481 1034 => Some("server is booting up"),
482 1035 => Some("server got an invalid status for this operation"),
483 1036 => Some("server modal quit"),
484 1037 => Some("server version is too old for command"),
485 1040 => Some("server blacklisted"),
486 1280 => Some("database error"),
487 1281 => Some("database empty result set"),
488 1282 => Some("database duplicate entry"),
489 1283 => Some("database no modifications"),
490 1284 => Some("database invalid constraint"),
491 1285 => Some("database reinvoke command"),
492 1536 => Some("invalid quote"),
493 1537 => Some("invalid parameter count"),
494 1538 => Some("invalid parameter"),
495 1539 => Some("parameter not found"),
496 1540 => Some("convert error"),
497 1541 => Some("invalid parameter size"),
498 1542 => Some("missing required parameter"),
499 1543 => Some("invalid checksum"),
500 1792 => Some("virtual server got a critical error"),
501 1793 => Some("Connection lost"),
502 1794 => Some("not connected"),
503 1795 => Some("no cached connection info"),
504 1796 => Some("currently not possible"),
505 1797 => Some("failed connection initialization"),
506 1798 => Some("could not resolve hostname"),
507 1799 => Some("invalid server connection handler ID"),
508 1800 => Some("could not initialize Input Manager"),
509 1801 => Some("client library not initialized"),
510 1802 => Some("server library not initialized"),
511 1803 => Some("too many whisper targets"),
512 1804 => Some("no whisper targets found"),
513 2048 => Some("invalid file name"),
514 2049 => Some("invalid file permissions"),
515 2050 => Some("file already exists"),
516 2051 => Some("file not found"),
517 2052 => Some("file input/output error"),
518 2053 => Some("invalid file transfer ID"),
519 2054 => Some("invalid file path"),
520 2055 => Some("no files available"),
521 2056 => Some("overwrite excludes resume"),
522 2057 => Some("invalid file size"),
523 2058 => Some("file already in use"),
524 2059 => Some("could not open file transfer connection"),
525 2060 => Some("no space left on device (disk full?)"),
526 2061 => Some("file exceeds file system's maximum file size"),
527 2062 => Some("file transfer connection timeout"),
528 2063 => Some("lost file transfer connection"),
529 2064 => Some("file exceeds supplied file size"),
530 2065 => Some("file transfer complete"),
531 2066 => Some("file transfer canceled"),
532 2067 => Some("file transfer interrupted"),
533 2068 => Some("file transfer server quota exceeded"),
534 2069 => Some("file transfer client quota exceeded"),
535 2070 => Some("file transfer reset"),
536 2071 => Some("file transfer limit reached"),
537 2304 => Some("preprocessor disabled"),
538 2305 => Some("internal preprocessor"),
539 2306 => Some("internal encoder"),
540 2307 => Some("internal playback"),
541 2308 => Some("no capture device available"),
542 2309 => Some("no playback device available"),
543 2310 => Some("could not open capture device"),
544 2311 => Some("could not open playback device"),
545 2312 => Some("ServerConnectionHandler has a device registered"),
546 2313 => Some("invalid capture device"),
547 2314 => Some("invalid clayback device"),
548 2315 => Some("invalid wave file"),
549 2316 => Some("wave file type not supported"),
550 2317 => Some("could not open wave file"),
551 2318 => Some("internal capture"),
552 2319 => Some("device still in use"),
553 2320 => Some("device already registerred"),
554 2321 => Some("device not registered/known"),
555 2322 => Some("unsupported frequency"),
556 2323 => Some("invalid channel count"),
557 2324 => Some("read error in wave"),
558 2325 => Some("sound need more data"),
559 2326 => Some("sound device was busy"),
560 2327 => Some("there is no sound data for this period"),
561 2328 => {
562 Some("Channelmask set bits count (speakers) is not the same as channel (count)")
563 }
564 2560 => Some("invalid group ID"),
565 2561 => Some("duplicate entry"),
566 2562 => Some("invalid permission ID"),
567 2563 => Some("empty result set"),
568 2564 => Some("access to default group is forbidden"),
569 2565 => Some("invalid size"),
570 2566 => Some("invalid value"),
571 2567 => Some("group is not empty"),
572 2568 => Some("insufficient client permissions"),
573 2569 => Some("insufficient group modify power"),
574 2570 => Some("insufficient permission modify power"),
575 2571 => Some("template group is currently used"),
576 2572 => Some("permission error"),
577 2816 => Some("virtualserver limit reached"),
578 2817 => Some("max slot limit reached"),
579 2818 => Some("license file not found"),
580 2819 => Some("license date not ok"),
581 2820 => Some("unable to connect to accounting server"),
582 2821 => Some("unknown accounting error"),
583 2822 => Some("accounting server error"),
584 2823 => Some("instance limit reached"),
585 2824 => Some("instance check error"),
586 2825 => Some("license file invalid"),
587 2826 => Some("virtualserver is running elsewhere"),
588 2827 => Some("virtualserver running in same instance already"),
589 2828 => Some("virtualserver already started"),
590 2829 => Some("virtualserver not started"),
591 3072 => Some("invalid message id"),
592 3328 => Some("invalid ban id"),
593 3329 => Some("connection failed, you are banned"),
594 3330 => Some("rename failed, new name is banned"),
595 3331 => Some("flood ban"),
596 3584 => Some("unable to initialize tts"),
597 3840 => Some("invalid privilege key"),
598 4352 => Some("invalid password"),
599 4353 => Some("invalid request"),
600 4354 => Some("no (more) slots available"),
601 4355 => Some("pool missing"),
602 4356 => Some("pool unknown"),
603 4357 => Some("unknown ip location (perhaps LAN ip?)"),
604 4358 => Some("internal error (tried exceeded)"),
605 4359 => Some("too many slots requested"),
606 4360 => Some("too many reserved"),
607 4361 => Some("could not connect to provisioning server"),
608 4368 => Some("authentication server not connected"),
609 4369 => Some("authentication data too large"),
610 4370 => Some("already initialized"),
611 4371 => Some("not initialized"),
612 4372 => Some("already connecting"),
613 4373 => Some("already connected"),
614 4375 => Some("io_error"),
615 _ => None,
616 }
617 }
618}
619
620impl std::fmt::Display for ErrorResponse {
621 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
622 if let Some(descr) = self.error_name() {
623 writeln!(f, "Error {}: {}, msg: {}", self.id, descr, self.msg)
624 } else {
625 writeln!(f, "Unknown Error code {}, msg: {}", self.id, self.msg)
626 }
627 }
628}