charcoal_client/actions/
channel_manager.rs

1use hearth_interconnect::messages::{JobRequest, Message};
2use hearth_interconnect::worker_communication::{DWCActionType, DirectWorkerCommunication};
3use std::time::Duration;
4use crate::PlayerObject;
5use async_trait::async_trait;
6use nanoid::nanoid;
7use crate::background::connector::{boilerplate_parse_ipc, BoilerplateParseIPCError};
8use crate::background::processor::IPCData;
9use snafu::prelude::*;
10use tokio::sync::broadcast::error::SendError;
11
12#[derive(Debug, Snafu)]
13pub enum CreateJobError {
14    #[snafu(display("Did not receive job creation confirmation within time-frame"))]
15    TimedOutWaitingForJobCreationConfirmation { source: BoilerplateParseIPCError },
16    #[snafu(display("Failed to send internal IPC job creation request"))]
17    FailedToSendIPC { source: SendError<IPCData> },
18}
19
20#[derive(Debug, Snafu)]
21pub enum ChannelManagerError {
22    #[snafu(display("Failed to send IPC request to Background thread"))]
23    FailedToSendIPCRequest { source: SendError<IPCData> },
24}
25
26/// Provides basic functionality to create a job on the hearth server, join a channel, and exit a channel
27#[async_trait]
28pub trait ChannelManager {
29    async fn join_channel(
30        &mut self,
31        voice_channel_id: String,
32        create_job: bool,
33    ) -> Result<(), CreateJobError>;
34    async fn exit_channel(&self) -> Result<(), ChannelManagerError>;
35}
36
37#[async_trait]
38impl ChannelManager for PlayerObject {
39    /// Create job on Hearth server for this PlayerObject
40    async fn join_channel(
41        &mut self,
42        voice_channel_id: String,
43        create_job: bool,
44    ) -> Result<(), CreateJobError> {
45        let guild_id = self.guild_id.clone();
46
47        let tx = self.tx.clone();
48        let bg_com = self.bg_com_tx.clone();
49
50        let worker_id = self.worker_id.clone();
51        let job_id = self.job_id.clone();
52
53        if !create_job {
54            self.bg_com_tx
55                .send(IPCData::new_from_main(
56                    Message::DirectWorkerCommunication(DirectWorkerCommunication {
57                        job_id: job_id.read().await.clone().unwrap(),
58                        worker_id: worker_id.read().await.clone().unwrap(),
59                        guild_id: self.guild_id.clone(),
60                        voice_channel_id: Some(voice_channel_id.clone()),
61                        play_audio_url: None,
62                        action_type: DWCActionType::JoinChannel,
63                        request_id: Some(nanoid!()),
64                        new_volume: None,
65                        seek_position: None,
66                        loop_times: None,
67                    }),
68                    self.tx.clone(),
69                    self.guild_id.clone(),
70                ))
71                .context(FailedToSendIPCSnafu)?;
72
73            return Ok(());
74        }
75
76        tokio::spawn(async move {
77            bg_com
78                .send(IPCData::new_from_main(
79                    Message::ExternalQueueJob(JobRequest {
80                        request_id: nanoid!(),
81                        guild_id: guild_id.clone(),
82                    }),
83                    tx.clone(),
84                    guild_id.clone(),
85                ))
86                .unwrap();
87            //
88            //
89            let mut job_id_a = job_id.write().await;
90            let mut worker_id_a = worker_id.write().await;
91            boilerplate_parse_ipc(
92                |msg| {
93                    if let IPCData::FromBackground(bg) = msg {
94                        if let Message::ExternalQueueJobResponse(q) = bg.message {
95                            *job_id_a = Some(q.job_id);
96                            *worker_id_a = Some(q.worker_id);
97                            return false;
98                        }
99                    }
100                    true
101                },
102                tx.subscribe(),
103                Duration::from_secs(3),
104            )
105            .await
106            .unwrap();
107            //
108            bg_com
109                .send(IPCData::new_from_main(
110                    Message::DirectWorkerCommunication(DirectWorkerCommunication {
111                        job_id: job_id_a.clone().unwrap(),
112                        worker_id: worker_id_a.clone().unwrap(),
113                        guild_id: guild_id.clone(),
114                        voice_channel_id: Some(voice_channel_id),
115                        play_audio_url: None,
116                        action_type: DWCActionType::JoinChannel,
117                        request_id: Some(nanoid!()),
118                        new_volume: None,
119                        seek_position: None,
120                        loop_times: None,
121                    }),
122                    tx.clone(),
123                    guild_id,
124                ))
125                .context(FailedToSendIPCRequestSnafu)
126                .unwrap();
127        });
128
129        Ok(())
130    }
131    /// Exit voice channel
132    async fn exit_channel(&self) -> Result<(), ChannelManagerError> {
133        self.bg_com_tx
134            .send(IPCData::new_from_main(
135                Message::DirectWorkerCommunication(DirectWorkerCommunication {
136                    job_id: self.job_id.read().await.clone().unwrap(),
137                    action_type: DWCActionType::LeaveChannel,
138                    play_audio_url: None,
139                    guild_id: self.guild_id.clone(),
140                    request_id: Some(nanoid!()),
141                    new_volume: None,
142                    seek_position: None,
143                    loop_times: None,
144                    worker_id: self.worker_id.read().await.clone().unwrap(),
145                    voice_channel_id: None,
146                }),
147                self.tx.clone(),
148                self.guild_id.clone(),
149            ))
150            .context(FailedToSendIPCRequestSnafu)?;
151
152        Ok(())
153    }
154}