diff --git a/.github/workflows/rust.yml b/.github/workflows/build_and_test.yml
similarity index 96%
rename from .github/workflows/rust.yml
rename to .github/workflows/build_and_test.yml
index 9b39ddf..4e98355 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/build_and_test.yml
@@ -1,4 +1,4 @@
-name: Rust
+name: Build and Test
on:
push:
@@ -10,7 +10,7 @@ env:
CARGO_TERM_COLOR: always
jobs:
- build_and_test:
+ rust:
runs-on: ubuntu-latest
diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml
new file mode 100644
index 0000000..ba12407
--- /dev/null
+++ b/.github/workflows/clippy.yml
@@ -0,0 +1,20 @@
+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
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 8e33c0d..cece3e2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,9 +29,6 @@ openssl = "0.10.52"
base64 = "0.21.2"
hostname = "0.3.1"
bitflags = { version = "2.2.1", features = ["serde"] }
-atomic = "0.5.3"
-bigdecimal = "0.3.1"
-num-bigint = "0.4.3"
lazy_static = "1.4.0"
poem = { version = "1.3.55", 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 }
diff --git a/README.md b/README.md
index 82ac173..9a75a54 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@
[![Contributors][contributors-shield]][contributors-url]
[![Forks][forks-shield]][forks-url]
[![Issues][issues-shield]][issues-url]
+
@@ -30,94 +31,106 @@
-## Progress Tracker/Roadmap:
-### Core Functionality
-- [x] Rate Limiter (hint: couldn't be fully tested due to [an Issue with the Spacebar Server](https://github.com/spacebarchat/server/issues/1022))
-- [x] [Login (the conventional way)](https://github.com/polyphony-chat/chorus/issues/1)
-- [ ] [2FA](https://github.com/polyphony-chat/chorus/issues/40)
-- [x] [Registration](https://github.com/polyphony-chat/chorus/issues/1)
+## About
-### Messaging
-- [x] [Sending messages](https://github.com/polyphony-chat/chorus/issues/23)
-- [x] [Events (Message, User, Channel, etc.)](https://github.com/polyphony-chat/chorus/issues/51)
-- [x] Channel creation
-- [x] Channel deletion
-- [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)
-- [ ] [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)
-- [ ] [Deleting messages](https://github.com/polyphony-chat/chorus/issues/91)
-- [ ] [Message threads](https://github.com/polyphony-chat/chorus/issues/90)
-- [x] [Reactions](https://github.com/polyphony-chat/chorus/issues/85)
-- [ ] Message Search
-- [ ] Message history
-- [ ] Emoji
-- [ ] Stickers
-- [ ] [Forum channels](https://github.com/polyphony-chat/chorus/issues/90)
+Chorus is a Rust library that allows developers to interact with multiple Spacebar-compatible APIs and Gateways simultaneously. The library provides a simple and efficient way to communicate with these services, making it easier for developers to build applications that rely on them. Chorus is open-source and welcomes contributions from the community.
-### User Management
-- [ ] [User profile customization](https://github.com/polyphony-chat/chorus/issues/41)
-- [x] Gettings users and user profiles
-- [ ] [Friend requests](https://github.com/polyphony-chat/chorus/issues/92)
-- [ ] [Blocking users](https://github.com/polyphony-chat/chorus/issues/92)
-- [ ] User presence (online, offline, idle, etc.)
-- [ ] User status (custom status, etc.)
-- [x] Account deletion
+## Contributing
-### Additional Features
-- [ ] Server discovery
-- [ ] Server templates
+If you would like to contribute, please feel free to open an Issue with the idea you have, or a
+Pull Request. Please keep our [contribution guidelines](https://github.com/polyphony-chat/.github/blob/main/CONTRIBUTION_GUIDELINES.md) in mind. Your contribution might not be
+accepted, if it violates these guidelines or [our Code of Conduct](https://github.com/polyphony-chat/.github/blob/main/CODE_OF_CONDUCT.md).
-### Voice and Video
-- [ ] [Voice chat support](https://github.com/polyphony-chat/chorus/issues/49)
-- [ ] [Video chat support](https://github.com/polyphony-chat/chorus/issues/49)
+
+ Progress Tracker/Roadmap
-### Permissions and Roles
-- [x] [Role management](https://github.com/polyphony-chat/chorus/issues/46) (creation, deletion, modification)
-- [x] [Permission management](https://github.com/polyphony-chat/chorus/issues/46) (assigning and revoking permissions)
-- [x] [Channel-specific permissions](https://github.com/polyphony-chat/chorus/issues/88)
-- [x] Role-based access control
+ ### Core Functionality
+ - [x] Rate Limiter (hint: couldn't be fully tested due to [an Issue with the Spacebar Server](https://github.com/spacebarchat/server/issues/1022))
+ - [x] [Login (the conventional way)](https://github.com/polyphony-chat/chorus/issues/1)
+ - [ ] [2FA](https://github.com/polyphony-chat/chorus/issues/40)
+ - [x] [Registration](https://github.com/polyphony-chat/chorus/issues/1)
-### Guild Management
-- [x] Guild creation
-- [x] Guild deletion
-- [ ] [Guild settings (name, description, icon, etc.)](https://github.com/polyphony-chat/chorus/issues/43)
-- [ ] Guild invites
+ ### Messaging
+ - [x] [Sending messages](https://github.com/polyphony-chat/chorus/issues/23)
+ - [x] [Events (Message, User, Channel, etc.)](https://github.com/polyphony-chat/chorus/issues/51)
+ - [x] Channel creation
+ - [x] Channel deletion
+ - [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)
+ - [ ] [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)
+ - [ ] [Deleting messages](https://github.com/polyphony-chat/chorus/issues/91)
+ - [ ] [Message threads](https://github.com/polyphony-chat/chorus/issues/90)
+ - [x] [Reactions](https://github.com/polyphony-chat/chorus/issues/85)
+ - [ ] Message Search
+ - [ ] Message history
+ - [ ] Emoji
+ - [ ] Stickers
+ - [ ] [Forum channels](https://github.com/polyphony-chat/chorus/issues/90)
-### Moderation
-- [ ] Channel moderation (slow mode, etc.)
-- [ ] User sanctions (mute, kick, ban)
-- [ ] Audit logs
+ ### User Management
+ - [ ] [User profile customization](https://github.com/polyphony-chat/chorus/issues/41)
+ - [x] Gettings users and user profiles
+ - [x] [Friend requests](https://github.com/polyphony-chat/chorus/issues/92)
+ - [x] [Blocking users](https://github.com/polyphony-chat/chorus/issues/92)
+ - [ ] User presence (online, offline, idle, etc.)
+ - [ ] User status (custom status, etc.)
+ - [x] Account deletion
-### Embeds and Rich Content
-- [x] Sending rich content in messages (links, images, videos)
-- [ ] Customizing embed appearance (title, description, color, fields)
+ ### Additional Features
+ - [ ] Server discovery
+ - [ ] Server templates
-### Notifications and Push Notifications
-- [ ] Notification settings management
+ ### Voice and Video
+ - [ ] [Voice chat support](https://github.com/polyphony-chat/chorus/issues/49)
+ - [ ] [Video chat support](https://github.com/polyphony-chat/chorus/issues/49)
-### Webhooks
-- [ ] Webhook creation and management
-- [ ] Handling incoming webhook events
+ ### Permissions and Roles
+ - [x] [Role management](https://github.com/polyphony-chat/chorus/issues/46) (creation, deletion, modification)
+ - [x] [Permission management](https://github.com/polyphony-chat/chorus/issues/46) (assigning and revoking permissions)
+ - [x] [Channel-specific permissions](https://github.com/polyphony-chat/chorus/issues/88)
+ - [x] Role-based access control
-### Documentation and Examples
-- [ ] Comprehensive documentation
-- [ ] Example usage and code snippets
-- [ ] Tutorials and guides
+ ### Guild Management
+ - [x] Guild creation
+ - [x] Guild deletion
+ - [ ] [Guild settings (name, description, icon, etc.)](https://github.com/polyphony-chat/chorus/issues/43)
+ - [ ] Guild invites
-[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=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=flat
-[contributors-url]: https://github.com/polyphony-chat/chorus/graphs/contributors
-[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=flat
-[stars-url]: https://github.com/polyphony-chat/chorus/stargazers
-[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=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
+ ### Moderation
+ - [ ] Channel moderation (slow mode, etc.)
+ - [ ] User sanctions (mute, kick, ban)
+ - [ ] Audit logs
+
+ ### Embeds and Rich Content
+ - [x] Sending rich content in messages (links, images, videos)
+ - [ ] Customizing embed appearance (title, description, color, fields)
+
+ ### Webhooks
+ - [ ] Webhook creation and management
+ - [ ] Handling incoming webhook events
+
+ ### Documentation and Examples
+ - [ ] Comprehensive documentation
+ - [ ] Example usage and code snippets
+ - [ ] Tutorials and guides
+
+ [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/build_and_test.yml?style=flat
+ [build-url]: https://github.com/polyphony-chat/chorus/blob/main/.github/workflows/build_and_test.yml
+ [clippy-shield]: https://img.shields.io/github/actions/workflow/status/polyphony-chat/chorus/clippy.yml?style=flat
+ [clippy-url]: https://github.com/polyphony-chat/chorus/blob/main/.github/workflows/clippy.yml
+ [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=flat
+ [forks-url]: https://github.com/polyphony-chat/chorus/network/members
+ [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=flat
+ [issues-url]: https://github.com/polyphony-chat/chorus/issues
+ [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
+
\ No newline at end of file
diff --git a/examples/gateway_observers.rs b/examples/gateway_observers.rs
index 166b84a..d8762e0 100644
--- a/examples/gateway_observers.rs
+++ b/examples/gateway_observers.rs
@@ -3,8 +3,8 @@ use chorus::{
gateway::{Gateway, Observer},
types::{GatewayIdentifyPayload, GatewayReady},
};
-use std::sync::Arc;
-use tokio::{self, sync::Mutex};
+use std::{sync::Arc, time::Duration};
+use tokio::{self, time::sleep};
// This example creates a simple gateway connection and a basic observer struct
@@ -17,7 +17,7 @@ pub struct ExampleObserver {}
// One struct can be an observer of multiple websocketevents, if needed
impl Observer for ExampleObserver {
// After we subscribe to an event this function is called every time we receive it
- fn update(&mut self, _data: &GatewayReady) {
+ fn update(&self, _data: &GatewayReady) {
println!("Observed Ready!");
}
}
@@ -33,8 +33,8 @@ async fn main() {
// Create an instance of our observer
let observer = ExampleObserver {};
- // Because observers have to reside in between the main and gateway thread, (they have to be shared between both) we need to put them in an Arc
- let shared_observer = Arc::new(Mutex::new(observer));
+ // Share ownership of the observer with the gateway
+ let shared_observer = Arc::new(observer);
// Subscribe our observer to the Ready event on this gateway
// From now on observer.update(data) will be called every time we receive the Ready event
@@ -44,8 +44,7 @@ async fn main() {
.await
.session
.ready
- .subscribe(shared_observer)
- .unwrap();
+ .subscribe(shared_observer);
// Authenticate so we will receive any events
let token = "SecretToken".to_string();
@@ -54,5 +53,7 @@ async fn main() {
gateway.send_identify(identify).await;
// Do something on the main thread so we don't quit
- loop {}
+ loop {
+ sleep(Duration::MAX).await;
+ }
}
diff --git a/examples/gateway_simple.rs b/examples/gateway_simple.rs
index c346839..26e8416 100644
--- a/examples/gateway_simple.rs
+++ b/examples/gateway_simple.rs
@@ -1,4 +1,7 @@
+use std::time::Duration;
+
use chorus::{self, gateway::Gateway, types::GatewayIdentifyPayload};
+use tokio::time::sleep;
/// This example creates a simple gateway connection and a session with an Identify event
#[tokio::main]
@@ -26,5 +29,7 @@ async fn main() {
gateway.send_identify(identify).await;
// Do something on the main thread so we don't quit
- loop {}
+ loop {
+ sleep(Duration::MAX).await;
+ }
}
diff --git a/src/api/auth/login.rs b/src/api/auth/login.rs
index 73abf24..28b50fe 100644
--- a/src/api/auth/login.rs
+++ b/src/api/auth/login.rs
@@ -17,7 +17,7 @@ impl Instance {
) -> Result {
let json_schema = json!(login_schema);
let client = Client::new();
- let endpoint_url = self.urls.get_api().to_string() + "/auth/login";
+ let endpoint_url = self.urls.api.clone() + "/auth/login";
let request_builder = client.post(endpoint_url).body(json_schema.to_string());
// We do not have a user yet, and the UserRateLimits will not be affected by a login
// request (since login is an instance wide limit), which is why we are just cloning the
diff --git a/src/api/auth/register.rs b/src/api/auth/register.rs
index 80485eb..85196cb 100644
--- a/src/api/auth/register.rs
+++ b/src/api/auth/register.rs
@@ -25,7 +25,7 @@ impl Instance {
) -> Result {
let json_schema = json!(register_schema);
let client = Client::new();
- let endpoint_url = self.urls.get_api().to_string() + "/auth/register";
+ let endpoint_url = self.urls.api.clone() + "/auth/register";
let request_builder = client.post(endpoint_url).body(json_schema.to_string());
// We do not have a user yet, and the UserRateLimits will not be affected by a login
// request (since register is an instance wide limit), which is why we are just cloning
@@ -59,11 +59,10 @@ impl Instance {
return Err(ChorusLibError::InvalidFormBodyError { error_type, error });
}
let user_object = self.get_user(token.clone(), None).await.unwrap();
- let settings =
- UserMeta::get_settings(&token, &self.urls.get_api().to_string(), &mut self.limits)
- .await
- .unwrap();
- let user: UserMeta = UserMeta::new(
+ let settings = UserMeta::get_settings(&token, &self.urls.api, &mut self.limits)
+ .await
+ .unwrap();
+ let user = UserMeta::new(
Rc::new(RefCell::new(self.clone())),
token.clone(),
cloned_limits,
diff --git a/src/api/channels/channels.rs b/src/api/channels/channels.rs
index 32d9c3a..290e240 100644
--- a/src/api/channels/channels.rs
+++ b/src/api/channels/channels.rs
@@ -10,9 +10,7 @@ use crate::{
impl Channel {
pub async fn get(user: &mut UserMeta, channel_id: &str) -> Result {
- let belongs_to = user.belongs_to.borrow_mut();
- let url = belongs_to.urls.get_api().to_string();
- drop(belongs_to);
+ let url = user.belongs_to.borrow_mut().urls.api.clone();
let request = Client::new()
.get(format!("{}/channels/{}/", url, channel_id))
.bearer_auth(user.token());
@@ -44,24 +42,19 @@ impl Channel {
///
/// # Returns
///
- /// An `Option` that contains an `ChorusLibError` if an error occurred during the request, or `None` if the request was successful.
- pub async fn delete(self, user: &mut UserMeta) -> Option {
- let belongs_to = user.belongs_to.borrow_mut();
+ /// A `Result` that contains a `ChorusLibError` if an error occurred during the request, or `()` if the request was successful.
+ pub async fn delete(self, user: &mut UserMeta) -> Result<(), ChorusLibError> {
let request = Client::new()
.delete(format!(
"{}/channels/{}/",
- belongs_to.urls.get_api(),
- self.id.to_string()
+ user.belongs_to.borrow_mut().urls.api,
+ self.id
))
.bearer_auth(user.token());
- drop(belongs_to);
let response =
- common::handle_request(request, user, crate::api::limits::LimitType::Channel).await;
- if response.is_err() {
- return Some(response.err().unwrap());
- } else {
- return None;
- }
+ common::handle_request_as_result(request, user, crate::api::limits::LimitType::Channel)
+ .await;
+ response
}
/// Modifies a channel.
@@ -83,16 +76,14 @@ impl Channel {
channel_id: &str,
user: &mut UserMeta,
) -> Result {
- let belongs_to = user.belongs_to.borrow();
let request = Client::new()
.patch(format!(
"{}/channels/{}/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
channel_id
))
.bearer_auth(user.token())
.body(to_string(&modify_data).unwrap());
- drop(belongs_to);
let channel = common::deserialize_response::(
request,
user,
diff --git a/src/api/channels/messages.rs b/src/api/channels/messages.rs
index a20570f..61801a8 100644
--- a/src/api/channels/messages.rs
+++ b/src/api/channels/messages.rs
@@ -25,9 +25,7 @@ impl Message {
message: &mut MessageSendSchema,
files: Option>,
) -> Result {
- let belongs_to = user.belongs_to.borrow();
- let url_api = belongs_to.urls.get_api().to_string();
- drop(belongs_to);
+ let url_api = user.belongs_to.borrow().urls.api.clone();
if files.is_none() {
let request = Client::new()
diff --git a/src/api/channels/permissions.rs b/src/api/channels/permissions.rs
index 120117b..263b3d1 100644
--- a/src/api/channels/permissions.rs
+++ b/src/api/channels/permissions.rs
@@ -2,7 +2,7 @@ use reqwest::Client;
use serde_json::to_string;
use crate::{
- api::handle_request,
+ api::{handle_request, handle_request_as_result},
errors::ChorusLibError,
instance::UserMeta,
types::{self, PermissionOverwrite},
@@ -19,35 +19,30 @@ impl types::Channel {
///
/// # Returns
///
- /// This function returns [`None`] if the request is successful, otherwise it returns a [`ChorusLibError`] instance.
+ /// This function returns a result that is either [`Ok(())`] if the request is successful, or an [`Err(ChorusLibError)`].
pub async fn edit_permissions(
user: &mut UserMeta,
channel_id: &str,
overwrite: PermissionOverwrite,
- ) -> Option {
- let belongs_to = user.belongs_to.borrow_mut();
- let url = format!(
- "{}/channels/{}/permissions/{}",
- belongs_to.urls.get_api(),
- channel_id,
- overwrite.id
- );
- drop(belongs_to);
+ ) -> Result<(), ChorusLibError> {
+ let url = {
+ format!(
+ "{}/channels/{}/permissions/{}",
+ user.belongs_to.borrow_mut().urls.api,
+ channel_id,
+ overwrite.id
+ )
+ };
let body = match to_string(&overwrite) {
Ok(string) => string,
Err(e) => {
- return Some(ChorusLibError::FormCreationError {
+ return Err(ChorusLibError::FormCreationError {
error: e.to_string(),
});
}
};
let request = Client::new().put(url).bearer_auth(user.token()).body(body);
- match handle_request(request, user, crate::api::limits::LimitType::Channel).await {
- Ok(_) => None,
- Err(e) => Some(ChorusLibError::InvalidResponseError {
- error: e.to_string(),
- }),
- }
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Channel).await
}
/// Deletes a permission overwrite for a channel.
@@ -60,26 +55,19 @@ impl types::Channel {
///
/// # Returns
///
- /// This function returns [`None`] if the request is successful, otherwise it returns a [`ChorusLibError`] instance.
+ /// This function returns a Result that is either [`Ok(())`] if the request is successfulm or an [`Err(ChorusLibError)`].
pub async fn delete_permission(
user: &mut UserMeta,
channel_id: &str,
overwrite_id: &str,
- ) -> Option {
- let belongs_to = user.belongs_to.borrow_mut();
+ ) -> Result<(), ChorusLibError> {
let url = format!(
"{}/channels/{}/permissions/{}",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow_mut().urls.api,
channel_id,
overwrite_id
);
- drop(belongs_to);
let request = Client::new().delete(url).bearer_auth(user.token());
- match handle_request(request, user, crate::api::limits::LimitType::Channel).await {
- Ok(_) => None,
- Err(e) => Some(ChorusLibError::InvalidResponseError {
- error: e.to_string(),
- }),
- }
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Channel).await
}
}
diff --git a/src/api/channels/reactions.rs b/src/api/channels/reactions.rs
index ea00219..77b7e32 100644
--- a/src/api/channels/reactions.rs
+++ b/src/api/channels/reactions.rs
@@ -1,7 +1,7 @@
use reqwest::Client;
use crate::{
- api::{handle_request, handle_request_as_option},
+ api::{handle_request, handle_request_as_result},
errors::ChorusLibError,
instance::UserMeta,
types,
@@ -24,28 +24,21 @@ impl ReactionMeta {
* `user` - A mutable reference to a [`UserMeta`] instance.
# Returns
- An `Option` [`crate::errors::ChorusLibError`] if something went wrong.
+ A `Result` [`()`] [`crate::errors::ChorusLibError`] if something went wrong.
Fires a `Message Reaction Remove All` Gateway event.
# Reference
See [https://discord.com/developers/docs/resources/channel#delete-all-reactions](https://discord.com/developers/docs/resources/channel#delete-all-reactions)
*/
- pub async fn delete_all(&self, user: &mut UserMeta) -> Option {
- let belongs_to = user.belongs_to.borrow();
+ pub async fn delete_all(&self, user: &mut UserMeta) -> Result<(), ChorusLibError> {
let url = format!(
"{}/channels/{}/messages/{}/reactions/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
self.channel_id,
self.message_id
);
- drop(belongs_to);
let request = Client::new().delete(url).bearer_auth(user.token());
- match handle_request(request, user, crate::api::limits::LimitType::Channel).await {
- Ok(_) => None,
- Err(e) => Some(ChorusLibError::InvalidResponseError {
- error: e.to_string(),
- }),
- }
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Channel).await
}
/**
@@ -58,28 +51,21 @@ impl ReactionMeta {
* `user` - A mutable reference to a [`UserMeta`] instance.
# Returns
- A [`crate::errors::ChorusLibError`] if something went wrong.
+ A Result that is [`Err(crate::errors::ChorusLibError)`] if something went wrong.
# Reference
See [https://discord.com/developers/docs/resources/channel#get-reactions](https://discord.com/developers/docs/resources/channel#get-reactions)
*/
- pub async fn get(&self, emoji: &str, user: &mut UserMeta) -> Option {
- let belongs_to = user.belongs_to.borrow();
+ pub async fn get(&self, emoji: &str, user: &mut UserMeta) -> Result<(), ChorusLibError> {
let url = format!(
"{}/channels/{}/messages/{}/reactions/{}/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
self.channel_id,
self.message_id,
emoji
);
- drop(belongs_to);
let request = Client::new().get(url).bearer_auth(user.token());
- match handle_request(request, user, crate::api::limits::LimitType::Channel).await {
- Ok(_) => None,
- Err(e) => Some(ChorusLibError::InvalidResponseError {
- error: e.to_string(),
- }),
- }
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Channel).await
}
/**
@@ -93,29 +79,26 @@ impl ReactionMeta {
* `user` - A mutable reference to a [`UserMeta`] instance.
# Returns
- A [`crate::errors::ChorusLibError`] if something went wrong.
+ A Result that is [`Err(crate::errors::ChorusLibError)`] if something went wrong.
Fires a `Message Reaction Remove Emoji` Gateway event.
# Reference
See [https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji](https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji)
*/
- pub async fn delete_emoji(&self, emoji: &str, user: &mut UserMeta) -> Option {
- let belongs_to = user.belongs_to.borrow();
+ pub async fn delete_emoji(
+ &self,
+ emoji: &str,
+ user: &mut UserMeta,
+ ) -> Result<(), ChorusLibError> {
let url = format!(
"{}/channels/{}/messages/{}/reactions/{}/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
self.channel_id,
self.message_id,
emoji
);
- drop(belongs_to);
let request = Client::new().delete(url).bearer_auth(user.token());
- match handle_request(request, user, crate::api::limits::LimitType::Channel).await {
- Ok(_) => None,
- Err(e) => Some(ChorusLibError::InvalidResponseError {
- error: e.to_string(),
- }),
- }
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Channel).await
}
/**
@@ -132,25 +115,21 @@ impl ReactionMeta {
* `user` - A mutable reference to a [`UserMeta`] instance.
# Returns
- A `Result` containing a [`reqwest::Response`] or a [`crate::errors::ChorusLibError`].
- Returns a 204 empty response on success.
- Fires a Message Reaction Add Gateway event.
+ A `Result` containing [`()`] or a [`crate::errors::ChorusLibError`].
# Reference
See [https://discord.com/developers/docs/resources/channel#create-reaction](https://discord.com/developers/docs/resources/channel#create-reaction)
*/
- pub async fn create(&self, emoji: &str, user: &mut UserMeta) -> Option {
- let belongs_to = user.belongs_to.borrow();
+ pub async fn create(&self, emoji: &str, user: &mut UserMeta) -> Result<(), ChorusLibError> {
let url = format!(
"{}/channels/{}/messages/{}/reactions/{}/@me/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
self.channel_id,
self.message_id,
emoji
);
- drop(belongs_to);
let request = Client::new().put(url).bearer_auth(user.token());
- handle_request_as_option(request, user, crate::api::limits::LimitType::Channel).await
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Channel).await
}
/**
@@ -163,25 +142,22 @@ impl ReactionMeta {
* `user` - A mutable reference to a [`UserMeta`] instance.
# Returns
- A `Result` containing a [`reqwest::Response`] or a [`crate::errors::ChorusLibError`].
- Returns a 204 empty response on success.
+ A `Result` containing [`()`] or a [`crate::errors::ChorusLibError`].
Fires a `Message Reaction Remove` Gateway event.
# Reference
See [https://discord.com/developers/docs/resources/channel#delete-own-reaction](https://discord.com/developers/docs/resources/channel#delete-own-reaction)
*/
- pub async fn remove(&self, emoji: &str, user: &mut UserMeta) -> Option {
- let belongs_to = user.belongs_to.borrow();
+ pub async fn remove(&self, emoji: &str, user: &mut UserMeta) -> Result<(), ChorusLibError> {
let url = format!(
"{}/channels/{}/messages/{}/reactions/{}/@me/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
self.channel_id,
self.message_id,
emoji
);
- drop(belongs_to);
let request = Client::new().delete(url).bearer_auth(user.token());
- handle_request_as_option(request, user, crate::api::limits::LimitType::Channel).await
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Channel).await
}
/**
@@ -197,8 +173,7 @@ impl ReactionMeta {
* `user` - A mutable reference to a [`UserMeta`] instance.
# Returns
- A `Result` containing a [`reqwest::Response`] or a [`crate::errors::ChorusLibError`].
- Returns a 204 empty response on success.
+ A `Result` containing [`()`] or a [`crate::errors::ChorusLibError`].
Fires a Message Reaction Remove Gateway event.
# Reference
@@ -209,18 +184,16 @@ impl ReactionMeta {
user_id: &str,
emoji: &str,
user: &mut UserMeta,
- ) -> Option {
- let belongs_to = user.belongs_to.borrow();
+ ) -> Result<(), ChorusLibError> {
let url = format!(
"{}/channels/{}/messages/{}/reactions/{}/{}",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
self.channel_id,
self.message_id,
emoji,
user_id
);
- drop(belongs_to);
let request = Client::new().delete(url).bearer_auth(user.token());
- handle_request_as_option(request, user, crate::api::limits::LimitType::Channel).await
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Channel).await
}
}
diff --git a/src/api/common.rs b/src/api/common.rs
index 0ca9063..f61ab19 100644
--- a/src/api/common.rs
+++ b/src/api/common.rs
@@ -12,30 +12,25 @@ pub async fn handle_request(
user: &mut UserMeta,
limit_type: LimitType,
) -> Result {
- let mut belongs_to = user.belongs_to.borrow_mut();
- match LimitedRequester::send_request(
+ LimitedRequester::send_request(
request,
limit_type,
- &mut belongs_to.limits,
+ &mut user.belongs_to.borrow_mut().limits,
&mut user.limits,
)
.await
- {
- Ok(response) => return Ok(response),
- Err(e) => return Err(e),
- }
}
-/// Sends a request to wherever it needs to go. Returns [`None`] on success and
-/// [`Some(ChorusLibError)`] on failure.
-pub async fn handle_request_as_option(
+/// Sends a request to wherever it needs to go. Returns [`Ok(())`] on success and
+/// [`Err(ChorusLibError)`] on failure.
+pub async fn handle_request_as_result(
request: RequestBuilder,
user: &mut UserMeta,
limit_type: LimitType,
-) -> Option {
+) -> Result<(), ChorusLibError> {
match handle_request(request, user, limit_type).await {
- Ok(_) => None,
- Err(e) => Some(ChorusLibError::InvalidResponseError {
+ Ok(_) => Ok(()),
+ Err(e) => Err(ChorusLibError::InvalidResponseError {
error: e.to_string(),
}),
}
@@ -53,7 +48,7 @@ pub async fn deserialize_response Deserialize<'a>>(
return Err(ChorusLibError::InvalidResponseError {
error: format!(
"Error while trying to process the HTTP response into a String: {}",
- e.to_string()
+ e
),
});
}
@@ -64,7 +59,7 @@ pub async fn deserialize_response Deserialize<'a>>(
return Err(ChorusLibError::InvalidResponseError {
error: format!(
"Error while trying to deserialize the JSON response into T: {}",
- e.to_string()
+ e
),
})
}
diff --git a/src/api/guilds/guilds.rs b/src/api/guilds/guilds.rs
index 8259c0e..05bf8c2 100644
--- a/src/api/guilds/guilds.rs
+++ b/src/api/guilds/guilds.rs
@@ -4,7 +4,7 @@ use serde_json::to_string;
use crate::api::deserialize_response;
use crate::api::handle_request;
-use crate::api::handle_request_as_option;
+use crate::api::handle_request_as_result;
use crate::api::limits::Limits;
use crate::errors::ChorusLibError;
use crate::instance::UserMeta;
@@ -32,9 +32,7 @@ impl Guild {
user: &mut UserMeta,
guild_create_schema: GuildCreateSchema,
) -> Result {
- let belongs_to = user.belongs_to.borrow();
- let url = format!("{}/guilds/", belongs_to.urls.get_api());
- drop(belongs_to);
+ let url = format!("{}/guilds/", user.belongs_to.borrow().urls.api);
let request = reqwest::Client::new()
.post(url.clone())
.bearer_auth(user.token.clone())
@@ -52,7 +50,7 @@ impl Guild {
///
/// # Returns
///
- /// An `Option` containing an `ChorusLibError` if an error occurred during the request, otherwise `None`.
+ /// An `Result` containing an `ChorusLibError` if an error occurred during the request, otherwise `()`.
///
/// # Example
///
@@ -66,14 +64,16 @@ impl Guild {
/// None => println!("Guild deleted successfully"),
/// }
/// ```
- pub async fn delete(user: &mut UserMeta, guild_id: &str) -> Option {
- let belongs_to = user.belongs_to.borrow();
- let url = format!("{}/guilds/{}/delete/", belongs_to.urls.get_api(), guild_id);
- drop(belongs_to);
+ pub async fn delete(user: &mut UserMeta, guild_id: &str) -> Result<(), ChorusLibError> {
+ let url = format!(
+ "{}/guilds/{}/delete/",
+ user.belongs_to.borrow().urls.api,
+ guild_id
+ );
let request = reqwest::Client::new()
.post(url.clone())
.bearer_auth(user.token.clone());
- handle_request_as_option(request, user, crate::api::limits::LimitType::Guild).await
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Guild).await
}
/// Sends a request to create a new channel in the guild.
@@ -97,7 +97,7 @@ impl Guild {
let mut belongs_to = user.belongs_to.borrow_mut();
Channel::_create(
&user.token,
- &format!("{}", belongs_to.urls.get_api()),
+ &format!("{}", belongs_to.urls.api),
&self.id.to_string(),
schema,
&mut user.limits,
@@ -116,15 +116,13 @@ impl Guild {
/// * `limits_instance` - A mutable reference to a `Limits` struct containing the instance's rate limits.
///
pub async fn channels(&self, user: &mut UserMeta) -> Result, ChorusLibError> {
- let belongs_to = user.belongs_to.borrow();
let request = Client::new()
.get(format!(
"{}/guilds/{}/channels/",
- belongs_to.urls.get_api(),
- self.id.to_string()
+ user.belongs_to.borrow().urls.api,
+ self.id
))
.bearer_auth(user.token());
- drop(belongs_to);
let result = handle_request(request, user, crate::api::limits::LimitType::Channel)
.await
.unwrap();
@@ -159,7 +157,7 @@ impl Guild {
pub async fn get(user: &mut UserMeta, guild_id: &str) -> Result {
let mut belongs_to = user.belongs_to.borrow_mut();
Guild::_get(
- &format!("{}", belongs_to.urls.get_api()),
+ &format!("{}", belongs_to.urls.api),
guild_id,
&user.token,
&mut user.limits,
@@ -219,7 +217,7 @@ impl Channel {
let mut belongs_to = user.belongs_to.borrow_mut();
Channel::_create(
&user.token,
- &format!("{}", belongs_to.urls.get_api()),
+ &format!("{}", belongs_to.urls.api),
guild_id,
schema,
&mut user.limits,
diff --git a/src/api/guilds/member.rs b/src/api/guilds/member.rs
index 8a18178..7b18aa7 100644
--- a/src/api/guilds/member.rs
+++ b/src/api/guilds/member.rs
@@ -1,7 +1,7 @@
use reqwest::Client;
use crate::{
- api::{deserialize_response, handle_request_as_option},
+ api::{deserialize_response, handle_request_as_result},
errors::ChorusLibError,
instance::UserMeta,
types,
@@ -24,14 +24,12 @@ impl types::GuildMember {
guild_id: &str,
member_id: &str,
) -> Result {
- let belongs_to = user.belongs_to.borrow();
let url = format!(
"{}/guilds/{}/members/{}/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
guild_id,
member_id
);
- drop(belongs_to);
let request = Client::new().get(url).bearer_auth(user.token());
deserialize_response::(
request,
@@ -52,24 +50,22 @@ impl types::GuildMember {
///
/// # Returns
///
- /// An `Option` containing a `ChorusLibError` if the request fails, or `None` if the request succeeds.
+ /// An `Result` containing a `ChorusLibError` if the request fails, or `()` if the request succeeds.
pub async fn add_role(
user: &mut UserMeta,
guild_id: &str,
member_id: &str,
role_id: &str,
- ) -> Option {
- let belongs_to = user.belongs_to.borrow();
+ ) -> Result<(), ChorusLibError> {
let url = format!(
"{}/guilds/{}/members/{}/roles/{}/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
guild_id,
member_id,
role_id
);
- drop(belongs_to);
let request = Client::new().put(url).bearer_auth(user.token());
- handle_request_as_option(request, user, crate::api::limits::LimitType::Guild).await
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Guild).await
}
/// Removes a role from a guild member.
@@ -83,23 +79,21 @@ impl types::GuildMember {
///
/// # Returns
///
- /// An `Option` containing a `ChorusLibError` if the request fails, or `None` if the request succeeds.
+ /// A `Result` containing a `ChorusLibError` if the request fails, or `()` if the request succeeds.
pub async fn remove_role(
user: &mut UserMeta,
guild_id: &str,
member_id: &str,
role_id: &str,
- ) -> Option {
- let belongs_to = user.belongs_to.borrow();
+ ) -> Result<(), crate::errors::ChorusLibError> {
let url = format!(
"{}/guilds/{}/members/{}/roles/{}/",
- belongs_to.urls.get_api(),
+ user.belongs_to.borrow().urls.api,
guild_id,
member_id,
role_id
);
- drop(belongs_to);
let request = Client::new().delete(url).bearer_auth(user.token());
- handle_request_as_option(request, user, crate::api::limits::LimitType::Guild).await
+ handle_request_as_result(request, user, crate::api::limits::LimitType::Guild).await
}
}
diff --git a/src/api/guilds/roles.rs b/src/api/guilds/roles.rs
index 15a2915..f05b7f1 100644
--- a/src/api/guilds/roles.rs
+++ b/src/api/guilds/roles.rs
@@ -27,9 +27,11 @@ impl types::RoleObject {
user: &mut UserMeta,
guild_id: &str,
) -> Result