1use std::borrow::Cow;
2use std::collections::{HashMap, HashSet};
3use std::net::{IpAddr, SocketAddr};
4use std::{iter, mem, u16};
5
6use serde::{Deserialize, Serialize};
7use time::{Duration, OffsetDateTime};
8use tsproto_packets::packets::OutCommand;
9use tsproto_types::crypto::EccKeyPubP256;
10use tsproto_types::*;
11
12use crate::events::{Event, ExtraInfo, PropertyId, PropertyValue, PropertyValueRef};
13use crate::messages::s2c::InMessage;
14use crate::messages::{c2s, s2c};
15use crate::{Error, MessageTarget, Result};
16
17include!(concat!(env!("OUT_DIR"), "/m2bdecls.rs"));
18include!(concat!(env!("OUT_DIR"), "/structs.rs"));
19include!(concat!(env!("OUT_DIR"), "/properties.rs"));
20
21pub mod exts {
22 use super::*;
23
24 include!(concat!(env!("OUT_DIR"), "/b2mdecls.rs"));
25}
26
27macro_rules! max_clients {
28 ($msg:ident) => {{
29 if $msg.is_max_clients_unlimited.unwrap_or_default() {
30 Some(MaxClients::Unlimited)
31 } else if $msg.max_clients.map(|i| i >= 0 && i <= u16::MAX as i32).unwrap_or_default() {
32 Some(MaxClients::Limited($msg.max_clients.unwrap() as u16))
33 } else {
34 None
36 }
37 }};
38}
39
40macro_rules! copy_attrs {
41 ($from:ident, $to:ident; $($attr:ident),* $(,)*; $($extra:ident: $ex:expr),* $(,)*) => {
42 $to {
43 $($attr: $from.$attr.clone(),)*
44 $($extra: $ex,)*
45 }
46 };
47}
48
49impl Connection {
50 pub fn new(public_key: EccKeyPubP256, msg: &s2c::InInitServer) -> Self {
51 let packet = msg.iter().next().unwrap();
52 Self {
53 own_client: packet.client_id,
54 server: copy_attrs!(packet, Server;
55 ask_for_privilegekey,
56 codec_encryption_mode,
57 created,
58 default_channel_group,
59 default_server_group,
60 hostbanner_gfx_interval,
61 hostbanner_gfx_url,
62 hostbanner_mode,
63 hostbanner_url,
64 hostbutton_gfx_url,
65 hostbutton_tooltip,
66 hostbutton_url,
67 hostmessage_mode,
68 hostmessage,
69 icon,
70 max_clients,
71 name,
72 nickname,
73 phonetic_name,
74 platform,
75 priority_speaker_dimm_modificator,
76 protocol_version,
77 temp_channel_default_delete_delay,
78 version,
79 welcome_message,
80 ;
81
82 id: packet.virtual_server_id,
83 public_key: public_key,
84 ips: packet.ips.clone().unwrap_or_else(Vec::new),
85 license: LicenseType::NoLicense,
87
88 optional_data: None,
89 connection_data: None,
90 ),
91 clients: HashMap::new(),
92 channels: HashMap::new(),
93 channel_groups: HashMap::new(),
94 server_groups: HashMap::new(),
95 }
96 }
97
98 pub fn handle_command(&mut self, msg: &s2c::InMessage) -> Result<(Vec<Event>, bool)> {
99 let (mut handled, mut events) = self.handle_command_generated(msg)?;
102 match msg {
104 InMessage::TextMessage(msg) => {
105 for msg in msg.iter() {
106 let target = match msg.target {
107 TextMessageTargetMode::Server => MessageTarget::Server,
108 TextMessageTargetMode::Channel => MessageTarget::Channel,
109 TextMessageTargetMode::Client => {
110 let client = if let Some(client) = msg.target_client_id {
111 client
112 } else {
113 return Err(Error::MessageWithoutTargetClientId);
114 };
115 MessageTarget::Client(client)
116 }
117 TextMessageTargetMode::Unknown => {
118 return Err(Error::UnknownTextMessageTargetMode);
119 }
120 };
121 events.push(Event::Message {
122 target,
123 invoker: Invoker {
124 name: msg.invoker_name.clone(),
125 id: msg.invoker_id,
126 uid: msg.invoker_uid.clone(),
127 },
128 message: msg.message.to_string(),
129 });
130 handled = true;
131 }
132 }
133 InMessage::ClientPoke(msg) => {
134 for msg in msg.iter() {
135 events.push(Event::Message {
136 target: MessageTarget::Poke(msg.invoker_id),
137 invoker: Invoker {
138 name: msg.invoker_name.clone(),
139 id: msg.invoker_id,
140 uid: msg.invoker_uid.clone(),
141 },
142 message: msg.message.to_string(),
143 });
144 handled = true;
145 }
146 }
147 InMessage::CommandError(_) => handled = true,
148 _ => {}
149 }
150
151 if let Some(invoker) = events.first().and_then(Event::get_invoker) {
152 if let Ok(client) = self.get_mut_client(invoker.id) {
154 if client.name != invoker.name {
155 let old = mem::replace(&mut client.name, invoker.name.clone());
156 events.push(Event::PropertyChanged {
157 id: PropertyId::ClientName(client.id),
158 old: PropertyValue::String(old),
159 invoker: None,
160 extra: ExtraInfo { reason: None },
161 });
162 }
163 }
164 }
165
166 Ok((events, handled))
167 }
168
169 fn get_server(&self) -> Result<&Server> { Ok(&self.server) }
170 fn get_mut_server(&mut self) -> Result<&mut Server> { Ok(&mut self.server) }
171
172 fn get_channel_group(&self, group: ChannelGroupId) -> Result<&ChannelGroup> {
173 self.channel_groups
174 .get(&group)
175 .ok_or_else(|| Error::NotFound("ChannelGroup", group.to_string()))
176 }
177 fn add_channel_group(
178 &mut self, group: ChannelGroupId, r: ChannelGroup, _: &mut Vec<Event>,
179 ) -> Result<Option<ChannelGroup>> {
180 Ok(self.channel_groups.insert(group, r))
181 }
182 fn get_server_group(&self, group: ServerGroupId) -> Result<&ServerGroup> {
183 self.server_groups
184 .get(&group)
185 .ok_or_else(|| Error::NotFound("ServerGroup", group.to_string()))
186 }
187 fn add_server_group(
188 &mut self, group: ServerGroupId, r: ServerGroup, _: &mut Vec<Event>,
189 ) -> Result<Option<ServerGroup>> {
190 Ok(self.server_groups.insert(group, r))
191 }
192
193 fn get_optional_server_data(&self) -> Result<Option<&OptionalServerData>> {
194 Ok(self.server.optional_data.as_ref())
195 }
196 fn replace_optional_server_data(
197 &mut self, r: OptionalServerData, _: &mut Vec<Event>,
198 ) -> Result<Option<OptionalServerData>> {
199 Ok(mem::replace(&mut self.server.optional_data, Some(r)))
200 }
201 fn remove_optional_server_data(
202 &mut self, _: &mut Vec<Event>,
203 ) -> Result<Option<OptionalServerData>> {
204 Ok(self.server.optional_data.take())
205 }
206
207 fn get_connection_server_data(&self) -> Result<Option<&ConnectionServerData>> {
208 Ok(self.server.connection_data.as_ref())
209 }
210 fn replace_connection_server_data(
211 &mut self, r: ConnectionServerData, _: &mut Vec<Event>,
212 ) -> Result<Option<ConnectionServerData>> {
213 Ok(mem::replace(&mut self.server.connection_data, Some(r)))
214 }
215
216 fn get_connection(&self) -> Result<&Connection> { Ok(&self) }
217
218 fn get_client(&self, client: ClientId) -> Result<&Client> {
219 self.clients.get(&client).ok_or_else(|| Error::NotFound("Client", client.to_string()))
220 }
221 fn get_mut_client(&mut self, client: ClientId) -> Result<&mut Client> {
222 self.clients.get_mut(&client).ok_or_else(|| Error::NotFound("Client", client.to_string()))
223 }
224 fn add_client(
225 &mut self, client: ClientId, r: Client, _: &mut Vec<Event>,
226 ) -> Result<Option<Client>> {
227 Ok(self.clients.insert(client, r))
228 }
229 fn remove_client(&mut self, client: ClientId, _: &mut Vec<Event>) -> Result<Option<Client>> {
230 Ok(self.clients.remove(&client))
231 }
232
233 fn get_connection_client_data(
234 &self, client: ClientId,
235 ) -> Result<Option<&ConnectionClientData>> {
236 if let Some(c) = self.clients.get(&client) {
237 Ok(c.connection_data.as_ref())
238 } else {
239 Err(Error::NotFound("Client", client.to_string()))
240 }
241 }
242 fn replace_connection_client_data(
243 &mut self, client: ClientId, r: ConnectionClientData, _: &mut Vec<Event>,
244 ) -> Result<Option<ConnectionClientData>> {
245 if let Some(client) = self.clients.get_mut(&client) {
246 Ok(mem::replace(&mut client.connection_data, Some(r)))
247 } else {
248 Err(Error::NotFound("Client", client.to_string()))
249 }
250 }
251
252 fn get_optional_client_data(&self, client: ClientId) -> Result<Option<&OptionalClientData>> {
253 if let Some(c) = self.clients.get(&client) {
254 Ok(c.optional_data.as_ref())
255 } else {
256 Err(Error::NotFound("Client", client.to_string()))
257 }
258 }
259 fn replace_optional_client_data(
260 &mut self, client: ClientId, r: OptionalClientData, _: &mut Vec<Event>,
261 ) -> Result<Option<OptionalClientData>> {
262 if let Some(c) = self.clients.get_mut(&client) {
263 Ok(mem::replace(&mut c.optional_data, Some(r)))
264 } else {
265 Err(Error::NotFound("Client", client.to_string()))
266 }
267 }
268
269 fn get_channel(&self, channel: ChannelId) -> Result<&Channel> {
270 self.channels.get(&channel).ok_or_else(|| Error::NotFound("Channel", channel.to_string()))
271 }
272 fn get_mut_channel(&mut self, channel: ChannelId) -> Result<&mut Channel> {
273 self.channels
274 .get_mut(&channel)
275 .ok_or_else(|| Error::NotFound("Channel", channel.to_string()))
276 }
277 fn add_channel(
278 &mut self, channel: ChannelId, r: Channel, events: &mut Vec<Event>,
279 ) -> Result<Option<Channel>> {
280 self.channel_order_insert(r.id, r.order, r.parent, events);
281 Ok(self.channels.insert(channel, r))
282 }
283 fn remove_channel(
284 &mut self, channel: ChannelId, events: &mut Vec<Event>,
285 ) -> Result<Option<Channel>> {
286 let old = self.channels.remove(&channel);
287 if let Some(ch) = &old {
288 self.channel_order_remove(ch.id, ch.order, events);
289 }
290 Ok(old)
291 }
292
293 fn get_optional_channel_data(
294 &self, channel: ChannelId,
295 ) -> Result<Option<&OptionalChannelData>> {
296 if let Some(c) = self.channels.get(&channel) {
297 Ok(c.optional_data.as_ref())
298 } else {
299 Err(Error::NotFound("Channel", channel.to_string()))
300 }
301 }
302 fn replace_optional_channel_data(
303 &mut self, channel: ChannelId, r: OptionalChannelData, _: &mut Vec<Event>,
304 ) -> Result<Option<OptionalChannelData>> {
305 if let Some(c) = self.channels.get_mut(&channel) {
306 Ok(mem::replace(&mut c.optional_data, Some(r)))
307 } else {
308 Err(Error::NotFound("Channel", channel.to_string()))
309 }
310 }
311 fn remove_optional_channel_data(
312 &mut self, channel: ChannelId, _: &mut Vec<Event>,
313 ) -> Result<Option<OptionalChannelData>> {
314 if let Some(c) = self.channels.get_mut(&channel) {
315 Ok(c.optional_data.take())
316 } else {
317 Err(Error::NotFound("Channel", channel.to_string()))
318 }
319 }
320
321 fn return_false<T>(&self, _: T, _: &mut Vec<Event>) -> Result<bool> { Ok(false) }
324 fn return_none<T, O>(&self, _: T, _: &mut Vec<Event>) -> Result<Option<O>> { Ok(None) }
325 fn return_some_none<T, O>(&self, _: T, _: &mut Vec<Event>) -> Result<Option<Option<O>>> {
326 Ok(Some(None))
327 }
328 fn void_fun<T, U, V>(&self, _: T, _: U, _: V) -> Result<()> { Ok(()) }
329
330 fn max_clients_cc_fun(
331 &self, msg: &s2c::InChannelCreatedPart, _: &mut Vec<Event>,
332 ) -> Result<(Option<MaxClients>, Option<MaxClients>)> {
333 let ch = max_clients!(msg);
334 let ch_fam = if msg.is_max_family_clients_unlimited.unwrap_or_default() {
335 Some(MaxClients::Unlimited)
336 } else if msg.inherits_max_family_clients.unwrap_or_default() {
337 Some(MaxClients::Inherited)
338 } else if msg.max_family_clients.map(|i| i >= 0 && i <= u16::MAX as i32).unwrap_or_default()
339 {
340 Some(MaxClients::Limited(msg.max_family_clients.unwrap() as u16))
341 } else {
342 None
344 };
345 Ok((ch, ch_fam))
346 }
347 fn max_clients_ce_fun(
348 &mut self, channel_id: ChannelId, msg: &s2c::InChannelEditedPart, events: &mut Vec<Event>,
349 ) -> Result<()> {
350 let channel = self.get_mut_channel(channel_id)?;
351
352 let ch = max_clients!(msg);
353 if let Some(ch) = ch {
354 events.push(Event::PropertyChanged {
355 id: PropertyId::ChannelMaxClients(channel_id),
356 old: PropertyValue::OptionMaxClients(channel.max_clients.take()),
357 invoker: msg.get_invoker(),
358 extra: ExtraInfo { reason: Some(msg.reason) },
359 });
360 channel.max_clients = Some(ch);
361 }
362 let ch_fam = if msg.is_max_family_clients_unlimited.unwrap_or_default() {
363 Some(MaxClients::Unlimited)
364 } else if msg.inherits_max_family_clients.unwrap_or_default() {
365 Some(MaxClients::Inherited)
366 } else if msg.max_family_clients.map(|i| i >= 0 && i <= u16::MAX as i32).unwrap_or_default()
367 {
368 Some(MaxClients::Limited(msg.max_family_clients.unwrap() as u16))
369 } else {
370 None
372 };
373 if let Some(ch_fam) = ch_fam {
374 events.push(Event::PropertyChanged {
375 id: PropertyId::ChannelMaxFamilyClients(channel_id),
376 old: PropertyValue::OptionMaxClients(channel.max_family_clients.take()),
377 invoker: msg.get_invoker(),
378 extra: ExtraInfo { reason: Some(msg.reason) },
379 });
380 channel.max_family_clients = Some(ch_fam);
381 }
382 Ok(())
383 }
384 fn max_clients_cl_fun(
385 &self, msg: &s2c::InChannelListPart, _: &mut Vec<Event>,
386 ) -> Result<(Option<MaxClients>, Option<MaxClients>)> {
387 let max_clients: i32 = msg.max_clients;
388 let ch = if msg.is_max_clients_unlimited {
389 Some(MaxClients::Unlimited)
390 } else if max_clients >= 0 && max_clients <= u16::MAX as i32 {
391 Some(MaxClients::Limited(max_clients as u16))
392 } else {
393 None
395 };
396
397 let max_clients: i32 = msg.max_family_clients;
398 let ch_fam = if msg.is_max_family_clients_unlimited {
399 Some(MaxClients::Unlimited)
400 } else if msg.inherits_max_family_clients {
401 Some(MaxClients::Inherited)
402 } else if max_clients >= 0 && max_clients <= u16::MAX as i32 {
403 Some(MaxClients::Limited(max_clients as u16))
404 } else {
405 Some(MaxClients::Unlimited)
407 };
408 Ok((ch, ch_fam))
409 }
410
411 fn channel_type_cc_fun(
412 &self, msg: &s2c::InChannelCreatedPart, _: &mut Vec<Event>,
413 ) -> Result<ChannelType> {
414 Ok(Self::channel_flags_to_type(msg.is_permanent, msg.is_semi_permanent))
415 }
416
417 fn channel_type_ce_fun(
418 &mut self, channel_id: ChannelId, msg: &s2c::InChannelEditedPart, events: &mut Vec<Event>,
419 ) -> Result<()> {
420 let channel = self.get_mut_channel(channel_id)?;
421
422 if !msg.is_permanent.is_some() && !msg.is_semi_permanent.is_some() {
423 return Ok(());
424 }
425
426 let typ = Self::channel_flags_to_type(msg.is_permanent, msg.is_semi_permanent);
427 events.push(Event::PropertyChanged {
428 id: PropertyId::ChannelChannelType(channel_id),
429 old: PropertyValue::ChannelType(channel.channel_type),
430 invoker: msg.get_invoker(),
431 extra: ExtraInfo { reason: Some(msg.reason) },
432 });
433 channel.channel_type = typ;
434 Ok(())
435 }
436
437 fn channel_type_cl_fun(
438 &self, msg: &s2c::InChannelListPart, _: &mut Vec<Event>,
439 ) -> Result<ChannelType> {
440 Ok(Self::channel_flags_to_type(Some(msg.is_permanent), Some(msg.is_semi_permanent)))
441 }
442
443 fn channel_flags_to_type(perm: Option<bool>, semi: Option<bool>) -> ChannelType {
444 match (perm.unwrap_or_default(), semi.unwrap_or_default()) {
445 (true, _) => ChannelType::Permanent,
446 (_, true) => ChannelType::SemiPermanent,
447 (false, false) => ChannelType::Temporary,
448 }
449 }
450
451 fn channel_codec_cc_fun(
452 &self, msg: &s2c::InChannelCreatedPart, _: &mut Vec<Event>,
453 ) -> Result<Codec> {
454 Ok(msg.codec.unwrap_or(Codec::OpusVoice))
455 }
456
457 fn away_cev_fun(
458 &self, msg: &s2c::InClientEnterViewPart, _: &mut Vec<Event>,
459 ) -> Result<Option<String>> {
460 if msg.is_away { Ok(Some(msg.away_message.clone())) } else { Ok(None) }
461 }
462
463 fn client_type_cev_fun(
464 &self, msg: &s2c::InClientEnterViewPart, _: &mut Vec<Event>,
465 ) -> Result<ClientType> {
466 if msg.uid.is_server_admin() {
467 if let ClientType::Query { .. } = msg.client_type {
468 return Ok(ClientType::Query { admin: true });
469 }
470 }
471 Ok(msg.client_type.clone())
472 }
473
474 fn away_cu_fun(
475 &mut self, client_id: ClientId, msg: &s2c::InClientUpdatedPart, events: &mut Vec<Event>,
476 ) -> Result<()> {
477 let client = self.get_mut_client(client_id)?;
478
479 if let Some(is_away) = msg.is_away {
480 if is_away != client.away_message.is_some() {
481 let away = if is_away {
482 Some(msg.away_message.clone().unwrap_or_else(String::new))
483 } else {
484 None
485 };
486 events.push(Event::PropertyChanged {
487 id: PropertyId::ClientAwayMessage(client_id),
488 old: PropertyValue::OptionString(client.away_message.take()),
489 invoker: msg.get_invoker(),
490 extra: ExtraInfo { reason: None },
491 });
492 client.away_message = away;
493 }
494 } else if let Some(away_message) = &msg.away_message {
495 if let Some(cur_msg) = &client.away_message {
496 if away_message != cur_msg {
497 events.push(Event::PropertyChanged {
498 id: PropertyId::ClientAwayMessage(client_id),
499 old: PropertyValue::OptionString(client.away_message.take()),
500 invoker: msg.get_invoker(),
501 extra: ExtraInfo { reason: None },
502 });
503 client.away_message = Some(away_message.clone());
504 }
505 }
506 }
507 Ok(())
508 }
509
510 fn talk_power_cev_fun(
511 &self, msg: &s2c::InClientEnterViewPart, _: &mut Vec<Event>,
512 ) -> Result<Option<TalkPowerRequest>> {
513 if msg.talk_power_request_time.unix_timestamp() > 0 {
514 Ok(Some(TalkPowerRequest {
515 time: msg.talk_power_request_time,
516 message: msg.talk_power_request_message.clone(),
517 }))
518 } else {
519 Ok(None)
520 }
521 }
522
523 fn talk_power_cu_fun(
524 &mut self, client_id: ClientId, msg: &s2c::InClientUpdatedPart, events: &mut Vec<Event>,
525 ) -> Result<()> {
526 if let Some(talk_request) = msg.talk_power_request_time {
527 let client = self.get_mut_client(client_id)?;
528
529 let talk_request = if talk_request.unix_timestamp() > 0 {
530 Some(TalkPowerRequest {
531 time: talk_request,
532 message: msg.talk_power_request_message.clone().unwrap_or_else(String::new),
533 })
534 } else {
535 None
536 };
537 events.push(Event::PropertyChanged {
538 id: PropertyId::ClientTalkPowerRequest(client_id),
539 old: PropertyValue::OptionTalkPowerRequest(client.talk_power_request.take()),
540 invoker: msg.get_invoker(),
541 extra: ExtraInfo { reason: None },
542 });
543 client.talk_power_request = talk_request;
544 }
545 Ok(())
546 }
547
548 fn address_fun(
549 &self, msg: &s2c::InClientConnectionInfoPart, _: &mut Vec<Event>,
550 ) -> Result<Option<Option<SocketAddr>>> {
551 if let (Some(ip), Some(port)) = (&msg.ip, &msg.port) {
552 if !ip.is_empty() {
553 return Ok(Some(Some(SocketAddr::new(
554 ip.trim_matches(&['[', ']'][..]).parse().map_err(Error::InvalidConnectionIp)?,
555 *port,
556 ))));
557 }
558 }
559 Ok(Some(None))
560 }
561
562 fn channel_subscribe_fun(
563 &mut self, channel_id: ChannelId, _: &s2c::InChannelSubscribedPart, events: &mut Vec<Event>,
564 ) -> Result<()> {
565 let channel = self.get_mut_channel(channel_id)?;
566 events.push(Event::PropertyChanged {
567 id: PropertyId::ChannelSubscribed(channel_id),
568 old: PropertyValue::Bool(channel.subscribed),
569 invoker: None,
570 extra: ExtraInfo { reason: None },
571 });
572 channel.subscribed = true;
573 Ok(())
574 }
575
576 fn channel_unsubscribe_fun(
577 &mut self, channel_id: ChannelId, _: &s2c::InChannelUnsubscribedPart,
578 events: &mut Vec<Event>,
579 ) -> Result<()> {
580 let channel = self.get_mut_channel(channel_id)?;
581 events.push(Event::PropertyChanged {
582 id: PropertyId::ChannelSubscribed(channel_id),
583 old: PropertyValue::Bool(channel.subscribed),
584 invoker: None,
585 extra: ExtraInfo { reason: None },
586 });
587 channel.subscribed = false;
588
589 let remove_clients = self
591 .clients
592 .values()
593 .filter_map(|c| if c.channel == channel_id { Some(c.id) } else { None })
594 .collect::<Vec<_>>();
595 for id in remove_clients {
596 events.push(Event::PropertyRemoved {
597 id: PropertyId::Client(id),
598 old: PropertyValue::Client(self.clients.remove(&id).unwrap()),
599 invoker: None,
600 extra: ExtraInfo { reason: None },
601 });
602 }
603 Ok(())
604 }
605
606 fn channel_order_remove(
607 &mut self, channel_id: ChannelId, channel_order: ChannelId, events: &mut Vec<Event>,
608 ) {
609 self.channels.values_mut().any(|c| {
613 if c.order == channel_id && c.id != channel_id {
614 events.push(Event::PropertyChanged {
615 id: PropertyId::ChannelOrder(c.id),
616 old: PropertyValue::ChannelId(c.order),
617 invoker: None,
618 extra: ExtraInfo { reason: None },
619 });
620 c.order = channel_order;
621 true
622 } else {
623 false
624 }
625 });
626 }
627
628 fn channel_order_insert(
629 &mut self, channel_id: ChannelId, channel_order: ChannelId, channel_parent: ChannelId,
630 events: &mut Vec<Event>,
631 ) {
632 self.channels.values_mut().any(|c| {
638 if c.order == channel_order && c.parent == channel_parent && c.id != channel_id {
639 events.push(Event::PropertyChanged {
640 id: PropertyId::ChannelOrder(c.id),
641 old: PropertyValue::ChannelId(c.order),
642 invoker: None,
643 extra: ExtraInfo { reason: None },
644 });
645 c.order = channel_id;
646 true
647 } else {
648 false
649 }
650 });
651 }
652
653 fn channel_order_cc_fun(
654 &mut self, msg: &s2c::InChannelCreatedPart, events: &mut Vec<Event>,
655 ) -> Result<ChannelId> {
656 self.channel_order_insert(msg.channel_id, msg.order, msg.parent_id, events);
657 Ok(msg.order)
658 }
659
660 fn channel_order_ce_fun(
661 &mut self, channel_id: ChannelId, msg: &s2c::InChannelEditedPart, events: &mut Vec<Event>,
662 ) -> Result<()> {
663 self.channel_order_move_fun(channel_id, msg.order, msg.parent_id, events)
664 }
665
666 fn channel_order_cm_fun(
667 &mut self, channel_id: ChannelId, msg: &s2c::InChannelMovedPart, events: &mut Vec<Event>,
668 ) -> Result<()> {
669 self.channel_order_move_fun(channel_id, Some(msg.order), Some(msg.parent_id), events)
670 }
671
672 fn channel_order_move_fun(
673 &mut self, channel_id: ChannelId, new_order: Option<ChannelId>, parent: Option<ChannelId>,
674 events: &mut Vec<Event>,
675 ) -> Result<()> {
676 if new_order.is_some() || parent.is_some() {
677 let old_order;
678 let new_parent;
679 {
680 let channel = self.get_mut_channel(channel_id)?;
681 old_order = channel.order;
682 new_parent = parent.unwrap_or(channel.parent);
683 if let Some(order) = new_order {
684 events.push(Event::PropertyChanged {
685 id: PropertyId::ChannelOrder(channel.id),
686 old: PropertyValue::ChannelId(channel.order),
687 invoker: None,
688 extra: ExtraInfo { reason: None },
689 });
690 channel.order = order;
691 }
692 }
693 self.channel_order_remove(channel_id, old_order, events);
694 self.channel_order_insert(
695 channel_id,
696 new_order.unwrap_or(old_order),
697 new_parent,
698 events,
699 );
700 }
701 Ok(())
702 }
703
704 fn subscribe_channel_fun(
705 &mut self, client_id: ClientId, msg: &s2c::InClientMovedPart, events: &mut Vec<Event>,
706 ) -> Result<()> {
707 if client_id == self.own_client && msg.target_channel_id.0 != 0 {
708 let channel = self.get_mut_channel(msg.target_channel_id)?;
709 events.push(Event::PropertyChanged {
710 id: PropertyId::ChannelSubscribed(msg.target_channel_id),
711 old: PropertyValue::Bool(channel.subscribed),
712 invoker: None,
713 extra: ExtraInfo { reason: None },
714 });
715 channel.subscribed = true;
716 }
717 Ok(())
718 }
719
720 fn away_fun_b2m<'a>(msg: Option<&'a str>) -> (bool, &'a str) {
722 if let Some(msg) = msg { (true, msg) } else { (false, "") }
723 }
724}
725
726impl Client {
727 fn password_b2m<'a>(password: &'a str) -> String {
729 tsproto_types::crypto::encode_password(password.as_bytes()).into()
730 }
731 fn channel_id_b2m(&self, channel: ChannelId) -> ChannelId { channel }
732
733 pub fn send_textmessage(&self, message: &str) -> OutCommand {
734 c2s::OutSendTextMessageMessage::new(&mut iter::once(c2s::OutSendTextMessagePart {
735 target: TextMessageTargetMode::Client,
736 target_client_id: Some(self.id),
737 message: message.into(),
738 }))
739 }
740
741 pub fn poke(&self, message: &str) -> OutCommand {
742 c2s::OutClientPokeRequestMessage::new(&mut iter::once(c2s::OutClientPokeRequestPart {
743 client_id: self.id,
744 message: message.into(),
745 }))
746 }
747}
748
749impl Channel {
750 fn password_b2m<'a>(&self, password: &'a str) -> String {
752 tsproto_types::crypto::encode_password(password.as_bytes()).into()
753 }
754
755 fn password_b2m2<'a>(password: &'a str) -> String {
756 tsproto_types::crypto::encode_password(password.as_bytes()).into()
757 }
758
759 fn password_flagged_b2m<'a>(password: Option<&'a str>) -> (bool, Cow<'static, str>) {
760 if let Some(password) = password {
761 (true, tsproto_types::crypto::encode_password(password.as_bytes()).into())
762 } else {
763 (false, "".into())
764 }
765 }
766
767 fn channel_type_fun_b2m(channel_type: ChannelType) -> (bool, bool) {
768 match channel_type {
769 ChannelType::Temporary => (false, false),
770 ChannelType::SemiPermanent => (true, false),
771 ChannelType::Permanent => (false, true),
772 }
773 }
774
775 fn max_clients_fun_b2m(max_clients: MaxClients) -> (i32, bool) {
776 match max_clients {
777 MaxClients::Inherited => (0, false),
778 MaxClients::Unlimited => (0, true),
779 MaxClients::Limited(num) => (num.into(), false),
780 }
781 }
782
783 fn max_family_clients_fun_b2m(max_clients: MaxClients) -> (i32, bool, bool) {
784 match max_clients {
785 MaxClients::Inherited => (0, false, true),
786 MaxClients::Unlimited => (0, true, false),
787 MaxClients::Limited(num) => (num.into(), false, false),
788 }
789 }
790
791 fn channel_id_b2m(&self, channel: ChannelId) -> ChannelId { channel }
792
793 pub fn set_subscribed(&self, subscribed: bool) -> OutCommand {
794 if subscribed {
795 c2s::OutChannelSubscribeMessage::new(&mut iter::once(c2s::OutChannelSubscribePart {
796 channel_id: self.id,
797 }))
798 } else {
799 c2s::OutChannelUnsubscribeMessage::new(&mut iter::once(
800 c2s::OutChannelUnsubscribePart { channel_id: self.id },
801 ))
802 }
803 }
804}
805
806#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
812pub struct ChannelOptions<'a> {
813 name: &'a str,
814 description: Option<&'a str>,
815 parent_id: Option<ChannelId>,
816 codec: Option<Codec>,
817 codec_quality: Option<u8>,
818 delete_delay: Option<Duration>,
819 password: Option<&'a str>,
820 is_default: bool,
821 max_clients: Option<MaxClients>,
822 max_family_clients: Option<MaxClients>,
823 channel_type: Option<ChannelType>,
824 is_unencrypted: Option<bool>,
825 order: Option<ChannelId>,
826 phonetic_name: Option<&'a str>,
827 topic: Option<&'a str>,
828}
829
830impl<'a> ChannelOptions<'a> {
831 pub fn new(name: &'a str) -> Self {
837 Self {
838 name,
839 description: None,
840 parent_id: None,
841 codec: None,
842 codec_quality: None,
843 delete_delay: None,
844 password: None,
845 is_default: false,
846 max_clients: None,
847 max_family_clients: None,
848 channel_type: None,
849 is_unencrypted: None,
850 order: None,
851 phonetic_name: None,
852 topic: None,
853 }
854 }
855
856 pub fn description(mut self, description: &'a str) -> Self {
857 self.description = Some(description);
858 self
859 }
860
861 pub fn parent_id(mut self, parent_id: ChannelId) -> Self {
862 self.parent_id = Some(parent_id);
863 self
864 }
865
866 pub fn codec(mut self, codec: Codec) -> Self {
867 self.codec = Some(codec);
868 self
869 }
870
871 pub fn codec_quality(mut self, codec_quality: u8) -> Self {
872 self.codec_quality = Some(codec_quality);
873 self
874 }
875
876 pub fn delete_delay(mut self, delete_delay: Duration) -> Self {
877 self.delete_delay = Some(delete_delay);
878 self
879 }
880
881 pub fn password(mut self, password: &'a str) -> Self {
882 self.password = Some(password);
883 self
884 }
885
886 pub fn default(mut self) -> Self {
887 self.is_default = true;
888 self
889 }
890
891 pub fn max_clients(mut self, max_clients: MaxClients) -> Self {
892 self.max_clients = Some(max_clients);
893 self
894 }
895
896 pub fn max_family_clients(mut self, max_family_clients: MaxClients) -> Self {
897 self.max_family_clients = Some(max_family_clients);
898 self
899 }
900
901 pub fn channel_type(mut self, channel_type: ChannelType) -> Self {
902 self.channel_type = Some(channel_type);
903 self
904 }
905
906 pub fn is_unencrypted(mut self, is_unencrypted: bool) -> Self {
907 self.is_unencrypted = Some(is_unencrypted);
908 self
909 }
910
911 pub fn order(mut self, order: ChannelId) -> Self {
913 self.order = Some(order);
914 self
915 }
916
917 pub fn phonetic_name(mut self, phonetic_name: &'a str) -> Self {
918 self.phonetic_name = Some(phonetic_name);
919 self
920 }
921
922 pub fn topic(mut self, topic: &'a str) -> Self {
923 self.topic = Some(topic);
924 self
925 }
926}
927
928impl Server {
929 pub fn add_channel(&self, options: ChannelOptions) -> OutCommand {
930 let inherits_max_family_clients = options
931 .max_family_clients
932 .as_ref()
933 .and_then(|m| if let MaxClients::Inherited = m { Some(true) } else { None });
934 let is_max_family_clients_unlimited = options
935 .max_family_clients
936 .as_ref()
937 .and_then(|m| if let MaxClients::Unlimited = m { Some(true) } else { None });
938 let max_family_clients = options
939 .max_family_clients
940 .as_ref()
941 .and_then(|m| if let MaxClients::Limited(n) = m { Some(*n as i32) } else { None });
942 let is_max_clients_unlimited = options
943 .max_clients
944 .as_ref()
945 .and_then(|m| if let MaxClients::Unlimited = m { Some(true) } else { None });
946 let max_clients = options
947 .max_clients
948 .as_ref()
949 .and_then(|m| if let MaxClients::Limited(n) = m { Some(*n as i32) } else { None });
950
951 let is_permanent = options
952 .channel_type
953 .as_ref()
954 .and_then(|t| if *t == ChannelType::Permanent { Some(true) } else { None });
955 let is_semi_permanent = options
956 .channel_type
957 .as_ref()
958 .and_then(|t| if *t == ChannelType::SemiPermanent { Some(true) } else { None });
959
960 c2s::OutChannelCreateMessage::new(&mut iter::once(c2s::OutChannelCreatePart {
961 name: options.name.into(),
962 description: options.description.map(Into::into),
963 parent_id: options.parent_id,
964 codec: options.codec,
965 codec_quality: options.codec_quality,
966 delete_delay: options.delete_delay,
967 has_password: if options.password.is_some() { Some(true) } else { None },
968 is_default: if options.is_default { Some(true) } else { None },
969 inherits_max_family_clients,
970 is_max_family_clients_unlimited,
971 is_max_clients_unlimited,
972 is_permanent,
973 is_semi_permanent,
974 max_family_clients,
975 max_clients,
976 is_unencrypted: options.is_unencrypted,
977 order: options.order,
978 password: options
979 .password
980 .map(|p| tsproto_types::crypto::encode_password(p.as_bytes()).into()),
981 phonetic_name: options.phonetic_name.map(Into::into),
982 topic: options.topic.map(Into::into),
983 }))
984 }
985
986 pub fn send_textmessage(&self, message: &str) -> OutCommand {
987 c2s::OutSendTextMessageMessage::new(&mut iter::once(c2s::OutSendTextMessagePart {
988 target: TextMessageTargetMode::Server,
989 target_client_id: None,
990 message: message.into(),
991 }))
992 }
993
994 pub fn set_subscribed(&self, subscribed: bool) -> OutCommand {
996 if subscribed {
997 c2s::OutChannelSubscribeAllMessage::new()
998 } else {
999 c2s::OutChannelUnsubscribeAllMessage::new()
1000 }
1001 }
1002
1003 fn zero_channel_id(&self) -> ChannelId { ChannelId(0) }
1004
1005 fn empty_string(&self) -> &'static str { "" }
1006
1007 fn password_b2m<'a>(password: Option<&'a str>) -> Cow<'static, str> {
1009 if let Some(password) = password {
1010 tsproto_types::crypto::encode_password(password.as_bytes()).into()
1011 } else {
1012 "".into()
1013 }
1014 }
1015}
1016
1017impl Connection {
1018 pub fn send_message(&self, target: MessageTarget, message: &str) -> OutCommand {
1019 match target {
1020 MessageTarget::Server => {
1021 c2s::OutSendTextMessageMessage::new(&mut iter::once(c2s::OutSendTextMessagePart {
1022 target: TextMessageTargetMode::Server,
1023 target_client_id: None,
1024 message: message.into(),
1025 }))
1026 }
1027 MessageTarget::Channel => {
1028 c2s::OutSendTextMessageMessage::new(&mut iter::once(c2s::OutSendTextMessagePart {
1029 target: TextMessageTargetMode::Channel,
1030 target_client_id: None,
1031 message: message.into(),
1032 }))
1033 }
1034 MessageTarget::Client(id) => {
1035 c2s::OutSendTextMessageMessage::new(&mut iter::once(c2s::OutSendTextMessagePart {
1036 target: TextMessageTargetMode::Client,
1037 target_client_id: Some(id),
1038 message: message.into(),
1039 }))
1040 }
1041 MessageTarget::Poke(id) => c2s::OutClientPokeRequestMessage::new(&mut iter::once(
1042 c2s::OutClientPokeRequestPart { client_id: id, message: message.into() },
1043 )),
1044 }
1045 }
1046
1047 pub fn disconnect(&self, options: crate::DisconnectOptions) -> OutCommand {
1048 c2s::OutDisconnectMessage::new(&mut iter::once(c2s::OutDisconnectPart {
1049 reason: options.reason,
1050 reason_message: options.message.map(Into::into),
1051 }))
1052 }
1053}