1use serde::{Deserialize, Serialize};
3use twilight_model::{
4 gateway::payload::incoming::VoiceServerUpdate,
5 id::{Id, marker::GuildMarker},
6};
7
8#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
11#[non_exhaustive]
12#[serde(rename_all = "camelCase")]
13pub struct UpdatePlayerTrack {
14 #[serde(flatten)]
16 pub track_string: TrackOption,
17}
18
19#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
24#[serde(rename_all = "lowercase")]
25pub enum TrackOption {
26 Encoded(Option<String>),
28 Identifier(String),
30}
31
32#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
34#[non_exhaustive]
35#[serde(untagged)]
36pub enum OutgoingEvent {
37 Destroy(Destroy),
39 Equalizer(Equalizer),
41 Pause(Pause),
43 Play(Play),
45 Seek(Seek),
47 Stop(Stop),
49 VoiceUpdate(VoiceUpdate),
51 Volume(Volume),
53}
54
55impl From<Destroy> for OutgoingEvent {
56 fn from(event: Destroy) -> OutgoingEvent {
57 Self::Destroy(event)
58 }
59}
60
61impl From<Equalizer> for OutgoingEvent {
62 fn from(event: Equalizer) -> OutgoingEvent {
63 Self::Equalizer(event)
64 }
65}
66
67impl From<Pause> for OutgoingEvent {
68 fn from(event: Pause) -> OutgoingEvent {
69 Self::Pause(event)
70 }
71}
72
73impl From<Play> for OutgoingEvent {
74 fn from(event: Play) -> OutgoingEvent {
75 Self::Play(event)
76 }
77}
78
79impl From<Seek> for OutgoingEvent {
80 fn from(event: Seek) -> OutgoingEvent {
81 Self::Seek(event)
82 }
83}
84
85impl From<Stop> for OutgoingEvent {
86 fn from(event: Stop) -> OutgoingEvent {
87 Self::Stop(event)
88 }
89}
90
91impl From<VoiceUpdate> for OutgoingEvent {
92 fn from(event: VoiceUpdate) -> OutgoingEvent {
93 Self::VoiceUpdate(event)
94 }
95}
96
97impl From<Volume> for OutgoingEvent {
98 fn from(event: Volume) -> OutgoingEvent {
99 Self::Volume(event)
100 }
101}
102
103impl OutgoingEvent {
104 pub const fn guild_id(&self) -> Id<GuildMarker> {
106 match self {
107 Self::VoiceUpdate(voice_update) => voice_update.guild_id,
108 Self::Play(play) => play.guild_id,
109 Self::Destroy(destroy) => destroy.guild_id,
110 Self::Equalizer(equalize) => equalize.guild_id,
111 Self::Pause(pause) => pause.guild_id,
112 Self::Seek(seek) => seek.guild_id,
113 Self::Stop(stop) => stop.guild_id,
114 Self::Volume(volume) => volume.guild_id,
115 }
116 }
117
118 pub(crate) const fn no_replace(&self) -> bool {
120 match self {
121 Self::Play(play) => play.no_replace,
122 Self::Stop(_) => false,
123 _ => true,
124 }
125 }
126}
127
128#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
130#[non_exhaustive]
131#[serde(rename_all = "camelCase")]
132pub struct Destroy {
133 pub guild_id: Id<GuildMarker>,
135}
136
137impl Destroy {
138 pub const fn new(guild_id: Id<GuildMarker>) -> Self {
140 Self { guild_id }
141 }
142}
143
144impl From<Id<GuildMarker>> for Destroy {
145 fn from(guild_id: Id<GuildMarker>) -> Self {
146 Self { guild_id }
147 }
148}
149
150#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
152#[non_exhaustive]
153#[serde(rename_all = "camelCase")]
154pub enum Filters {
155 Equalizer(Equalizer),
157}
158
159#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
161#[non_exhaustive]
162#[serde(rename_all = "camelCase")]
163pub struct Equalizer {
164 pub equalizer: Vec<EqualizerBand>,
166 #[serde(skip_serializing)]
168 pub guild_id: Id<GuildMarker>,
169}
170
171impl Equalizer {
172 pub fn new(guild_id: Id<GuildMarker>, bands: Vec<EqualizerBand>) -> Self {
174 Self::from((guild_id, bands))
175 }
176}
177
178impl From<(Id<GuildMarker>, Vec<EqualizerBand>)> for Equalizer {
179 fn from((guild_id, bands): (Id<GuildMarker>, Vec<EqualizerBand>)) -> Self {
180 Self {
181 equalizer: bands,
182 guild_id,
183 }
184 }
185}
186
187#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
189#[non_exhaustive]
190#[serde(rename_all = "camelCase")]
191pub struct EqualizerBand {
192 pub band: i64,
194 pub gain: f64,
196}
197
198impl EqualizerBand {
199 pub fn new(band: i64, gain: f64) -> Self {
201 Self::from((band, gain))
202 }
203}
204
205impl From<(i64, f64)> for EqualizerBand {
206 fn from((band, gain): (i64, f64)) -> Self {
207 Self { band, gain }
208 }
209}
210
211#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
213#[non_exhaustive]
214#[serde(rename_all = "camelCase")]
215pub struct Pause {
216 pub guild_id: Id<GuildMarker>,
218 pub paused: bool,
222}
223
224impl Pause {
225 pub fn new(guild_id: Id<GuildMarker>, pause: bool) -> Self {
229 Self::from((guild_id, pause))
230 }
231}
232
233impl From<(Id<GuildMarker>, bool)> for Pause {
234 fn from((guild_id, pause): (Id<GuildMarker>, bool)) -> Self {
235 Self {
236 guild_id,
237 paused: pause,
238 }
239 }
240}
241
242#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
244#[non_exhaustive]
245#[serde(rename_all = "camelCase")]
246pub struct Play {
247 #[serde(skip_serializing_if = "Option::is_none")]
251 pub end_time: Option<Option<u64>>,
252 #[serde(skip_serializing)]
254 pub guild_id: Id<GuildMarker>,
255 #[serde(skip_serializing)]
261 pub no_replace: bool,
262 #[serde(skip_serializing_if = "Option::is_none")]
264 pub position: Option<u64>,
265 #[serde(skip_serializing_if = "Option::is_none")]
267 pub paused: Option<bool>,
268 #[serde(skip_serializing_if = "Option::is_none")]
270 pub track: Option<UpdatePlayerTrack>,
271 #[serde(skip_serializing_if = "Option::is_none")]
273 pub volume: Option<u64>,
274}
275
276impl Play {
277 pub fn new(
279 guild_id: Id<GuildMarker>,
280 track: impl Into<String>,
281 start_time: impl Into<Option<u64>>,
282 end_time: impl Into<Option<u64>>,
283 no_replace: bool,
284 ) -> Self {
285 Self::from((guild_id, track, start_time, end_time, no_replace))
286 }
287}
288
289impl<T: Into<String>> From<(Id<GuildMarker>, T)> for Play {
290 fn from((guild_id, track): (Id<GuildMarker>, T)) -> Self {
291 Self::from((guild_id, track, None, None, true))
292 }
293}
294
295impl<T: Into<String>, S: Into<Option<u64>>> From<(Id<GuildMarker>, T, S)> for Play {
296 fn from((guild_id, track, start_time): (Id<GuildMarker>, T, S)) -> Self {
297 Self::from((guild_id, track, start_time, None, true))
298 }
299}
300
301impl<T: Into<String>, S: Into<Option<u64>>, E: Into<Option<u64>>> From<(Id<GuildMarker>, T, S, E)>
302 for Play
303{
304 fn from((guild_id, track, start_time, end_time): (Id<GuildMarker>, T, S, E)) -> Self {
305 Self::from((guild_id, track, start_time, end_time, true))
306 }
307}
308
309impl<T: Into<String>, S: Into<Option<u64>>, E: Into<Option<u64>>>
310 From<(Id<GuildMarker>, T, S, E, bool)> for Play
311{
312 fn from(
313 (guild_id, track, start_time, end_time, no_replace): (Id<GuildMarker>, T, S, E, bool),
314 ) -> Self {
315 Self {
316 guild_id,
317 no_replace,
318 position: start_time.into(),
319 end_time: Some(end_time.into()),
320 volume: None,
321 paused: None,
322 track: Some(UpdatePlayerTrack {
323 track_string: TrackOption::Encoded(Some(track.into())),
324 }),
325 }
326 }
327}
328
329#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
331#[non_exhaustive]
332#[serde(rename_all = "camelCase")]
333pub struct Seek {
334 #[serde(skip_serializing)]
336 pub guild_id: Id<GuildMarker>,
337 pub position: i64,
339}
340
341impl Seek {
342 pub fn new(guild_id: Id<GuildMarker>, position: i64) -> Self {
344 Self::from((guild_id, position))
345 }
346}
347
348impl From<(Id<GuildMarker>, i64)> for Seek {
349 fn from((guild_id, position): (Id<GuildMarker>, i64)) -> Self {
350 Self { guild_id, position }
351 }
352}
353
354#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
356#[non_exhaustive]
357#[serde(rename_all = "camelCase")]
358pub struct Stop {
359 #[serde(skip_serializing)]
361 pub guild_id: Id<GuildMarker>,
362 pub track: UpdatePlayerTrack,
364}
365
366impl Stop {
367 pub fn new(guild_id: Id<GuildMarker>) -> Self {
369 Self::from(guild_id)
370 }
371}
372
373impl From<Id<GuildMarker>> for Stop {
374 fn from(guild_id: Id<GuildMarker>) -> Self {
375 Self {
376 guild_id,
377 track: UpdatePlayerTrack {
378 track_string: TrackOption::Encoded(None),
379 },
380 }
381 }
382}
383#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
385#[non_exhaustive]
386#[serde(rename_all = "camelCase")]
387pub struct Voice {
388 pub endpoint: String,
390 pub session_id: String,
392 pub token: String,
394}
395
396#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
398#[non_exhaustive]
399#[serde(rename_all = "camelCase")]
400pub struct VoiceUpdate {
401 #[serde(skip_serializing)]
403 pub guild_id: Id<GuildMarker>,
404 pub voice: Voice,
406}
407
408impl VoiceUpdate {
409 pub fn new(
411 guild_id: Id<GuildMarker>,
412 session_id: impl Into<String>,
413 event: VoiceServerUpdate,
414 ) -> Self {
415 Self::from((guild_id, session_id, event))
416 }
417}
418
419impl<T: Into<String>> From<(Id<GuildMarker>, T, VoiceServerUpdate)> for VoiceUpdate {
420 fn from((guild_id, session_id, event): (Id<GuildMarker>, T, VoiceServerUpdate)) -> Self {
421 Self {
422 guild_id,
423 voice: Voice {
424 token: event.token,
425 endpoint: event.endpoint.unwrap_or("NO_ENDPOINT_RETURNED".to_string()),
426 session_id: session_id.into(),
427 },
428 }
429 }
430}
431
432#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
434#[non_exhaustive]
435#[serde(rename_all = "camelCase")]
436pub struct Volume {
437 #[serde(skip_serializing)]
439 pub guild_id: Id<GuildMarker>,
440 pub volume: i64,
442}
443
444impl Volume {
445 pub fn new(guild_id: Id<GuildMarker>, volume: i64) -> Self {
447 Self::from((guild_id, volume))
448 }
449}
450
451impl From<(Id<GuildMarker>, i64)> for Volume {
452 fn from((guild_id, volume): (Id<GuildMarker>, i64)) -> Self {
453 Self { guild_id, volume }
454 }
455}