Merge branch 'main' into feature/full-gateway-coverage

This commit is contained in:
kozabrada123 2023-05-24 16:23:00 +02:00
commit 9b9df72e22
11 changed files with 259 additions and 24 deletions

View File

@ -1,17 +1,15 @@
<div align="center">
[![Rust]][Rust-url]
[![Discord]][Discord-invite]
[![Build][build-shield]][build-url]
[![Contributors][contributors-shield]][contributors-url]
[![Forks][forks-shield]][forks-url]
[![Stargazers][stars-shield]][stars-url]
[![Issues][issues-shield]][issues-url]
[![GPL3 License][license-shield]][license-url]
</br>
<div align="center">
<a href="https://github.com/polyphony-chat/chorus">
<img src="images/polyphony-chorus-round.png" alt="Logo" width="128" height="128">
<img src="https://raw.githubusercontent.com/polyphony-chat/design/main/branding/polyphony-chorus-round-8bit.png" alt="Logo" width="128" height="128">
</a>
<h3 align="center">Chorus</h3>
@ -54,15 +52,17 @@ Core functionality:
[Rust]: https://img.shields.io/badge/Rust-orange?style=plastic&logo=rust
[Rust-url]: https://www.rust-lang.org/
[build-shield]: https://img.shields.io/github/actions/workflow/status/polyphony-chat/chorus/rust.yml?style=plastic
[build-shield]: https://img.shields.io/github/actions/workflow/status/polyphony-chat/chorus/rust.yml?style=flat
[build-url]: https://github.com/polyphony-chat/chorus/blob/main/.github/workflows/rust.yml
[contributors-shield]: https://img.shields.io/github/contributors/polyphony-chat/chorus.svg?style=plastic
[contributors-shield]: https://img.shields.io/github/contributors/polyphony-chat/chorus.svg?style=flat
[contributors-url]: https://github.com/polyphony-chat/chorus/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/polyphony-chat/chorus.svg?style=plastic
[forks-shield]: https://img.shields.io/github/forks/polyphony-chat/chorus.svg?style=flat
[forks-url]: https://github.com/polyphony-chat/chorus/network/members
[stars-shield]: https://img.shields.io/github/stars/polyphony-chat/chorus.svg?style=plastic
[stars-shield]: https://img.shields.io/github/stars/polyphony-chat/chorus.svg?style=flat
[stars-url]: https://github.com/polyphony-chat/chorus/stargazers
[issues-shield]: https://img.shields.io/github/issues/polyphony-chat/chorus.svg?style=plastic
[issues-shield]: https://img.shields.io/github/issues/polyphony-chat/chorus.svg?style=flat
[issues-url]: https://github.com/polyphony-chat/chorus/issues
[license-shield]: https://img.shields.io/github/license/polyphony-chat/chorus.svg?style=plastic
[license-shield]: https://img.shields.io/github/license/polyphony-chat/chorus.svg?style=f;at
[license-url]: https://github.com/polyphony-chat/chorus/blob/master/LICENSE
[Discord]: https://dcbadge.vercel.app/api/server/m3FpcapGDD?style=flat
[Discord-invite]: https://discord.com/invite/m3FpcapGDD

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 337 KiB

View File

@ -0,0 +1,43 @@
use reqwest::Client;
use serde_json::from_str;
use crate::{
api::{limits::Limits, types},
errors::InstanceServerError,
limit::LimitedRequester,
};
impl types::Channel {
pub async fn get(
token: &str,
url_api: &str,
channel_id: &str,
limits_user: &mut Limits,
limits_instance: &mut Limits,
) -> Result<types::Channel, InstanceServerError> {
let request = Client::new()
.get(format!("{}/channels/{}/", url_api, channel_id))
.bearer_auth(token);
let mut requester = 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 result_text = result.text().await.unwrap();
match from_str::<types::Channel>(&result_text) {
Ok(object) => Ok(object),
Err(e) => Err(InstanceServerError::RequestErrorError {
url: format!("{}/channels/{}/", url_api, channel_id),
error: e.to_string(),
}),
}
}
}

View File

@ -1,3 +1,5 @@
pub mod channels;
pub mod messages;
pub use channels::*;
pub use messages::*;

View File

@ -1,11 +1,14 @@
use reqwest::Client;
use serde_json::from_str;
use serde_json::to_string;
use crate::api::limits::Limits;
use crate::api::schemas;
use crate::api::types;
use crate::errors::InstanceServerError;
use crate::limit::LimitedRequester;
impl<'a> types::Guild {
impl types::Guild {
/// Creates a new guild with the given parameters.
///
/// # Arguments
@ -113,4 +116,86 @@ impl<'a> types::Guild {
None
}
}
/// Sends a request to create a new channel in the guild.
///
/// # Arguments
///
/// * `url_api` - The base URL for the Discord API.
/// * `token` - A Discord bot token.
/// * `schema` - A `ChannelCreateSchema` struct containing the properties of the new channel.
/// * `limits_user` - A mutable reference to a `Limits` struct containing the user's rate limits.
/// * `limits_instance` - A mutable reference to a `Limits` struct containing the instance's rate limits.
///
/// # Returns
///
/// A `Result` containing a `reqwest::Response` if the request was successful, or an `InstanceServerError` if there was an error.
pub async fn create_channel(
&self,
url_api: &str,
token: &str,
schema: schemas::ChannelCreateSchema,
limits_user: &mut Limits,
limits_instance: &mut Limits,
) -> Result<types::Channel, InstanceServerError> {
types::Channel::create(
token,
url_api,
&self.id,
schema,
limits_user,
limits_instance,
)
.await
}
}
impl types::Channel {
/// Sends a request to create a new channel in a guild.
///
/// # Arguments
///
/// * `token` - A Discord bot token.
/// * `url_api` - The base URL for the Discord API.
/// * `guild_id` - The ID of the guild where the channel will be created.
/// * `schema` - A `ChannelCreateSchema` struct containing the properties of the new channel.
/// * `limits_user` - A mutable reference to a `Limits` struct containing the user's rate limits.
/// * `limits_instance` - A mutable reference to a `Limits` struct containing the instance's rate limits.
///
/// # Returns
///
/// A `Result` containing a `reqwest::Response` if the request was successful, or an `InstanceServerError` if there was an error.
pub async fn create(
token: &str,
url_api: &str,
guild_id: &str,
schema: schemas::ChannelCreateSchema,
limits_user: &mut Limits,
limits_instance: &mut Limits,
) -> Result<types::Channel, InstanceServerError> {
let request = Client::new()
.post(format!("{}/guilds/{}/channels/", url_api, guild_id))
.bearer_auth(token)
.body(to_string(&schema).unwrap());
let mut requester = 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),
};
match from_str::<types::Channel>(&result.text().await.unwrap()) {
Ok(object) => Ok(object),
Err(e) => Err(InstanceServerError::RequestErrorError {
url: format!("{}/guilds/{}/channels/", url_api, guild_id),
error: e.to_string(),
}),
}
}
}

View File

@ -314,6 +314,31 @@ pub struct UserModifySchema {
pub discriminator: Option<i16>,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
// TODO: Implement in polyphony/types
pub struct ChannelCreateSchema {
pub name: String,
#[serde(rename = "type")]
pub channel_type: Option<u8>,
pub topic: Option<String>,
pub icon: Option<String>,
pub bitrate: Option<i32>,
pub user_limit: Option<i32>,
pub rate_limit_per_user: Option<i32>,
pub position: Option<i32>,
pub permission_overwrites: Option<Vec<crate::api::types::PermissionOverwrite>>,
pub parent_id: Option<String>,
pub id: Option<String>,
pub nsfw: Option<bool>,
pub rtc_region: Option<String>,
pub default_auto_archive_duration: Option<i32>,
pub default_reaction_emoji: Option<String>,
pub flags: Option<i32>,
pub default_thread_rate_limit_per_user: Option<i32>,
pub video_quality_mode: Option<i32>,
}
// 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
#[cfg(test)]

View File

@ -327,7 +327,7 @@ pub struct RoleObject {
pub tags: Option<RoleTags>,
}
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
/// See https://discord.com/developers/docs/topics/permissions#role-object-role-tags-structure
pub struct RoleTags {
#[serde(default)]
@ -785,7 +785,7 @@ pub struct MessageInteraction {
pub member: Option<GuildMember>,
}
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct GuildMember {
pub user: Option<UserObject>,
pub nick: Option<String>,
@ -801,7 +801,7 @@ pub struct GuildMember {
pub communication_disabled_until: Option<String>,
}
#[derive(Default, Debug, Serialize, Deserialize, Clone)]
#[derive(Default, Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct Channel {
pub id: String,
#[serde(rename = "type")]
@ -840,7 +840,7 @@ pub struct Channel {
pub default_forum_layout: Option<i32>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
pub struct Tag {
#[serde(default)]
#[serde(deserialize_with = "deserialize_number_from_string")]
@ -853,7 +853,7 @@ pub struct Tag {
pub emoji_name: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub struct PermissionOverwrite {
pub id: String,
#[serde(rename = "type")]
@ -867,7 +867,7 @@ pub struct PermissionOverwrite {
pub deny: String,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
pub struct ThreadMetadata {
pub archived: bool,
pub auto_archive_duration: i32,
@ -877,7 +877,7 @@ pub struct ThreadMetadata {
pub create_timestamp: Option<String>,
}
#[derive(Default, Debug, Deserialize, Serialize, Clone)]
#[derive(Default, Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
pub struct ThreadMember {
pub id: Option<u64>,
pub user_id: Option<u64>,
@ -927,7 +927,7 @@ pub struct StageInstance {
pub guild_scheduled_event_id: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
pub struct DefaultReaction {
#[serde(default)]
#[serde(deserialize_with = "deserialize_option_number_from_string")]

View File

@ -1,5 +1,6 @@
use chorus::{
api::{AuthUsername, RegisterSchema, User},
api::schemas,
api::{AuthUsername, Channel, Guild, GuildCreateSchema, RegisterSchema, User},
instance::Instance,
URLBundle,
};
@ -8,6 +9,9 @@ use chorus::{
struct TestBundle {
urls: URLBundle,
user: User,
instance: Instance,
guild_id: String,
channel: Channel,
}
// Set up a test by creating an Instance and a User. Reduces Test boilerplate.
@ -32,18 +36,72 @@ async fn setup() -> TestBundle {
None,
)
.unwrap();
let user = instance.register_account(&reg).await.unwrap();
let guild_create_schema = GuildCreateSchema {
name: Some("Test-Guild!".to_string()),
region: None,
icon: None,
channels: None,
guild_template_code: None,
system_channel_id: None,
rules_channel_id: None,
};
let channel_create_schema = schemas::ChannelCreateSchema {
name: "testchannel".to_string(),
channel_type: Some(0),
topic: None,
icon: None,
bitrate: None,
user_limit: None,
rate_limit_per_user: None,
position: None,
permission_overwrites: None,
parent_id: None,
id: None,
nsfw: Some(false),
rtc_region: None,
default_auto_archive_duration: None,
default_reaction_emoji: None,
flags: Some(0),
default_thread_rate_limit_per_user: Some(0),
video_quality_mode: None,
};
let mut user = instance.register_account(&reg).await.unwrap();
let guild_id = Guild::create(&mut user, urls.get_api(), guild_create_schema)
.await
.unwrap();
let channel = Channel::create(
&user.token,
urls.get_api(),
guild_id.as_str(),
channel_create_schema,
&mut user.limits,
&mut instance.limits,
)
.await
.unwrap();
TestBundle { urls, user }
TestBundle {
urls,
user,
instance,
guild_id,
channel,
}
}
// Teardown method to clean up after a test.
async fn teardown(bundle: TestBundle) {
async fn teardown(mut bundle: TestBundle) {
Guild::delete(
&mut bundle.user,
bundle.instance.urls.get_api(),
bundle.guild_id,
)
.await;
bundle.user.delete().await;
}
mod guild {
use chorus::api::{schemas, types};
use chorus::api::{schemas, types, Channel};
#[tokio::test]
async fn guild_creation_deletion() {
@ -70,5 +128,27 @@ mod guild {
None => assert!(true),
Some(_) => assert!(false),
}
crate::teardown(bundle).await
}
#[tokio::test]
async fn get_channel() {
let mut bundle = crate::setup().await;
let bundle_channel = bundle.channel.clone();
let bundle_user = &mut bundle.user;
assert_eq!(
bundle_channel,
Channel::get(
bundle_user.token.as_str(),
bundle.instance.urls.get_api(),
&bundle_channel.id,
&mut bundle_user.limits,
&mut bundle.instance.limits
)
.await
.unwrap()
);
crate::teardown(bundle).await
}
}