Guild routes (#410)

Merging this adds some new Guild routes, and also checks some boxes in
the Guild Meta Issue.
This commit is contained in:
Flori 2023-08-25 01:46:20 +02:00 committed by GitHub
commit c6caa4907e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 251 additions and 5 deletions

View File

@ -8,7 +8,8 @@ use crate::errors::ChorusResult;
use crate::instance::ChorusUser;
use crate::ratelimiter::ChorusRequest;
use crate::types::{
Channel, ChannelCreateSchema, Guild, GuildBanCreateSchema, GuildCreateSchema, GuildModifySchema,
Channel, ChannelCreateSchema, Guild, GuildBanCreateSchema, GuildCreateSchema, GuildMember,
GuildMemberSearchSchema, GuildModifySchema, GuildPreview,
};
use crate::types::{GuildBan, Snowflake};
@ -180,12 +181,120 @@ impl Guild {
guild_id,
))
.header("Authorization", user.token())
.header("Content-Type", "application/json")
.body(to_string(&schema).unwrap()),
limit_type: LimitType::Guild(guild_id),
};
let response = chorus_request.deserialize_response::<Guild>(user).await?;
Ok(response)
}
/// Returns a guild preview object for the given guild ID. If the user is not in the guild, the guild must be discoverable.
/// # Reference:
///
/// See <https://discord-userdoccers.vercel.app/resources/guild#get-guild-preview>
pub async fn get_preview(
guild_id: Snowflake,
user: &mut ChorusUser,
) -> ChorusResult<GuildPreview> {
let chorus_request = ChorusRequest {
request: Client::new()
.patch(format!(
"{}/guilds/{}/preview",
user.belongs_to.borrow().urls.api,
guild_id,
))
.header("Authorization", user.token())
.header("Content-Type", "application/json"),
limit_type: LimitType::Guild(guild_id),
};
let response = chorus_request
.deserialize_response::<GuildPreview>(user)
.await?;
Ok(response)
}
/// Returns a list of guild member objects that are members of the guild.
///
/// # Reference
/// See <https://discord-userdoccers.vercel.app/resources/guild#get-guild-members>
pub async fn get_members(
guild_id: Snowflake,
user: &mut ChorusUser,
) -> ChorusResult<Vec<GuildMember>> {
let request = ChorusRequest::new(
http::Method::GET,
format!(
"{}/guilds/{}/members",
user.belongs_to.borrow().urls.api,
guild_id,
)
.as_str(),
None,
None,
None,
Some(user),
LimitType::Guild(guild_id),
);
request.deserialize_response::<Vec<GuildMember>>(user).await
}
/// Returns a list of guild member objects whose username or nickname starts with a provided string.
///
/// # Reference:
/// See <https://discord-userdoccers.vercel.app/resources/guild#search-guild-members>
pub async fn search_members(
guild_id: Snowflake,
query: GuildMemberSearchSchema,
user: &mut ChorusUser,
) -> ChorusResult<Vec<GuildMember>> {
let mut request = ChorusRequest::new(
http::Method::GET,
format!(
"{}/guilds/{}/members/search",
user.belongs_to.borrow().urls.api,
guild_id,
)
.as_str(),
None,
None,
None,
Some(user),
LimitType::Guild(guild_id),
);
request.request = request
.request
.query(&[("query", to_string(&query).unwrap())]);
request.deserialize_response::<Vec<GuildMember>>(user).await
}
/// Removes a member from a guild. Requires the KICK_MEMBERS permission. Returns a 204 empty response on success.
///
/// # Reference
/// See <https://discord-userdoccers.vercel.app/resources/guild#remove-guild-member>
pub async fn remove_member(
guild_id: Snowflake,
member_id: Snowflake,
audit_log_reason: Option<String>,
user: &mut ChorusUser,
) -> ChorusResult<()> {
let request = ChorusRequest::new(
http::Method::DELETE,
format!(
"{}/guilds/{}/members/{}",
user.belongs_to.borrow().urls.api,
guild_id,
member_id,
)
.as_str(),
None,
audit_log_reason.as_deref(),
None,
Some(user),
LimitType::Guild(guild_id),
);
request.handle_request_as_result(user).await
}
}
impl Channel {

View File

@ -1,10 +1,11 @@
use reqwest::Client;
use serde_json::to_string;
use crate::api::LimitType;
use crate::errors::ChorusResult;
use crate::instance::ChorusUser;
use crate::ratelimiter::ChorusRequest;
use crate::types::Snowflake;
use crate::types::{GetUserGuildSchema, Guild, Snowflake};
impl ChorusUser {
/// Leaves a given guild.
@ -30,4 +31,28 @@ impl ChorusUser {
.handle_request_as_result(self)
.await
}
/// Returns a list of user guild objects representing the guilds the current user is a member of.
/// This endpoint returns 200 guilds by default
///
/// # Reference:
/// See: <https://discord-userdoccers.vercel.app/resources/guild#get-user-guilds>
pub async fn get_guilds(
&mut self,
query: Option<GetUserGuildSchema>,
) -> ChorusResult<Vec<Guild>> {
let url = format!("{}/users/@me/guilds", self.belongs_to.borrow().urls.api,);
let chorus_request = ChorusRequest {
request: Client::new()
.get(url)
.header("Authorization", self.token())
.header("Content-Type", "application/json")
.body(to_string(&query).unwrap()),
limit_type: LimitType::Global,
};
chorus_request
.deserialize_response::<Vec<Guild>>(self)
.await
}
}

View File

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use crate::types::{entities::User, utils::Snowflake};
#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
/// Represents a sticker that can be sent in messages.
///
@ -28,6 +28,68 @@ pub struct Sticker {
pub sort_value: Option<u8>,
}
impl PartialEq for Sticker {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
&& self.pack_id == other.pack_id
&& self.name == other.name
&& self.description == other.description
&& self.tags == other.tags
&& self.asset == other.asset
&& self.sticker_type == other.sticker_type
&& self.format_type == other.format_type
&& self.available == other.available
&& self.guild_id == other.guild_id
&& self.sort_value == other.sort_value
}
}
impl PartialOrd for Sticker {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.id.partial_cmp(&other.id) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.pack_id.partial_cmp(&other.pack_id) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.name.partial_cmp(&other.name) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.description.partial_cmp(&other.description) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.tags.partial_cmp(&other.tags) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.asset.partial_cmp(&other.asset) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.sticker_type.partial_cmp(&other.sticker_type) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.format_type.partial_cmp(&other.format_type) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.available.partial_cmp(&other.available) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
match self.guild_id.partial_cmp(&other.guild_id) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
self.sort_value.partial_cmp(&other.sort_value)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
/// A partial sticker object.
///

View File

@ -3,8 +3,8 @@ use serde::{Deserialize, Serialize};
use crate::types::entities::Channel;
use crate::types::types::guild_configuration::GuildFeatures;
use crate::types::{
ExplicitContentFilterLevel, MessageNotificationLevel, Snowflake, SystemChannelFlags,
VerificationLevel,
Emoji, ExplicitContentFilterLevel, MessageNotificationLevel, Snowflake, Sticker,
SystemChannelFlags, VerificationLevel,
};
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
@ -56,3 +56,53 @@ pub struct GuildModifySchema {
pub preferred_locale: Option<String>,
pub premium_progress_bar_enabled: Option<bool>,
}
#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct GetUserGuildSchema {
pub before: Option<Snowflake>,
pub after: Option<Snowflake>,
pub limit: Option<u8>,
pub with_counts: Option<bool>,
}
impl std::default::Default for GetUserGuildSchema {
fn default() -> Self {
Self {
before: Default::default(),
after: Default::default(),
limit: Some(200),
with_counts: Some(false),
}
}
}
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, PartialOrd)]
pub struct GuildPreview {
pub id: Snowflake,
pub name: String,
pub icon: Option<String>,
pub description: Option<String>,
pub splash: Option<String>,
pub discovery_splash: Option<String>,
pub home_header: Option<String>,
pub features: Vec<String>,
pub emojis: Vec<Emoji>,
pub stickers: Vec<Sticker>,
pub approximate_member_count: u32,
pub approximate_presence_count: u32,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct GuildMemberSearchSchema {
pub query: String,
pub limit: Option<u16>,
}
impl Default for GuildMemberSearchSchema {
fn default() -> Self {
Self {
query: Default::default(),
limit: Some(1),
}
}
}