charcoal_client/actions/
channel_manager.rs1use 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#[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 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 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 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 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}