Merge pull request #55 from polyphony-chat/feature/guild-creation-deletion

Feature/guild creation deletion
This commit is contained in:
Flori 2023-05-14 22:54:53 +02:00 committed by GitHub
commit 62e46ac160
10 changed files with 984 additions and 218 deletions

View File

@ -5,7 +5,6 @@ pub mod messages {
use serde_json::to_string; use serde_json::to_string;
use crate::api::types::{Message, PartialDiscordFileAttachment, User}; use crate::api::types::{Message, PartialDiscordFileAttachment, User};
use crate::errors::InstanceServerError;
use crate::limit::LimitedRequester; use crate::limit::LimitedRequester;
impl Message { impl Message {

169
src/api/guilds/guilds.rs Normal file
View File

@ -0,0 +1,169 @@
use serde_json::from_str;
use serde_json::to_string;
use crate::api::schemas;
use crate::api::types;
use crate::errors::InstanceServerError;
impl<'a> types::Guild {
/// Creates a new guild with the given parameters.
///
/// # Arguments
///
/// * `user` - A mutable reference to the user creating the guild.
/// * `instance` - A mutable reference to the instance where the guild will be created.
/// * `guild_create_schema` - A reference to the schema containing the guild creation parameters.
///
/// # Returns
///
/// A `Result<String>` containing the ID of the newly created guild, or an error if the request fails.
///
/// # Errors
///
/// Returns an `InstanceServerError` if the request fails.
///
/// # Examples
///
/// ```rs
/// let guild_create_schema = chorus::api::schemas::GuildCreateSchema::new(insert args here);
///
/// let result = Guild::create(&mut user, &mut instance, &guild_create_schema).await;
///
/// match result {
/// Ok(guild_id) => println!("Created guild with ID {}", guild_id),
/// Err(e) => println!("Failed to create guild: {}", e),
/// }
/// ```
pub async fn create(
user: &mut types::User<'a>,
url_api: &str,
guild_create_schema: schemas::GuildCreateSchema,
) -> Result<String, crate::errors::InstanceServerError> {
let url = format!("{}/guilds/", url_api);
let limits_user = user.limits.get_as_mut();
let limits_instance = &mut user.belongs_to.limits;
let request = reqwest::Client::new()
.post(url.clone())
.bearer_auth(user.token.clone())
.body(to_string(&guild_create_schema).unwrap());
let mut requester = crate::limit::LimitedRequester::new().await;
let result = match requester
.send_request(
request,
crate::api::limits::LimitType::Guild,
limits_instance,
limits_user,
)
.await
{
Ok(result) => result,
Err(e) => return Err(e),
};
let id: types::GuildCreateResponse = from_str(&result.text().await.unwrap()).unwrap();
Ok(id.id)
}
/// Deletes a guild.
///
/// # Arguments
///
/// * `user` - A mutable reference to a `User` instance.
/// * `instance` - A mutable reference to an `Instance` instance.
/// * `guild_id` - A `String` representing the ID of the guild to delete.
///
/// # Returns
///
/// An `Option` containing an `InstanceServerError` if an error occurred during the request, otherwise `None`.
///
/// # Example
///
/// ```rs
/// let mut user = User::new();
/// let mut instance = Instance::new();
/// let guild_id = String::from("1234567890");
///
/// match Guild::delete(&mut user, &mut instance, guild_id) {
/// Some(e) => println!("Error deleting guild: {:?}", e),
/// None => println!("Guild deleted successfully"),
/// }
/// ```
pub async fn delete(
user: &mut types::User<'a>,
url_api: &str,
guild_id: String,
) -> Option<InstanceServerError> {
let url = format!("{}/guilds/{}/delete/", url_api, guild_id);
let limits_user = user.limits.get_as_mut();
let limits_instance = &mut user.belongs_to.limits;
let request = reqwest::Client::new()
.post(url.clone())
.bearer_auth(user.token.clone());
let mut requester = crate::limit::LimitedRequester::new().await;
let result = requester
.send_request(
request,
crate::api::limits::LimitType::Guild,
limits_instance,
limits_user,
)
.await;
if result.is_err() {
Some(result.err().unwrap())
} else {
None
}
}
}
#[cfg(test)]
mod test {
use crate::api::schemas;
use crate::api::types;
use crate::instance::Instance;
#[tokio::test]
async fn guild_creation_deletion() {
let mut instance = Instance::new(
crate::URLBundle {
api: "http://localhost:3001/api".to_string(),
wss: "ws://localhost:3001/".to_string(),
cdn: "http://localhost:3001".to_string(),
},
crate::limit::LimitedRequester::new().await,
)
.await
.unwrap();
let login_schema: schemas::LoginSchema = schemas::LoginSchema::new(
schemas::AuthUsername::new("user@test.xyz".to_string()).unwrap(),
"transrights".to_string(),
None,
None,
None,
None,
)
.unwrap();
let mut user = instance.login_account(&login_schema).await.unwrap();
let guild_create_schema = schemas::GuildCreateSchema {
name: Some("test".to_string()),
region: None,
icon: None,
channels: None,
guild_template_code: None,
system_channel_id: None,
rules_channel_id: None,
};
let guild =
types::Guild::create(&mut user, "http://localhost:3001/api", guild_create_schema)
.await
.unwrap();
println!("{}", guild);
match types::Guild::delete(&mut user, "http://localhost:3001/api", guild).await {
None => assert!(true),
Some(_) => assert!(false),
}
}
}

3
src/api/guilds/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod guilds;
use guilds::*;

View File

@ -1,11 +1,13 @@
pub mod auth; pub mod auth;
pub mod channels; pub mod channels;
pub mod guilds;
pub mod policies; pub mod policies;
pub mod schemas; pub mod schemas;
pub mod types; pub mod types;
pub mod users; pub mod users;
pub use channels::messages::*; pub use channels::messages::*;
pub use guilds::*;
pub use policies::instance::instance::*; pub use policies::instance::instance::*;
pub use policies::instance::limits::*; pub use policies::instance::limits::*;
pub use schemas::*; pub use schemas::*;

View File

@ -1,5 +1,5 @@
pub mod limits { pub mod limits {
use std::{collections::HashMap}; use std::collections::HashMap;
use reqwest::Client; use reqwest::Client;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -20,6 +20,23 @@ pub mod limits {
Webhook, Webhook,
} }
impl ToString for LimitType {
fn to_string(&self) -> String {
match self {
LimitType::AuthRegister => "AuthRegister".to_string(),
LimitType::AuthLogin => "AuthLogin".to_string(),
LimitType::AbsoluteMessage => "AbsoluteMessage".to_string(),
LimitType::AbsoluteRegister => "AbsoluteRegister".to_string(),
LimitType::Global => "Global".to_string(),
LimitType::Ip => "Ip".to_string(),
LimitType::Channel => "Channel".to_string(),
LimitType::Error => "Error".to_string(),
LimitType::Guild => "Guild".to_string(),
LimitType::Webhook => "Webhook".to_string(),
}
}
}
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub struct User { pub struct User {

View File

@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use crate::errors::FieldFormatError; use crate::errors::FieldFormatError;
use super::Embed; use super::{Channel, Embed};
/** /**
A struct that represents a well-formed email address. A struct that represents a well-formed email address.
@ -287,6 +287,18 @@ impl MessageSendSchema {
} }
} }
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct GuildCreateSchema {
pub name: Option<String>,
pub region: Option<String>,
pub icon: Option<String>,
pub channels: Option<Vec<Channel>>,
pub guild_template_code: Option<String>,
pub system_channel_id: Option<String>,
pub rules_channel_id: Option<String>,
}
// I know that some of these tests are... really really basic and unneccessary, but sometimes, I // I know that some of these tests are... really really basic and unneccessary, but sometimes, I
// just feel like writing tests, so there you go :) -@bitfl0wer // just feel like writing tests, so there you go :) -@bitfl0wer
#[cfg(test)] #[cfg(test)]

View File

@ -6,6 +6,7 @@ I do not feel like re-documenting all of this, as everything is already perfectl
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::from_value;
use crate::{api::limits::Limits, instance::Instance}; use crate::{api::limits::Limits, instance::Instance};
@ -136,10 +137,187 @@ pub struct Error {
#[derive(Serialize, Deserialize, Debug, Default)] #[derive(Serialize, Deserialize, Debug, Default)]
pub struct UnavailableGuild { pub struct UnavailableGuild {
id: String, id: String,
unavailable: bool unavailable: bool,
} }
#[derive(Serialize, Deserialize, Debug, Default)] /// See https://discord.com/developers/docs/resources/guild
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct Guild {
pub id: String,
pub name: String,
pub icon: Option<String>,
pub icon_hash: Option<String>,
pub splash: Option<String>,
pub discovery_splash: Option<String>,
pub owner: Option<UserObject>,
pub owner_id: Option<String>,
pub permissions: Option<String>,
pub afk_channel_id: Option<String>,
pub afk_timeout: Option<u8>,
pub widget_enabled: Option<bool>,
pub widget_channel_id: Option<String>,
pub widget_channel: Option<Channel>,
pub verification_level: Option<u8>,
pub default_message_notifications: Option<u8>,
pub explicit_content_filter: Option<u8>,
pub roles: Vec<RoleObject>,
pub emojis: Vec<Emoji>,
pub features: Vec<String>,
pub application_id: Option<String>,
pub system_channel_id: Option<String>,
pub system_channel_flags: Option<u8>,
pub rules_channel_id: Option<String>,
pub rules_channel: Option<String>,
pub max_presences: Option<u64>,
pub max_members: Option<u64>,
pub vanity_url_code: Option<String>,
pub description: Option<String>,
pub banner: Option<String>,
pub premium_tier: Option<u8>,
pub premium_subscription_count: Option<u64>,
pub preferred_locale: Option<String>,
pub public_updates_channel_id: Option<String>,
pub public_updates_channel: Option<Channel>,
pub max_video_channel_users: Option<u8>,
pub max_stage_video_channel_users: Option<u8>,
pub approximate_member_count: Option<u64>,
pub approximate_presence_count: Option<u64>,
pub member_count: Option<u64>,
pub presence_count: Option<u64>,
pub welcome_screen: Option<WelcomeScreenObject>,
pub nsfw_level: u8,
pub nsfw: bool,
pub stickers: Option<Vec<Sticker>>,
pub premium_progress_bar_enabled: Option<bool>,
pub joined_at: String,
pub afk_channel: Option<Channel>,
pub bans: Option<Vec<GuildBan>>,
pub primary_category_id: Option<String>,
pub large: Option<bool>,
pub channels: Option<Vec<Channel>>,
pub template_id: Option<String>,
pub template: Option<GuildTemplate>,
pub invites: Option<Vec<GuildInvite>>,
pub voice_states: Option<Vec<VoiceState>>,
pub webhooks: Option<Vec<Webhook>>,
pub mfa_level: Option<u8>,
pub region: Option<String>,
pub unavailable: bool,
pub parent: Option<String>,
}
/// See https://docs.spacebar.chat/routes/#get-/guilds/-guild_id-/bans/-user-
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct GuildBan {
pub id: String,
pub user_id: String,
pub guild_id: String,
pub executor_id: String,
pub reason: Option<String>,
}
/// See https://discord.com/developers/docs/topics/gateway-events#guild-create-guild-create-extra-fields
/// This is like [Guild], expect it has extra fields
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct GuildCreateGuild {
pub id: String,
pub name: String,
pub icon: Option<String>,
pub icon_hash: Option<String>,
pub splash: Option<String>,
pub discovery_splash: Option<String>,
pub owner: Option<bool>,
pub owner_id: String,
pub permissions: Option<String>,
pub afk_channel_id: Option<String>,
pub afk_timeout: u8,
pub widget_enabled: Option<bool>,
pub widget_channel_id: Option<String>,
pub verification_level: u8,
pub default_message_notifications: u8,
pub explicit_content_filter: u8,
pub roles: Vec<RoleObject>,
pub emojis: Vec<Emoji>,
pub features: Vec<String>,
pub mfa_level: u8,
pub application_id: Option<String>,
pub system_channel_id: Option<String>,
pub system_channel_flags: u8,
pub rules_channel_id: Option<String>,
pub max_presences: Option<u64>,
pub max_members: Option<u64>,
pub vanity_url_code: Option<String>,
pub description: Option<String>,
pub banner: Option<String>,
pub premium_tier: u8,
pub premium_subscription_count: Option<u64>,
pub preferred_locale: String,
pub public_updates_channel_id: Option<String>,
pub max_video_channel_users: Option<u8>,
pub max_stage_video_channel_users: Option<u8>,
pub approximate_member_count: Option<u64>,
pub approximate_presence_count: Option<u64>,
pub welcome_screen: Option<WelcomeScreenObject>,
pub nsfw_level: u8,
pub stickers: Option<Vec<Sticker>>,
pub premium_progress_bar_enabled: bool,
// ------ Extra Fields ------
pub joined_at: DateTime<Utc>,
pub large: bool,
pub unavailable: Option<bool>,
pub member_count: u64,
// to:do implement voice states
//pub voice_states: Vec<VoiceState>,
pub members: Vec<GuildMember>,
pub channels: Vec<Channel>,
pub threads: Vec<Channel>,
pub presences: Vec<PresenceUpdate>,
// to:do add stage instances
//pub stage_instances: Vec<StageInstance>,
// to:do add guild schedules events
//pub guild_scheduled_events: Vec<GuildScheduledEvent>
}
impl GuildCreateGuild {
/// Converts self to a [Guild], discarding the extra fields
pub fn to_guild(&self) -> Guild {
let as_value = serde_json::to_value(&self).unwrap();
return from_value(as_value).unwrap();
}
}
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct WelcomeScreenObject {
pub description: Option<String>,
pub welcome_channels: Vec<WelcomeScreenChannel>,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct WelcomeScreenChannel {
pub channel_id: String,
pub description: String,
pub emoji_id: Option<String>,
pub emoji_name: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
/// See https://discord.com/developers/docs/topics/permissions#role-object
pub struct RoleObject {
pub id: String,
pub name: String,
pub color: f64,
pub hoist: bool,
pub icon: Option<String>,
pub unicode_emoji: Option<String>,
pub position: u16,
pub permissions: String,
pub managed: bool,
pub mentionable: bool,
// to:do add role tags https://discord.com/developers/docs/topics/permissions#role-object-role-tags-structure
//pub tags: Option<RoleTags>
}
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct UserObject { pub struct UserObject {
pub id: String, pub id: String,
username: String, username: String,
@ -447,201 +625,242 @@ struct EmbedField {
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct Reaction { pub struct Reaction {
count: i32, pub count: i32,
me: bool, pub me: bool,
emoji: Emoji, pub emoji: Emoji,
} }
#[derive(Debug, Deserialize, Serialize, Default)] #[derive(Debug, Deserialize, Serialize, Default, Clone)]
struct Emoji { pub struct Emoji {
id: Option<u64>, pub id: Option<u64>,
name: Option<String>, pub name: Option<String>,
roles: Option<Vec<u64>>, pub roles: Option<Vec<u64>>,
user: Option<UserObject>, pub user: Option<UserObject>,
require_colons: Option<bool>, pub require_colons: Option<bool>,
managed: Option<bool>, pub managed: Option<bool>,
animated: Option<bool>, pub animated: Option<bool>,
available: Option<bool>, pub available: Option<bool>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct MessageActivity { pub struct MessageActivity {
#[serde(rename = "type")] #[serde(rename = "type")]
activity_type: i64, pub activity_type: i64,
party_id: Option<String>, pub party_id: Option<String>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct Application { pub struct Application {
id: String, pub id: String,
name: String, pub name: String,
icon: Option<String>, pub icon: Option<String>,
description: String, pub description: String,
rpc_origins: Option<Vec<String>>, pub rpc_origins: Option<Vec<String>>,
bot_public: bool, pub bot_public: bool,
bot_require_code_grant: bool, pub bot_require_code_grant: bool,
terms_of_service_url: Option<String>, pub terms_of_service_url: Option<String>,
privacy_policy_url: Option<String>, pub privacy_policy_url: Option<String>,
owner: Option<UserObject>, pub owner: Option<UserObject>,
summary: String, pub summary: String,
verify_key: String, pub verify_key: String,
team: Option<Team>, pub team: Option<Team>,
guild_id: Option<String>, pub guild_id: Option<String>,
primary_sku_id: Option<String>, pub primary_sku_id: Option<String>,
slug: Option<String>, pub slug: Option<String>,
cover_image: Option<String>, pub cover_image: Option<String>,
flags: Option<i32>, pub flags: Option<i32>,
tags: Option<Vec<String>>, pub tags: Option<Vec<String>>,
install_params: Option<InstallParams>, pub install_params: Option<InstallParams>,
custom_install_url: Option<String>, pub custom_install_url: Option<String>,
role_connections_verification_url: Option<String>, pub role_connections_verification_url: Option<String>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct Team { pub struct Team {
icon: Option<String>, pub icon: Option<String>,
id: u64, pub id: u64,
members: Vec<TeamMember>, pub members: Vec<TeamMember>,
name: String, pub name: String,
owner_user_id: u64, pub owner_user_id: u64,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct TeamMember { pub struct TeamMember {
membership_state: u8, pub membership_state: u8,
permissions: Vec<String>, pub permissions: Vec<String>,
team_id: u64, pub team_id: u64,
user: UserObject, pub user: UserObject,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[serde(rename_all = "SCREAMING_SNAKE_CASE")]
enum MembershipState { pub enum MembershipState {
Invited = 1, Invited = 1,
Accepted = 2, Accepted = 2,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Clone)]
struct InstallParams { pub struct InstallParams {
scopes: Vec<String>, pub scopes: Vec<String>,
permissions: String, pub permissions: String,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct MessageReference { pub struct MessageReference {
message_id: String, pub message_id: String,
channel_id: String, pub channel_id: String,
guild_id: Option<String>, pub guild_id: Option<String>,
fail_if_not_exists: Option<bool>, pub fail_if_not_exists: Option<bool>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
struct MessageInteraction { pub struct MessageInteraction {
id: u64, pub id: u64,
#[serde(rename = "type")] #[serde(rename = "type")]
interaction_type: u8, pub interaction_type: u8,
name: String, pub name: String,
user: UserObject, pub user: UserObject,
member: Option<GuildMember>, pub member: Option<GuildMember>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct GuildMember { pub struct GuildMember {
user: Option<UserObject>, pub user: Option<UserObject>,
nick: Option<String>, pub nick: Option<String>,
avatar: Option<String>, pub avatar: Option<String>,
roles: Vec<String>, pub roles: Vec<String>,
joined_at: String, pub joined_at: String,
premium_since: Option<String>, pub premium_since: Option<String>,
deaf: bool, pub deaf: bool,
mute: bool, pub mute: bool,
flags: i32, pub flags: i32,
pending: Option<bool>, pub pending: Option<bool>,
permissions: Option<String>, pub permissions: Option<String>,
communication_disabled_until: Option<String>, pub communication_disabled_until: Option<String>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Default, Debug, Serialize, Deserialize, Clone)]
struct Channel { pub struct Channel {
id: String, pub id: String,
#[serde(rename = "type")] #[serde(rename = "type")]
channel_type: i32, pub channel_type: i32,
guild_id: Option<String>, pub guild_id: Option<String>,
position: Option<i32>, pub position: Option<i32>,
permission_overwrites: Option<Vec<PermissionOverwrite>>, pub permission_overwrites: Option<Vec<PermissionOverwrite>>,
name: Option<String>, pub name: Option<String>,
topic: Option<String>, pub topic: Option<String>,
nsfw: Option<bool>, pub nsfw: Option<bool>,
last_message_id: Option<String>, pub last_message_id: Option<String>,
bitrate: Option<i32>, pub bitrate: Option<i32>,
user_limit: Option<i32>, pub user_limit: Option<i32>,
rate_limit_per_user: Option<i32>, pub rate_limit_per_user: Option<i32>,
recipients: Option<Vec<UserObject>>, pub recipients: Option<Vec<UserObject>>,
icon: Option<String>, pub icon: Option<String>,
owner_id: Option<String>, pub owner_id: Option<String>,
application_id: Option<String>, pub application_id: Option<String>,
parent_id: Option<String>, pub parent_id: Option<String>,
last_pin_timestamp: Option<String>, pub last_pin_timestamp: Option<String>,
rtc_region: Option<String>, pub rtc_region: Option<String>,
video_quality_mode: Option<i32>, pub video_quality_mode: Option<i32>,
message_count: Option<i32>, pub message_count: Option<i32>,
member_count: Option<i32>, pub member_count: Option<i32>,
thread_metadata: Option<ThreadMetadata>, pub thread_metadata: Option<ThreadMetadata>,
member: Option<ThreadMember>, pub member: Option<ThreadMember>,
default_auto_archive_duration: Option<i32>, pub default_auto_archive_duration: Option<i32>,
permissions: Option<String>, pub permissions: Option<String>,
flags: Option<i32>, pub flags: Option<i32>,
total_message_sent: Option<i32>, pub total_message_sent: Option<i32>,
available_tags: Option<Vec<Tag>>, pub available_tags: Option<Vec<Tag>>,
applied_tags: Option<Vec<String>>, pub applied_tags: Option<Vec<String>>,
default_reaction_emoji: Option<DefaultReaction>, pub default_reaction_emoji: Option<DefaultReaction>,
default_thread_rate_limit_per_user: Option<i32>, pub default_thread_rate_limit_per_user: Option<i32>,
default_sort_order: Option<i32>, pub default_sort_order: Option<i32>,
default_forum_layout: Option<i32>, pub default_forum_layout: Option<i32>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct Tag { pub struct Tag {
id: u64, pub id: u64,
name: String, pub name: String,
moderated: bool, pub moderated: bool,
emoji_id: Option<u64>, pub emoji_id: Option<u64>,
emoji_name: Option<String>, pub emoji_name: Option<String>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PermissionOverwrite { pub struct PermissionOverwrite {
id: String, pub id: String,
#[serde(rename = "type")] #[serde(rename = "type")]
overwrite_type: u8, pub overwrite_type: u8,
allow: String, pub allow: String,
deny: String, pub deny: String,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct ThreadMetadata { pub struct ThreadMetadata {
archived: bool, pub archived: bool,
auto_archive_duration: i32, pub auto_archive_duration: i32,
archive_timestamp: String, pub archive_timestamp: String,
locked: bool, pub locked: bool,
invitable: Option<bool>, pub invitable: Option<bool>,
create_timestamp: Option<String>, pub create_timestamp: Option<String>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Default, Debug, Deserialize, Serialize, Clone)]
struct ThreadMember { pub struct ThreadMember {
id: Option<u64>, pub id: Option<u64>,
user_id: Option<u64>, pub user_id: Option<u64>,
join_timestamp: Option<String>, pub join_timestamp: Option<String>,
flags: Option<u64>, pub flags: Option<u64>,
member: Option<GuildMember>, pub member: Option<GuildMember>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Default, Debug, Deserialize, Serialize, Clone)]
struct DefaultReaction { /// See https://discord.com/developers/docs/resources/guild#integration-object-integration-structure
emoji_id: Option<String>, pub struct Integration {
emoji_name: Option<String>, pub id: String,
pub name: String,
#[serde(rename = "type")]
pub integration_type: String,
pub enabled: bool,
pub syncing: Option<bool>,
pub role_id: Option<String>,
pub enabled_emoticons: Option<bool>,
pub expire_behaviour: Option<u8>,
pub expire_grace_period: Option<u16>,
pub user: Option<UserObject>,
pub account: IntegrationAccount,
pub synced_at: Option<DateTime<Utc>>,
pub subscriber_count: Option<f64>,
pub revoked: Option<bool>,
pub application: Option<Application>,
pub scopes: Option<Vec<String>>,
}
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
/// See https://discord.com/developers/docs/resources/guild#integration-account-object-integration-account-structure
pub struct IntegrationAccount {
pub id: String,
pub name: String,
}
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
/// See https://discord.com/developers/docs/resources/stage-instance#stage-instance-object
pub struct StageInstance {
pub id: String,
pub guild_id: String,
pub channel_id: String,
pub topic: String,
pub privacy_level: u8,
pub discoverable_disabled: bool,
pub guild_scheduled_event_id: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct DefaultReaction {
pub emoji_id: Option<String>,
pub emoji_name: Option<String>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -657,44 +876,44 @@ pub enum Component {
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct StickerItem { pub struct StickerItem {
id: u64, pub id: u64,
name: String, pub name: String,
format_type: u8, pub format_type: u8,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize, Clone)]
struct Sticker { pub struct Sticker {
id: u64, pub id: u64,
pack_id: Option<u64>, pub pack_id: Option<u64>,
name: String, pub name: String,
description: Option<String>, pub description: Option<String>,
tags: String, pub tags: String,
asset: Option<String>, pub asset: Option<String>,
#[serde(rename = "type")] #[serde(rename = "type")]
sticker_type: u8, pub sticker_type: u8,
format_type: u8, pub format_type: u8,
available: Option<bool>, pub available: Option<bool>,
guild_id: Option<u64>, pub guild_id: Option<u64>,
user: Option<UserObject>, pub user: Option<UserObject>,
sort_value: Option<u8>, pub sort_value: Option<u8>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct RoleSubscriptionData { pub struct RoleSubscriptionData {
role_subscription_listing_id: u64, pub role_subscription_listing_id: u64,
tier_name: String, pub tier_name: String,
total_months_subscribed: u32, pub total_months_subscribed: u32,
is_renewal: bool, pub is_renewal: bool,
} }
#[derive(Debug, Deserialize, Serialize, Default)] #[derive(Debug, Deserialize, Serialize, Default)]
pub struct TypingStartEvent { pub struct TypingStartEvent {
channel_id: String, pub channel_id: String,
guild_id: Option<String>, pub guild_id: Option<String>,
user_id: String, pub user_id: String,
timestamp: i64, pub timestamp: i64,
member: Option<GuildMember>, pub member: Option<GuildMember>,
} }
impl WebSocketEvent for TypingStartEvent {} impl WebSocketEvent for TypingStartEvent {}
@ -719,18 +938,28 @@ pub struct GatewayIdentifyConnectionProps {
pub device: String, pub device: String,
} }
#[derive(Debug, Deserialize, Serialize, Default)] #[derive(Debug, Deserialize, Serialize, Default, Clone)]
/// See https://discord.com/developers/docs/topics/gateway-events#presence-update-presence-update-event-fields
pub struct PresenceUpdate { pub struct PresenceUpdate {
since: Option<i64>, pub user: UserObject,
activities: Vec<Activity>, pub guild_id: String,
status: String, pub status: String,
afk: Option<bool>, pub activities: Vec<Activity>,
pub client_status: ClientStatusObject,
}
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
/// See https://discord.com/developers/docs/topics/gateway-events#client-status-object
pub struct ClientStatusObject {
pub desktop: Option<String>,
pub mobile: Option<String>,
pub web: Option<String>,
} }
impl WebSocketEvent for PresenceUpdate {} impl WebSocketEvent for PresenceUpdate {}
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct Activity { pub struct Activity {
name: String, name: String,
#[serde(rename = "type")] #[serde(rename = "type")]
activity_type: i32, activity_type: i32,
@ -749,19 +978,19 @@ struct Activity {
buttons: Option<Vec<ActivityButton>>, buttons: Option<Vec<ActivityButton>>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct ActivityTimestamps { struct ActivityTimestamps {
start: Option<i64>, start: Option<i64>,
end: Option<i64>, end: Option<i64>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct ActivityParty { struct ActivityParty {
id: Option<String>, id: Option<String>,
size: Option<Vec<(i32, i32)>>, size: Option<Vec<(i32, i32)>>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct ActivityAssets { struct ActivityAssets {
large_image: Option<String>, large_image: Option<String>,
large_text: Option<String>, large_text: Option<String>,
@ -769,7 +998,7 @@ struct ActivityAssets {
small_text: Option<String>, small_text: Option<String>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct ActivitySecrets { struct ActivitySecrets {
join: Option<String>, join: Option<String>,
spectate: Option<String>, spectate: Option<String>,
@ -777,7 +1006,7 @@ struct ActivitySecrets {
match_string: Option<String>, match_string: Option<String>,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize, Clone)]
struct ActivityButton { struct ActivityButton {
label: String, label: String,
url: String, url: String,
@ -863,7 +1092,7 @@ impl WebSocketEvent for GatewayHeartbeatAck {}
pub struct ChannelPinsUpdate { pub struct ChannelPinsUpdate {
pub guild_id: Option<String>, pub guild_id: Option<String>,
pub channel_id: String, pub channel_id: String,
pub last_pin_timestamp: Option<DateTime<Utc>> pub last_pin_timestamp: Option<DateTime<Utc>>,
} }
impl WebSocketEvent for ChannelPinsUpdate {} impl WebSocketEvent for ChannelPinsUpdate {}
@ -895,6 +1124,132 @@ pub struct UserUpdate {
impl WebSocketEvent for UserUpdate {} impl WebSocketEvent for UserUpdate {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#channel-create
/// Not directly serialized, as the inner payload is a channel object
pub struct ChannelCreate {
pub channel: Channel,
}
impl WebSocketEvent for ChannelCreate {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#channel-update
/// Not directly serialized, as the inner payload is a channel object
pub struct ChannelUpdate {
pub channel: Channel,
}
impl WebSocketEvent for ChannelUpdate {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#channel-delete
/// Not directly serialized, as the inner payload is a channel object
pub struct ChannelDelete {
pub channel: Channel,
}
impl WebSocketEvent for ChannelDelete {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#thread-create
/// Not directly serialized, as the inner payload is a channel object
pub struct ThreadCreate {
pub thread: Channel,
}
impl WebSocketEvent for ThreadCreate {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#thread-update
/// Not directly serialized, as the inner payload is a channel object
pub struct ThreadUpdate {
pub thread: Channel,
}
impl WebSocketEvent for ThreadUpdate {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#thread-delete
/// Not directly serialized, as the inner payload is a channel object
pub struct ThreadDelete {
pub thread: Channel,
}
impl WebSocketEvent for ThreadDelete {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#thread-list-sync
pub struct ThreadListSync {
pub guild_id: String,
pub channel_ids: Option<Vec<String>>,
pub threads: Vec<Channel>,
pub members: Vec<ThreadMember>,
}
impl WebSocketEvent for ThreadListSync {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#thread-member-update
/// The inner payload is a thread member object with an extra field.
/// The extra field is a bit painful, because we can't just serialize a thread member object
pub struct ThreadMemberUpdate {
pub id: Option<u64>,
pub user_id: Option<u64>,
pub join_timestamp: Option<String>,
pub flags: Option<u64>,
pub member: Option<GuildMember>,
pub guild_id: String,
}
impl ThreadMemberUpdate {
/// Convert self to a thread member, losing the added guild_id field
pub fn to_thread_member(&self) -> ThreadMember {
ThreadMember {
id: self.id,
user_id: self.user_id,
join_timestamp: self.join_timestamp.clone(),
flags: self.flags,
member: self.member.clone(),
}
}
}
impl WebSocketEvent for ThreadMemberUpdate {}
#[derive(Debug, Default, Deserialize, Serialize)]
/// See https://discord.com/developers/docs/topics/gateway-events#thread-members-update
pub struct ThreadMembersUpdate {
pub id: String,
pub guild_id: String,
/// Capped at 50
pub member_count: u8,
pub added_members: Option<Vec<ThreadMember>>,
pub removed_members: Option<Vec<String>>,
}
impl WebSocketEvent for ThreadMembersUpdate {}
#[derive(Debug, Deserialize, Serialize, Default)]
/// See https://discord.com/developers/docs/topics/gateway-events#guild-create
/// This one is particularly painful, it can be a Guild object with extra field or an unavailbile guild object
pub struct GuildCreate {
pub d: GuildCreateDataOption,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum GuildCreateDataOption {
UnavailableGuild(UnavailableGuild),
Guild(Guild),
}
impl Default for GuildCreateDataOption {
fn default() -> Self {
GuildCreateDataOption::UnavailableGuild(UnavailableGuild::default())
}
}
impl WebSocketEvent for GuildCreate {}
#[derive(Debug, Default, Deserialize, Serialize)] #[derive(Debug, Default, Deserialize, Serialize)]
pub struct GatewayPayload { pub struct GatewayPayload {
pub op: u8, pub op: u8,
@ -980,6 +1335,7 @@ impl PartialDiscordFileAttachment {
proxy_url: self.proxy_url, proxy_url: self.proxy_url,
height: self.height, height: self.height,
width: self.width, width: self.width,
ephemeral: self.ephemeral, ephemeral: self.ephemeral,
duration_secs: self.duration_secs, duration_secs: self.duration_secs,
waveform: self.waveform, waveform: self.waveform,
@ -1033,3 +1389,96 @@ pub enum AllowedMentionType {
pub struct Token { pub struct Token {
pub token: String, pub token: String,
} }
/// See https://docs.spacebar.chat/routes/#cmp--schemas-template
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct GuildTemplate {
pub code: String,
pub name: String,
pub description: Option<String>,
pub usage_count: Option<u64>,
pub creator_id: String,
pub creator: UserObject,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub source_guild_id: String,
pub source_guild: Vec<Guild>, // Unsure how a {recursive: Guild} looks like, might be a Vec?
pub serialized_source_guild: Vec<Guild>,
id: String,
}
/// See https://docs.spacebar.chat/routes/#cmp--schemas-invite
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct GuildInvite {
pub code: String,
pub temporary: Option<bool>,
pub uses: Option<i32>,
pub max_uses: Option<i32>,
pub max_age: Option<i32>,
pub created_at: DateTime<Utc>,
pub expires_at: Option<DateTime<Utc>>,
pub guild_id: String,
pub guild: Option<Guild>,
pub channel_id: String,
pub channel: Option<Channel>,
pub inviter_id: Option<String>,
pub inviter: Option<UserObject>,
pub target_user_id: Option<String>,
pub target_user: Option<String>,
pub target_user_type: Option<i32>,
pub vanity_url: Option<bool>,
}
/// See https://docs.spacebar.chat/routes/#cmp--schemas-voicestate
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct VoiceState {
pub guild_id: String,
pub guild: Option<Guild>,
pub channel_id: String,
pub channel: Option<Channel>,
pub user_id: String,
pub user: Option<UserObject>,
pub member: Option<GuildMember>,
pub session_id: String,
pub token: String,
pub deaf: bool,
pub mute: bool,
pub self_deaf: bool,
pub self_mute: bool,
pub self_stream: Option<bool>,
pub self_video: bool,
pub suppress: bool,
pub request_to_speak_timestamp: Option<DateTime<Utc>>,
pub id: String,
}
/// See https://docs.spacebar.chat/routes/#cmp--schemas-webhook
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct Webhook {
#[serde(rename = "type")]
pub webhook_type: i32,
pub name: String,
pub avatar: String,
pub token: String,
pub guild_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub guild: Option<Guild>,
pub channel_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub channel: Option<Channel>,
pub application_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub application: Option<Application>,
pub user_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub user: Option<UserObject>,
pub source_guild_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_guild: Option<Guild>,
pub id: String,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct GuildCreateResponse {
pub id: String,
}

View File

@ -17,8 +17,11 @@ custom_error! {
ReceivedErrorCodeError{error_code:String} = "Received the following error code while requesting from the route: {error_code}", ReceivedErrorCodeError{error_code:String} = "Received the following error code while requesting from the route: {error_code}",
CantGetInfoError{error:String} = "Something seems to be wrong with the instance. Cannot get information about the instance: {error}", CantGetInfoError{error:String} = "Something seems to be wrong with the instance. Cannot get information about the instance: {error}",
InvalidFormBodyError{error_type: String, error:String} = "The server responded with: {error_type}: {error}", InvalidFormBodyError{error_type: String, error:String} = "The server responded with: {error_type}: {error}",
RateLimited = "Ratelimited.", RateLimited{bucket:String} = "Ratelimited on Bucket {bucket}",
MultipartCreationError{error: String} = "Got an error whilst creating the form: {}", MultipartCreationError{error: String} = "Got an error whilst creating the form: {}",
TokenExpired = "Token expired, invalid or not found.",
NoPermission = "You do not have the permissions needed to perform this action.",
NotFound{error: String} = "The provided resource hasn't been found: {}",
} }
custom_error! { custom_error! {

View File

@ -167,7 +167,9 @@ impl Gateway {
return; return;
} }
let gateway_payload: GatewayPayload = serde_json::from_str(msg.to_text().unwrap()).unwrap(); let msg_string = msg.to_string();
let gateway_payload: GatewayPayload = serde_json::from_str(&msg_string).unwrap();
// See https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes // See https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes
match gateway_payload.op { match gateway_payload.op {
@ -189,17 +191,56 @@ impl Gateway {
"AUTO_MODERATION_RULE_UPDATE" => {} "AUTO_MODERATION_RULE_UPDATE" => {}
"AUTO_MODERATION_RULE_DELETE" => {} "AUTO_MODERATION_RULE_DELETE" => {}
"AUTO_MODERATION_ACTION_EXECUTION" => {} "AUTO_MODERATION_ACTION_EXECUTION" => {}
"CHANNEL_CREATE" => {} "CHANNEL_CREATE" => {
"CHANNEL_UPDATE" => {} let channel: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
"CHANNEL_DELETE" => {} let new_data = ChannelCreate {channel};
"CHANNEL_PINS_UPDATE" => {} self.events.lock().await.channel.create.update_data(new_data).await;
"THREAD_CREATE" => {} }
"THREAD_UPDATE" => {} "CHANNEL_UPDATE" => {
"THREAD_DELETE" => {} let channel: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
"THREAD_LIST_SYNC" => {} let new_data = ChannelUpdate {channel};
"THREAD_MEMBER_UPDATE" => {} self.events.lock().await.channel.update.update_data(new_data).await;
"THREAD_MEMBERS_UPDATE" => {} }
"GUILD_CREATE" => {} "CHANNEL_DELETE" => {
let channel: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
let new_data = ChannelDelete {channel};
self.events.lock().await.channel.delete.update_data(new_data).await;
}
"CHANNEL_PINS_UPDATE" => {
let new_data: ChannelPinsUpdate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.channel.pins_update.update_data(new_data).await;
}
"THREAD_CREATE" => {
let thread: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
let new_data = ThreadCreate {thread};
self.events.lock().await.thread.create.update_data(new_data).await;
}
"THREAD_UPDATE" => {
let thread: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
let new_data = ThreadUpdate {thread};
self.events.lock().await.thread.update.update_data(new_data).await;
}
"THREAD_DELETE" => {
let thread: Channel = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
let new_data = ThreadDelete {thread};
self.events.lock().await.thread.delete.update_data(new_data).await;
}
"THREAD_LIST_SYNC" => {
let new_data: ThreadListSync = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.thread.list_sync.update_data(new_data).await;
}
"THREAD_MEMBER_UPDATE" => {
let new_data: ThreadMemberUpdate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.thread.member_update.update_data(new_data).await;
}
"THREAD_MEMBERS_UPDATE" => {
let new_data: ThreadMembersUpdate = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
self.events.lock().await.thread.members_update.update_data(new_data).await;
}
"GUILD_CREATE" => {
let new_data: GuildCreate = serde_json::from_str(&msg_string).unwrap();
self.events.lock().await.guild.create.update_data(new_data).await;
}
"GUILD_UPDATE" => {} "GUILD_UPDATE" => {}
"GUILD_DELETE" => { "GUILD_DELETE" => {
let _new_data: UnavailableGuild = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let _new_data: UnavailableGuild = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
@ -280,7 +321,7 @@ impl Gateway {
"USER_UPDATE" => { "USER_UPDATE" => {
let user: UserObject = serde_json::from_value(gateway_payload.d.unwrap()).unwrap(); let user: UserObject = serde_json::from_value(gateway_payload.d.unwrap()).unwrap();
let new_data = UserUpdate {user}; let new_data = UserUpdate {user};
self.events.lock().await.user.user_update.update_data(new_data).await; self.events.lock().await.user.update.update_data(new_data).await;
} }
"VOICE_STATE_UPDATE" => {} "VOICE_STATE_UPDATE" => {}
"VOICE_SERVER_UPDATE" => {} "VOICE_SERVER_UPDATE" => {}
@ -473,6 +514,9 @@ mod events {
pub struct Events { pub struct Events {
pub message: Message, pub message: Message,
pub user: User, pub user: User,
pub channel: Channel,
pub thread: Thread,
pub guild: Guild,
pub gateway_identify_payload: GatewayEvent<GatewayIdentifyPayload>, pub gateway_identify_payload: GatewayEvent<GatewayIdentifyPayload>,
pub gateway_resume: GatewayEvent<GatewayResume>, pub gateway_resume: GatewayEvent<GatewayResume>,
} }
@ -491,10 +535,53 @@ mod events {
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct User { pub struct User {
pub user_update: GatewayEvent<UserUpdate>, pub update: GatewayEvent<UserUpdate>,
pub presence_update: GatewayEvent<PresenceUpdate>, pub presence_update: GatewayEvent<PresenceUpdate>,
pub typing_start_event: GatewayEvent<TypingStartEvent>, pub typing_start_event: GatewayEvent<TypingStartEvent>,
} }
#[derive(Default, Debug)]
pub struct Channel {
pub create: GatewayEvent<ChannelCreate>,
pub update: GatewayEvent<ChannelUpdate>,
pub delete: GatewayEvent<ChannelDelete>,
pub pins_update: GatewayEvent<ChannelPinsUpdate>
}
#[derive(Default, Debug)]
pub struct Thread {
pub create: GatewayEvent<ThreadCreate>,
pub update: GatewayEvent<ThreadUpdate>,
pub delete: GatewayEvent<ThreadDelete>,
pub list_sync: GatewayEvent<ThreadListSync>,
pub member_update: GatewayEvent<ThreadMemberUpdate>,
pub members_update: GatewayEvent<ThreadMembersUpdate>,
}
#[derive(Default, Debug)]
pub struct Guild {
pub create: GatewayEvent<GuildCreate>,
/*pub update: GatewayEvent<ThreadCreate>,
pub delete: GatewayEvent<ThreadCreate>,
pub audit_log_entry_create: GatewayEvent<ThreadCreate>,
pub ban_add: GatewayEvent<ThreadCreate>,
pub ban_remove: GatewayEvent<ThreadCreate>,
pub emojis_update: GatewayEvent<ThreadCreate>,
pub stickers_update: GatewayEvent<ThreadCreate>,
pub integrations_update: GatewayEvent<ThreadCreate>,
pub member_add: GatewayEvent<ThreadCreate>,
pub member_remove: GatewayEvent<ThreadCreate>,
pub member_update: GatewayEvent<ThreadCreate>,
pub members_chunk: GatewayEvent<ThreadCreate>,
pub role_create: GatewayEvent<ThreadCreate>,
pub role_update: GatewayEvent<ThreadCreate>,
pub role_delete: GatewayEvent<ThreadCreate>,
pub role_scheduled_event_create: GatewayEvent<ThreadCreate>,
pub role_scheduled_event_update: GatewayEvent<ThreadCreate>,
pub role_scheduled_event_delete: GatewayEvent<ThreadCreate>,
pub role_scheduled_event_user_add: GatewayEvent<ThreadCreate>,
pub role_scheduled_event_user_remove: GatewayEvent<ThreadCreate>,*/
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -57,7 +57,8 @@ impl LimitedRequester {
## Errors ## Errors
This method will panic, if: This method will error, if:
- The request does not return a success status code (200-299)
- The supplied [`RequestBuilder`](reqwest::RequestBuilder) contains invalid or incomplete - The supplied [`RequestBuilder`](reqwest::RequestBuilder) contains invalid or incomplete
information information
- There has been an error with processing (unwrapping) the [`Response`](`reqwest::Response`) - There has been an error with processing (unwrapping) the [`Response`](`reqwest::Response`)
@ -72,13 +73,23 @@ impl LimitedRequester {
user_rate_limits: &mut Limits, user_rate_limits: &mut Limits,
) -> Result<Response, InstanceServerError> { ) -> Result<Response, InstanceServerError> {
if self.can_send_request(limit_type, instance_rate_limits, user_rate_limits) { if self.can_send_request(limit_type, instance_rate_limits, user_rate_limits) {
let built_request = request let built_request = match request.build() {
.build() Ok(request) => request,
.unwrap_or_else(|e| panic!("Error while building the Request for sending: {}", e)); Err(e) => {
return Err(InstanceServerError::RequestErrorError {
url: "".to_string(),
error: e.to_string(),
})
}
};
let result = self.http.execute(built_request).await; let result = self.http.execute(built_request).await;
let response = match result { let response = match result {
Ok(is_response) => is_response, Ok(is_response) => is_response,
Err(e) => panic!("An error occured while processing the response: {}", e), Err(e) => {
return Err(InstanceServerError::ReceivedErrorCodeError {
error_code: e.to_string(),
})
}
}; };
self.update_limits( self.update_limits(
&response, &response,
@ -86,13 +97,27 @@ impl LimitedRequester {
instance_rate_limits, instance_rate_limits,
user_rate_limits, user_rate_limits,
); );
Ok(response) if !response.status().is_success() {
match response.status().as_u16() {
401 => return Err(InstanceServerError::TokenExpired),
403 => return Err(InstanceServerError::TokenExpired),
_ => {
return Err(InstanceServerError::ReceivedErrorCodeError {
error_code: response.status().as_str().to_string(),
})
}
}
} else {
Ok(response)
}
} else { } else {
self.requests.push_back(TypedRequest { self.requests.push_back(TypedRequest {
request, request,
limit_type, limit_type,
}); });
Err(InstanceServerError::RateLimited) Err(InstanceServerError::RateLimited {
bucket: limit_type.to_string(),
})
} }
} }