Make `ChorusUser` `Send` (#423)

Replace `belongs_to: Rc<RefCell<Instance>>` with `Arc<RwLock<Instance>>`
to make `ChorusUser` `Send`
This commit is contained in:
Flori 2023-08-28 18:23:36 +02:00 committed by GitHub
commit 62a03d2280
17 changed files with 117 additions and 102 deletions

View File

@ -1,7 +1,7 @@
[package] [package]
name = "chorus" name = "chorus"
description = "A library for interacting with multiple Spacebar-compatible Instances at once." description = "A library for interacting with multiple Spacebar-compatible Instances at once."
version = "0.2.0" version = "0.3.0"
license = "AGPL-3.0" license = "AGPL-3.0"
edition = "2021" edition = "2021"
repository = "https://github.com/polyphony-chat/chorus" repository = "https://github.com/polyphony-chat/chorus"

View File

@ -1,5 +1,3 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use reqwest::Client; use reqwest::Client;
@ -30,7 +28,7 @@ impl Instance {
// request (since login is an instance wide limit), which is why we are just cloning the // request (since login is an instance wide limit), which is why we are just cloning the
// instances' limits to pass them on as user_rate_limits later. // instances' limits to pass them on as user_rate_limits later.
let mut shell = let mut shell =
ChorusUser::shell(Rc::new(RefCell::new(self.clone())), "None".to_string()).await; ChorusUser::shell(Arc::new(RwLock::new(self.clone())), "None".to_string()).await;
let login_result = chorus_request let login_result = chorus_request
.deserialize_response::<LoginResult>(&mut shell) .deserialize_response::<LoginResult>(&mut shell)
.await?; .await?;
@ -43,7 +41,7 @@ impl Instance {
identify.token = login_result.token.clone(); identify.token = login_result.token.clone();
gateway.send_identify(identify).await; gateway.send_identify(identify).await;
let user = ChorusUser::new( let user = ChorusUser::new(
Rc::new(RefCell::new(self.clone())), Arc::new(RwLock::new(self.clone())),
login_result.token, login_result.token,
self.clone_limits_if_some(), self.clone_limits_if_some(),
login_result.settings, login_result.settings,

View File

@ -1,5 +1,4 @@
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::{cell::RefCell, rc::Rc};
use reqwest::Client; use reqwest::Client;
use serde_json::to_string; use serde_json::to_string;
@ -35,7 +34,7 @@ impl Instance {
// request (since register is an instance wide limit), which is why we are just cloning // request (since register is an instance wide limit), which is why we are just cloning
// the instances' limits to pass them on as user_rate_limits later. // the instances' limits to pass them on as user_rate_limits later.
let mut shell = let mut shell =
ChorusUser::shell(Rc::new(RefCell::new(self.clone())), "None".to_string()).await; ChorusUser::shell(Arc::new(RwLock::new(self.clone())), "None".to_string()).await;
let token = chorus_request let token = chorus_request
.deserialize_response::<Token>(&mut shell) .deserialize_response::<Token>(&mut shell)
.await? .await?
@ -50,7 +49,7 @@ impl Instance {
identify.token = token.clone(); identify.token = token.clone();
gateway.send_identify(identify).await; gateway.send_identify(identify).await;
let user = ChorusUser::new( let user = ChorusUser::new(
Rc::new(RefCell::new(self.clone())), Arc::new(RwLock::new(self.clone())),
token.clone(), token.clone(),
self.clone_limits_if_some(), self.clone_limits_if_some(),
Arc::new(RwLock::new(settings)), Arc::new(RwLock::new(settings)),

View File

@ -20,7 +20,7 @@ impl Channel {
http::Method::GET, http::Method::GET,
&format!( &format!(
"{}/channels/{}", "{}/channels/{}",
user.belongs_to.borrow().urls.api.clone(), user.belongs_to.read().unwrap().urls.api.clone(),
channel_id channel_id
), ),
None, None,
@ -45,7 +45,11 @@ impl Channel {
audit_log_reason: Option<String>, audit_log_reason: Option<String>,
user: &mut ChorusUser, user: &mut ChorusUser,
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!("{}/channels/{}", user.belongs_to.borrow().urls.api, self.id,); let url = format!(
"{}/channels/{}",
user.belongs_to.read().unwrap().urls.api,
self.id,
);
let request = ChorusRequest::new( let request = ChorusRequest::new(
http::Method::DELETE, http::Method::DELETE,
@ -83,7 +87,7 @@ impl Channel {
let channel_id = self.id; let channel_id = self.id;
let url = format!( let url = format!(
"{}/channels/{}", "{}/channels/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id channel_id
); );
@ -116,7 +120,7 @@ impl Channel {
) -> Result<Vec<Message>, ChorusError> { ) -> Result<Vec<Message>, ChorusError> {
let url = format!( let url = format!(
"{}/channels/{}/messages", "{}/channels/{}/messages",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id channel_id
); );
@ -149,7 +153,7 @@ impl Channel {
let mut request = Client::new() let mut request = Client::new()
.put(format!( .put(format!(
"{}/channels/{}/recipients/{}", "{}/channels/{}/recipients/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.id, self.id,
recipient_id recipient_id
)) ))
@ -177,7 +181,7 @@ impl Channel {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/recipients/{}", "{}/channels/{}/recipients/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.id, self.id,
recipient_id recipient_id
); );
@ -207,7 +211,7 @@ impl Channel {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/guilds/{}/channels", "{}/guilds/{}/channels",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id guild_id
); );

View File

@ -23,7 +23,7 @@ impl Message {
channel_id: Snowflake, channel_id: Snowflake,
mut message: MessageSendSchema, mut message: MessageSendSchema,
) -> ChorusResult<Message> { ) -> ChorusResult<Message> {
let url_api = user.belongs_to.borrow().urls.api.clone(); let url_api = user.belongs_to.read().unwrap().urls.api.clone();
if message.attachments.is_none() { if message.attachments.is_none() {
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
@ -98,7 +98,7 @@ impl Message {
request: Client::new() request: Client::new()
.get(format!( .get(format!(
"{}/{}/messages/search", "{}/{}/messages/search",
&user.belongs_to.borrow().urls.api, &user.belongs_to.read().unwrap().urls.api,
endpoint endpoint
)) ))
.header("Authorization", user.token()) .header("Authorization", user.token())
@ -142,7 +142,7 @@ impl Message {
http::Method::GET, http::Method::GET,
format!( format!(
"{}/channels/{}/pins", "{}/channels/{}/pins",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id channel_id
) )
.as_str(), .as_str(),
@ -172,7 +172,7 @@ impl Message {
http::Method::PUT, http::Method::PUT,
format!( format!(
"{}/channels/{}/pins/{}", "{}/channels/{}/pins/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
message_id message_id
) )
@ -199,7 +199,7 @@ impl Message {
http::Method::DELETE, http::Method::DELETE,
format!( format!(
"{}/channels/{}/pins/{}", "{}/channels/{}/pins/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
message_id message_id
) )
@ -226,7 +226,7 @@ impl Message {
request: Client::new() request: Client::new()
.get(format!( .get(format!(
"{}/channels/{}/messages/{}", "{}/channels/{}/messages/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
message_id message_id
)) ))
@ -249,7 +249,7 @@ impl Message {
http::Method::POST, http::Method::POST,
format!( format!(
"{}/channels/{}/messages/greet", "{}/channels/{}/messages/greet",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
) )
.as_str(), .as_str(),
@ -282,7 +282,7 @@ impl Message {
http::Method::POST, http::Method::POST,
format!( format!(
"{}/channels/{}/messages/{}/ack", "{}/channels/{}/messages/{}/ack",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
message_id message_id
) )
@ -311,7 +311,7 @@ impl Message {
http::Method::POST, http::Method::POST,
format!( format!(
"{}/channels/{}/messages/{}/crosspost", "{}/channels/{}/messages/{}/crosspost",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
message_id message_id
) )
@ -336,7 +336,7 @@ impl Message {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}/hide-guild-feed", "{}/channels/{}/messages/{}/hide-guild-feed",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
message_id message_id
); );
@ -370,7 +370,7 @@ impl Message {
) -> ChorusResult<Message> { ) -> ChorusResult<Message> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}", "{}/channels/{}/messages/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
message_id message_id
); );
@ -396,7 +396,7 @@ impl Message {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}", "{}/channels/{}/messages/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
message_id message_id
); );
@ -438,7 +438,7 @@ impl Message {
http::Method::POST, http::Method::POST,
format!( format!(
"{}/channels/{}/messages/bulk-delete", "{}/channels/{}/messages/bulk-delete",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
) )
.as_str(), .as_str(),
@ -463,7 +463,7 @@ impl Message {
http::Method::POST, http::Method::POST,
format!( format!(
"{}/channels/{}/pins/ack", "{}/channels/{}/pins/ack",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
) )
.as_str(), .as_str(),

View File

@ -28,7 +28,7 @@ impl types::Channel {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/permissions/{}", "{}/channels/{}/permissions/{}",
user.belongs_to.borrow_mut().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
overwrite.id overwrite.id
); );
@ -70,7 +70,7 @@ impl types::Channel {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/permissions/{}", "{}/channels/{}/permissions/{}",
user.belongs_to.borrow_mut().urls.api, user.belongs_to.read().unwrap().urls.api,
channel_id, channel_id,
overwrite_id overwrite_id
); );

View File

@ -23,7 +23,7 @@ impl ReactionMeta {
pub async fn delete_all(&self, user: &mut ChorusUser) -> ChorusResult<()> { pub async fn delete_all(&self, user: &mut ChorusUser) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}/reactions", "{}/channels/{}/messages/{}/reactions",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.channel_id, self.channel_id,
self.message_id self.message_id
); );
@ -51,7 +51,7 @@ impl ReactionMeta {
pub async fn get(&self, emoji: &str, user: &mut ChorusUser) -> ChorusResult<Vec<PublicUser>> { pub async fn get(&self, emoji: &str, user: &mut ChorusUser) -> ChorusResult<Vec<PublicUser>> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}/reactions/{}", "{}/channels/{}/messages/{}/reactions/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.channel_id, self.channel_id,
self.message_id, self.message_id,
emoji emoji
@ -82,7 +82,7 @@ impl ReactionMeta {
pub async fn delete_emoji(&self, emoji: &str, user: &mut ChorusUser) -> ChorusResult<()> { pub async fn delete_emoji(&self, emoji: &str, user: &mut ChorusUser) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}/reactions/{}", "{}/channels/{}/messages/{}/reactions/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.channel_id, self.channel_id,
self.message_id, self.message_id,
emoji emoji
@ -116,7 +116,7 @@ impl ReactionMeta {
pub async fn create(&self, emoji: &str, user: &mut ChorusUser) -> ChorusResult<()> { pub async fn create(&self, emoji: &str, user: &mut ChorusUser) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}/reactions/{}/@me", "{}/channels/{}/messages/{}/reactions/{}/@me",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.channel_id, self.channel_id,
self.message_id, self.message_id,
emoji emoji
@ -145,7 +145,7 @@ impl ReactionMeta {
pub async fn remove(&self, emoji: &str, user: &mut ChorusUser) -> ChorusResult<()> { pub async fn remove(&self, emoji: &str, user: &mut ChorusUser) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}/reactions/{}/@me", "{}/channels/{}/messages/{}/reactions/{}/@me",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.channel_id, self.channel_id,
self.message_id, self.message_id,
emoji emoji
@ -181,7 +181,7 @@ impl ReactionMeta {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/channels/{}/messages/{}/reactions/{}/{}", "{}/channels/{}/messages/{}/reactions/{}/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.channel_id, self.channel_id,
self.message_id, self.message_id,
emoji, emoji,

View File

@ -23,7 +23,7 @@ impl Guild {
user: &mut ChorusUser, user: &mut ChorusUser,
guild_create_schema: GuildCreateSchema, guild_create_schema: GuildCreateSchema,
) -> ChorusResult<Guild> { ) -> ChorusResult<Guild> {
let url = format!("{}/guilds", user.belongs_to.borrow().urls.api); let url = format!("{}/guilds", user.belongs_to.read().unwrap().urls.api);
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
request: Client::new() request: Client::new()
.post(url.clone()) .post(url.clone())
@ -57,7 +57,7 @@ impl Guild {
pub async fn delete(user: &mut ChorusUser, guild_id: Snowflake) -> ChorusResult<()> { pub async fn delete(user: &mut ChorusUser, guild_id: Snowflake) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/guilds/{}/delete", "{}/guilds/{}/delete",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id guild_id
); );
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
@ -99,7 +99,7 @@ impl Guild {
request: Client::new() request: Client::new()
.get(format!( .get(format!(
"{}/guilds/{}/channels", "{}/guilds/{}/channels",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
self.id self.id
)) ))
.header("Authorization", user.token()), .header("Authorization", user.token()),
@ -133,7 +133,7 @@ impl Guild {
request: Client::new() request: Client::new()
.get(format!( .get(format!(
"{}/guilds/{}", "{}/guilds/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id guild_id
)) ))
.header("Authorization", user.token()), .header("Authorization", user.token()),
@ -155,7 +155,7 @@ impl Guild {
http::Method::PUT, http::Method::PUT,
format!( format!(
"{}/guilds/{}/bans/{}", "{}/guilds/{}/bans/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
user_id user_id
) )
@ -180,7 +180,7 @@ impl Guild {
request: Client::new() request: Client::new()
.patch(format!( .patch(format!(
"{}/guilds/{}", "{}/guilds/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
)) ))
.header("Authorization", user.token()) .header("Authorization", user.token())
@ -204,7 +204,7 @@ impl Guild {
request: Client::new() request: Client::new()
.patch(format!( .patch(format!(
"{}/guilds/{}/preview", "{}/guilds/{}/preview",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
)) ))
.header("Authorization", user.token()) .header("Authorization", user.token())
@ -229,7 +229,7 @@ impl Guild {
http::Method::GET, http::Method::GET,
format!( format!(
"{}/guilds/{}/members", "{}/guilds/{}/members",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
) )
.as_str(), .as_str(),
@ -255,7 +255,7 @@ impl Guild {
http::Method::GET, http::Method::GET,
format!( format!(
"{}/guilds/{}/members/search", "{}/guilds/{}/members/search",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
) )
.as_str(), .as_str(),
@ -285,7 +285,7 @@ impl Guild {
http::Method::DELETE, http::Method::DELETE,
format!( format!(
"{}/guilds/{}/members/{}", "{}/guilds/{}/members/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
member_id, member_id,
) )
@ -315,7 +315,7 @@ impl Guild {
http::Method::PATCH, http::Method::PATCH,
format!( format!(
"{}/guilds/{}/members/{}", "{}/guilds/{}/members/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
member_id, member_id,
) )
@ -343,7 +343,7 @@ impl Guild {
http::Method::PATCH, http::Method::PATCH,
format!( format!(
"{}/guilds/{}/members/@me", "{}/guilds/{}/members/@me",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
) )
.as_str(), .as_str(),
@ -369,7 +369,7 @@ impl Guild {
http::Method::PATCH, http::Method::PATCH,
format!( format!(
"{}/guilds/{}/profile/@me", "{}/guilds/{}/profile/@me",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
) )
.as_str(), .as_str(),
@ -395,7 +395,7 @@ impl Guild {
) -> ChorusResult<Vec<GuildBan>> { ) -> ChorusResult<Vec<GuildBan>> {
let url = format!( let url = format!(
"{}/guilds/{}/bans", "{}/guilds/{}/bans",
user.belongs_to.borrow_mut().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
); );
@ -425,7 +425,7 @@ impl Guild {
) -> ChorusResult<GuildBan> { ) -> ChorusResult<GuildBan> {
let url = format!( let url = format!(
"{}/guilds/{}/bans/{}", "{}/guilds/{}/bans/{}",
user.belongs_to.borrow_mut().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
user_id user_id
); );
@ -454,7 +454,7 @@ impl Guild {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/guilds/{}/bans/{}", "{}/guilds/{}/bans/{}",
user.belongs_to.borrow_mut().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
user_id user_id
); );
@ -488,7 +488,7 @@ impl Channel {
let mut request = Client::new() let mut request = Client::new()
.post(format!( .post(format!(
"{}/guilds/{}/channels", "{}/guilds/{}/channels",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id guild_id
)) ))
.header("Authorization", user.token()) .header("Authorization", user.token())

View File

@ -20,7 +20,7 @@ impl types::GuildMember {
) -> ChorusResult<GuildMember> { ) -> ChorusResult<GuildMember> {
let url = format!( let url = format!(
"{}/guilds/{}/members/{}", "{}/guilds/{}/members/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
member_id member_id
); );
@ -47,7 +47,7 @@ impl types::GuildMember {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/guilds/{}/members/{}/roles/{}", "{}/guilds/{}/members/{}/roles/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
member_id, member_id,
role_id role_id
@ -76,7 +76,7 @@ impl types::GuildMember {
) -> Result<(), crate::errors::ChorusError> { ) -> Result<(), crate::errors::ChorusError> {
let url = format!( let url = format!(
"{}/guilds/{}/members/{}/roles/{}", "{}/guilds/{}/members/{}/roles/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
member_id, member_id,
role_id role_id

View File

@ -20,7 +20,7 @@ impl types::RoleObject {
) -> ChorusResult<Vec<RoleObject>> { ) -> ChorusResult<Vec<RoleObject>> {
let url = format!( let url = format!(
"{}/guilds/{}/roles", "{}/guilds/{}/roles",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id guild_id
); );
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
@ -45,7 +45,7 @@ impl types::RoleObject {
) -> ChorusResult<RoleObject> { ) -> ChorusResult<RoleObject> {
let url = format!( let url = format!(
"{}/guilds/{}/roles/{}", "{}/guilds/{}/roles/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
role_id role_id
); );
@ -71,7 +71,7 @@ impl types::RoleObject {
) -> ChorusResult<RoleObject> { ) -> ChorusResult<RoleObject> {
let url = format!( let url = format!(
"{}/guilds/{}/roles", "{}/guilds/{}/roles",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id guild_id
); );
let body = to_string::<RoleCreateModifySchema>(&role_create_schema).map_err(|e| { let body = to_string::<RoleCreateModifySchema>(&role_create_schema).map_err(|e| {
@ -105,7 +105,7 @@ impl types::RoleObject {
) -> ChorusResult<RoleObject> { ) -> ChorusResult<RoleObject> {
let url = format!( let url = format!(
"{}/guilds/{}/roles", "{}/guilds/{}/roles",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id guild_id
); );
let body = let body =
@ -139,7 +139,7 @@ impl types::RoleObject {
) -> ChorusResult<RoleObject> { ) -> ChorusResult<RoleObject> {
let url = format!( let url = format!(
"{}/guilds/{}/roles/{}", "{}/guilds/{}/roles/{}",
user.belongs_to.borrow().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
role_id role_id
); );
@ -173,7 +173,7 @@ impl types::RoleObject {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/guilds/{}/roles/{}", "{}/guilds/{}/roles/{}",
user.belongs_to.borrow_mut().urls.api, user.belongs_to.read().unwrap().urls.api,
guild_id, guild_id,
role_id role_id
); );

View File

@ -22,7 +22,7 @@ impl ChorusUser {
request: Client::new() request: Client::new()
.post(format!( .post(format!(
"{}/invites/{}", "{}/invites/{}",
self.belongs_to.borrow().urls.api, self.belongs_to.read().unwrap().urls.api,
invite_code invite_code
)) ))
.header("Authorization", self.token()), .header("Authorization", self.token()),
@ -48,7 +48,7 @@ impl ChorusUser {
request: Client::new() request: Client::new()
.post(format!( .post(format!(
"{}/users/@me/invites", "{}/users/@me/invites",
self.belongs_to.borrow().urls.api self.belongs_to.read().unwrap().urls.api
)) ))
.body(to_string(&code).unwrap()) .body(to_string(&code).unwrap())
.header("Authorization", self.token()) .header("Authorization", self.token())
@ -75,7 +75,7 @@ impl ChorusUser {
request: Client::new() request: Client::new()
.post(format!( .post(format!(
"{}/channels/{}/invites", "{}/channels/{}/invites",
self.belongs_to.borrow().urls.api, self.belongs_to.read().unwrap().urls.api,
channel_id channel_id
)) ))
.header("Authorization", self.token()) .header("Authorization", self.token())

View File

@ -21,7 +21,10 @@ impl ChorusUser {
&mut self, &mut self,
create_private_channel_schema: PrivateChannelCreateSchema, create_private_channel_schema: PrivateChannelCreateSchema,
) -> ChorusResult<Channel> { ) -> ChorusResult<Channel> {
let url = format!("{}/users/@me/channels", self.belongs_to.borrow().urls.api); let url = format!(
"{}/users/@me/channels",
self.belongs_to.read().unwrap().urls.api
);
ChorusRequest { ChorusRequest {
request: Client::new() request: Client::new()
.post(url) .post(url)

View File

@ -20,7 +20,7 @@ impl ChorusUser {
request: Client::new() request: Client::new()
.delete(format!( .delete(format!(
"{}/users/@me/guilds/{}", "{}/users/@me/guilds/{}",
self.belongs_to.borrow().urls.api, self.belongs_to.read().unwrap().urls.api,
guild_id guild_id
)) ))
.header("Authorization", self.token()) .header("Authorization", self.token())
@ -41,7 +41,10 @@ impl ChorusUser {
&mut self, &mut self,
query: Option<GetUserGuildSchema>, query: Option<GetUserGuildSchema>,
) -> ChorusResult<Vec<Guild>> { ) -> ChorusResult<Vec<Guild>> {
let url = format!("{}/users/@me/guilds", self.belongs_to.borrow().urls.api,); let url = format!(
"{}/users/@me/guilds",
self.belongs_to.read().unwrap().urls.api,
);
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
request: Client::new() request: Client::new()
.get(url) .get(url)

View File

@ -22,7 +22,7 @@ impl ChorusUser {
) -> ChorusResult<Vec<types::PublicUser>> { ) -> ChorusResult<Vec<types::PublicUser>> {
let url = format!( let url = format!(
"{}/users/{}/relationships", "{}/users/{}/relationships",
self.belongs_to.borrow().urls.api, self.belongs_to.read().unwrap().urls.api,
user_id user_id
); );
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
@ -41,7 +41,7 @@ impl ChorusUser {
pub async fn get_relationships(&mut self) -> ChorusResult<Vec<types::Relationship>> { pub async fn get_relationships(&mut self) -> ChorusResult<Vec<types::Relationship>> {
let url = format!( let url = format!(
"{}/users/@me/relationships", "{}/users/@me/relationships",
self.belongs_to.borrow().urls.api self.belongs_to.read().unwrap().urls.api
); );
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
request: Client::new().get(url).header("Authorization", self.token()), request: Client::new().get(url).header("Authorization", self.token()),
@ -62,7 +62,7 @@ impl ChorusUser {
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/users/@me/relationships", "{}/users/@me/relationships",
self.belongs_to.borrow().urls.api self.belongs_to.read().unwrap().urls.api
); );
let body = to_string(&schema).unwrap(); let body = to_string(&schema).unwrap();
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
@ -84,7 +84,7 @@ impl ChorusUser {
user_id: Snowflake, user_id: Snowflake,
relationship_type: RelationshipType, relationship_type: RelationshipType,
) -> ChorusResult<()> { ) -> ChorusResult<()> {
let api_url = self.belongs_to.borrow().urls.api.clone(); let api_url = self.belongs_to.read().unwrap().urls.api.clone();
match relationship_type { match relationship_type {
RelationshipType::None => { RelationshipType::None => {
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
@ -136,7 +136,7 @@ impl ChorusUser {
pub async fn remove_relationship(&mut self, user_id: Snowflake) -> ChorusResult<()> { pub async fn remove_relationship(&mut self, user_id: Snowflake) -> ChorusResult<()> {
let url = format!( let url = format!(
"{}/users/@me/relationships/{}", "{}/users/@me/relationships/{}",
self.belongs_to.borrow().urls.api, self.belongs_to.read().unwrap().urls.api,
user_id user_id
); );
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {

View File

@ -1,4 +1,4 @@
use std::{cell::RefCell, rc::Rc}; use std::sync::{Arc, RwLock};
use reqwest::Client; use reqwest::Client;
use serde_json::to_string; use serde_json::to_string;
@ -48,7 +48,10 @@ impl ChorusUser {
return Err(ChorusError::PasswordRequired); return Err(ChorusError::PasswordRequired);
} }
let request = Client::new() let request = Client::new()
.patch(format!("{}/users/@me", self.belongs_to.borrow().urls.api)) .patch(format!(
"{}/users/@me",
self.belongs_to.read().unwrap().urls.api
))
.body(to_string(&modify_schema).unwrap()) .body(to_string(&modify_schema).unwrap())
.header("Authorization", self.token()) .header("Authorization", self.token())
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
@ -67,7 +70,7 @@ impl ChorusUser {
let request = Client::new() let request = Client::new()
.post(format!( .post(format!(
"{}/users/@me/delete", "{}/users/@me/delete",
self.belongs_to.borrow().urls.api self.belongs_to.read().unwrap().urls.api
)) ))
.header("Authorization", self.token()) .header("Authorization", self.token())
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
@ -86,7 +89,7 @@ impl User {
/// See <https://discord-userdoccers.vercel.app/resources/user#get-user> and /// See <https://discord-userdoccers.vercel.app/resources/user#get-user> and
/// <https://discord-userdoccers.vercel.app/resources/user#get-current-user> /// <https://discord-userdoccers.vercel.app/resources/user#get-current-user>
pub async fn get(user: &mut ChorusUser, id: Option<&String>) -> ChorusResult<User> { pub async fn get(user: &mut ChorusUser, id: Option<&String>) -> ChorusResult<User> {
let url_api = user.belongs_to.borrow().urls.api.clone(); let url_api = user.belongs_to.read().unwrap().urls.api.clone();
let url = if id.is_none() { let url = if id.is_none() {
format!("{}/users/@me", url_api) format!("{}/users/@me", url_api)
} else { } else {
@ -121,7 +124,7 @@ impl User {
.get(format!("{}/users/@me/settings", url_api)) .get(format!("{}/users/@me/settings", url_api))
.header("Authorization", token); .header("Authorization", token);
let mut user = let mut user =
ChorusUser::shell(Rc::new(RefCell::new(instance.clone())), token.clone()).await; ChorusUser::shell(Arc::new(RwLock::new(instance.clone())), token.clone()).await;
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
request, request,
limit_type: LimitType::Global, limit_type: LimitType::Global,
@ -131,8 +134,12 @@ impl User {
Err(e) => Err(e), Err(e) => Err(e),
}; };
if instance.limits_information.is_some() { if instance.limits_information.is_some() {
instance.limits_information.as_mut().unwrap().ratelimits = instance.limits_information.as_mut().unwrap().ratelimits = user
user.belongs_to.borrow().clone_limits_if_some().unwrap(); .belongs_to
.read()
.unwrap()
.clone_limits_if_some()
.unwrap();
} }
result result
} }
@ -148,11 +155,15 @@ impl Instance {
/// See <https://discord-userdoccers.vercel.app/resources/user#get-user> and /// See <https://discord-userdoccers.vercel.app/resources/user#get-user> and
/// <https://discord-userdoccers.vercel.app/resources/user#get-current-user> /// <https://discord-userdoccers.vercel.app/resources/user#get-current-user>
pub async fn get_user(&mut self, token: String, id: Option<&String>) -> ChorusResult<User> { pub async fn get_user(&mut self, token: String, id: Option<&String>) -> ChorusResult<User> {
let mut user = ChorusUser::shell(Rc::new(RefCell::new(self.clone())), token).await; let mut user = ChorusUser::shell(Arc::new(RwLock::new(self.clone())), token).await;
let result = User::get(&mut user, id).await; let result = User::get(&mut user, id).await;
if self.limits_information.is_some() { if self.limits_information.is_some() {
self.limits_information.as_mut().unwrap().ratelimits = self.limits_information.as_mut().unwrap().ratelimits = user
user.belongs_to.borrow().clone_limits_if_some().unwrap(); .belongs_to
.read()
.unwrap()
.clone_limits_if_some()
.unwrap();
} }
result result
} }

View File

@ -1,9 +1,8 @@
//! Instance and ChorusUser objects. //! Instance and ChorusUser objects.
use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::rc::Rc;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use reqwest::Client; use reqwest::Client;
@ -90,7 +89,7 @@ impl fmt::Display for Token {
/// It is used for most authenticated actions on a Spacebar server. /// It is used for most authenticated actions on a Spacebar server.
/// It also has its own [Gateway] connection. /// It also has its own [Gateway] connection.
pub struct ChorusUser { pub struct ChorusUser {
pub belongs_to: Rc<RefCell<Instance>>, pub belongs_to: Arc<RwLock<Instance>>,
pub token: String, pub token: String,
pub limits: Option<HashMap<LimitType, Limit>>, pub limits: Option<HashMap<LimitType, Limit>>,
pub settings: Arc<RwLock<UserSettings>>, pub settings: Arc<RwLock<UserSettings>>,
@ -113,7 +112,7 @@ impl ChorusUser {
/// This isn't the prefered way to create a ChorusUser. /// This isn't the prefered way to create a ChorusUser.
/// See [Instance::login_account] and [Instance::register_account] instead. /// See [Instance::login_account] and [Instance::register_account] instead.
pub fn new( pub fn new(
belongs_to: Rc<RefCell<Instance>>, belongs_to: Arc<RwLock<Instance>>,
token: String, token: String,
limits: Option<HashMap<LimitType, Limit>>, limits: Option<HashMap<LimitType, Limit>>,
settings: Arc<RwLock<UserSettings>>, settings: Arc<RwLock<UserSettings>>,
@ -135,17 +134,18 @@ impl ChorusUser {
/// registering or logging in to the Instance, where you do not yet have a User object, but still /// registering or logging in to the Instance, where you do not yet have a User object, but still
/// need to make a RateLimited request. To use the [`GatewayHandle`], you will have to identify /// need to make a RateLimited request. To use the [`GatewayHandle`], you will have to identify
/// first. /// first.
pub(crate) async fn shell(instance: Rc<RefCell<Instance>>, token: String) -> ChorusUser { pub(crate) async fn shell(instance: Arc<RwLock<Instance>>, token: String) -> ChorusUser {
let settings = Arc::new(RwLock::new(UserSettings::default())); let settings = Arc::new(RwLock::new(UserSettings::default()));
let object = Arc::new(RwLock::new(User::default())); let object = Arc::new(RwLock::new(User::default()));
let wss_url = instance.borrow().urls.wss.clone(); let wss_url = instance.read().unwrap().urls.wss.clone();
// Dummy gateway object // Dummy gateway object
let gateway = Gateway::new(wss_url).await.unwrap(); let gateway = Gateway::new(wss_url).await.unwrap();
ChorusUser { ChorusUser {
token, token,
belongs_to: instance.clone(), belongs_to: instance.clone(),
limits: instance limits: instance
.borrow() .read()
.unwrap()
.limits_information .limits_information
.as_ref() .as_ref()
.map(|info| info.ratelimits.clone()), .map(|info| info.ratelimits.clone()),

View File

@ -82,12 +82,8 @@ impl ChorusRequest {
bucket: format!("{:?}", self.limit_type), bucket: format!("{:?}", self.limit_type),
}); });
} }
let belongs_to = user.belongs_to.borrow(); let client = user.belongs_to.read().unwrap().client.clone();
let result = match belongs_to let result = match client.execute(self.request.build().unwrap()).await {
.client
.execute(self.request.build().unwrap())
.await
{
Ok(result) => { Ok(result) => {
debug!("Request successful: {:?}", result); debug!("Request successful: {:?}", result);
result result
@ -100,12 +96,13 @@ impl ChorusRequest {
}); });
} }
}; };
drop(belongs_to); drop(client);
if !result.status().is_success() { if !result.status().is_success() {
if result.status().as_u16() == 429 { if result.status().as_u16() == 429 {
log::warn!("Rate limit hit unexpectedly. Bucket: {:?}. Setting the instances' remaining global limit to 0 to have cooldown.", self.limit_type); log::warn!("Rate limit hit unexpectedly. Bucket: {:?}. Setting the instances' remaining global limit to 0 to have cooldown.", self.limit_type);
user.belongs_to user.belongs_to
.borrow_mut() .write()
.unwrap()
.limits_information .limits_information
.as_mut() .as_mut()
.unwrap() .unwrap()
@ -126,7 +123,7 @@ impl ChorusRequest {
fn can_send_request(user: &mut ChorusUser, limit_type: &LimitType) -> bool { fn can_send_request(user: &mut ChorusUser, limit_type: &LimitType) -> bool {
log::trace!("Checking if user or instance is rate-limited..."); log::trace!("Checking if user or instance is rate-limited...");
let mut belongs_to = user.belongs_to.borrow_mut(); let mut belongs_to = user.belongs_to.write().unwrap();
if belongs_to.limits_information.is_none() { if belongs_to.limits_information.is_none() {
log::trace!("Instance indicates no rate limits are configured. Continuing."); log::trace!("Instance indicates no rate limits are configured. Continuing.");
return true; return true;
@ -288,7 +285,7 @@ impl ChorusRequest {
/// reset to the rate limit limit. /// reset to the rate limit limit.
/// 2. The remaining rate limit is decreased by 1. /// 2. The remaining rate limit is decreased by 1.
fn update_rate_limits(user: &mut ChorusUser, limit_type: &LimitType, response_was_err: bool) { fn update_rate_limits(user: &mut ChorusUser, limit_type: &LimitType, response_was_err: bool) {
if user.belongs_to.borrow().limits_information.is_none() { if user.belongs_to.read().unwrap().limits_information.is_none() {
return; return;
} }
let instance_dictated_limits = [ let instance_dictated_limits = [
@ -311,7 +308,7 @@ impl ChorusRequest {
} }
let time: u64 = chrono::Utc::now().timestamp() as u64; let time: u64 = chrono::Utc::now().timestamp() as u64;
for relevant_limit in relevant_limits.iter() { for relevant_limit in relevant_limits.iter() {
let mut belongs_to = user.belongs_to.borrow_mut(); let mut belongs_to = user.belongs_to.write().unwrap();
let limit = match relevant_limit.0 { let limit = match relevant_limit.0 {
LimitOrigin::Instance => { LimitOrigin::Instance => {
log::trace!( log::trace!(