ts3/
event.rs

1// Required for ts3_derive macro.
2#[allow(unused_imports)]
3use crate as ts3;
4
5use crate::client::Client;
6use crate::shared::list::Comma;
7use crate::shared::{ChannelGroupId, ChannelId, ClientDatabaseId, ClientId, List, ServerGroupId};
8use crate::{Decode, DecodeError, Error, ErrorKind};
9use async_trait::async_trait;
10use tokio::task::spawn;
11
12impl Client {
13    // Check buf for an event key. If one is found, a new task is spawned, the event
14    // is dispatched to the associated handler and true is returned. If buf does not
15    // contain event data, false is returned.
16    pub(crate) fn dispatch_event(&self, buf: &[u8]) -> bool {
17        let c = self.clone();
18        let handler = c.inner.read().unwrap().handler.clone();
19
20        // Split of the first argument (separated by ' '). It contains the event name.
21        // The rest of the buffer contains the event data.
22        let (event_name, rest): (&[u8], &[u8]);
23        {
24            let vec: Vec<&[u8]> = buf.splitn(2, |c| *c == b' ').collect();
25            event_name = vec[0];
26            rest = vec[1];
27        }
28
29        // buf contains the event data which will be moved to the event task.
30        let buf = rest.to_owned();
31
32        match event_name {
33            b"notifycliententerview" => {
34                let event = match ClientEnterView::decode(&buf) {
35                    Ok(event) => event,
36                    Err(err) => {
37                        handler.error(c, err);
38                        return true;
39                    }
40                };
41
42                spawn(async move { handler.cliententerview(c, event).await });
43            }
44            b"notifyclientleftview" => {
45                let event = match ClientLeftView::decode(&buf) {
46                    Ok(event) => event,
47                    Err(err) => {
48                        handler.error(c, err);
49                        return true;
50                    }
51                };
52
53                spawn(async move { handler.clientleftview(c, event).await });
54            }
55            b"notifyserveredited" => {
56                let event = match ServerEdited::decode(&buf) {
57                    Ok(event) => event,
58                    Err(err) => {
59                        handler.error(c, err);
60                        return true;
61                    }
62                };
63
64                spawn(async move { handler.serveredited(c, event).await });
65            }
66            b"notifychanneldescriptionchanged" => {
67                let event = match ChannelDescriptionChanged::decode(&buf) {
68                    Ok(event) => event,
69                    Err(err) => {
70                        handler.error(c, err);
71                        return true;
72                    }
73                };
74
75                spawn(async move { handler.channeldescriptionchanged(c, event).await });
76            }
77            b"notifychannelpasswordchanged" => {
78                let event = match ChannelPasswordChanged::decode(&buf) {
79                    Ok(event) => event,
80                    Err(err) => {
81                        handler.error(c, err);
82                        return true;
83                    }
84                };
85
86                spawn(async move { handler.channelpasswordchanged(c, event).await });
87            }
88            b"notifychannelmoved" => {
89                let event = match ChannelMoved::decode(&buf) {
90                    Ok(event) => event,
91                    Err(err) => {
92                        handler.error(c, err);
93                        return true;
94                    }
95                };
96
97                spawn(async move { handler.channelmoved(c, event).await });
98            }
99            b"notifychanneledited" => {
100                let event = match ChannelEdited::decode(&buf) {
101                    Ok(event) => event,
102                    Err(err) => {
103                        handler.error(c, err);
104                        return true;
105                    }
106                };
107
108                spawn(async move { handler.channeledited(c, event).await });
109            }
110            b"notifychannelcreated" => {
111                let event = match ChannelCreated::decode(&buf) {
112                    Ok(event) => event,
113                    Err(err) => {
114                        handler.error(c, err);
115                        return true;
116                    }
117                };
118
119                spawn(async move { handler.channelcreated(c, event).await });
120            }
121            b"notifychanneldeleted" => {
122                let event = match ChannelDeleted::decode(&buf) {
123                    Ok(event) => event,
124                    Err(err) => {
125                        handler.error(c, err);
126                        return true;
127                    }
128                };
129
130                spawn(async move { handler.channeldeleted(c, event).await });
131            }
132            b"notifyclientmoved" => {
133                let event = match ClientMoved::decode(&buf) {
134                    Ok(event) => event,
135                    Err(err) => {
136                        handler.error(c, err);
137                        return true;
138                    }
139                };
140
141                spawn(async move { handler.clientmoved(c, event).await });
142            }
143            b"notifytextmessage" => {
144                let event = match TextMessage::decode(&buf) {
145                    Ok(event) => event,
146                    Err(err) => {
147                        handler.error(c, err);
148                        return true;
149                    }
150                };
151
152                spawn(async move { handler.textmessage(c, event).await });
153            }
154            b"notifytokenused" => {
155                let event = match TokenUsed::decode(&buf) {
156                    Ok(event) => event,
157                    Err(err) => {
158                        handler.error(c, err);
159                        return true;
160                    }
161                };
162
163                spawn(async move { handler.tokenused(c, event).await });
164            }
165            _ => return false,
166        }
167
168        true
169    }
170}
171
172/// All events sent by the server will be dispatched to their appropriate trait method.
173/// In order to receive events you must subscribe to the events you want to receive using servernotifyregister.
174#[async_trait]
175pub trait EventHandler: Send + Sync {
176    async fn cliententerview(&self, _client: Client, _event: ClientEnterView) {}
177    async fn clientleftview(&self, _client: Client, _event: ClientLeftView) {}
178    async fn serveredited(&self, _client: Client, _event: ServerEdited) {}
179    async fn channeldescriptionchanged(&self, _client: Client, _event: ChannelDescriptionChanged) {}
180    async fn channelpasswordchanged(&self, _client: Client, _event: ChannelPasswordChanged) {}
181    async fn channelmoved(&self, _client: Client, _event: ChannelMoved) {}
182    async fn channeledited(&self, _client: Client, _event: ChannelEdited) {}
183    async fn channelcreated(&self, _client: Client, _event: ChannelCreated) {}
184    async fn channeldeleted(&self, _client: Client, _event: ChannelDeleted) {}
185    async fn clientmoved(&self, _client: Client, _event: ClientMoved) {}
186    async fn textmessage(&self, _client: Client, _event: TextMessage) {}
187    async fn tokenused(&self, _client: Client, _event: TokenUsed) {}
188
189    fn error(&self, _client: Client, error: Error) {
190        println!("connection error: {}", error);
191    }
192}
193
194/// Defines a reason why an event happened. Used in multiple event types.
195#[derive(Debug)]
196pub enum ReasonId {
197    /// Switched channel themselves or joined server
198    SwitchChannel = 0,
199    // Moved by another client or channel
200    Moved,
201    // Left server because of timeout (disconnect)
202    Timeout,
203    // Kicked from channel
204    ChannelKick,
205    // Kicked from server
206    ServerKick,
207    // Banned from server
208    Ban,
209    // Left server themselves
210    ServerLeave,
211    // Edited channel or server
212    Edited,
213    // Left server due shutdown
214    ServerShutdown,
215}
216
217impl Decode for ReasonId {
218    type Error = Error;
219
220    fn decode(buf: &[u8]) -> Result<ReasonId, Self::Error> {
221        match u8::decode(buf)? {
222            0 => Ok(Self::SwitchChannel),
223            1 => Ok(Self::Moved),
224            2 => Ok(Self::Timeout),
225            3 => Ok(Self::ChannelKick),
226            4 => Ok(Self::ServerKick),
227            5 => Ok(Self::Ban),
228            6 => Ok(Self::ServerLeave),
229            7 => Ok(Self::Edited),
230            8 => Ok(Self::ServerShutdown),
231            b => Err(Error(ErrorKind::Decode(DecodeError::InvalidReasonId(b)))),
232        }
233    }
234}
235
236impl Default for ReasonId {
237    fn default() -> ReasonId {
238        ReasonId::SwitchChannel
239    }
240}
241
242/// Data for a `cliententerview` event.
243#[derive(Debug, Decode, Default)]
244pub struct ClientEnterView {
245    pub cfid: ChannelId,
246    pub ctid: ChannelId,
247    pub reasonid: ReasonId,
248    pub clid: ClientId,
249    pub client_unique_identifier: String,
250    pub client_nickname: String,
251    pub client_input_muted: bool,
252    pub client_output_muted: bool,
253    pub client_outputonly_muted: bool,
254    pub client_input_hardware: u64,
255    pub client_output_hardware: u64,
256    // client_meta_data: (),
257    pub client_is_recording: bool,
258    pub client_database_id: ClientDatabaseId,
259    pub client_channel_group_id: ChannelGroupId,
260    pub client_servergroups: List<ServerGroupId, Comma>,
261    pub client_away: bool,
262    pub client_away_message: String,
263    pub client_type: u8,
264    // client_flag_avatar: (),
265    pub client_talk_power: u64,
266    pub client_talk_request: bool,
267    pub client_talk_request_msg: String,
268    pub client_description: String,
269    pub client_is_talker: bool,
270    pub client_nickname_phoentic: String,
271    pub client_needed_serverquey_view_power: u64,
272    pub client_icon_id: u64,
273    pub client_country: String,
274    pub client_channel_group_inherited_channel_id: u64,
275    pub client_badges: String,
276}
277
278/// Data for a `clientleftview` event.
279#[derive(Debug, Decode, Default)]
280pub struct ClientLeftView {
281    pub cfid: ChannelId,
282    pub ctid: ChannelId,
283    pub reasonid: ReasonId,
284    pub invokerid: ClientId,
285    pub invokername: String,
286    pub invokeruid: String,
287    pub reasonmsg: String,
288    pub bantime: u64,
289    pub clid: ClientId,
290}
291
292/// Data for a `serveredited` event.
293#[derive(Debug, Decode, Default)]
294pub struct ServerEdited {
295    pub reasonid: ReasonId,
296    pub invokerid: ClientId,
297    pub invokername: String,
298    pub invokeruid: String,
299    pub virtualserver_name: String,
300    pub virtualserver_codec_encryption_mode: String,
301    pub virtualserver_default_server_group: ServerGroupId,
302    pub virtualserver_default_channel_group: ChannelGroupId,
303    pub virtualserver_hostbanner_url: String,
304    pub virtualserver_hostbanner_gfx_url: String,
305    pub virtualserver_hostbanner_gfx_interval: u64,
306    pub virtualserver_priority_speaker_dimm_modificator: String,
307    pub virtualserver_hostbutton_tooltip: String,
308    pub virtualserver_hostbutton_url: String,
309    pub virtualserver_hostbutton_gfx_url: String,
310    pub virtualserver_name_phoentic: String,
311    pub virtualserver_icon_id: u64,
312    pub virtualserver_hostbanner_mode: String,
313    pub virtualserver_channel_temp_delete_delay_default: u64,
314}
315
316/// Data for a `channeldescriptionchanged` event.
317#[derive(Debug, Decode, Default)]
318pub struct ChannelDescriptionChanged {
319    pub cid: ChannelId,
320}
321
322/// Data for a `channelpasswordchanged` event.
323#[derive(Debug, Decode, Default)]
324pub struct ChannelPasswordChanged {
325    pub cid: ChannelId,
326}
327
328/// Data for a `channelmoved` event.
329#[derive(Debug, Decode, Default)]
330pub struct ChannelMoved {
331    pub cid: ChannelId,
332    pub cpid: ChannelId,
333    pub order: u64,
334    pub reasonid: ReasonId,
335    pub invokerid: ClientId,
336    pub invokername: String,
337    pub invokeruid: String,
338}
339
340/// Data for a `channeledited` event. The fields `cid`, `reasonid`,
341/// `invokerid`, `invokername` and `invokeruid` are always included.
342/// All fields prefixed channel_... are only included if the value of
343/// the channel was changed.
344#[derive(Debug, Decode, Default)]
345pub struct ChannelEdited {
346    pub cid: ChannelId,
347    pub reasonid: ReasonId,
348    pub invokerid: ClientId,
349    pub invokername: String,
350    pub invokeruid: String,
351    pub channel_name: String,
352    pub channel_topic: String,
353    // 4 for Opus Voice, 5 for Opus Music
354    pub channel_codec: u8,
355    pub channel_codec_quality: u8,
356    pub channel_maxclients: u16,
357    pub channel_maxfamilyclients: u16,
358    pub channel_order: u64,
359    pub channel_flag_permanent: bool,
360    pub channel_flag_semi_permanent: bool,
361    pub channel_flag_default: bool,
362    pub channel_flag_password: String,
363    pub channel_codec_latency_factor: u64,
364    pub channel_codec_is_unencrypted: bool,
365    pub channel_delete_delay: u32,
366    pub channel_flag_maxclients_unlimited: bool,
367    pub channel_flag_maxfamilyclients_unlimited: bool,
368    pub channel_flag_maxfamilyclients_inherited: bool,
369    pub channel_needed_talk_power: u32,
370    pub channel_name_phonetic: String,
371    pub channel_icon_id: u64,
372}
373
374/// Data for a `channelcreated` event.
375#[derive(Debug, Decode, Default)]
376pub struct ChannelCreated {
377    pub cid: ChannelId,
378    pub cpid: ChannelId,
379    pub channel_name: String,
380    pub channel_topic: String,
381    // 4 for Opus Voice, 5 for Opus Music
382    pub channel_codec: u8,
383    pub channel_codec_quality: u8,
384    pub channel_maxclients: u16,
385    pub channel_maxfamilyclients: u16,
386    pub channel_order: u64,
387    pub channel_flag_permanent: bool,
388    pub channel_flag_semi_permanent: bool,
389    pub channel_flag_default: bool,
390    pub channel_flag_password: bool,
391    pub channel_codec_latency_factor: u64,
392    pub channel_codec_is_unencrypted: bool,
393    pub channel_delete_delay: u32,
394    pub channel_flag_maxclients_unlimited: bool,
395    pub channel_flag_maxfamilyclients_unlimited: bool,
396    pub channel_flag_maxfamilyclients_inherited: bool,
397    pub channel_needed_talk_power: u32,
398    pub channel_name_phonetic: String,
399    pub channel_icon_id: u64,
400    pub invokerid: ClientId,
401    pub invokername: String,
402    pub invokeruid: String,
403}
404
405/// Data for a `channeldeleted` event.
406#[derive(Debug, Decode, Default)]
407pub struct ChannelDeleted {
408    /// 0 if deleted by the server after exceeding the channel_delete_delay.
409    pub invokerid: ClientId,
410    /// "Server" if deleted by the server after exceeding the channel_delete_delay.
411    pub invokername: String,
412    /// Empty if deleted by the server after exceeding the channel_delete_delay.
413    pub invokeruid: String,
414    pub cid: ChannelId,
415}
416
417/// Data for a `clientmoved` event.
418#[derive(Debug, Decode, Default)]
419pub struct ClientMoved {
420    pub ctid: ChannelId,
421    pub reasonid: ReasonId,
422    pub invokerid: ClientId,
423    pub invokername: String,
424    pub invokeruid: String,
425    pub clid: ChannelId,
426}
427
428/// Data for a `textmessage` event.
429#[derive(Debug, Decode, Default)]
430pub struct TextMessage {
431    pub targetmode: u64,
432    pub msg: String,
433    pub target: ClientId,
434    pub invokerid: ClientId,
435    pub invokername: String,
436    pub invokeruid: String,
437}
438
439/// Data for a `tokenused` event.
440#[derive(Debug, Decode, Default)]
441pub struct TokenUsed {
442    pub clid: ClientId,
443    pub cldbid: ClientDatabaseId,
444    pub cluid: String,
445    pub token: String,
446    pub tokencustomset: String,
447    /// GroupID assigned by the token.
448    pub token1: u64,
449    /// ChannelID for the token, 0 if Server Group.
450    pub token2: u64,
451}
452
453// Empty default impl for EventHandler
454// Used internally as a default handler
455pub(crate) struct Handler;
456
457impl EventHandler for Handler {}