aboutsummaryrefslogtreecommitdiffstats
path: root/src/teamspeak.rs
blob: f1abaecb9fd4f95c73d6475e73bd8c57c37b8f83 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

use futures::compat::Future01CompatExt;
use futures01::{future::Future, sink::Sink};
use tokio02::sync::mpsc::UnboundedSender;

use tsclientlib::Event::ConEvents;
use tsclientlib::{
    events::Event, ChannelId, ClientId, ConnectOptions, Connection, DisconnectOptions,
    MessageTarget, Reason,
};

use log::error;

use crate::bot::{Message, MusicBotMessage};

pub struct TeamSpeakConnection {
    conn: Connection,
}

fn get_message<'a>(event: &Event) -> Option<Message> {
    match event {
        Event::Message {
            from: target,
            invoker: sender,
            message: msg,
        } => Some(Message {
            target: target.clone(),
            invoker: sender.clone(),
            text: msg.clone(),
        }),
        _ => None,
    }
}

impl TeamSpeakConnection {
    pub async fn new(
        tx: Arc<Mutex<UnboundedSender<MusicBotMessage>>>,
        options: ConnectOptions,
    ) -> Result<TeamSpeakConnection, tsclientlib::Error> {
        let conn = Connection::new(options).compat().await?;
        let packet = conn.lock().server.set_subscribed(true);
        conn.send_packet(packet).compat().await.unwrap();

        conn.add_event_listener(
            String::from("listener"),
            Box::new(move |e| {
                if let ConEvents(_conn, events) = e {
                    for event in *events {
                        if let Some(msg) = get_message(event) {
                            let tx = tx.lock().unwrap();
                            tx.send(MusicBotMessage::TextMessage(msg)).unwrap();
                        }
                    }
                }
            }),
        );

        Ok(TeamSpeakConnection { conn })
    }

    pub fn send_audio_packet(&self, samples: &[u8]) {
        let packet =
            tsproto_packets::packets::OutAudio::new(&tsproto_packets::packets::AudioData::C2S {
                id: 0,
                codec: tsproto_packets::packets::CodecType::OpusMusic,
                data: samples,
            });

        let send_packet = self
            .conn
            .get_packet_sink()
            .send(packet)
            .map(|_| ())
            .map_err(|_| error!("Failed to send voice packet"));

        tokio::run(send_packet);
    }

    pub fn channel_path_of_user(&self, id: ClientId) -> String {
        let conn = self.conn.lock();

        let channel_id = conn.clients.get(&id).expect("can find poke sender").channel;

        let mut channel = conn
            .channels
            .get(&channel_id)
            .expect("can find user channel");

        let mut names = vec![&channel.name[..]];

        // Channel 0 is the root channel
        while channel.parent != ChannelId(0) {
            names.push("/");
            channel = conn
                .channels
                .get(&channel.parent)
                .expect("can find user channel");
            names.push(&channel.name);
        }

        let mut path = String::new();
        while let Some(name) = names.pop() {
            path.push_str(name);
        }

        path
    }

    pub fn set_nickname(&self, name: &str) {
        tokio::spawn(
            self.conn
                .lock()
                .to_mut()
                .set_name(name)
                .map_err(|e| error!("Failed to set nickname: {}", e)),
        );
    }

    pub fn set_description(&self, desc: &str) {
        tokio::spawn(
            self.conn
                .lock()
                .to_mut()
                .get_client(&self.conn.lock().own_client)
                .expect("Can get myself")
                .set_description(desc)
                .map_err(|e| error!("Failed to change description: {}", e)),
        );
    }

    pub fn send_message_to_channel(&self, text: &str) {
        tokio::spawn(
            self.conn
                .lock()
                .to_mut()
                .send_message(MessageTarget::Channel, text)
                .map_err(|e| error!("Failed to send message: {}", e)),
        );
    }

    pub fn disconnect(&self, reason: &str) {
        let opt = DisconnectOptions::new()
            .reason(Reason::Clientdisconnect)
            .message(reason);
        tokio::spawn(
            self.conn
                .disconnect(opt)
                .map_err(|e| error!("Failed to send message: {}", e)),
        );
        // Might or might not be required to keep tokio running while the bot disconnects
        tokio::spawn(
            tokio::timer::Delay::new(Instant::now() + Duration::from_secs(1)).map_err(|_| ()),
        );
    }
}