Skip to content

feat(all \ {gateway-queue, lavalink, mention, util}): voice channel status #2419

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
4 changes: 4 additions & 0 deletions examples/cache-optimization/models/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@ impl CacheableChannel for MinimalCachedChannel {
fn set_last_pin_timestamp(&mut self, _timestamp: Option<Timestamp>) {
// We don't store this information, so this is a no-op
}

fn set_status(&mut self, _status: Option<String>) {
// We don't store this information, so this is a no-op
}
}
13 changes: 13 additions & 0 deletions twilight-cache-inmemory/src/event/channel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{traits::CacheableChannel, CacheableModels, InMemoryCache, ResourceType, UpdateCache};
use twilight_model::gateway::payload::incoming::VoiceChannelStatusUpdate;
use twilight_model::{
channel::Channel,
gateway::payload::incoming::{ChannelCreate, ChannelDelete, ChannelPinsUpdate, ChannelUpdate},
Expand Down Expand Up @@ -83,6 +84,18 @@ impl<CacheModels: CacheableModels> UpdateCache<CacheModels> for ChannelUpdate {
}
}

impl<CacheModels: CacheableModels> UpdateCache<CacheModels> for VoiceChannelStatusUpdate {
fn update(&self, cache: &InMemoryCache<CacheModels>) {
if !cache.wants(ResourceType::CHANNEL) {
return;
}

if let Some(mut channel) = cache.channels.get_mut(&self.id) {
channel.set_status(self.status.clone());
}
}
}

#[cfg(test)]
mod tests {
use crate::{test, DefaultInMemoryCache};
Expand Down
2 changes: 2 additions & 0 deletions twilight-cache-inmemory/src/event/guild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ mod tests {
rate_limit_per_user: None,
recipients: None,
rtc_region: None,
status: None,
thread_metadata: None,
topic: None,
user_limit: None,
Expand Down Expand Up @@ -276,6 +277,7 @@ mod tests {
rate_limit_per_user: None,
recipients: None,
rtc_region: None,
status: None,
thread_metadata: Some(ThreadMetadata {
archived: false,
auto_archive_duration: AutoArchiveDuration::Hour,
Expand Down
1 change: 1 addition & 0 deletions twilight-cache-inmemory/src/event/interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ mod tests {
rate_limit_per_user: None,
recipients: None,
rtc_region: None,
status: None,
topic: None,
user_limit: None,
application_id: None,
Expand Down
3 changes: 3 additions & 0 deletions twilight-cache-inmemory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ impl<CacheModels: CacheableModels> Default for InMemoryCache<CacheModels> {
}

mod private {
use twilight_model::gateway::payload::incoming::VoiceChannelStatusUpdate;
use twilight_model::gateway::{
event::Event,
payload::incoming::{
Expand Down Expand Up @@ -922,6 +923,7 @@ mod private {
impl Sealed for ThreadUpdate {}
impl Sealed for UnavailableGuild {}
impl Sealed for UserUpdate {}
impl Sealed for VoiceChannelStatusUpdate {}
impl Sealed for VoiceStateUpdate {}
impl Sealed for GuildScheduledEventCreate {}
impl Sealed for GuildScheduledEventDelete {}
Expand Down Expand Up @@ -1013,6 +1015,7 @@ impl<CacheModels: CacheableModels> UpdateCache<CacheModels> for Event {
Event::ThreadUpdate(v) => cache.update(v.deref()),
Event::UnavailableGuild(v) => cache.update(v),
Event::UserUpdate(v) => cache.update(v),
Event::VoiceChannelStatusUpdate(v) => cache.update(v),
Event::VoiceStateUpdate(v) => cache.update(v.deref()),

// Ignored events.
Expand Down
2 changes: 2 additions & 0 deletions twilight-cache-inmemory/src/permission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ mod tests {
rate_limit_per_user: None,
recipients: None,
rtc_region: None,
status: None,
thread_metadata: None,
topic: None,
user_limit: None,
Expand Down Expand Up @@ -866,6 +867,7 @@ mod tests {
rate_limit_per_user: None,
recipients: None,
rtc_region: None,
status: None,
thread_metadata: None,
topic: None,
user_limit: None,
Expand Down
1 change: 1 addition & 0 deletions twilight-cache-inmemory/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ pub fn guild_channel_text() -> (Id<GuildMarker>, Id<ChannelMarker>, Channel) {
rate_limit_per_user: None,
recipients: None,
rtc_region: None,
status: None,
thread_metadata: None,
topic: None,
user_limit: None,
Expand Down
7 changes: 7 additions & 0 deletions twilight-cache-inmemory/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ pub trait CacheableChannel:

/// Set the last pin timestamp to a new timestamp.
fn set_last_pin_timestamp(&mut self, timestamp: Option<Timestamp>);

/// Sets the status of the channel.
fn set_status(&mut self, status: Option<String>);
}

impl CacheableChannel for Channel {
Expand Down Expand Up @@ -194,6 +197,10 @@ impl CacheableChannel for Channel {
fn set_last_pin_timestamp(&mut self, timestamp: Option<Timestamp>) {
self.last_pin_timestamp = timestamp;
}

fn set_status(&mut self, status: Option<String>) {
self.status = status;
}
}

/// Trait for a generic cached representation of a [`Guild`].
Expand Down
3 changes: 3 additions & 0 deletions twilight-gateway/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ bitflags! {
const UNAVAILABLE_GUILD = 1 << 40;
/// Current user's profile has been updated.
const USER_UPDATE = 1 << 41;
/// A voice channel status has been updated.
const VOICE_CHANNEL_STATUS_UPDATE = 1 << 79;
/// Voice server has provided an update with voice session details.
const VOICE_SERVER_UPDATE = 1 << 42;
/// User's state in a voice channel has been updated.
Expand Down Expand Up @@ -405,6 +407,7 @@ impl From<EventType> for EventTypeFlags {
EventType::TypingStart => Self::TYPING_START,
EventType::UnavailableGuild => Self::UNAVAILABLE_GUILD,
EventType::UserUpdate => Self::USER_UPDATE,
EventType::VoiceChannelStatusUpdate => Self::VOICE_CHANNEL_STATUS_UPDATE,
EventType::VoiceServerUpdate => Self::VOICE_SERVER_UPDATE,
EventType::VoiceStateUpdate => Self::VOICE_STATE_UPDATE,
EventType::WebhooksUpdate => Self::WEBHOOKS_UPDATE,
Expand Down
3 changes: 3 additions & 0 deletions twilight-http-ratelimiting/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ pub enum Path {
ChannelsIdThreads(u64),
/// Operating on a channel's typing indicator.
ChannelsIdTyping(u64),
/// Operating on a channel's voice status.
ChannelsIdVoiceStatus(u64),
/// Operating on a channel's webhooks.
ChannelsIdWebhooks(u64),
/// Operating on an application's entitlements.
Expand Down Expand Up @@ -397,6 +399,7 @@ impl FromStr for Path {
["channels", id, "thread-members", _] => ChannelsIdThreadMembersId(parse_id(id)?),
["channels", id, "threads"] => ChannelsIdThreads(parse_id(id)?),
["channels", id, "typing"] => ChannelsIdTyping(parse_id(id)?),
["channels", id, "voice-status"] => ChannelsIdVoiceStatus(parse_id(id)?),
["channels", id, "webhooks"] | ["channels", id, "webhooks", _] => {
ChannelsIdWebhooks(parse_id(id)?)
}
Expand Down
9 changes: 9 additions & 0 deletions twilight-http/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod interaction;

pub use self::{builder::ClientBuilder, interaction::InteractionClient};

use crate::request::channel::SetVoiceChannelStatus;
use crate::request::{
application::{
emoji::{
Expand Down Expand Up @@ -2882,6 +2883,14 @@ impl Client {
DeleteApplicationEmoji::new(self, application_id, emoji_id)
}

/// Sets the status of a voice channel.
pub const fn set_voice_channel_status(
&self,
channel_id: Id<ChannelMarker>,
) -> SetVoiceChannelStatus<'_> {
SetVoiceChannelStatus::new(self, channel_id)
}

/// Execute a request, returning a future resolving to a [`Response`].
///
/// # Errors
Expand Down
4 changes: 3 additions & 1 deletion twilight-http/src/request/channel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod delete_pin;
mod follow_news_channel;
mod get_channel;
mod get_pins;
mod set_voice_channel_status;
mod update_channel;
mod update_channel_permission;

Expand All @@ -22,5 +23,6 @@ pub use self::{
delete_channel::DeleteChannel, delete_channel_permission::DeleteChannelPermission,
delete_channel_permission_configured::DeleteChannelPermissionConfigured, delete_pin::DeletePin,
follow_news_channel::FollowNewsChannel, get_channel::GetChannel, get_pins::GetPins,
update_channel::UpdateChannel, update_channel_permission::UpdateChannelPermission,
set_voice_channel_status::SetVoiceChannelStatus, update_channel::UpdateChannel,
update_channel_permission::UpdateChannelPermission,
};
72 changes: 72 additions & 0 deletions twilight-http/src/request/channel/set_voice_channel_status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use crate::client::Client;
use crate::request::{Request, TryIntoRequest};
use crate::response::marker::EmptyBody;
use crate::response::ResponseFuture;
use crate::routing::Route;
use crate::{Error, Response};
use serde::Serialize;
use std::future::IntoFuture;
use twilight_model::id::{marker::ChannelMarker, Id};
use twilight_validate::channel::{status as validate_status, ChannelValidationError};

#[derive(Serialize)]
pub(crate) struct SetVoiceChannelStatusFields<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
status: Option<&'a str>,
}

/// Sets the status of a voice channel.
#[must_use = "requests must be configured and executed"]
pub struct SetVoiceChannelStatus<'a> {
channel_id: Id<ChannelMarker>,
fields: Result<SetVoiceChannelStatusFields<'a>, ChannelValidationError>,
http: &'a Client,
}

impl<'a> SetVoiceChannelStatus<'a> {
pub(crate) const fn new(http: &'a Client, channel_id: Id<ChannelMarker>) -> Self {
Self {
channel_id,
fields: Ok(SetVoiceChannelStatusFields { status: None }),
http,
}
}

pub fn status(mut self, status: &'a str) -> Self {
self.fields = self.fields.and_then(|mut fields| {
validate_status(status)?;
fields.status.replace(status);

Ok(fields)
});

self
}
}

impl IntoFuture for SetVoiceChannelStatus<'_> {
type Output = Result<Response<EmptyBody>, Error>;

type IntoFuture = ResponseFuture<EmptyBody>;

fn into_future(self) -> Self::IntoFuture {
let http = self.http;

match self.try_into_request() {
Ok(request) => http.request(request),
Err(source) => ResponseFuture::error(source),
}
}
}

impl TryIntoRequest for SetVoiceChannelStatus<'_> {
fn try_into_request(self) -> Result<Request, Error> {
let fields = self.fields.map_err(Error::validation)?;

Request::builder(&Route::SetVoiceChannelStatus {
channel_id: self.channel_id.get(),
})
.json(&fields)
.build()
}
}
2 changes: 2 additions & 0 deletions twilight-http/src/request/try_into_request.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod private {
use crate::request::channel::SetVoiceChannelStatus;
use crate::request::{
application::{
command::{
Expand Down Expand Up @@ -265,6 +266,7 @@ mod private {
impl Sealed for SearchGuildMembers<'_> {}
impl Sealed for SetGlobalCommands<'_> {}
impl Sealed for SetGuildCommands<'_> {}
impl Sealed for SetVoiceChannelStatus<'_> {}
impl Sealed for SyncTemplate<'_> {}
impl Sealed for UpdateAutoModerationRule<'_> {}
impl Sealed for UpdateChannel<'_> {}
Expand Down
24 changes: 24 additions & 0 deletions twilight-http/src/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,11 @@ pub enum Route<'a> {
/// The ID of the guild.
guild_id: u64,
},
/// Route information to set voice channel status.
SetVoiceChannelStatus {
/// The ID of the channel.
channel_id: u64,
},
/// Route information to sync a guild's integration.
SyncGuildIntegration {
/// The ID of the guild.
Expand Down Expand Up @@ -1406,6 +1411,7 @@ impl Route<'_> {
| Self::PinMessage { .. }
| Self::SetGlobalCommands { .. }
| Self::SetGuildCommands { .. }
| Self::SetVoiceChannelStatus { .. }
| Self::SyncTemplate { .. }
| Self::UpdateCommandPermissions { .. }
| Self::UpdateGuildOnboarding { .. }
Expand Down Expand Up @@ -1742,6 +1748,7 @@ impl Route<'_> {
Self::EndPoll { channel_id, .. } | Self::GetAnswerVoters { channel_id, .. } => {
Path::ChannelsIdPolls(channel_id)
}
Self::SetVoiceChannelStatus { channel_id } => Path::ChannelsIdVoiceStatus(channel_id),
}
}
}
Expand Down Expand Up @@ -2066,6 +2073,12 @@ impl Display for Route<'_> {

f.write_str("/typing")
}
Route::SetVoiceChannelStatus { channel_id } => {
f.write_str("channels/")?;
Display::fmt(channel_id, f)?;

f.write_str("/voice-status")
}
Route::CreateWebhook { channel_id } | Route::GetChannelWebhooks { channel_id } => {
f.write_str("channels/")?;
Display::fmt(channel_id, f)?;
Expand Down Expand Up @@ -4864,4 +4877,15 @@ mod tests {
let route = Route::GetSKUs { application_id: 1 };
assert_eq!(route.to_string(), format!("applications/1/skus"));
}

#[test]
fn set_voice_channel_status() {
let route = Route::SetVoiceChannelStatus {
channel_id: CHANNEL_ID,
};
assert_eq!(
route.to_string(),
format!("channels/{CHANNEL_ID}/voice-status")
);
}
}
1 change: 1 addition & 0 deletions twilight-model/src/application/interaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ mod tests {
member_count: None,
message_count: None,
newly_created: None,
status: None,
thread_metadata: None,
video_quality_mode: None,
}),
Expand Down
Loading