Skip to content

Commit

Permalink
Add support for filtering by user ids when requesting guild chunks (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
james7132 authored Oct 27, 2020
1 parent 85b5489 commit 0d9b821
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/client/bridge/gateway/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub use self::shard_manager_monitor::{ShardManagerMonitor, ShardManagerError};
pub use self::shard_messenger::ShardMessenger;
pub use self::shard_queuer::ShardQueuer;
pub use self::shard_runner::{ShardRunner, ShardRunnerOptions};
pub use self::shard_runner_message::ShardRunnerMessage;
pub use self::shard_runner_message::{ShardRunnerMessage, ChunkGuildFilter};
pub use self::intents::GatewayIntents;

use std::{
Expand Down
12 changes: 7 additions & 5 deletions src/client/bridge/gateway/shard_messenger.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::gateway::InterMessage;
use crate::model::prelude::*;
use super::{ShardClientMessage, ShardRunnerMessage};
use super::{ShardClientMessage, ShardRunnerMessage, ChunkGuildFilter};
use futures::channel::mpsc::{UnboundedSender as Sender, TrySendError};
use async_tungstenite::tungstenite::Message;
#[cfg(feature = "collector")]
Expand Down Expand Up @@ -53,6 +53,7 @@ impl ShardMessenger {
///
/// ```rust,no_run
/// # use tokio::sync::Mutex;
/// # use serenity::client::bridge::gateway::ChunkGuildFilter;
/// # use serenity::gateway::Shard;
/// # use std::sync::Arc;
/// #
Expand All @@ -65,7 +66,7 @@ impl ShardMessenger {
///
/// let guild_ids = vec![GuildId(81384788765712384)];
///
/// shard.chunk_guilds(guild_ids, Some(2000), None, None);
/// shard.chunk_guilds(guild_ids, Some(2000), ChunkGuildFilter::None, None);
/// # Ok(())
/// # }
/// ```
Expand All @@ -75,6 +76,7 @@ impl ShardMessenger {
///
/// ```rust,no_run
/// # use tokio::sync::Mutex;
/// # use serenity::client::bridge::gateway::ChunkGuildFilter;
/// # use serenity::gateway::Shard;
/// # use std::sync::Arc;
/// #
Expand All @@ -87,7 +89,7 @@ impl ShardMessenger {
///
/// let guild_ids = vec![GuildId(81384788765712384)];
///
/// shard.chunk_guilds(guild_ids, Some(20), Some("do"), Some("request"));
/// shard.chunk_guilds(guild_ids, Some(20), ChunkGuildFilter::Query("do".to_owned()), Some("request"));
/// # Ok(())
/// # }
/// ```
Expand All @@ -99,15 +101,15 @@ impl ShardMessenger {
&self,
guild_ids: It,
limit: Option<u16>,
query: Option<String>,
filter: ChunkGuildFilter,
nonce: Option<String>,
) where It: IntoIterator<Item=GuildId> {
let guilds = guild_ids.into_iter().collect::<Vec<GuildId>>();

let _ = self.send_to_shard(ShardRunnerMessage::ChunkGuilds {
guild_ids: guilds,
limit,
query,
filter,
nonce,
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/client/bridge/gateway/shard_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,11 +362,11 @@ impl ShardRunner {

true
},
ShardClientMessage::Runner(ShardRunnerMessage::ChunkGuilds { guild_ids, limit, query, nonce }) => {
ShardClientMessage::Runner(ShardRunnerMessage::ChunkGuilds { guild_ids, limit, filter, nonce }) => {
self.shard.chunk_guilds(
guild_ids,
limit,
query.as_deref(),
filter,
nonce.as_deref(),
).await.is_ok()
},
Expand Down
25 changes: 16 additions & 9 deletions src/client/bridge/gateway/shard_runner_message.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
use crate::model::{
gateway::Activity,
id::GuildId,
id::{GuildId, UserId},
user::OnlineStatus,
};

#[cfg(feature = "collector")]
use crate::collector::{MessageFilter, ReactionFilter};
use async_tungstenite::tungstenite::Message;

#[derive(Clone, Debug)]
pub enum ChunkGuildFilter {
/// Returns all members of the guilds specified. Requires GUILD_MEMBERS intent.
None,
/// A common username prefix filter for the members returned.
Query(String),
/// A set of exact user IDs to query for.
UserIds(Vec<UserId>),
}

/// A message to send from a shard over a WebSocket.
// Once we can use `Box` as part of a pattern, we will reconsider boxing.
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug)]
pub enum ShardRunnerMessage {
/// Indicates that the client is to send a member chunk message.
ChunkGuilds {
// FIXME: When intents are enabled, chunking guilds is limited to 1 guild per chunk
// request. Will be mandatory when using API v8.
/// The IDs of the [`Guild`]s to chunk.
///
/// [`Guild`]: ../../../model/guild/struct.Guild.html
Expand All @@ -24,14 +36,9 @@ pub enum ShardRunnerMessage {
///
/// [`GuildMembersChunkEvent`]: ../../../model/event/struct.GuildMembersChunkEvent.html
limit: Option<u16>,
/// Text to filter members by.
///
/// For example, a query of `"s"` will cause only [`Member`]s whose
/// usernames start with `"s"` to be chunked.
///
/// [`Member`]: ../../../model/guild/struct.Member.html
query: Option<String>,
/// Nonce to identify [`GuildMembersChunkEvent`] responses.
/// A filter to apply to the returned members.
filter: ChunkGuildFilter,
/// Optional nonce to identify [`GuildMembersChunkEvent`] responses.
///
/// [`GuildMembersChunkEvent`]: ../../../model/event/struct.GuildMembersChunkEvent.html
nonce: Option<String>,
Expand Down
12 changes: 7 additions & 5 deletions src/gateway/shard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::model::{
user::OnlineStatus
};
use tokio::sync::Mutex;
use crate::client::bridge::gateway::GatewayIntents;
use crate::client::bridge::gateway::{GatewayIntents, ChunkGuildFilter};
use std::{
sync::Arc,
time::{Duration as StdDuration, Instant}
Expand Down Expand Up @@ -685,6 +685,7 @@ impl Shard {
///
/// ```rust,no_run
/// # use tokio::sync::Mutex;
/// # use serenity::client::bridge::gateway::ChunkGuildFilter;
/// # use serenity::gateway::Shard;
/// # use std::sync::Arc;
/// #
Expand All @@ -697,7 +698,7 @@ impl Shard {
///
/// let guild_ids = vec![GuildId(81384788765712384)];
///
/// shard.chunk_guilds(guild_ids, Some(2000), None, None).await?;
/// shard.chunk_guilds(guild_ids, Some(2000), ChunkGuildFilter::None, None).await?;
/// # Ok(())
/// # }
/// ```
Expand All @@ -708,6 +709,7 @@ impl Shard {
/// ```rust,no_run
/// # use tokio::sync::Mutex;
/// # use serenity::gateway::Shard;
/// # use serenity::client::bridge::gateway::ChunkGuildFilter;
/// # use std::error::Error;
/// # use std::sync::Arc;
/// #
Expand All @@ -720,7 +722,7 @@ impl Shard {
///
/// let guild_ids = vec![GuildId(81384788765712384)];
///
/// shard.chunk_guilds(guild_ids, Some(20), Some("do"), Some("request")).await?;
/// shard.chunk_guilds(guild_ids, Some(20), ChunkGuildFilter::Query("do".to_owned()), Some("request")).await?;
/// # Ok(())
/// # }
/// ```
Expand All @@ -733,7 +735,7 @@ impl Shard {
&mut self,
guild_ids: It,
limit: Option<u16>,
query: Option<&str>,
filter: ChunkGuildFilter,
nonce: Option<&str>,
) -> Result<()> where It: IntoIterator<Item=GuildId> + Send {
debug!("[Shard {:?}] Requesting member chunks", self.shard_info);
Expand All @@ -742,7 +744,7 @@ impl Shard {
guild_ids,
&self.shard_info,
limit,
query,
filter,
nonce,
).await
}
Expand Down
28 changes: 19 additions & 9 deletions src/gateway/ws_client_ext.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use crate::client::bridge::gateway::{ChunkGuildFilter, GatewayIntents};
use crate::constants::{self, OpCode};
use crate::gateway::{CurrentPresence, WsStream};
use crate::client::bridge::gateway::GatewayIntents;
use crate::internal::prelude::*;
use crate::internal::ws_impl::SenderExt;
use crate::model::id::GuildId;
use async_trait::async_trait;
use serde_json::json;
use std::env::consts;
use std::time::SystemTime;
use tracing::{debug, trace};
use async_trait::async_trait;
use tracing::instrument;
use tracing::{debug, trace};

#[async_trait]
pub trait WebSocketGatewayClientExt {
Expand All @@ -18,7 +18,7 @@ pub trait WebSocketGatewayClientExt {
guild_ids: It,
shard_info: &[u64; 2],
limit: Option<u16>,
query: Option<&str>,
filter: ChunkGuildFilter,
nonce: Option<&str>,
) -> Result<()> where It: IntoIterator<Item=GuildId> + Send;

Expand Down Expand Up @@ -51,20 +51,30 @@ impl WebSocketGatewayClientExt for WsStream {
guild_ids: It,
shard_info: &[u64; 2],
limit: Option<u16>,
query: Option<&str>,
filter: ChunkGuildFilter,
nonce: Option<&str>,
) -> Result<()> where It: IntoIterator<Item=GuildId> + Send {
) -> Result<()> where It: IntoIterator<Item = GuildId> + Send, {
debug!("[Shard {:?}] Requesting member chunks", shard_info);

self.send_json(&json!({
let mut payload = json!({
"op": OpCode::GetGuildMembers.num(),
"d": {
"guild_id": guild_ids.into_iter().map(|x| x.as_ref().0).collect::<Vec<u64>>(),
"limit": limit.unwrap_or(0),
"query": query.unwrap_or(""),
"nonce": nonce.unwrap_or(""),
},
})).await.map_err(From::from)
});

match filter {
ChunkGuildFilter::None => {},
ChunkGuildFilter::Query(query) => payload["d"]["query"] = json!(query),
ChunkGuildFilter::UserIds(user_ids) => {
let ids = user_ids.iter().map(|x| x.as_ref().0).collect::<Vec<u64>>();
payload["d"]["user_ids"] = json!(ids)
},
};

self.send_json(&payload).await.map_err(From::from)
}

#[instrument(skip(self))]
Expand Down

0 comments on commit 0d9b821

Please sign in to comment.