1use serde::{Deserialize, Serialize};
3use twilight_model::{
4 gateway::payload::incoming::VoiceServerUpdate,
5 id::{
6 Id,
7 marker::{ChannelMarker, GuildMarker},
8 },
9};
10
11#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
14#[non_exhaustive]
15#[serde(rename_all = "camelCase")]
16pub struct UpdatePlayerTrack {
17 #[serde(flatten)]
19 pub track_string: TrackOption,
20}
21
22#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
27#[serde(rename_all = "lowercase")]
28pub enum TrackOption {
29 Encoded(Option<String>),
31 Identifier(String),
33}
34
35#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
37#[non_exhaustive]
38#[serde(untagged)]
39pub enum OutgoingEvent {
40 Destroy(Destroy),
42 Equalizer(Equalizer),
44 Pause(Pause),
46 Play(Play),
48 Seek(Seek),
50 Stop(Stop),
52 VoiceUpdate(VoiceUpdate),
54 Volume(Volume),
56}
57
58impl From<Destroy> for OutgoingEvent {
59 fn from(event: Destroy) -> OutgoingEvent {
60 Self::Destroy(event)
61 }
62}
63
64impl From<Equalizer> for OutgoingEvent {
65 fn from(event: Equalizer) -> OutgoingEvent {
66 Self::Equalizer(event)
67 }
68}
69
70impl From<Pause> for OutgoingEvent {
71 fn from(event: Pause) -> OutgoingEvent {
72 Self::Pause(event)
73 }
74}
75
76impl From<Play> for OutgoingEvent {
77 fn from(event: Play) -> OutgoingEvent {
78 Self::Play(event)
79 }
80}
81
82impl From<Seek> for OutgoingEvent {
83 fn from(event: Seek) -> OutgoingEvent {
84 Self::Seek(event)
85 }
86}
87
88impl From<Stop> for OutgoingEvent {
89 fn from(event: Stop) -> OutgoingEvent {
90 Self::Stop(event)
91 }
92}
93
94impl From<VoiceUpdate> for OutgoingEvent {
95 fn from(event: VoiceUpdate) -> OutgoingEvent {
96 Self::VoiceUpdate(event)
97 }
98}
99
100impl From<Volume> for OutgoingEvent {
101 fn from(event: Volume) -> OutgoingEvent {
102 Self::Volume(event)
103 }
104}
105
106impl OutgoingEvent {
107 pub const fn guild_id(&self) -> Id<GuildMarker> {
109 match self {
110 Self::VoiceUpdate(voice_update) => voice_update.guild_id,
111 Self::Play(play) => play.guild_id,
112 Self::Destroy(destroy) => destroy.guild_id,
113 Self::Equalizer(equalize) => equalize.guild_id,
114 Self::Pause(pause) => pause.guild_id,
115 Self::Seek(seek) => seek.guild_id,
116 Self::Stop(stop) => stop.guild_id,
117 Self::Volume(volume) => volume.guild_id,
118 }
119 }
120
121 pub(crate) const fn no_replace(&self) -> bool {
123 match self {
124 Self::Play(play) => play.no_replace,
125 Self::Stop(_) => false,
126 _ => true,
127 }
128 }
129}
130
131#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
133#[non_exhaustive]
134#[serde(rename_all = "camelCase")]
135pub struct Destroy {
136 pub guild_id: Id<GuildMarker>,
138}
139
140impl Destroy {
141 pub const fn new(guild_id: Id<GuildMarker>) -> Self {
143 Self { guild_id }
144 }
145}
146
147impl From<Id<GuildMarker>> for Destroy {
148 fn from(guild_id: Id<GuildMarker>) -> Self {
149 Self { guild_id }
150 }
151}
152
153#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
155#[non_exhaustive]
156#[serde(rename_all = "camelCase")]
157pub enum Filters {
158 Equalizer(Equalizer),
160}
161
162#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
164#[non_exhaustive]
165#[serde(rename_all = "camelCase")]
166pub struct Equalizer {
167 pub equalizer: Vec<EqualizerBand>,
169 #[serde(skip_serializing)]
171 pub guild_id: Id<GuildMarker>,
172}
173
174impl Equalizer {
175 pub fn new(guild_id: Id<GuildMarker>, bands: Vec<EqualizerBand>) -> Self {
177 Self::from((guild_id, bands))
178 }
179}
180
181impl From<(Id<GuildMarker>, Vec<EqualizerBand>)> for Equalizer {
182 fn from((guild_id, bands): (Id<GuildMarker>, Vec<EqualizerBand>)) -> Self {
183 Self {
184 equalizer: bands,
185 guild_id,
186 }
187 }
188}
189
190#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
192#[non_exhaustive]
193#[serde(rename_all = "camelCase")]
194pub struct EqualizerBand {
195 pub band: i64,
197 pub gain: f64,
199}
200
201impl EqualizerBand {
202 pub fn new(band: i64, gain: f64) -> Self {
204 Self::from((band, gain))
205 }
206}
207
208impl From<(i64, f64)> for EqualizerBand {
209 fn from((band, gain): (i64, f64)) -> Self {
210 Self { band, gain }
211 }
212}
213
214#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
216#[non_exhaustive]
217#[serde(rename_all = "camelCase")]
218pub struct Pause {
219 pub guild_id: Id<GuildMarker>,
221 pub paused: bool,
225}
226
227impl Pause {
228 pub fn new(guild_id: Id<GuildMarker>, pause: bool) -> Self {
232 Self::from((guild_id, pause))
233 }
234}
235
236impl From<(Id<GuildMarker>, bool)> for Pause {
237 fn from((guild_id, pause): (Id<GuildMarker>, bool)) -> Self {
238 Self {
239 guild_id,
240 paused: pause,
241 }
242 }
243}
244
245#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
247#[non_exhaustive]
248#[serde(rename_all = "camelCase")]
249pub struct Play {
250 #[serde(skip_serializing_if = "Option::is_none")]
254 pub end_time: Option<Option<u64>>,
255 #[serde(skip_serializing)]
257 pub guild_id: Id<GuildMarker>,
258 #[serde(skip_serializing)]
264 pub no_replace: bool,
265 #[serde(skip_serializing_if = "Option::is_none")]
267 pub position: Option<u64>,
268 #[serde(skip_serializing_if = "Option::is_none")]
270 pub paused: Option<bool>,
271 #[serde(skip_serializing_if = "Option::is_none")]
273 pub track: Option<UpdatePlayerTrack>,
274 #[serde(skip_serializing_if = "Option::is_none")]
276 pub volume: Option<u64>,
277}
278
279impl Play {
280 pub fn new(
282 guild_id: Id<GuildMarker>,
283 track: impl Into<String>,
284 start_time: impl Into<Option<u64>>,
285 end_time: impl Into<Option<u64>>,
286 no_replace: bool,
287 ) -> Self {
288 Self::from((guild_id, track, start_time, end_time, no_replace))
289 }
290}
291
292impl<T: Into<String>> From<(Id<GuildMarker>, T)> for Play {
293 fn from((guild_id, track): (Id<GuildMarker>, T)) -> Self {
294 Self::from((guild_id, track, None, None, true))
295 }
296}
297
298impl<T: Into<String>, S: Into<Option<u64>>> From<(Id<GuildMarker>, T, S)> for Play {
299 fn from((guild_id, track, start_time): (Id<GuildMarker>, T, S)) -> Self {
300 Self::from((guild_id, track, start_time, None, true))
301 }
302}
303
304impl<T: Into<String>, S: Into<Option<u64>>, E: Into<Option<u64>>> From<(Id<GuildMarker>, T, S, E)>
305 for Play
306{
307 fn from((guild_id, track, start_time, end_time): (Id<GuildMarker>, T, S, E)) -> Self {
308 Self::from((guild_id, track, start_time, end_time, true))
309 }
310}
311
312impl<T: Into<String>, S: Into<Option<u64>>, E: Into<Option<u64>>>
313 From<(Id<GuildMarker>, T, S, E, bool)> for Play
314{
315 fn from(
316 (guild_id, track, start_time, end_time, no_replace): (Id<GuildMarker>, T, S, E, bool),
317 ) -> Self {
318 Self {
319 guild_id,
320 no_replace,
321 position: start_time.into(),
322 end_time: Some(end_time.into()),
323 volume: None,
324 paused: None,
325 track: Some(UpdatePlayerTrack {
326 track_string: TrackOption::Encoded(Some(track.into())),
327 }),
328 }
329 }
330}
331
332#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
334#[non_exhaustive]
335#[serde(rename_all = "camelCase")]
336pub struct Seek {
337 #[serde(skip_serializing)]
339 pub guild_id: Id<GuildMarker>,
340 pub position: i64,
342}
343
344impl Seek {
345 pub fn new(guild_id: Id<GuildMarker>, position: i64) -> Self {
347 Self::from((guild_id, position))
348 }
349}
350
351impl From<(Id<GuildMarker>, i64)> for Seek {
352 fn from((guild_id, position): (Id<GuildMarker>, i64)) -> Self {
353 Self { guild_id, position }
354 }
355}
356
357#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
359#[non_exhaustive]
360#[serde(rename_all = "camelCase")]
361pub struct Stop {
362 #[serde(skip_serializing)]
364 pub guild_id: Id<GuildMarker>,
365 pub track: UpdatePlayerTrack,
367}
368
369impl Stop {
370 pub fn new(guild_id: Id<GuildMarker>) -> Self {
372 Self::from(guild_id)
373 }
374}
375
376impl From<Id<GuildMarker>> for Stop {
377 fn from(guild_id: Id<GuildMarker>) -> Self {
378 Self {
379 guild_id,
380 track: UpdatePlayerTrack {
381 track_string: TrackOption::Encoded(None),
382 },
383 }
384 }
385}
386#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
388#[non_exhaustive]
389#[serde(rename_all = "camelCase")]
390pub struct Voice {
391 #[serde(skip_serializing_if = "Option::is_none")]
393 pub channel_id: Option<Id<ChannelMarker>>,
394 pub endpoint: String,
396 pub session_id: String,
398 pub token: String,
400}
401
402#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
404#[non_exhaustive]
405#[serde(rename_all = "camelCase")]
406pub struct VoiceUpdate {
407 #[serde(skip_serializing)]
409 pub guild_id: Id<GuildMarker>,
410 pub voice: Voice,
412}
413
414impl VoiceUpdate {
415 pub fn new(
417 guild_id: Id<GuildMarker>,
418 session_id: impl Into<String>,
419 channel_id: Option<Id<ChannelMarker>>,
420 event: VoiceServerUpdate,
421 ) -> Self {
422 Self::from((guild_id, session_id, channel_id, event))
423 }
424}
425
426impl<T: Into<String>>
427 From<(
428 Id<GuildMarker>,
429 T,
430 Option<Id<ChannelMarker>>,
431 VoiceServerUpdate,
432 )> for VoiceUpdate
433{
434 fn from(
435 (guild_id, session_id, channel_id, event): (
436 Id<GuildMarker>,
437 T,
438 Option<Id<ChannelMarker>>,
439 VoiceServerUpdate,
440 ),
441 ) -> Self {
442 Self {
443 guild_id,
444 voice: Voice {
445 channel_id,
446 token: event.token,
447 endpoint: event.endpoint.unwrap_or("NO_ENDPOINT_RETURNED".to_string()),
448 session_id: session_id.into(),
449 },
450 }
451 }
452}
453
454#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
456#[non_exhaustive]
457#[serde(rename_all = "camelCase")]
458pub struct Volume {
459 #[serde(skip_serializing)]
461 pub guild_id: Id<GuildMarker>,
462 pub volume: i64,
464}
465
466impl Volume {
467 pub fn new(guild_id: Id<GuildMarker>, volume: i64) -> Self {
469 Self::from((guild_id, volume))
470 }
471}
472
473impl From<(Id<GuildMarker>, i64)> for Volume {
474 fn from((guild_id, volume): (Id<GuildMarker>, i64)) -> Self {
475 Self { guild_id, volume }
476 }
477}