1#![allow(dead_code)]
67
68extern crate chrono;
69#[macro_use]
70extern crate lazy_static;
71extern crate ts3plugin_sys;
72
73pub use ts3plugin_sys::plugin_definitions::*;
74pub use ts3plugin_sys::public_definitions::*;
75pub use ts3plugin_sys::public_errors::Error;
76pub use ts3plugin_sys::ts3functions::Ts3Functions;
77
78pub use crate::plugin::*;
79
80use chrono::*;
81use std::collections::HashMap as Map;
82use std::ffi::{CStr, CString};
83use std::fmt;
84use std::mem::transmute;
85use std::ops::{Deref, DerefMut};
86use std::os::raw::{c_char, c_int};
87use std::sync::{MutexGuard, RwLock};
88
89macro_rules! to_cstring {
91 ($string: expr_2021) => {
92 CString::new($string).unwrap_or(CString::new("String contains null character").unwrap())
93 };
94}
95
96macro_rules! to_string {
98 ($string: expr_2021) => {{ String::from_utf8_lossy(CStr::from_ptr($string).to_bytes()).into_owned() }};
99}
100
101pub mod plugin;
103pub mod ts3interface;
104
105include!(concat!(env!("OUT_DIR"), "/channel.rs"));
107include!(concat!(env!("OUT_DIR"), "/connection.rs"));
108include!(concat!(env!("OUT_DIR"), "/server.rs"));
109
110#[doc(hidden)]
115pub static TS3_FUNCTIONS: RwLock<Option<Ts3Functions>> = RwLock::new(None);
116
117#[derive(Clone)]
121pub enum MessageReceiver {
122 Connection(ConnectionId),
123 Channel,
124 Server,
125}
126
127#[derive(Debug, PartialEq, Eq, Clone)]
129pub struct Permissions;
130
131#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
133pub struct ServerId(u64);
134
135#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
137pub struct ChannelId(u64);
138
139#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
141pub struct ConnectionId(u16);
142
143#[derive(Debug, Clone)]
144pub struct Permission {}
145
146#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
147pub struct PermissionId(u32);
148
149#[derive(Debug, Clone)]
150pub struct ServerGroup {}
151
152#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
153pub struct ServerGroupId(u64);
154
155#[derive(Debug, Clone)]
156pub struct ChannelGroup {}
157
158#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
159pub struct ChannelGroupId(u64);
160
161#[derive(Debug, Eq)]
165pub struct InvokerData {
166 id: ConnectionId,
167 uid: String,
168 name: String,
169}
170
171impl PartialEq<InvokerData> for InvokerData {
172 fn eq(&self, other: &InvokerData) -> bool {
173 self.id == other.id
174 }
175}
176
177impl InvokerData {
178 fn new(id: ConnectionId, uid: String, name: String) -> InvokerData {
179 InvokerData { id, uid, name }
180 }
181
182 pub fn get_id(&self) -> ConnectionId {
184 self.id
185 }
186
187 pub fn get_uid(&self) -> &String {
189 &self.uid
190 }
191
192 pub fn get_name(&self) -> &String {
194 &self.name
195 }
196}
197
198#[derive(Debug, Eq)]
201pub struct Invoker<'a> {
202 server: Server<'a>,
203 data: InvokerData,
204}
205
206impl<'a, 'b> PartialEq<Invoker<'b>> for Invoker<'a> {
207 fn eq(&self, other: &Invoker) -> bool {
208 self.server == other.server && self.data == other.data
209 }
210}
211impl<'a> Deref for Invoker<'a> {
212 type Target = InvokerData;
213 fn deref(&self) -> &Self::Target {
214 &self.data
215 }
216}
217
218impl<'a> Invoker<'a> {
219 fn new(server: Server<'a>, data: InvokerData) -> Invoker<'a> {
220 Invoker { server, data }
221 }
222
223 pub fn get_connection(&'_ self) -> Option<Connection<'_>> {
224 self.server.get_connection(self.id)
225 }
226}
227
228#[derive(Clone)]
230pub struct Server<'a> {
231 api: &'a TsApi,
232 data: Result<&'a ServerData, ServerId>,
233}
234
235impl<'a, 'b> PartialEq<Server<'b>> for Server<'a> {
236 fn eq(&self, other: &Server<'b>) -> bool {
237 self.get_id() == other.get_id()
238 }
239}
240impl<'a> Eq for Server<'a> {}
241impl<'a> fmt::Debug for Server<'a> {
242 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243 write!(f, "Server({})", self.get_id().0)
244 }
245}
246
247impl PartialEq<ServerData> for ServerData {
248 fn eq(&self, other: &ServerData) -> bool {
249 self.id == other.id
250 }
251}
252impl Eq for ServerData {}
253
254impl ServerData {
255 fn get_property_as_string(
257 id: ServerId, property: VirtualServerProperties,
258 ) -> Result<String, Error> {
259 unsafe {
260 let mut name: *mut c_char = std::ptr::null_mut();
261 let res: Error =
262 transmute((TS3_FUNCTIONS
263 .read()
264 .unwrap()
265 .as_ref()
266 .expect("Functions should be loaded")
267 .get_server_variable_as_string)(id.0, property as usize, &mut name));
268 match res {
269 Error::Ok => Ok(to_string!(name)),
270 _ => Err(res),
271 }
272 }
273 }
274
275 fn get_property_as_int(id: ServerId, property: VirtualServerProperties) -> Result<i32, Error> {
277 unsafe {
278 let mut number: c_int = 0;
279 let res: Error =
280 transmute((TS3_FUNCTIONS
281 .read()
282 .unwrap()
283 .as_ref()
284 .expect("Functions should be loaded")
285 .get_server_variable_as_int)(id.0, property as usize, &mut number));
286 match res {
287 Error::Ok => Ok(number as i32),
288 _ => Err(res),
289 }
290 }
291 }
292
293 fn get_property_as_uint64(
295 id: ServerId, property: VirtualServerProperties,
296 ) -> Result<u64, Error> {
297 unsafe {
298 let mut number: u64 = 0;
299 let res: Error = transmute((TS3_FUNCTIONS
300 .read()
301 .unwrap()
302 .as_ref()
303 .expect("Functions should be loaded")
304 .get_server_variable_as_uint64)(
305 id.0, property as usize, &mut number
306 ));
307 match res {
308 Error::Ok => Ok(number),
309 _ => Err(res),
310 }
311 }
312 }
313
314 fn query_own_connection_id(id: ServerId) -> Result<ConnectionId, Error> {
317 unsafe {
318 let mut number: u16 = 0;
319 let res: Error = transmute((TS3_FUNCTIONS
320 .read()
321 .unwrap()
322 .as_ref()
323 .expect("Functions should be loaded")
324 .get_client_id)(id.0, &mut number));
325 match res {
326 Error::Ok => Ok(ConnectionId(number)),
327 _ => Err(res),
328 }
329 }
330 }
331
332 fn query_connections(id: ServerId) -> Map<ConnectionId, ConnectionData> {
336 let mut map = Map::new();
337 let mut result: *mut u16 = std::ptr::null_mut();
339 let res: Error = unsafe {
340 transmute((TS3_FUNCTIONS
341 .read()
342 .unwrap()
343 .as_ref()
344 .expect("Functions should be loaded")
345 .get_client_list)(id.0, &mut result))
346 };
347 if res == Error::Ok {
348 unsafe {
349 let mut counter = 0;
350 while *result.offset(counter) != 0 {
351 let connection_id = ConnectionId(*result.offset(counter));
352 let mut connection = ConnectionData::new(id, connection_id);
353 connection.update();
354 map.insert(connection_id, connection);
355 counter += 1;
356 }
357 }
358 }
359 map
360 }
361
362 fn query_channels(id: ServerId) -> Result<Map<ChannelId, ChannelData>, Error> {
366 let mut map = Map::new();
367 let mut result: *mut u64 = std::ptr::null_mut();
369 let res: Error = unsafe {
370 transmute((TS3_FUNCTIONS
371 .read()
372 .unwrap()
373 .as_ref()
374 .expect("Functions should be loaded")
375 .get_channel_list)(id.0, &mut result))
376 };
377 if res == Error::Ok {
378 unsafe {
379 let mut counter = 0;
380 while *result.offset(counter) != 0 {
381 let channel_id = ChannelId(*result.offset(counter));
382 let mut channel = ChannelData::new(id, channel_id);
383 channel.update();
384 map.insert(channel_id, channel);
385 counter += 1;
386 }
387 }
388 Ok(map)
389 } else {
390 Err(res)
391 }
392 }
393
394 fn add_connection(&mut self, connection_id: ConnectionId) -> &mut ConnectionData {
397 let mut connection = ConnectionData::new(self.id, connection_id);
398 connection.update();
399 self.visible_connections.insert(connection_id, connection);
400 self.visible_connections.get_mut(&connection_id).unwrap()
401 }
402
403 fn remove_connection(&mut self, connection_id: ConnectionId) -> Option<ConnectionData> {
404 self.visible_connections.remove(&connection_id)
405 }
406
407 fn add_channel(&mut self, channel_id: ChannelId) -> Result<&mut ChannelData, Error> {
408 match self.channels {
409 Ok(ref mut cs) => {
410 let mut channel = ChannelData::new(self.id, channel_id);
411 channel.update();
412 cs.insert(channel_id, channel);
413 Ok(cs.get_mut(&channel_id).unwrap())
414 }
415 Err(error) => Err(error),
416 }
417 }
418
419 fn remove_channel(&mut self, channel_id: ChannelId) -> Option<ChannelData> {
420 self.channels.as_mut().ok().and_then(|cs| cs.remove(&channel_id))
421 }
422
423 fn get_mut_connection(&mut self, connection_id: ConnectionId) -> Option<&mut ConnectionData> {
426 self.visible_connections.get_mut(&connection_id)
427 }
428
429 fn get_mut_channel(&mut self, channel_id: ChannelId) -> Option<&mut ChannelData> {
432 self.channels.as_mut().ok().and_then(|cs| cs.get_mut(&channel_id))
433 }
434}
435
436impl<'a> Server<'a> {
437 fn new(api: &'a TsApi, data: &'a ServerData) -> Server<'a> {
438 Server { api, data: Ok(data) }
439 }
440
441 fn new_err(api: &'a TsApi, server_id: ServerId) -> Server<'a> {
442 Server { api, data: Err(server_id) }
443 }
444
445 pub fn get_id(&self) -> ServerId {
446 match self.data {
447 Ok(data) => data.get_id(),
448 Err(id) => id,
449 }
450 }
451
452 fn get_connection_unwrap(&self, connection_id: ConnectionId) -> Connection<'a> {
455 self.get_connection(connection_id).unwrap_or_else(|| {
456 self.api.log_or_print(
457 format!("Can't find connection {:?}", connection_id),
458 "rust-ts3plugin",
459 crate::LogLevel::Warning,
460 );
461 Connection::new_err(&self.api, self.get_id(), connection_id)
462 })
463 }
464
465 fn get_channel_unwrap(&self, channel_id: ChannelId) -> Channel<'a> {
468 self.get_channel(channel_id).unwrap_or_else(|| {
469 self.api.log_or_print(
470 format!("Can't find channel {:?}", channel_id),
471 "rust-ts3plugin",
472 crate::LogLevel::Warning,
473 );
474 Channel::new_owned(&self.api, self.get_id(), channel_id)
475 })
476 }
477
478 fn get_server_group_unwrap(&self, server_group_id: ServerGroupId) -> ServerGroup {
479 self.get_server_group(server_group_id).unwrap_or_else(|| {
480 ServerGroup {}
484 })
485 }
486
487 fn get_channel_group_unwrap(&self, channel_group_id: ChannelGroupId) -> ChannelGroup {
488 self.get_channel_group(channel_group_id).unwrap_or_else(|| {
489 ChannelGroup {}
492 })
493 }
494
495 pub fn get_own_connection(&self) -> Result<Connection<'a>, Error> {
504 match self.data {
505 Ok(data) => data.get_own_connection_id().map(|id| self.get_connection_unwrap(id)),
506 Err(_) => Err(Error::Ok),
507 }
508 }
509
510 pub fn get_connections(&self) -> Vec<Connection<'a>> {
512 match self.data {
513 Ok(data) => {
514 data.visible_connections.values().map(|c| Connection::new(self.api, &c)).collect()
515 }
516 Err(_) => Vec::new(),
517 }
518 }
519
520 pub fn get_channels(&self) -> Vec<Channel<'a>> {
522 match self.data {
523 Ok(data) => match data.channels {
524 Ok(ref cs) => cs.values().map(|c| Channel::new(self.api, &c)).collect(),
525 Err(_) => Vec::new(),
526 },
527 Err(_) => Vec::new(),
528 }
529 }
530
531 pub fn get_connection(&self, connection_id: ConnectionId) -> Option<Connection<'a>> {
534 self.data.ok().and_then(|data| {
535 data.visible_connections.get(&connection_id).map(|c| Connection::new(&self.api, c))
536 })
537 }
538
539 pub fn get_channel(&self, channel_id: ChannelId) -> Option<Channel<'a>> {
542 self.data.ok().and_then(|data| {
543 data.channels
544 .as_ref()
545 .ok()
546 .and_then(|cs| cs.get(&channel_id))
547 .map(|c| Channel::new(&self.api, c))
548 })
549 }
550
551 pub fn get_server_group(&self, _server_group_id: ServerGroupId) -> Option<ServerGroup> {
552 Some(ServerGroup {})
554 }
555
556 pub fn get_channel_group(&self, _channel_group_id: ChannelGroupId) -> Option<ChannelGroup> {
557 Some(ChannelGroup {})
559 }
560
561 pub fn send_message<S: AsRef<str>>(&self, message: S) -> Result<(), Error> {
563 unsafe {
564 let text = to_cstring!(message.as_ref());
565 let res: Error = transmute((TS3_FUNCTIONS
566 .read()
567 .unwrap()
568 .as_ref()
569 .expect("Functions should be loaded")
570 .request_send_server_text_msg)(
571 self.get_id().0, text.as_ptr(), std::ptr::null()
572 ));
573 match res {
574 Error::Ok => Ok(()),
575 _ => Err(res),
576 }
577 }
578 }
579
580 pub fn send_plugin_message<S: AsRef<str>>(&self, message: S) {
587 let text = to_cstring!(message.as_ref());
588 (TS3_FUNCTIONS
589 .read()
590 .unwrap()
591 .as_ref()
592 .expect("Functions should be loaded")
593 .send_plugin_command)(
594 self.get_id().0,
595 to_cstring!(self.api.get_plugin_id()).as_ptr(),
596 text.as_ptr(),
597 PluginTargetMode::Server as i32,
598 std::ptr::null(),
599 std::ptr::null(),
600 );
601 }
602
603 pub fn print_message<S: AsRef<str>>(&self, message: S, target: MessageTarget) {
606 let text = to_cstring!(message.as_ref());
607 (TS3_FUNCTIONS.read().unwrap().as_ref().expect("Functions should be loaded").print_message)(
608 self.get_id().0,
609 text.as_ptr(),
610 target,
611 );
612 }
613}
614
615#[derive(Clone)]
617pub struct Channel<'a> {
618 api: &'a TsApi,
619 data: Result<&'a ChannelData, (ServerId, ChannelId)>,
620}
621
622impl<'a, 'b> PartialEq<Channel<'b>> for Channel<'a> {
623 fn eq(&self, other: &Channel<'b>) -> bool {
624 self.get_server_id() == other.get_server_id() && self.get_id() == other.get_id()
625 }
626}
627impl<'a> Eq for Channel<'a> {}
628impl<'a> fmt::Debug for Channel<'a> {
629 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
630 write!(f, "Channel({})", self.get_id().0)
631 }
632}
633
634impl PartialEq<ChannelData> for ChannelData {
635 fn eq(&self, other: &ChannelData) -> bool {
636 self.server_id == other.server_id && self.id == other.id
637 }
638}
639impl Eq for ChannelData {}
640
641impl ChannelData {
642 fn get_property_as_string(
644 server_id: ServerId, id: ChannelId, property: ChannelProperties,
645 ) -> Result<String, Error> {
646 unsafe {
647 let mut name: *mut c_char = std::ptr::null_mut();
648 let res: Error = transmute((TS3_FUNCTIONS
649 .read()
650 .unwrap()
651 .as_ref()
652 .expect("Functions should be loaded")
653 .get_channel_variable_as_string)(
654 server_id.0, id.0, property as usize, &mut name
655 ));
656 match res {
657 Error::Ok => Ok(to_string!(name)),
658 _ => Err(res),
659 }
660 }
661 }
662
663 fn get_property_as_int(
665 server_id: ServerId, id: ChannelId, property: ChannelProperties,
666 ) -> Result<i32, Error> {
667 unsafe {
668 let mut number: c_int = 0;
669 let res: Error = transmute((TS3_FUNCTIONS
670 .read()
671 .unwrap()
672 .as_ref()
673 .expect("Functions should be loaded")
674 .get_channel_variable_as_int)(
675 server_id.0, id.0, property as usize, &mut number
676 ));
677 match res {
678 Error::Ok => Ok(number as i32),
679 _ => Err(res),
680 }
681 }
682 }
683
684 fn get_property_as_uint64(
686 server_id: ServerId, id: ChannelId, property: ChannelProperties,
687 ) -> Result<i32, Error> {
688 unsafe {
689 let mut number: u64 = 0;
690 let res: Error = transmute((TS3_FUNCTIONS
691 .read()
692 .unwrap()
693 .as_ref()
694 .expect("Functions should be loaded")
695 .get_channel_variable_as_uint64)(
696 server_id.0, id.0, property as usize, &mut number
697 ));
698 match res {
699 Error::Ok => Ok(number as i32),
700 _ => Err(res),
701 }
702 }
703 }
704
705 fn query_parent_channel_id(server_id: ServerId, id: ChannelId) -> Result<ChannelId, Error> {
707 unsafe {
708 let mut number: u64 = 0;
709 let res: Error =
710 transmute((TS3_FUNCTIONS
711 .read()
712 .unwrap()
713 .as_ref()
714 .expect("Functions should be loaded")
715 .get_parent_channel_of_channel)(server_id.0, id.0, &mut number));
716 match res {
717 Error::Ok => Ok(ChannelId(number)),
718 _ => Err(res),
719 }
720 }
721 }
722}
723
724impl<'a> Channel<'a> {
725 fn new(api: &'a TsApi, data: &'a ChannelData) -> Channel<'a> {
726 Channel { api, data: Ok(data) }
727 }
728
729 fn new_owned(api: &'a TsApi, server_id: ServerId, channel_id: ChannelId) -> Channel<'a> {
730 Channel { api, data: Err((server_id, channel_id)) }
731 }
732
733 fn get_server_id(&self) -> ServerId {
734 match self.data {
735 Ok(data) => data.get_server_id(),
736 Err((server_id, _)) => server_id,
737 }
738 }
739
740 pub fn get_id(&self) -> ChannelId {
741 match self.data {
742 Ok(data) => data.get_id(),
743 Err((_, channel_id)) => channel_id,
744 }
745 }
746
747 pub fn get_server(&self) -> Server<'a> {
749 self.api.get_server_unwrap(self.get_server_id())
750 }
751
752 pub fn get_parent_channel(&self) -> Result<Option<Channel<'a>>, Error> {
753 match self.data {
754 Ok(data) => data.get_parent_channel_id().map(|parent_channel_id| {
755 if parent_channel_id.0 == 0 {
756 None
757 } else {
758 Some(self.get_server().get_channel_unwrap(parent_channel_id))
759 }
760 }),
761 Err(_) => Err(Error::Ok),
762 }
763 }
764
765 pub fn send_message<S: AsRef<str>>(&self, message: S) -> Result<(), Error> {
767 unsafe {
768 let text = to_cstring!(message.as_ref());
769 let res: Error = transmute((TS3_FUNCTIONS
770 .read()
771 .unwrap()
772 .as_ref()
773 .expect("Functions should be loaded")
774 .request_send_channel_text_msg)(
775 self.data.unwrap().server_id.0,
776 text.as_ptr(),
777 self.data.unwrap().id.0,
778 std::ptr::null(),
779 ));
780 match res {
781 Error::Ok => Ok(()),
782 _ => Err(res),
783 }
784 }
785 }
786}
787
788#[derive(Clone)]
790pub struct Connection<'a> {
791 api: &'a TsApi,
792 data: Result<&'a ConnectionData, (ServerId, ConnectionId)>,
793}
794
795impl<'a, 'b> PartialEq<Connection<'b>> for Connection<'a> {
796 fn eq(&self, other: &Connection<'b>) -> bool {
797 self.get_server_id() == other.get_server_id() && self.get_id() == other.get_id()
798 }
799}
800impl<'a> Eq for Connection<'a> {}
801impl<'a> fmt::Debug for Connection<'a> {
802 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
803 write!(f, "Connection({})", self.get_id().0)
804 }
805}
806
807impl PartialEq<ConnectionData> for ConnectionData {
808 fn eq(&self, other: &ConnectionData) -> bool {
809 self.server_id == other.server_id && self.id == other.id
810 }
811}
812impl Eq for ConnectionData {}
813
814impl ConnectionData {
815 fn get_connection_property_as_string(
817 server_id: ServerId, id: ConnectionId, property: ConnectionProperties,
818 ) -> Result<String, Error> {
819 unsafe {
820 let mut name: *mut c_char = std::ptr::null_mut();
821 let res: Error = transmute((TS3_FUNCTIONS
822 .read()
823 .unwrap()
824 .as_ref()
825 .expect("Functions should be loaded")
826 .get_connection_variable_as_string)(
827 server_id.0, id.0, property as usize, &mut name
828 ));
829 match res {
830 Error::Ok => Ok(to_string!(name)),
831 _ => Err(res),
832 }
833 }
834 }
835
836 fn get_connection_property_as_uint64(
838 server_id: ServerId, id: ConnectionId, property: ConnectionProperties,
839 ) -> Result<u64, Error> {
840 unsafe {
841 let mut number: u64 = 0;
842 let res: Error = transmute((TS3_FUNCTIONS
843 .read()
844 .unwrap()
845 .as_ref()
846 .expect("Functions should be loaded")
847 .get_connection_variable_as_uint64)(
848 server_id.0, id.0, property as usize, &mut number
849 ));
850 match res {
851 Error::Ok => Ok(number),
852 _ => Err(res),
853 }
854 }
855 }
856
857 fn get_connection_property_as_double(
859 server_id: ServerId, id: ConnectionId, property: ConnectionProperties,
860 ) -> Result<f64, Error> {
861 unsafe {
862 let mut number: f64 = 0.0;
863 let res: Error = transmute((TS3_FUNCTIONS
864 .read()
865 .unwrap()
866 .as_ref()
867 .expect("Functions should be loaded")
868 .get_connection_variable_as_double)(
869 server_id.0, id.0, property as usize, &mut number
870 ));
871 match res {
872 Error::Ok => Ok(number),
873 _ => Err(res),
874 }
875 }
876 }
877
878 fn get_client_property_as_string(
880 server_id: ServerId, id: ConnectionId, property: ClientProperties,
881 ) -> Result<String, Error> {
882 unsafe {
883 let mut name: *mut c_char = std::ptr::null_mut();
884 let res: Error = transmute((TS3_FUNCTIONS
885 .read()
886 .unwrap()
887 .as_ref()
888 .expect("Functions should be loaded")
889 .get_client_variable_as_string)(
890 server_id.0, id.0, property as usize, &mut name
891 ));
892 match res {
893 Error::Ok => Ok(to_string!(name)),
894 _ => Err(res),
895 }
896 }
897 }
898
899 fn get_client_property_as_int(
901 server_id: ServerId, id: ConnectionId, property: ClientProperties,
902 ) -> Result<c_int, Error> {
903 unsafe {
904 let mut number: c_int = 0;
905 let res: Error = transmute((TS3_FUNCTIONS
906 .read()
907 .unwrap()
908 .as_ref()
909 .expect("Functions should be loaded")
910 .get_client_variable_as_int)(
911 server_id.0, id.0, property as usize, &mut number
912 ));
913 match res {
914 Error::Ok => Ok(number),
915 _ => Err(res),
916 }
917 }
918 }
919
920 fn query_channel_id(server_id: ServerId, id: ConnectionId) -> Result<ChannelId, Error> {
922 unsafe {
923 let mut number: u64 = 0;
924 let res: Error = transmute((TS3_FUNCTIONS
925 .read()
926 .unwrap()
927 .as_ref()
928 .expect("Functions should be loaded")
929 .get_channel_of_client)(server_id.0, id.0, &mut number));
930 match res {
931 Error::Ok => Ok(ChannelId(number)),
932 _ => Err(res),
933 }
934 }
935 }
936
937 fn query_whispering(server_id: ServerId, id: ConnectionId) -> Result<bool, Error> {
940 unsafe {
941 let mut number: c_int = 0;
942 let res: Error = transmute((TS3_FUNCTIONS
943 .read()
944 .unwrap()
945 .as_ref()
946 .expect("Functions should be loaded")
947 .is_whispering)(server_id.0, id.0, &mut number));
948 match res {
949 Error::Ok => Ok(number != 0),
950 _ => Err(res),
951 }
952 }
953 }
954}
955
956impl<'a> Connection<'a> {
957 fn new(api: &'a TsApi, data: &'a ConnectionData) -> Connection<'a> {
958 Connection { api, data: Ok(data) }
959 }
960
961 fn new_err(api: &'a TsApi, server_id: ServerId, connection_id: ConnectionId) -> Connection<'a> {
962 Connection { api, data: Err((server_id, connection_id)) }
963 }
964
965 fn get_server_id(&self) -> ServerId {
966 match self.data {
967 Ok(data) => data.get_server_id(),
968 Err((server_id, _)) => server_id,
969 }
970 }
971
972 pub fn get_id(&self) -> ConnectionId {
973 match self.data {
974 Ok(data) => data.get_id(),
975 Err((_, connection_id)) => connection_id,
976 }
977 }
978
979 pub fn get_server(&self) -> Server<'a> {
981 self.api.get_server_unwrap(self.get_server_id())
982 }
983
984 pub fn get_channel(&self) -> Result<Channel<'a>, Error> {
986 match self.data {
987 Ok(data) => data.get_channel_id().map(|c| self.get_server().get_channel_unwrap(c)),
988 Err(_) => Err(Error::Ok),
989 }
990 }
991
992 pub fn get_channel_group_inherited_channel(&self) -> Result<Channel<'a>, Error> {
993 match self.data {
994 Ok(data) => data
995 .get_channel_group_inherited_channel_id()
996 .map(|c| self.get_server().get_channel_unwrap(c)),
997 Err(_) => Err(Error::Ok),
998 }
999 }
1000
1001 pub fn send_message<S: AsRef<str>>(&self, message: S) -> Result<(), Error> {
1018 unsafe {
1019 let text = to_cstring!(message.as_ref());
1020 let res: Error = transmute((TS3_FUNCTIONS
1021 .read()
1022 .unwrap()
1023 .as_ref()
1024 .expect("Functions should be loaded")
1025 .request_send_private_text_msg)(
1026 self.data.unwrap().server_id.0,
1027 text.as_ptr(),
1028 self.data.unwrap().id.0,
1029 std::ptr::null(),
1030 ));
1031 match res {
1032 Error::Ok => Ok(()),
1033 _ => Err(res),
1034 }
1035 }
1036 }
1037}
1038
1039pub struct TsApiLock {
1040 guard: MutexGuard<'static, (Option<(TsApi, Box<dyn Plugin>)>, Option<String>)>,
1041}
1042impl Deref for TsApiLock {
1043 type Target = TsApi;
1044 fn deref(&self) -> &Self::Target {
1045 &self.guard.0.as_ref().unwrap().0
1046 }
1047}
1048impl DerefMut for TsApiLock {
1049 fn deref_mut(&mut self) -> &mut Self::Target {
1050 &mut self.guard.0.as_mut().unwrap().0
1051 }
1052}
1053
1054pub struct PluginLock {
1055 guard: MutexGuard<'static, (Option<(TsApi, Box<dyn Plugin>)>, Option<String>)>,
1056}
1057impl Deref for PluginLock {
1058 type Target = dyn Plugin;
1059 fn deref(&self) -> &Self::Target {
1060 &*self.guard.0.as_ref().unwrap().1
1061 }
1062}
1063impl DerefMut for PluginLock {
1064 fn deref_mut(&mut self) -> &mut Self::Target {
1065 &mut *self.guard.0.as_mut().unwrap().1
1066 }
1067}
1068
1069pub struct TsApi {
1072 servers: Map<ServerId, ServerData>,
1074 plugin_id: String,
1076}
1077
1078impl TsApi {
1081 fn new(plugin_id: String) -> TsApi {
1083 TsApi { servers: Map::new(), plugin_id: plugin_id }
1084 }
1085
1086 fn load(&mut self) -> Result<(), Error> {
1089 let mut result: *mut u64 = std::ptr::null_mut();
1091 let res: Error = unsafe {
1092 transmute((TS3_FUNCTIONS
1093 .read()
1094 .unwrap()
1095 .as_ref()
1096 .expect("Functions should be loaded")
1097 .get_server_connection_handler_list)(&mut result))
1098 };
1099 match res {
1100 Error::Ok => unsafe {
1101 let mut counter = 0;
1102 while *result.offset(counter) != 0 {
1103 let mut status: c_int = 0;
1106 let res: Error = transmute((TS3_FUNCTIONS
1107 .read()
1108 .unwrap()
1109 .as_ref()
1110 .expect("Functions should be loaded")
1111 .get_connection_status)(
1112 *result.offset(counter), &mut status
1113 ));
1114 if res == Error::Ok
1115 && transmute::<c_int, ConnectStatus>(status) != ConnectStatus::Disconnected
1116 {
1117 self.add_server(ServerId(*result.offset(counter)));
1118 }
1119 counter += 1;
1120 }
1121 },
1122 _ => return Err(res),
1123 }
1124 Ok(())
1125 }
1126
1127 pub fn lock_api() -> Option<TsApiLock> {
1130 let guard = ts3interface::DATA.lock().unwrap();
1131 if guard.0.is_none() { None } else { Some(TsApiLock { guard }) }
1132 }
1133
1134 pub fn lock_plugin() -> Option<PluginLock> {
1136 let guard = ts3interface::DATA.lock().unwrap();
1137 if guard.0.is_none() { None } else { Some(PluginLock { guard }) }
1138 }
1139
1140 pub fn static_log_message<S1: AsRef<str>, S2: AsRef<str>>(
1142 message: S1, channel: S2, severity: LogLevel,
1143 ) -> Result<(), Error> {
1144 unsafe {
1145 let res: Error = transmute((TS3_FUNCTIONS
1146 .read()
1147 .unwrap()
1148 .as_ref()
1149 .expect("Functions should be loaded")
1150 .log_message)(
1151 to_cstring!(message.as_ref()).as_ptr(),
1152 severity,
1153 to_cstring!(channel.as_ref()).as_ptr(),
1154 0,
1155 ));
1156 match res {
1157 Error::Ok => Ok(()),
1158 _ => Err(res),
1159 }
1160 }
1161 }
1162
1163 pub fn static_log_or_print<S1: AsRef<str>, S2: AsRef<str>>(
1165 message: S1, channel: S2, severity: LogLevel,
1166 ) {
1167 if let Err(error) = TsApi::static_log_message(message.as_ref(), channel.as_ref(), severity)
1168 {
1169 println!(
1170 "Error {:?} while printing '{}' to '{}' ({:?})",
1171 error,
1172 message.as_ref(),
1173 channel.as_ref(),
1174 severity
1175 );
1176 }
1177 }
1178
1179 pub fn static_get_error_message(error: Error) -> Result<String, Error> {
1181 unsafe {
1182 let mut message: *mut c_char = std::ptr::null_mut();
1183 let res: Error = transmute((TS3_FUNCTIONS
1184 .read()
1185 .unwrap()
1186 .as_ref()
1187 .expect("Functions should be loaded")
1188 .get_error_message)(error as u32, &mut message));
1189 match res {
1190 Error::Ok => Ok(to_string!(message)),
1191 _ => Err(res),
1192 }
1193 }
1194 }
1195
1196 fn add_server(&mut self, server_id: ServerId) -> &mut ServerData {
1201 self.servers.insert(server_id, ServerData::new(server_id));
1202 let server = self.servers.get_mut(&server_id).unwrap();
1203 server.update();
1204 server
1205 }
1206
1207 fn remove_server(&mut self, server_id: ServerId) -> Option<ServerData> {
1209 self.servers.remove(&server_id)
1210 }
1211
1212 pub fn get_plugin_id(&self) -> &str {
1214 &self.plugin_id
1215 }
1216
1217 fn try_update_invoker(&mut self, server_id: ServerId, invoker: &InvokerData) {
1220 if let Some(server) = self.get_mut_server(server_id) {
1221 if let Some(connection) = server.get_mut_connection(invoker.get_id()) {
1222 if connection.get_uid() != Ok(invoker.get_uid()) {
1223 connection.uid = Ok(invoker.get_uid().clone());
1224 }
1225 if connection.get_name() != Ok(invoker.get_name()) {
1226 connection.name = Ok(invoker.get_name().clone())
1227 }
1228 }
1229 }
1230 }
1231
1232 fn get_path<F: Fn(*mut c_char, usize)>(fun: F) -> String {
1239 const START_SIZE: usize = 512;
1240 const MAX_SIZE: usize = 100_000;
1241 let mut size = START_SIZE;
1242 loop {
1243 let mut buf = vec![0 as u8; size];
1244 fun(buf.as_mut_ptr() as *mut c_char, size - 1);
1245 if buf[size - 3] != 0 {
1247 size *= 2;
1248 if size > MAX_SIZE {
1249 return String::new();
1250 }
1251 } else {
1252 buf[size - 1] = 0;
1254 let s = unsafe { CStr::from_ptr(buf.as_ptr() as *const c_char) };
1255 let result = s.to_string_lossy();
1256 return result.into_owned();
1257 }
1258 }
1259 }
1260
1261 fn get_mut_server(&mut self, server_id: ServerId) -> Option<&mut ServerData> {
1264 self.servers.get_mut(&server_id)
1265 }
1266
1267 fn get_server_unwrap<'a>(&'a self, server_id: ServerId) -> Server<'a> {
1268 self.servers.get(&server_id).map(|s| Server::<'a>::new(&self, s)).unwrap_or_else(|| {
1269 Server::new_err(&self, server_id)
1274 })
1275 }
1276
1277 pub fn get_servers<'a>(&'a self) -> Vec<Server<'a>> {
1287 self.servers.values().map(|s| Server::new(&self, &s)).collect()
1288 }
1289
1290 pub fn log_message<S1: AsRef<str>, S2: AsRef<str>>(
1292 &self, message: S1, channel: S2, severity: LogLevel,
1293 ) -> Result<(), Error> {
1294 TsApi::static_log_message(message, channel, severity)
1295 }
1296
1297 pub fn log_or_print<S1: AsRef<str>, S2: AsRef<str>>(
1300 &self, message: S1, channel: S2, severity: LogLevel,
1301 ) {
1302 TsApi::static_log_or_print(message, channel, severity)
1303 }
1304
1305 pub fn get_server(&'_ self, server_id: ServerId) -> Option<Server<'_>> {
1308 self.servers.get(&server_id).map(|s| Server::new(&self, s))
1309 }
1310
1311 pub fn get_permission(&self, _permission_id: PermissionId) -> Option<&Permission> {
1312 Some(&Permission {})
1314 }
1315
1316 pub fn print_message<S: AsRef<str>>(&self, message: S) {
1319 let text = to_cstring!(message.as_ref());
1320 (TS3_FUNCTIONS
1321 .read()
1322 .unwrap()
1323 .as_ref()
1324 .expect("Functions should be loaded")
1325 .print_message_to_current_tab)(text.as_ptr());
1326 }
1327
1328 pub fn get_app_path(&self) -> String {
1330 TsApi::get_path(|p, l| {
1331 (TS3_FUNCTIONS
1332 .read()
1333 .unwrap()
1334 .as_ref()
1335 .expect("Functions should be loaded")
1336 .get_app_path)(p, l)
1337 })
1338 }
1339
1340 pub fn get_resources_path(&self) -> String {
1342 TsApi::get_path(|p, l| {
1343 (TS3_FUNCTIONS
1344 .read()
1345 .unwrap()
1346 .as_ref()
1347 .expect("Functions should be loaded")
1348 .get_resources_path)(p, l)
1349 })
1350 }
1351
1352 pub fn get_config_path(&self) -> String {
1355 TsApi::get_path(|p, l| {
1356 (TS3_FUNCTIONS
1357 .read()
1358 .unwrap()
1359 .as_ref()
1360 .expect("Functions should be loaded")
1361 .get_config_path)(p, l)
1362 })
1363 }
1364
1365 pub fn get_plugin_path(&self) -> String {
1367 TsApi::get_path(|p, l| {
1368 (TS3_FUNCTIONS
1369 .read()
1370 .unwrap()
1371 .as_ref()
1372 .expect("Functions should be loaded")
1373 .get_plugin_path)(p, l, to_cstring!(self.plugin_id.as_str()).as_ptr())
1374 })
1375 }
1376}