ts_bookkeeping/
data.rs

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			// Max clients is less than zero or too high so ignore it
35			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				// TODO Get from license struct
86				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		// Returns if it handled the message so we can warn if a message is
100		// unhandled.
101		let (mut handled, mut events) = self.handle_command_generated(msg)?;
102		// Handle special messages
103		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 we know this client and the name change, adjust the name.
153			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	// Backing functions for MessageToBook declarations
322
323	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			// Max clients is less than zero or too high so ignore it
343			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			// Max clients is less than zero or too high so ignore it
371			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			// Max clients is less than zero or too high so ignore it
394			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			// Max clients is less than zero or too high so ignore it
406			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		// Remove all known clients from this channel
590		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		// [ C:7 | O:_ ]
610		// [ C:5 | O:7 ] ─>X
611		// [ C:_ | O:5 ]     (Upd: O -> 7)
612		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		// [ C:7 | O:_ ]
633		// [            <── (New: C:5 | O:7)
634		// [ C:_ | O:7 ]    (Upd: O -> 5)
635		//
636		// Also work for the first channel, the order will be 0.
637		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	// Book to messages
721	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	// Book to messages
728	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	// Book to messages
751	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/// The `ChannelOptions` are used to set initial properties of a new channel.
807///
808/// A channel can be created with [`ServerMut::add_channel`]. The only necessary
809/// property of a channel is the name, all other properties will be set to their
810/// default value.
811#[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	/// Create new `ChannelOptions` to add a new channel to a server.
832	///
833	/// # Arguments
834	/// You have to supply a name for the new channel. All other properties are
835	/// optional.
836	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	/// The previous order
912	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	/// Subscribe or unsubscribe from all channels.
995	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	// Book to messages
1008	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}