Merge branch 'main' into perpetual/gateway-dev
This commit is contained in:
commit
b1559353b6
|
@ -16,19 +16,21 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Clone spacebar server
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y git python3 build-essential
|
|
||||||
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
|
|
||||||
sudo apt-get install -y nodejs
|
|
||||||
git clone https://github.com/bitfl0wer/server.git
|
git clone https://github.com/bitfl0wer/server.git
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: server/package-lock.json
|
||||||
- name: Prepare and start Spacebar server
|
- name: Prepare and start Spacebar server
|
||||||
run: |
|
run: |
|
||||||
npm install
|
npm install
|
||||||
npm run setup
|
npm run setup
|
||||||
npm run start &
|
npm run start &
|
||||||
working-directory: ./server
|
working-directory: ./server
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo build --verbose
|
run: cargo build --verbose
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
name: Clippy check
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
|
|
||||||
|
|
||||||
# Make sure CI fails on all warnings, including Clippy lints
|
|
||||||
env:
|
|
||||||
RUSTFLAGS: "-Dwarnings"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
clippy_check:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Run Clippy
|
|
||||||
run: cargo clippy --all-targets --all-features
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
# This workflow uses actions that are not certified by GitHub.
|
||||||
|
# They are provided by a third-party and are governed by
|
||||||
|
# separate terms of service, privacy policy, and support
|
||||||
|
# documentation.
|
||||||
|
# rust-clippy is a tool that runs a bunch of lints to catch common
|
||||||
|
# mistakes in your Rust code and help improve your Rust code.
|
||||||
|
# More details at https://github.com/rust-lang/rust-clippy
|
||||||
|
# and https://rust-lang.github.io/rust-clippy/
|
||||||
|
|
||||||
|
name: rust-clippy analyze
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main", "preserve/*" ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ "main" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
rust-clippy-analyze:
|
||||||
|
name: Run rust-clippy analyzing
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Rust toolchain
|
||||||
|
uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af #@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
components: clippy
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Install required cargo
|
||||||
|
run: cargo install clippy-sarif sarif-fmt
|
||||||
|
|
||||||
|
- name: Run rust-clippy
|
||||||
|
run:
|
||||||
|
cargo clippy
|
||||||
|
--all-features
|
||||||
|
--message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Upload analysis results to GitHub
|
||||||
|
uses: github/codeql-action/upload-sarif@v2
|
||||||
|
with:
|
||||||
|
sarif_file: rust-clippy-results.sarif
|
||||||
|
wait-for-processing: true
|
|
@ -2,19 +2,18 @@
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
/target/
|
/target/
|
||||||
|
|
||||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
|
||||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
|
||||||
Cargo.lock
|
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
|
||||||
# Added by cargo
|
# Added by cargo
|
||||||
|
|
||||||
/target
|
/target
|
||||||
|
|
||||||
###
|
# IDE specific folders and configs
|
||||||
|
|
||||||
.vscode/**
|
.vscode/**
|
||||||
.idea/**
|
.idea/**
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
|
||||||
|
**/.DS_Store
|
File diff suppressed because it is too large
Load Diff
26
Cargo.toml
26
Cargo.toml
|
@ -10,34 +10,34 @@ backend = ["poem", "sqlx"]
|
||||||
client = []
|
client = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = {version = "1.28.1"}
|
tokio = {version = "1.29.1", features = ["macros"]}
|
||||||
serde = {version = "1.0.163", features = ["derive"]}
|
serde = {version = "1.0.171", features = ["derive"]}
|
||||||
serde_json = {version= "1.0.96", features = ["raw_value"]}
|
serde_json = {version= "1.0.103", features = ["raw_value"]}
|
||||||
serde-aux = "4.2.0"
|
serde-aux = "4.2.0"
|
||||||
serde_with = "3.0.0"
|
serde_with = "3.0.0"
|
||||||
serde_repr = "0.1.12"
|
serde_repr = "0.1.14"
|
||||||
reqwest = {version = "0.11.16", features = ["multipart"]}
|
reqwest = {version = "0.11.18", features = ["multipart"]}
|
||||||
url = "2.3.1"
|
url = "2.4.0"
|
||||||
chrono = {version = "0.4.24", features = ["serde"]}
|
chrono = {version = "0.4.26", features = ["serde"]}
|
||||||
regex = "1.7.3"
|
regex = "1.9.1"
|
||||||
custom_error = "1.9.2"
|
custom_error = "1.9.2"
|
||||||
native-tls = "0.2.11"
|
native-tls = "0.2.11"
|
||||||
tokio-tungstenite = {version = "0.19.0", features = ["native-tls"]}
|
tokio-tungstenite = {version = "0.19.0", features = ["native-tls"]}
|
||||||
futures-util = "0.3.28"
|
futures-util = "0.3.28"
|
||||||
http = "0.2.9"
|
http = "0.2.9"
|
||||||
openssl = "0.10.52"
|
openssl = "0.10.55"
|
||||||
base64 = "0.21.2"
|
base64 = "0.21.2"
|
||||||
hostname = "0.3.1"
|
hostname = "0.3.1"
|
||||||
bitflags = { version = "2.2.1", features = ["serde"] }
|
bitflags = { version = "2.3.3", features = ["serde"] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
poem = { version = "1.3.55", optional = true }
|
poem = { version = "1.3.56", optional = true }
|
||||||
sqlx = { git = "https://github.com/zert3x/sqlx", branch="feature/skip", features = ["mysql", "sqlite", "json", "chrono", "ipnetwork", "runtime-tokio-native-tls", "any"], optional = true }
|
sqlx = { git = "https://github.com/zert3x/sqlx", branch="feature/skip", features = ["mysql", "sqlite", "json", "chrono", "ipnetwork", "runtime-tokio-native-tls", "any"], optional = true }
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.43"
|
||||||
jsonwebtoken = "8.3.0"
|
jsonwebtoken = "8.3.0"
|
||||||
log = "0.4.19"
|
log = "0.4.19"
|
||||||
async-trait = "0.1.71"
|
async-trait = "0.1.71"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = {version = "1.28.1", features = ["full"]}
|
tokio = {version = "1.29.1", features = ["full"]}
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
rusty-hook = "0.11.2"
|
rusty-hook = "0.11.2"
|
||||||
|
|
|
@ -56,9 +56,9 @@ accepted, if it violates these guidelines or [our Code of Conduct](https://githu
|
||||||
- [x] Channel creation
|
- [x] Channel creation
|
||||||
- [x] Channel deletion
|
- [x] Channel deletion
|
||||||
- [x] [Channel management (name, description, icon, etc.)](https://github.com/polyphony-chat/chorus/issues/48)
|
- [x] [Channel management (name, description, icon, etc.)](https://github.com/polyphony-chat/chorus/issues/48)
|
||||||
- [ ] [Join and Leave Guilds](https://github.com/polyphony-chat/chorus/issues/45)
|
- [x] [Join and Leave Guilds](https://github.com/polyphony-chat/chorus/issues/45)
|
||||||
- [ ] [Start DMs](https://github.com/polyphony-chat/chorus/issues/45)
|
- [x] [Start DMs](https://github.com/polyphony-chat/chorus/issues/45)
|
||||||
- [ ] [Group DM creation, deletion and member management](https://github.com/polyphony-chat/chorus/issues/89)
|
- [x] [Group DM creation, deletion and member management](https://github.com/polyphony-chat/chorus/issues/89)
|
||||||
- [ ] [Deleting messages](https://github.com/polyphony-chat/chorus/issues/91)
|
- [ ] [Deleting messages](https://github.com/polyphony-chat/chorus/issues/91)
|
||||||
- [ ] [Message threads](https://github.com/polyphony-chat/chorus/issues/90)
|
- [ ] [Message threads](https://github.com/polyphony-chat/chorus/issues/90)
|
||||||
- [x] [Reactions](https://github.com/polyphony-chat/chorus/issues/85)
|
- [x] [Reactions](https://github.com/polyphony-chat/chorus/issues/85)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
|
||||||
|
use crate::types::AddChannelRecipientSchema;
|
||||||
use crate::{
|
use crate::{
|
||||||
api::LimitType,
|
api::LimitType,
|
||||||
errors::{ChorusError, ChorusResult},
|
errors::{ChorusError, ChorusResult},
|
||||||
|
@ -105,4 +106,54 @@ impl Channel {
|
||||||
.deserialize_response::<Vec<Message>>(user)
|
.deserialize_response::<Vec<Message>>(user)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Reference:
|
||||||
|
/// Read: <https://discord-userdoccers.vercel.app/resources/channel#add-channel-recipient>
|
||||||
|
pub async fn add_channel_recipient(
|
||||||
|
&self,
|
||||||
|
recipient_id: Snowflake,
|
||||||
|
user: &mut UserMeta,
|
||||||
|
add_channel_recipient_schema: Option<AddChannelRecipientSchema>,
|
||||||
|
) -> ChorusResult<()> {
|
||||||
|
let mut request = Client::new()
|
||||||
|
.put(format!(
|
||||||
|
"{}/channels/{}/recipients/{}/",
|
||||||
|
user.belongs_to.borrow().urls.api,
|
||||||
|
self.id,
|
||||||
|
recipient_id
|
||||||
|
))
|
||||||
|
.bearer_auth(user.token());
|
||||||
|
if let Some(schema) = add_channel_recipient_schema {
|
||||||
|
request = request.body(to_string(&schema).unwrap());
|
||||||
|
}
|
||||||
|
ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::Channel(self.id),
|
||||||
|
}
|
||||||
|
.handle_request_as_result(user)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Reference:
|
||||||
|
/// Read: <https://discord-userdoccers.vercel.app/resources/channel#remove-channel-recipient>
|
||||||
|
pub async fn remove_channel_recipient(
|
||||||
|
&self,
|
||||||
|
recipient_id: Snowflake,
|
||||||
|
user: &mut UserMeta,
|
||||||
|
) -> ChorusResult<()> {
|
||||||
|
let request = Client::new()
|
||||||
|
.delete(format!(
|
||||||
|
"{}/channels/{}/recipients/{}/",
|
||||||
|
user.belongs_to.borrow().urls.api,
|
||||||
|
self.id,
|
||||||
|
recipient_id
|
||||||
|
))
|
||||||
|
.bearer_auth(user.token());
|
||||||
|
ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::Channel(self.id),
|
||||||
|
}
|
||||||
|
.handle_request_as_result(user)
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,34 +6,22 @@ use serde_json::to_string;
|
||||||
use crate::api::LimitType;
|
use crate::api::LimitType;
|
||||||
use crate::instance::UserMeta;
|
use crate::instance::UserMeta;
|
||||||
use crate::ratelimiter::ChorusRequest;
|
use crate::ratelimiter::ChorusRequest;
|
||||||
use crate::types::{Message, MessageSendSchema, PartialDiscordFileAttachment, Snowflake};
|
use crate::types::{Message, MessageSendSchema, Snowflake};
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
/**
|
|
||||||
Sends a message to the Spacebar server.
|
|
||||||
# Arguments
|
|
||||||
* `url_api` - The URL of the Spacebar server's API.
|
|
||||||
* `message` - The [`Message`] that will be sent to the Spacebar server.
|
|
||||||
* `limits_user` - The [`Limits`] of the user.
|
|
||||||
* `limits_instance` - The [`Limits`] of the instance.
|
|
||||||
* `requester` - The [`LimitedRequester`] that will be used to make requests to the Spacebar server.
|
|
||||||
# Errors
|
|
||||||
* [`ChorusLibError`] - If the message cannot be sent.
|
|
||||||
*/
|
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
user: &mut UserMeta,
|
user: &mut UserMeta,
|
||||||
channel_id: Snowflake,
|
channel_id: Snowflake,
|
||||||
message: &mut MessageSendSchema,
|
mut message: MessageSendSchema,
|
||||||
files: Option<Vec<PartialDiscordFileAttachment>>,
|
|
||||||
) -> Result<Message, crate::errors::ChorusError> {
|
) -> Result<Message, crate::errors::ChorusError> {
|
||||||
let url_api = user.belongs_to.borrow().urls.api.clone();
|
let url_api = user.belongs_to.borrow().urls.api.clone();
|
||||||
|
|
||||||
if files.is_none() {
|
if message.attachments.is_none() {
|
||||||
let chorus_request = ChorusRequest {
|
let chorus_request = ChorusRequest {
|
||||||
request: Client::new()
|
request: Client::new()
|
||||||
.post(format!("{}/channels/{}/messages/", url_api, channel_id))
|
.post(format!("{}/channels/{}/messages/", url_api, channel_id))
|
||||||
.bearer_auth(user.token())
|
.bearer_auth(user.token())
|
||||||
.body(to_string(message).unwrap()),
|
.body(to_string(&message).unwrap()),
|
||||||
limit_type: LimitType::Channel(channel_id),
|
limit_type: LimitType::Channel(channel_id),
|
||||||
};
|
};
|
||||||
chorus_request.deserialize_response::<Message>(user).await
|
chorus_request.deserialize_response::<Message>(user).await
|
||||||
|
@ -42,12 +30,12 @@ impl Message {
|
||||||
attachment.get_mut(index).unwrap().set_id(index as i16);
|
attachment.get_mut(index).unwrap().set_id(index as i16);
|
||||||
}
|
}
|
||||||
let mut form = reqwest::multipart::Form::new();
|
let mut form = reqwest::multipart::Form::new();
|
||||||
let payload_json = to_string(message).unwrap();
|
let payload_json = to_string(&message).unwrap();
|
||||||
let payload_field = reqwest::multipart::Part::text(payload_json);
|
let payload_field = reqwest::multipart::Part::text(payload_json);
|
||||||
|
|
||||||
form = form.part("payload_json", payload_field);
|
form = form.part("payload_json", payload_field);
|
||||||
|
|
||||||
for (index, attachment) in files.unwrap().into_iter().enumerate() {
|
for (index, attachment) in message.attachments.unwrap().into_iter().enumerate() {
|
||||||
let (attachment_content, current_attachment) = attachment.move_content();
|
let (attachment_content, current_attachment) = attachment.move_content();
|
||||||
let (attachment_filename, _) = current_attachment.move_filename();
|
let (attachment_filename, _) = current_attachment.move_filename();
|
||||||
let part_name = format!("files[{}]", index);
|
let part_name = format!("files[{}]", index);
|
||||||
|
@ -78,24 +66,11 @@ impl Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserMeta {
|
impl UserMeta {
|
||||||
/// Shorthand call for Message::send()
|
|
||||||
/**
|
|
||||||
Sends a message to the Spacebar server.
|
|
||||||
# Arguments
|
|
||||||
* `url_api` - The URL of the Spacebar server's API.
|
|
||||||
* `message` - The [`Message`] that will be sent to the Spacebar server.
|
|
||||||
* `limits_user` - The [`Limits`] of the user.
|
|
||||||
* `limits_instance` - The [`Limits`] of the instance.
|
|
||||||
* `requester` - The [`LimitedRequester`] that will be used to make requests to the Spacebar server.
|
|
||||||
# Errors
|
|
||||||
* [`ChorusLibError`] - If the message cannot be sent.
|
|
||||||
*/
|
|
||||||
pub async fn send_message(
|
pub async fn send_message(
|
||||||
&mut self,
|
&mut self,
|
||||||
message: &mut MessageSendSchema,
|
message: MessageSendSchema,
|
||||||
channel_id: Snowflake,
|
channel_id: Snowflake,
|
||||||
files: Option<Vec<PartialDiscordFileAttachment>>,
|
|
||||||
) -> Result<Message, crate::errors::ChorusError> {
|
) -> Result<Message, crate::errors::ChorusError> {
|
||||||
Message::send(self, channel_id, message, files).await
|
Message::send(self, channel_id, message).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
use reqwest::Client;
|
||||||
|
use serde_json::to_string;
|
||||||
|
|
||||||
|
use crate::errors::ChorusResult;
|
||||||
|
use crate::instance::UserMeta;
|
||||||
|
use crate::ratelimiter::ChorusRequest;
|
||||||
|
use crate::types::{CreateChannelInviteSchema, GuildInvite, Invite, Snowflake};
|
||||||
|
|
||||||
|
impl UserMeta {
|
||||||
|
/// # Arguments
|
||||||
|
/// - invite_code: The invite code to accept the invite for.
|
||||||
|
/// - session_id: The session ID that is accepting the invite, required for guest invites.
|
||||||
|
///
|
||||||
|
/// # Reference:
|
||||||
|
/// Read <https://discord-userdoccers.vercel.app/resources/invite#accept-invite>
|
||||||
|
pub async fn accept_invite(
|
||||||
|
&mut self,
|
||||||
|
invite_code: &str,
|
||||||
|
session_id: Option<&str>,
|
||||||
|
) -> ChorusResult<Invite> {
|
||||||
|
let mut request = ChorusRequest {
|
||||||
|
request: Client::new()
|
||||||
|
.post(format!(
|
||||||
|
"{}/invites/{}/",
|
||||||
|
self.belongs_to.borrow().urls.api,
|
||||||
|
invite_code
|
||||||
|
))
|
||||||
|
.bearer_auth(self.token()),
|
||||||
|
limit_type: super::LimitType::Global,
|
||||||
|
};
|
||||||
|
if session_id.is_some() {
|
||||||
|
request.request = request
|
||||||
|
.request
|
||||||
|
.body(to_string(session_id.unwrap()).unwrap());
|
||||||
|
}
|
||||||
|
request.deserialize_response::<Invite>(self).await
|
||||||
|
}
|
||||||
|
/// Note: Spacebar does not yet implement this endpoint.
|
||||||
|
pub async fn create_user_invite(&mut self, code: Option<&str>) -> ChorusResult<Invite> {
|
||||||
|
ChorusRequest {
|
||||||
|
request: Client::new()
|
||||||
|
.post(format!(
|
||||||
|
"{}/users/@me/invites/",
|
||||||
|
self.belongs_to.borrow().urls.api
|
||||||
|
))
|
||||||
|
.body(to_string(&code).unwrap())
|
||||||
|
.bearer_auth(self.token()),
|
||||||
|
limit_type: super::LimitType::Global,
|
||||||
|
}
|
||||||
|
.deserialize_response::<Invite>(self)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_guild_invite(
|
||||||
|
&mut self,
|
||||||
|
create_channel_invite_schema: CreateChannelInviteSchema,
|
||||||
|
channel_id: Snowflake,
|
||||||
|
) -> ChorusResult<GuildInvite> {
|
||||||
|
ChorusRequest {
|
||||||
|
request: Client::new()
|
||||||
|
.post(format!(
|
||||||
|
"{}/channels/{}/invites/",
|
||||||
|
self.belongs_to.borrow().urls.api,
|
||||||
|
channel_id
|
||||||
|
))
|
||||||
|
.bearer_auth(self.token())
|
||||||
|
.body(to_string(&create_channel_invite_schema).unwrap()),
|
||||||
|
limit_type: super::LimitType::Channel(channel_id),
|
||||||
|
}
|
||||||
|
.deserialize_response::<GuildInvite>(self)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
pub use channels::messages::*;
|
pub use channels::messages::*;
|
||||||
pub use guilds::*;
|
pub use guilds::*;
|
||||||
|
pub use invites::*;
|
||||||
pub use policies::instance::instance::*;
|
pub use policies::instance::instance::*;
|
||||||
pub use policies::instance::ratelimits::*;
|
pub use policies::instance::ratelimits::*;
|
||||||
|
pub use users::*;
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod channels;
|
pub mod channels;
|
||||||
pub mod guilds;
|
pub mod guilds;
|
||||||
|
pub mod invites;
|
||||||
pub mod policies;
|
pub mod policies;
|
||||||
pub mod users;
|
pub mod users;
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::Snowflake;
|
use crate::types::Snowflake;
|
||||||
|
|
||||||
/// The different types of ratelimits that can be applied to a request. Includes "Baseline"-variants
|
/// The different types of ratelimits that can be applied to a request. Includes "Baseline"-variants
|
||||||
/// for when the Snowflake is not yet known.
|
/// for when the Snowflake is not yet known.
|
||||||
/// See <https://discord.com/developers/docs/topics/rate-limits#rate-limits> for more information.
|
/// See <https://discord.com/developers/docs/topics/rate-limits#rate-limits> for more information.
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, Default, Hash)]
|
#[derive(Clone, Copy, Eq, PartialEq, Debug, Default, Hash, Serialize, Deserialize)]
|
||||||
pub enum LimitType {
|
pub enum LimitType {
|
||||||
AuthRegister,
|
AuthRegister,
|
||||||
AuthLogin,
|
AuthLogin,
|
||||||
|
@ -25,7 +27,7 @@ pub enum LimitType {
|
||||||
/// Unlike [`RateLimits`], this struct shows the current ratelimits, not the rate limit
|
/// Unlike [`RateLimits`], this struct shows the current ratelimits, not the rate limit
|
||||||
/// configuration for the instance.
|
/// configuration for the instance.
|
||||||
/// See <https://discord.com/developers/docs/topics/rate-limits#rate-limits> for more information.
|
/// See <https://discord.com/developers/docs/topics/rate-limits#rate-limits> for more information.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Limit {
|
pub struct Limit {
|
||||||
pub bucket: LimitType,
|
pub bucket: LimitType,
|
||||||
pub limit: u64,
|
pub limit: u64,
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
use reqwest::Client;
|
||||||
|
use serde_json::to_string;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
api::LimitType,
|
||||||
|
errors::ChorusResult,
|
||||||
|
instance::UserMeta,
|
||||||
|
ratelimiter::ChorusRequest,
|
||||||
|
types::{Channel, PrivateChannelCreateSchema},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl UserMeta {
|
||||||
|
/// Creates a DM channel or group DM channel.
|
||||||
|
///
|
||||||
|
/// # Reference:
|
||||||
|
/// Read <https://discord-userdoccers.vercel.app/resources/channel#create-private-channel>
|
||||||
|
pub async fn create_private_channel(
|
||||||
|
&mut self,
|
||||||
|
create_private_channel_schema: PrivateChannelCreateSchema,
|
||||||
|
) -> ChorusResult<Channel> {
|
||||||
|
let url = format!("{}/users/@me/channels", self.belongs_to.borrow().urls.api);
|
||||||
|
ChorusRequest {
|
||||||
|
request: Client::new()
|
||||||
|
.post(url)
|
||||||
|
.bearer_auth(self.token())
|
||||||
|
.body(to_string(&create_private_channel_schema).unwrap()),
|
||||||
|
limit_type: LimitType::Global,
|
||||||
|
}
|
||||||
|
.deserialize_response::<Channel>(self)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
use reqwest::Client;
|
||||||
|
use serde_json::to_string;
|
||||||
|
|
||||||
|
use crate::errors::ChorusResult;
|
||||||
|
use crate::instance::UserMeta;
|
||||||
|
use crate::ratelimiter::ChorusRequest;
|
||||||
|
use crate::types::Snowflake;
|
||||||
|
|
||||||
|
impl UserMeta {
|
||||||
|
/// # Arguments:
|
||||||
|
/// - lurking: Whether the user is lurking in the guild
|
||||||
|
///
|
||||||
|
/// # Reference:
|
||||||
|
/// Read <https://discord-userdoccers.vercel.app/resources/guild#leave-guild>
|
||||||
|
pub async fn leave_guild(&mut self, guild_id: &Snowflake, lurking: bool) -> ChorusResult<()> {
|
||||||
|
ChorusRequest {
|
||||||
|
request: Client::new()
|
||||||
|
.delete(format!(
|
||||||
|
"{}/users/@me/guilds/{}/",
|
||||||
|
self.belongs_to.borrow().urls.api,
|
||||||
|
guild_id
|
||||||
|
))
|
||||||
|
.bearer_auth(self.token())
|
||||||
|
.body(to_string(&lurking).unwrap()),
|
||||||
|
limit_type: crate::api::LimitType::Guild(*guild_id),
|
||||||
|
}
|
||||||
|
.handle_request_as_result(self)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,9 @@
|
||||||
|
pub use channels::*;
|
||||||
|
pub use guilds::*;
|
||||||
pub use relationships::*;
|
pub use relationships::*;
|
||||||
pub use users::*;
|
pub use users::*;
|
||||||
|
|
||||||
|
pub mod channels;
|
||||||
|
pub mod guilds;
|
||||||
pub mod relationships;
|
pub mod relationships;
|
||||||
pub mod users;
|
pub mod users;
|
||||||
|
|
1152
src/gateway.rs
1152
src/gateway.rs
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,7 @@ pub struct Instance {
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct LimitsInformation {
|
pub struct LimitsInformation {
|
||||||
pub ratelimits: HashMap<LimitType, Limit>,
|
pub ratelimits: HashMap<LimitType, Limit>,
|
||||||
pub configuration: RateLimits,
|
pub configuration: RateLimits,
|
||||||
|
@ -88,7 +88,7 @@ impl fmt::Display for Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct UserMeta {
|
pub struct UserMeta {
|
||||||
pub belongs_to: Rc<RefCell<Instance>>,
|
pub belongs_to: Rc<RefCell<Instance>>,
|
||||||
pub token: String,
|
pub token: String,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use log;
|
use log::{self, debug};
|
||||||
use reqwest::{Client, RequestBuilder, Response};
|
use reqwest::{Client, RequestBuilder, Response};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::from_str;
|
use serde_json::from_str;
|
||||||
|
@ -37,7 +37,10 @@ impl ChorusRequest {
|
||||||
.execute(self.request.build().unwrap())
|
.execute(self.request.build().unwrap())
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(result) => result,
|
Ok(result) => {
|
||||||
|
debug!("Request successful: {:?}", result);
|
||||||
|
result
|
||||||
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
log::warn!("Request failed: {:?}", error);
|
log::warn!("Request failed: {:?}", error);
|
||||||
return Err(ChorusError::RequestFailed {
|
return Err(ChorusError::RequestFailed {
|
||||||
|
@ -430,6 +433,7 @@ impl ChorusRequest {
|
||||||
user: &mut UserMeta,
|
user: &mut UserMeta,
|
||||||
) -> ChorusResult<T> {
|
) -> ChorusResult<T> {
|
||||||
let response = self.send_request(user).await?;
|
let response = self.send_request(user).await?;
|
||||||
|
debug!("Got response: {:?}", response);
|
||||||
let response_text = match response.text().await {
|
let response_text = match response.text().await {
|
||||||
Ok(string) => string,
|
Ok(string) => string,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -446,8 +450,8 @@ impl ChorusRequest {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(ChorusError::InvalidResponse {
|
return Err(ChorusError::InvalidResponse {
|
||||||
error: format!(
|
error: format!(
|
||||||
"Error while trying to deserialize the JSON response into T: {}",
|
"Error while trying to deserialize the JSON response into requested type T: {}. JSON Response: {}",
|
||||||
e
|
e, response_text
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use sqlx::{
|
||||||
database::{HasArguments, HasValueRef},
|
database::{HasArguments, HasValueRef},
|
||||||
encode::IsNull,
|
encode::IsNull,
|
||||||
error::BoxDynError,
|
error::BoxDynError,
|
||||||
Decode, Encode, MySql,
|
Decode, MySql,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::types::config::types::subconfigs::guild::{
|
use crate::types::config::types::subconfigs::guild::{
|
||||||
|
@ -139,7 +139,7 @@ pub enum GuildFeatures {
|
||||||
InvitesClosed,
|
InvitesClosed,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, Eq)]
|
||||||
pub struct GuildFeaturesList(Vec<GuildFeatures>);
|
pub struct GuildFeaturesList(Vec<GuildFeatures>);
|
||||||
|
|
||||||
impl Deref for GuildFeaturesList {
|
impl Deref for GuildFeaturesList {
|
||||||
|
|
|
@ -11,58 +11,58 @@ use crate::types::{
|
||||||
#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
pub id: Snowflake,
|
|
||||||
pub created_at: Option<chrono::DateTime<Utc>>,
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub channel_type: ChannelType,
|
|
||||||
pub guild_id: Option<Snowflake>,
|
|
||||||
pub position: Option<i32>,
|
|
||||||
#[cfg(feature = "sqlx")]
|
|
||||||
pub permission_overwrites: Option<sqlx::types::Json<Vec<PermissionOverwrite>>>,
|
|
||||||
#[cfg(not(feature = "sqlx"))]
|
|
||||||
pub permission_overwrites: Option<Vec<PermissionOverwrite>>,
|
|
||||||
pub name: Option<String>,
|
|
||||||
pub topic: Option<String>,
|
|
||||||
pub nsfw: Option<bool>,
|
|
||||||
pub last_message_id: Option<Snowflake>,
|
|
||||||
pub bitrate: Option<i32>,
|
|
||||||
pub user_limit: Option<i32>,
|
|
||||||
pub rate_limit_per_user: Option<i32>,
|
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
|
||||||
pub recipients: Option<Vec<User>>,
|
|
||||||
pub icon: Option<String>,
|
|
||||||
pub owner_id: Option<Snowflake>,
|
|
||||||
pub application_id: Option<Snowflake>,
|
pub application_id: Option<Snowflake>,
|
||||||
pub managed: Option<bool>,
|
|
||||||
pub parent_id: Option<Snowflake>,
|
|
||||||
pub last_pin_timestamp: Option<String>,
|
|
||||||
pub rtc_region: Option<String>,
|
|
||||||
pub video_quality_mode: Option<i32>,
|
|
||||||
pub message_count: Option<i32>,
|
|
||||||
pub member_count: Option<i32>,
|
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
|
||||||
pub thread_metadata: Option<ThreadMetadata>,
|
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
|
||||||
pub member: Option<ThreadMember>,
|
|
||||||
pub default_auto_archive_duration: Option<i32>,
|
|
||||||
pub permissions: Option<String>,
|
|
||||||
pub flags: Option<i32>,
|
|
||||||
pub total_message_sent: Option<i32>,
|
|
||||||
#[cfg(feature = "sqlx")]
|
|
||||||
pub available_tags: Option<sqlx::types::Json<Vec<Tag>>>,
|
|
||||||
#[cfg(not(feature = "sqlx"))]
|
|
||||||
pub available_tags: Option<Vec<Tag>>,
|
|
||||||
#[cfg(feature = "sqlx")]
|
#[cfg(feature = "sqlx")]
|
||||||
pub applied_tags: Option<sqlx::types::Json<Vec<String>>>,
|
pub applied_tags: Option<sqlx::types::Json<Vec<String>>>,
|
||||||
#[cfg(not(feature = "sqlx"))]
|
#[cfg(not(feature = "sqlx"))]
|
||||||
pub applied_tags: Option<Vec<String>>,
|
pub applied_tags: Option<Vec<String>>,
|
||||||
#[cfg(feature = "sqlx")]
|
#[cfg(feature = "sqlx")]
|
||||||
|
pub available_tags: Option<sqlx::types::Json<Vec<Tag>>>,
|
||||||
|
#[cfg(not(feature = "sqlx"))]
|
||||||
|
pub available_tags: Option<Vec<Tag>>,
|
||||||
|
pub bitrate: Option<i32>,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub channel_type: ChannelType,
|
||||||
|
pub created_at: Option<chrono::DateTime<Utc>>,
|
||||||
|
pub default_auto_archive_duration: Option<i32>,
|
||||||
|
pub default_forum_layout: Option<i32>,
|
||||||
|
#[cfg(feature = "sqlx")]
|
||||||
pub default_reaction_emoji: Option<sqlx::types::Json<DefaultReaction>>,
|
pub default_reaction_emoji: Option<sqlx::types::Json<DefaultReaction>>,
|
||||||
#[cfg(not(feature = "sqlx"))]
|
#[cfg(not(feature = "sqlx"))]
|
||||||
pub default_reaction_emoji: Option<DefaultReaction>,
|
pub default_reaction_emoji: Option<DefaultReaction>,
|
||||||
pub default_thread_rate_limit_per_user: Option<i32>,
|
|
||||||
pub default_sort_order: Option<i32>,
|
pub default_sort_order: Option<i32>,
|
||||||
pub default_forum_layout: Option<i32>,
|
pub default_thread_rate_limit_per_user: Option<i32>,
|
||||||
|
pub flags: Option<i32>,
|
||||||
|
pub guild_id: Option<Snowflake>,
|
||||||
|
pub icon: Option<String>,
|
||||||
|
pub id: Snowflake,
|
||||||
|
pub last_message_id: Option<Snowflake>,
|
||||||
|
pub last_pin_timestamp: Option<String>,
|
||||||
|
pub managed: Option<bool>,
|
||||||
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
|
pub member: Option<ThreadMember>,
|
||||||
|
pub member_count: Option<i32>,
|
||||||
|
pub message_count: Option<i32>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub nsfw: Option<bool>,
|
||||||
|
pub owner_id: Option<Snowflake>,
|
||||||
|
pub parent_id: Option<Snowflake>,
|
||||||
|
#[cfg(feature = "sqlx")]
|
||||||
|
pub permission_overwrites: Option<sqlx::types::Json<Vec<PermissionOverwrite>>>,
|
||||||
|
#[cfg(not(feature = "sqlx"))]
|
||||||
|
pub permission_overwrites: Option<Vec<PermissionOverwrite>>,
|
||||||
|
pub permissions: Option<String>,
|
||||||
|
pub position: Option<i32>,
|
||||||
|
pub rate_limit_per_user: Option<i32>,
|
||||||
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
|
pub recipients: Option<Vec<User>>,
|
||||||
|
pub rtc_region: Option<String>,
|
||||||
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
|
pub thread_metadata: Option<ThreadMetadata>,
|
||||||
|
pub topic: Option<String>,
|
||||||
|
pub total_message_sent: Option<i32>,
|
||||||
|
pub user_limit: Option<i32>,
|
||||||
|
pub video_quality_mode: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
|
@ -74,7 +74,7 @@ pub struct Tag {
|
||||||
pub emoji_name: Option<String>,
|
pub emoji_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd)]
|
||||||
pub struct PermissionOverwrite {
|
pub struct PermissionOverwrite {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
|
|
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use crate::types::entities::User;
|
use crate::types::entities::User;
|
||||||
use crate::types::Snowflake;
|
use crate::types::Snowflake;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize, Default)]
|
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, Default)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct Emoji {
|
pub struct Emoji {
|
||||||
pub id: Option<Snowflake>,
|
pub id: Option<Snowflake>,
|
||||||
|
|
|
@ -91,7 +91,7 @@ pub struct Guild {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See https://docs.spacebar.chat/routes/#get-/guilds/-guild_id-/bans/-user-
|
/// See https://docs.spacebar.chat/routes/#get-/guilds/-guild_id-/bans/-user-
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct GuildBan {
|
pub struct GuildBan {
|
||||||
pub user_id: Snowflake,
|
pub user_id: Snowflake,
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::types::{Snowflake, WelcomeScreenObject};
|
||||||
|
|
||||||
|
use super::guild::GuildScheduledEvent;
|
||||||
|
use super::{Application, Channel, GuildMember, User};
|
||||||
|
|
||||||
|
/// Represents a code that when used, adds a user to a guild or group DM channel, or creates a relationship between two users.
|
||||||
|
/// See <https://discord-userdoccers.vercel.app/resources/invite#invite-object>
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Invite {
|
||||||
|
pub approximate_member_count: Option<i32>,
|
||||||
|
pub approximate_presence_count: Option<i32>,
|
||||||
|
pub channel: Option<Channel>,
|
||||||
|
pub code: String,
|
||||||
|
pub created_at: Option<DateTime<Utc>>,
|
||||||
|
pub expires_at: Option<DateTime<Utc>>,
|
||||||
|
pub flags: Option<i32>,
|
||||||
|
pub guild: Option<InviteGuild>,
|
||||||
|
pub guild_id: Option<Snowflake>,
|
||||||
|
pub guild_scheduled_event: Option<GuildScheduledEvent>,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub invite_type: Option<i32>,
|
||||||
|
pub inviter: Option<User>,
|
||||||
|
pub max_age: Option<i32>,
|
||||||
|
pub max_uses: Option<i32>,
|
||||||
|
pub stage_instance: Option<InviteStageInstance>,
|
||||||
|
pub target_application: Option<Application>,
|
||||||
|
pub target_type: Option<i32>,
|
||||||
|
pub target_user: Option<User>,
|
||||||
|
pub temporary: Option<bool>,
|
||||||
|
pub uses: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The guild an invite is for.
|
||||||
|
/// See <https://discord-userdoccers.vercel.app/resources/invite#invite-guild-object>
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct InviteGuild {
|
||||||
|
pub id: Snowflake,
|
||||||
|
pub name: String,
|
||||||
|
pub icon: Option<String>,
|
||||||
|
pub splash: Option<String>,
|
||||||
|
pub verification_level: i32,
|
||||||
|
pub features: Vec<String>,
|
||||||
|
pub vanity_url_code: Option<String>,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub banner: Option<String>,
|
||||||
|
pub premium_subscription_count: Option<i32>,
|
||||||
|
#[serde(rename = "nsfw")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub nsfw_deprecated: Option<bool>,
|
||||||
|
pub nsfw_level: NSFWLevel,
|
||||||
|
pub welcome_screen: Option<WelcomeScreenObject>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See <https://discord-userdoccers.vercel.app/resources/guild#nsfw-level> for an explanation on what
|
||||||
|
/// the levels mean.
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum NSFWLevel {
|
||||||
|
Default = 0,
|
||||||
|
Explicit = 1,
|
||||||
|
Safe = 2,
|
||||||
|
AgeRestricted = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See <https://discord-userdoccers.vercel.app/resources/invite#invite-stage-instance-object>
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct InviteStageInstance {
|
||||||
|
pub members: Vec<GuildMember>,
|
||||||
|
pub participant_count: i32,
|
||||||
|
pub speaker_count: i32,
|
||||||
|
pub topic: String,
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ pub use emoji::*;
|
||||||
pub use guild::*;
|
pub use guild::*;
|
||||||
pub use guild_member::*;
|
pub use guild_member::*;
|
||||||
pub use integration::*;
|
pub use integration::*;
|
||||||
|
pub use invite::*;
|
||||||
pub use message::*;
|
pub use message::*;
|
||||||
pub use relationship::*;
|
pub use relationship::*;
|
||||||
pub use role::*;
|
pub use role::*;
|
||||||
|
@ -31,6 +32,7 @@ mod emoji;
|
||||||
mod guild;
|
mod guild;
|
||||||
mod guild_member;
|
mod guild_member;
|
||||||
mod integration;
|
mod integration;
|
||||||
|
mod invite;
|
||||||
mod message;
|
mod message;
|
||||||
mod relationship;
|
mod relationship;
|
||||||
mod role;
|
mod role;
|
||||||
|
|
|
@ -43,9 +43,9 @@ pub struct User {
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
pub theme_colors: Option<Vec<u8>>,
|
pub theme_colors: Option<Vec<u8>>,
|
||||||
pub phone: Option<String>,
|
pub phone: Option<String>,
|
||||||
pub nsfw_allowed: bool,
|
pub nsfw_allowed: Option<bool>,
|
||||||
pub premium: bool,
|
pub premium: Option<bool>,
|
||||||
pub purchased_flags: i32,
|
pub purchased_flags: Option<i32>,
|
||||||
pub premium_usage_flags: Option<i32>,
|
pub premium_usage_flags: Option<i32>,
|
||||||
pub disabled: Option<bool>,
|
pub disabled: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,7 @@ impl WebSocketEvent for GatewayHello {}
|
||||||
/// Contains info on how often the client should send heartbeats to the server;
|
/// Contains info on how often the client should send heartbeats to the server;
|
||||||
pub struct HelloData {
|
pub struct HelloData {
|
||||||
/// How often a client should send heartbeats, in milliseconds
|
/// How often a client should send heartbeats, in milliseconds
|
||||||
// u128 because std used u128s for milliseconds
|
pub heartbeat_interval: u64,
|
||||||
pub heartbeat_interval: u128,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for HelloData {}
|
impl WebSocketEvent for HelloData {}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
use bitflags::bitflags;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::{entities::PermissionOverwrite, Snowflake};
|
use crate::types::{entities::PermissionOverwrite, Snowflake};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize, Default, PartialEq, PartialOrd)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub struct ChannelCreateSchema {
|
pub struct ChannelCreateSchema {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -26,7 +27,7 @@ pub struct ChannelCreateSchema {
|
||||||
pub video_quality_mode: Option<i32>,
|
pub video_quality_mode: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialEq, PartialOrd)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub struct ChannelModifySchema {
|
pub struct ChannelModifySchema {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
@ -48,7 +49,7 @@ pub struct ChannelModifySchema {
|
||||||
pub video_quality_mode: Option<i32>,
|
pub video_quality_mode: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
|
||||||
pub struct GetChannelMessagesSchema {
|
pub struct GetChannelMessagesSchema {
|
||||||
/// Between 1 and 100, defaults to 50.
|
/// Between 1 and 100, defaults to 50.
|
||||||
pub limit: Option<i32>,
|
pub limit: Option<i32>,
|
||||||
|
@ -56,7 +57,7 @@ pub struct GetChannelMessagesSchema {
|
||||||
pub anchor: ChannelMessagesAnchor,
|
pub anchor: ChannelMessagesAnchor,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum ChannelMessagesAnchor {
|
pub enum ChannelMessagesAnchor {
|
||||||
Before(Snowflake),
|
Before(Snowflake),
|
||||||
|
@ -94,3 +95,56 @@ impl GetChannelMessagesSchema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, PartialOrd)]
|
||||||
|
pub struct CreateChannelInviteSchema {
|
||||||
|
pub flags: Option<InviteFlags>,
|
||||||
|
pub max_age: Option<u32>,
|
||||||
|
pub max_uses: Option<u8>,
|
||||||
|
pub temporary: Option<bool>,
|
||||||
|
pub unique: Option<bool>,
|
||||||
|
pub validate: Option<String>,
|
||||||
|
pub target_type: Option<InviteType>,
|
||||||
|
pub target_user_id: Option<Snowflake>,
|
||||||
|
pub target_application_id: Option<Snowflake>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CreateChannelInviteSchema {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
flags: None,
|
||||||
|
max_age: Some(86400),
|
||||||
|
max_uses: Some(0),
|
||||||
|
temporary: Some(false),
|
||||||
|
unique: Some(false),
|
||||||
|
validate: None,
|
||||||
|
target_type: None,
|
||||||
|
target_user_id: None,
|
||||||
|
target_application_id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
|
||||||
|
pub struct InviteFlags: u64 {
|
||||||
|
const GUEST = 1 << 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum InviteType {
|
||||||
|
#[default]
|
||||||
|
Stream = 1,
|
||||||
|
EmbeddedApplication = 2,
|
||||||
|
RoleSubscriptions = 3,
|
||||||
|
CreatorPage = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See <https://discord-userdoccers.vercel.app/resources/channel#add-channel-recipient>
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialOrd, Ord, PartialEq, Eq)]
|
||||||
|
pub struct AddChannelRecipientSchema {
|
||||||
|
pub access_token: Option<String>,
|
||||||
|
pub nick: Option<String>,
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::types::Snowflake;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub struct UserModifySchema {
|
pub struct UserModifySchema {
|
||||||
|
@ -14,3 +18,17 @@ pub struct UserModifySchema {
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
pub discriminator: Option<i16>,
|
pub discriminator: Option<i16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Attributes:
|
||||||
|
/// - recipients: The users to include in the private channel
|
||||||
|
/// - access_tokens: The access tokens of users that have granted your app the `gdm.join` scope. Only usable for OAuth2 requests (which can only create group DMs).
|
||||||
|
/// - nicks: A mapping of user IDs to their respective nicknames. Only usable for OAuth2 requests (which can only create group DMs).
|
||||||
|
///
|
||||||
|
/// # Reference:
|
||||||
|
/// Read: <https://discord-userdoccers.vercel.app/resources/channel#json-params>
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct PrivateChannelCreateSchema {
|
||||||
|
pub recipients: Option<Vec<Snowflake>>,
|
||||||
|
pub access_tokens: Option<Vec<String>>,
|
||||||
|
pub nicks: Option<HashMap<Snowflake, String>>,
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ const EPOCH: i64 = 1420070400000;
|
||||||
|
|
||||||
/// Unique identifier including a timestamp.
|
/// Unique identifier including a timestamp.
|
||||||
/// See https://discord.com/developers/docs/reference#snowflakes
|
/// See https://discord.com/developers/docs/reference#snowflakes
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
#[cfg_attr(feature = "sqlx", derive(Type))]
|
#[cfg_attr(feature = "sqlx", derive(Type))]
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(transparent))]
|
#[cfg_attr(feature = "sqlx", sqlx(transparent))]
|
||||||
pub struct Snowflake(u64);
|
pub struct Snowflake(u64);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use chorus::types::{
|
use chorus::types::{
|
||||||
self, Channel, GetChannelMessagesSchema, MessageSendSchema, PermissionFlags,
|
self, Channel, GetChannelMessagesSchema, MessageSendSchema, PermissionFlags,
|
||||||
PermissionOverwrite, Snowflake,
|
PermissionOverwrite, PrivateChannelCreateSchema, RelationshipType, Snowflake,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
@ -89,12 +89,11 @@ async fn get_channel_messages() {
|
||||||
let _ = bundle
|
let _ = bundle
|
||||||
.user
|
.user
|
||||||
.send_message(
|
.send_message(
|
||||||
&mut MessageSendSchema {
|
MessageSendSchema {
|
||||||
content: Some("A Message!".to_string()),
|
content: Some("A Message!".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
bundle.channel.id,
|
bundle.channel.id,
|
||||||
None,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -136,3 +135,81 @@ async fn get_channel_messages() {
|
||||||
|
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn create_dm() {
|
||||||
|
let mut bundle = common::setup().await;
|
||||||
|
let other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
|
let user = &mut bundle.user;
|
||||||
|
let private_channel_create_schema = PrivateChannelCreateSchema {
|
||||||
|
recipients: Some(Vec::from([other_user.object.id])),
|
||||||
|
access_tokens: None,
|
||||||
|
nicks: None,
|
||||||
|
};
|
||||||
|
let dm_channel = user
|
||||||
|
.create_private_channel(private_channel_create_schema)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(dm_channel.recipients.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
dm_channel.recipients.as_ref().unwrap().get(0).unwrap().id,
|
||||||
|
other_user.object.id
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
dm_channel.recipients.as_ref().unwrap().get(1).unwrap().id,
|
||||||
|
user.object.id
|
||||||
|
);
|
||||||
|
common::teardown(bundle).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[tokio::test]
|
||||||
|
// This test currently is broken due to an issue with the Spacebar Server.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
async fn remove_add_person_from_to_dm() {
|
||||||
|
let mut bundle = common::setup().await;
|
||||||
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
|
let mut third_user = bundle.create_user("integrationtestuser3").await;
|
||||||
|
let user = &mut bundle.user;
|
||||||
|
let private_channel_create_schema = PrivateChannelCreateSchema {
|
||||||
|
recipients: Some(Vec::from([other_user.object.id, third_user.object.id])),
|
||||||
|
access_tokens: None,
|
||||||
|
nicks: None,
|
||||||
|
};
|
||||||
|
let dm_channel = user
|
||||||
|
.create_private_channel(private_channel_create_schema)
|
||||||
|
.await
|
||||||
|
.unwrap(); // Creates the Channel and stores the response Channel object
|
||||||
|
dm_channel
|
||||||
|
.remove_channel_recipient(other_user.object.id, user)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(dm_channel.recipients.as_ref().unwrap().get(1).is_none());
|
||||||
|
other_user
|
||||||
|
.modify_user_relationship(user.object.id, RelationshipType::Friends)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
user.modify_user_relationship(other_user.object.id, RelationshipType::Friends)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
third_user
|
||||||
|
.modify_user_relationship(user.object.id, RelationshipType::Friends)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
user.modify_user_relationship(third_user.object.id, RelationshipType::Friends)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
// Users 1-2 and 1-3 are now friends
|
||||||
|
dm_channel
|
||||||
|
.add_channel_recipient(other_user.object.id, user, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(dm_channel.recipients.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
dm_channel.recipients.as_ref().unwrap().get(0).unwrap().id,
|
||||||
|
other_user.object.id
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
dm_channel.recipients.as_ref().unwrap().get(1).unwrap().id,
|
||||||
|
user.object.id
|
||||||
|
);
|
||||||
|
}
|
|
@ -7,8 +7,9 @@ use chorus::{
|
||||||
UrlBundle,
|
UrlBundle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TestBundle {
|
pub(crate) struct TestBundle {
|
||||||
pub urls: UrlBundle,
|
pub urls: UrlBundle,
|
||||||
pub user: UserMeta,
|
pub user: UserMeta,
|
||||||
pub instance: Instance,
|
pub instance: Instance,
|
||||||
|
@ -17,8 +18,24 @@ pub struct TestBundle {
|
||||||
pub channel: Channel,
|
pub channel: Channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TestBundle {
|
||||||
|
#[allow(unused)]
|
||||||
|
pub(crate) async fn create_user(&mut self, username: &str) -> UserMeta {
|
||||||
|
let register_schema = RegisterSchema {
|
||||||
|
username: username.to_string(),
|
||||||
|
consent: true,
|
||||||
|
date_of_birth: Some("2000-01-01".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
self.instance
|
||||||
|
.register_account(®ister_schema)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set up a test by creating an Instance and a User. Reduces Test boilerplate.
|
// Set up a test by creating an Instance and a User. Reduces Test boilerplate.
|
||||||
pub async fn setup() -> TestBundle {
|
pub(crate) async fn setup() -> TestBundle {
|
||||||
let urls = UrlBundle::new(
|
let urls = UrlBundle::new(
|
||||||
"http://localhost:3001/api".to_string(),
|
"http://localhost:3001/api".to_string(),
|
||||||
"ws://localhost:3001".to_string(),
|
"ws://localhost:3001".to_string(),
|
||||||
|
@ -93,7 +110,7 @@ pub async fn setup() -> TestBundle {
|
||||||
|
|
||||||
// Teardown method to clean up after a test.
|
// Teardown method to clean up after a test.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn teardown(mut bundle: TestBundle) {
|
pub(crate) async fn teardown(mut bundle: TestBundle) {
|
||||||
Guild::delete(&mut bundle.user, bundle.guild.id)
|
Guild::delete(&mut bundle.user, bundle.guild.id)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
use chorus::types::CreateChannelInviteSchema;
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn create_accept_invite() {
|
||||||
|
let mut bundle = common::setup().await;
|
||||||
|
let channel = bundle.channel.clone();
|
||||||
|
let mut user = bundle.user.clone();
|
||||||
|
let create_channel_invite_schema = CreateChannelInviteSchema::default();
|
||||||
|
let mut other_user = bundle.create_user("testuser1312").await;
|
||||||
|
assert!(chorus::types::Guild::get(bundle.guild.id, &mut other_user)
|
||||||
|
.await
|
||||||
|
.is_err());
|
||||||
|
let invite = user
|
||||||
|
.create_guild_invite(create_channel_invite_schema, channel.id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
other_user.accept_invite(&invite.code, None).await.unwrap();
|
||||||
|
assert!(chorus::types::Guild::get(bundle.guild.id, &mut other_user)
|
||||||
|
.await
|
||||||
|
.is_ok());
|
||||||
|
common::teardown(bundle).await;
|
||||||
|
}
|
|
@ -8,13 +8,13 @@ mod common;
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_message() {
|
async fn send_message() {
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let mut message = types::MessageSendSchema {
|
let message = types::MessageSendSchema {
|
||||||
content: Some("A Message!".to_string()),
|
content: Some("A Message!".to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let _ = bundle
|
let _ = bundle
|
||||||
.user
|
.user
|
||||||
.send_message(&mut message, bundle.channel.id, None)
|
.send_message(message, bundle.channel.id)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
|
@ -45,7 +45,7 @@ async fn send_message_attachment() {
|
||||||
content: buffer,
|
content: buffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut message = types::MessageSendSchema {
|
let message = types::MessageSendSchema {
|
||||||
content: Some("trans rights now".to_string()),
|
content: Some("trans rights now".to_string()),
|
||||||
attachments: Some(vec![attachment.clone()]),
|
attachments: Some(vec![attachment.clone()]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -55,11 +55,7 @@ async fn send_message_attachment() {
|
||||||
let _arg = Some(&vec_attach);
|
let _arg = Some(&vec_attach);
|
||||||
bundle
|
bundle
|
||||||
.user
|
.user
|
||||||
.send_message(
|
.send_message(message, bundle.channel.id)
|
||||||
&mut message,
|
|
||||||
bundle.channel.id,
|
|
||||||
Some(vec![attachment.clone()]),
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
|
@ -1,20 +1,12 @@
|
||||||
use chorus::types::{self, RegisterSchema, Relationship, RelationshipType};
|
use chorus::types::{self, Relationship, RelationshipType};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_get_mutual_relationships() {
|
async fn test_get_mutual_relationships() {
|
||||||
let register_schema = RegisterSchema {
|
|
||||||
username: "integrationtestuser2".to_string(),
|
|
||||||
consent: true,
|
|
||||||
date_of_birth: Some("2000-01-01".to_string()),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let belongs_to = &mut bundle.instance;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let mut other_user = belongs_to.register_account(®ister_schema).await.unwrap();
|
|
||||||
let friend_request_schema = types::FriendRequestSendSchema {
|
let friend_request_schema = types::FriendRequestSendSchema {
|
||||||
username: user.object.username.clone(),
|
username: user.object.username.clone(),
|
||||||
discriminator: Some(user.object.discriminator.clone()),
|
discriminator: Some(user.object.discriminator.clone()),
|
||||||
|
@ -30,17 +22,9 @@ async fn test_get_mutual_relationships() {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_get_relationships() {
|
async fn test_get_relationships() {
|
||||||
let register_schema = RegisterSchema {
|
|
||||||
username: "integrationtestuser2".to_string(),
|
|
||||||
consent: true,
|
|
||||||
date_of_birth: Some("2000-01-01".to_string()),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let belongs_to = &mut bundle.instance;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let mut other_user = belongs_to.register_account(®ister_schema).await.unwrap();
|
|
||||||
let friend_request_schema = types::FriendRequestSendSchema {
|
let friend_request_schema = types::FriendRequestSendSchema {
|
||||||
username: user.object.username.clone(),
|
username: user.object.username.clone(),
|
||||||
discriminator: Some(user.object.discriminator.clone()),
|
discriminator: Some(user.object.discriminator.clone()),
|
||||||
|
@ -56,17 +40,9 @@ async fn test_get_relationships() {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_modify_relationship_friends() {
|
async fn test_modify_relationship_friends() {
|
||||||
let register_schema = RegisterSchema {
|
|
||||||
username: "integrationtestuser2".to_string(),
|
|
||||||
consent: true,
|
|
||||||
date_of_birth: Some("2000-01-01".to_string()),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let belongs_to = &mut bundle.instance;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let mut other_user = belongs_to.register_account(®ister_schema).await.unwrap();
|
|
||||||
let _ = other_user
|
let _ = other_user
|
||||||
.modify_user_relationship(user.object.id, types::RelationshipType::Friends)
|
.modify_user_relationship(user.object.id, types::RelationshipType::Friends)
|
||||||
.await;
|
.await;
|
||||||
|
@ -105,17 +81,9 @@ async fn test_modify_relationship_friends() {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_modify_relationship_block() {
|
async fn test_modify_relationship_block() {
|
||||||
let register_schema = RegisterSchema {
|
|
||||||
username: "integrationtestuser2".to_string(),
|
|
||||||
consent: true,
|
|
||||||
date_of_birth: Some("2000-01-01".to_string()),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut bundle = common::setup().await;
|
let mut bundle = common::setup().await;
|
||||||
let belongs_to = &mut bundle.instance;
|
let mut other_user = bundle.create_user("integrationtestuser2").await;
|
||||||
let user = &mut bundle.user;
|
let user = &mut bundle.user;
|
||||||
let mut other_user = belongs_to.register_account(®ister_schema).await.unwrap();
|
|
||||||
let _ = other_user
|
let _ = other_user
|
||||||
.modify_user_relationship(user.object.id, types::RelationshipType::Blocked)
|
.modify_user_relationship(user.object.id, types::RelationshipType::Blocked)
|
||||||
.await;
|
.await;
|
||||||
|
|
Loading…
Reference in New Issue