Merge branch 'main' into refactor/rename-apierror
This commit is contained in:
commit
8ccd6a8d4b
|
@ -1,5 +1,5 @@
|
||||||
[hooks]
|
[hooks]
|
||||||
pre-push = "cargo fmt --all -- --check --color always"
|
pre-commit = "cargo fmt -p chorus && exit 0"
|
||||||
|
|
||||||
[logging]
|
[logging]
|
||||||
verbose = true
|
verbose = true
|
||||||
|
|
|
@ -39,10 +39,10 @@
|
||||||
|
|
||||||
### Messaging
|
### Messaging
|
||||||
- [x] [Sending messages](https://github.com/polyphony-chat/chorus/issues/23)
|
- [x] [Sending messages](https://github.com/polyphony-chat/chorus/issues/23)
|
||||||
- [ ] [Events (Message, User, Channel, etc.)](https://github.com/polyphony-chat/chorus/issues/51)
|
- [x] [Events (Message, User, Channel, etc.)](https://github.com/polyphony-chat/chorus/issues/51)
|
||||||
- [x] Channel creation
|
- [x] Channel creation
|
||||||
- [x] Channel deletion
|
- [x] Channel deletion
|
||||||
- [ ] Channel management (name, description, icon, etc.)
|
- [x] [Channel management (name, description, icon, etc.)](https://github.com/polyphony-chat/chorus/issues/48)
|
||||||
- [ ] Deleting messages
|
- [ ] Deleting messages
|
||||||
- [ ] Message threads
|
- [ ] Message threads
|
||||||
- [ ] Reactions
|
- [ ] Reactions
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
use chorus::{
|
||||||
|
self,
|
||||||
|
gateway::{Gateway, Observer},
|
||||||
|
types::{GatewayIdentifyPayload, GatewayReady},
|
||||||
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::{self, sync::Mutex};
|
||||||
|
|
||||||
|
// This example creates a simple gateway connection and a basic observer struct
|
||||||
|
|
||||||
|
// Due to certain limitations all observers must impl debug
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ExampleObserver {}
|
||||||
|
|
||||||
|
// This struct can observe GatewayReady events when subscribed, because it implements the trait Observer<GatewayReady>.
|
||||||
|
// The Observer trait can be implemented for a struct for a given websocketevent to handle observing it
|
||||||
|
// One struct can be an observer of multiple websocketevents, if needed
|
||||||
|
impl Observer<GatewayReady> for ExampleObserver {
|
||||||
|
// After we subscribe to an event this function is called every time we receive it
|
||||||
|
fn update(&self, data: &GatewayReady) {
|
||||||
|
println!("Observed Ready!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
// Find the gateway websocket url of the server we want to connect to
|
||||||
|
let websocket_url_spacebar = "wss://gateway.old.server.spacebar.chat/".to_string();
|
||||||
|
|
||||||
|
// Initiate the gateway connection
|
||||||
|
let gateway = Gateway::new(websocket_url_spacebar).await.unwrap();
|
||||||
|
|
||||||
|
// 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<Mutex>
|
||||||
|
let shared_observer = Arc::new(Mutex::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
|
||||||
|
gateway
|
||||||
|
.events
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.session
|
||||||
|
.ready
|
||||||
|
.subscribe(shared_observer)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Authenticate so we will receive any events
|
||||||
|
let token = "SecretToken".to_string();
|
||||||
|
let mut identify = GatewayIdentifyPayload::common();
|
||||||
|
identify.token = token;
|
||||||
|
gateway.send_identify(identify).await;
|
||||||
|
|
||||||
|
// Do something on the main thread so we don't quit
|
||||||
|
loop {}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
use chorus::{self, gateway::Gateway, types::GatewayIdentifyPayload};
|
||||||
|
use tokio;
|
||||||
|
|
||||||
|
/// This example creates a simple gateway connection and a session with an Identify event
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
// Find the gateway websocket url of the server we want to connect to
|
||||||
|
let websocket_url_spacebar = "wss://gateway.old.server.spacebar.chat/".to_string();
|
||||||
|
|
||||||
|
// Initiate the gateway connection, starting a listener in one thread and a heartbeat handler in another
|
||||||
|
let gateway = Gateway::new(websocket_url_spacebar).await.unwrap();
|
||||||
|
|
||||||
|
// At this point, we are connected to the server and are sending heartbeats, however we still haven't authenticated
|
||||||
|
|
||||||
|
// Get a token for an account on the server
|
||||||
|
let token = "SecretToken".to_string();
|
||||||
|
|
||||||
|
// Create an identify event
|
||||||
|
// An Identify event is how the server authenticates us and gets info about our os and browser, along with our intents / capabilities
|
||||||
|
// (Chorus never sends real telemetry data about your system to servers, always just using the most common option or a custom set one)
|
||||||
|
// By default the capabilities requests all the data of a regular client
|
||||||
|
let mut identify = GatewayIdentifyPayload::common();
|
||||||
|
|
||||||
|
identify.token = token;
|
||||||
|
|
||||||
|
// Send off the event
|
||||||
|
gateway.send_identify(identify).await;
|
||||||
|
|
||||||
|
// Do something on the main thread so we don't quit
|
||||||
|
loop {}
|
||||||
|
}
|
|
@ -48,7 +48,6 @@ pub mod register {
|
||||||
let response_unwrap = response.unwrap();
|
let response_unwrap = response.unwrap();
|
||||||
let status = response_unwrap.status();
|
let status = response_unwrap.status();
|
||||||
let response_unwrap_text = response_unwrap.text().await.unwrap();
|
let response_unwrap_text = response_unwrap.text().await.unwrap();
|
||||||
println!("{}", response_unwrap_text);
|
|
||||||
let token = from_str::<Token>(&response_unwrap_text).unwrap();
|
let token = from_str::<Token>(&response_unwrap_text).unwrap();
|
||||||
let token = token.token;
|
let token = token.token;
|
||||||
if status.is_client_error() {
|
if status.is_client_error() {
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::from_str;
|
use serde_json::{from_str, to_string};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::limits::Limits, errors::InstanceServerError, limit::LimitedRequester, types::Channel,
|
api::limits::Limits,
|
||||||
|
errors::InstanceServerError,
|
||||||
|
limit::LimitedRequester,
|
||||||
|
types::{Channel, ChannelModifySchema},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
|
@ -38,4 +41,84 @@ impl Channel {
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deletes a channel.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `token` - A string slice that holds the authorization token.
|
||||||
|
/// * `url_api` - A string slice that holds the URL of the API.
|
||||||
|
/// * `channel` - A `Channel` object that represents the channel to be deleted.
|
||||||
|
/// * `limits_user` - A mutable reference to a `Limits` object that represents the user's rate limits.
|
||||||
|
/// * `limits_instance` - A mutable reference to a `Limits` object that represents the instance's rate limits.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// An `Option` that contains an `InstanceServerError` if an error occurred during the request, or `None` if the request was successful.
|
||||||
|
pub async fn delete(
|
||||||
|
self,
|
||||||
|
token: &str,
|
||||||
|
url_api: &str,
|
||||||
|
limits_user: &mut Limits,
|
||||||
|
limits_instance: &mut Limits,
|
||||||
|
) -> Option<InstanceServerError> {
|
||||||
|
let request = Client::new()
|
||||||
|
.delete(format!("{}/channels/{}/", url_api, self.id.to_string()))
|
||||||
|
.bearer_auth(token);
|
||||||
|
match LimitedRequester::new()
|
||||||
|
.await
|
||||||
|
.send_request(
|
||||||
|
request,
|
||||||
|
crate::api::limits::LimitType::Channel,
|
||||||
|
limits_instance,
|
||||||
|
limits_user,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => None,
|
||||||
|
Err(e) => return Some(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifies a channel.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `modify_data` - A `ChannelModifySchema` object that represents the modifications to be made to the channel.
|
||||||
|
/// * `token` - A string slice that holds the authorization token.
|
||||||
|
/// * `url_api` - A string slice that holds the URL of the API.
|
||||||
|
/// * `channel_id` - A string slice that holds the ID of the channel to be modified.
|
||||||
|
/// * `limits_user` - A mutable reference to a `Limits` object that represents the user's rate limits.
|
||||||
|
/// * `limits_instance` - A mutable reference to a `Limits` object that represents the instance's rate limits.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// A `Result` that contains a `Channel` object if the request was successful, or an `InstanceServerError` if an error occurred during the request.
|
||||||
|
pub async fn modify(
|
||||||
|
modify_data: ChannelModifySchema,
|
||||||
|
token: &str,
|
||||||
|
url_api: &str,
|
||||||
|
channel_id: &str,
|
||||||
|
limits_user: &mut Limits,
|
||||||
|
limits_instance: &mut Limits,
|
||||||
|
) -> Result<Channel, InstanceServerError> {
|
||||||
|
let request = Client::new()
|
||||||
|
.patch(format!("{}/channels/{}/", url_api, channel_id))
|
||||||
|
.bearer_auth(token)
|
||||||
|
.body(to_string(&modify_data).unwrap());
|
||||||
|
let channel = match LimitedRequester::new()
|
||||||
|
.await
|
||||||
|
.send_request(
|
||||||
|
request,
|
||||||
|
crate::api::limits::LimitType::Channel,
|
||||||
|
limits_instance,
|
||||||
|
limits_user,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(channel) => from_str::<Channel>(&channel.text().await.unwrap()).unwrap(),
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
Ok(channel)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,8 +78,6 @@ pub mod messages {
|
||||||
.bearer_auth(token)
|
.bearer_auth(token)
|
||||||
.multipart(form);
|
.multipart(form);
|
||||||
|
|
||||||
println!("[Request Headers: ] {:?}", message_request);
|
|
||||||
|
|
||||||
requester
|
requester
|
||||||
.send_request(
|
.send_request(
|
||||||
message_request,
|
message_request,
|
||||||
|
|
|
@ -19,32 +19,20 @@ impl Guild {
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// A `Result<String>` containing the ID of the newly created guild, or an error if the request fails.
|
/// A `Result<Guild>` containing the object of the newly created guild, or an error if the request fails.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// Returns an `InstanceServerError` if the request fails.
|
/// Returns an `InstanceServerError` if the request fails.
|
||||||
///
|
///
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rs
|
|
||||||
/// let guild_create_schema = chorus::api::schemas::GuildCreateSchema::new(insert args here);
|
|
||||||
///
|
|
||||||
/// let result = Guild::create(&mut user, &mut instance, &guild_create_schema).await;
|
|
||||||
///
|
|
||||||
/// match result {
|
|
||||||
/// Ok(guild_id) => println!("Created guild with ID {}", guild_id),
|
|
||||||
/// Err(e) => println!("Failed to create guild: {}", e),
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub async fn create(
|
pub async fn create(
|
||||||
user: &mut UserMeta,
|
user: &mut UserMeta,
|
||||||
url_api: &str,
|
url_api: &str,
|
||||||
guild_create_schema: GuildCreateSchema,
|
guild_create_schema: GuildCreateSchema,
|
||||||
) -> Result<String, crate::errors::InstanceServerError> {
|
) -> Result<Guild, crate::errors::InstanceServerError> {
|
||||||
let url = format!("{}/guilds/", url_api);
|
let url = format!("{}/guilds/", url_api);
|
||||||
let limits_user = user.limits.get_as_mut();
|
let mut limits_user = user.limits.get_as_mut();
|
||||||
let limits_instance = &mut user.belongs_to.borrow_mut().limits;
|
let mut limits_instance = &mut user.belongs_to.borrow_mut().limits;
|
||||||
let request = reqwest::Client::new()
|
let request = reqwest::Client::new()
|
||||||
.post(url.clone())
|
.post(url.clone())
|
||||||
.bearer_auth(user.token.clone())
|
.bearer_auth(user.token.clone())
|
||||||
|
@ -63,7 +51,16 @@ impl Guild {
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
let id: GuildCreateResponse = from_str(&result.text().await.unwrap()).unwrap();
|
let id: GuildCreateResponse = from_str(&result.text().await.unwrap()).unwrap();
|
||||||
Ok(id.id)
|
let guild = Guild::get(
|
||||||
|
url_api,
|
||||||
|
&id.id,
|
||||||
|
&user.token,
|
||||||
|
&mut limits_user,
|
||||||
|
&mut limits_instance,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
Ok(guild)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes a guild.
|
/// Deletes a guild.
|
||||||
|
@ -93,7 +90,7 @@ impl Guild {
|
||||||
pub async fn delete(
|
pub async fn delete(
|
||||||
user: &mut UserMeta,
|
user: &mut UserMeta,
|
||||||
url_api: &str,
|
url_api: &str,
|
||||||
guild_id: String,
|
guild_id: &str,
|
||||||
) -> Option<InstanceServerError> {
|
) -> Option<InstanceServerError> {
|
||||||
let url = format!("{}/guilds/{}/delete/", url_api, guild_id);
|
let url = format!("{}/guilds/{}/delete/", url_api, guild_id);
|
||||||
let limits_user = user.limits.get_as_mut();
|
let limits_user = user.limits.get_as_mut();
|
||||||
|
@ -148,6 +145,97 @@ impl Guild {
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a `Result` containing a vector of `Channel` structs if the request was successful, or an `InstanceServerError` if there was an error.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `url_api` - A string slice that holds the URL of the API.
|
||||||
|
/// * `token` - A string slice that holds the authorization token.
|
||||||
|
/// * `limits_user` - A mutable reference to a `Limits` struct containing the user's rate limits.
|
||||||
|
/// * `limits_instance` - A mutable reference to a `Limits` struct containing the instance's rate limits.
|
||||||
|
///
|
||||||
|
pub async fn channels(
|
||||||
|
&self,
|
||||||
|
url_api: &str,
|
||||||
|
token: &str,
|
||||||
|
limits_user: &mut Limits,
|
||||||
|
limits_instance: &mut Limits,
|
||||||
|
) -> Result<Vec<Channel>, InstanceServerError> {
|
||||||
|
let request = Client::new()
|
||||||
|
.get(format!(
|
||||||
|
"{}/guilds/{}/channels/",
|
||||||
|
url_api,
|
||||||
|
self.id.to_string()
|
||||||
|
))
|
||||||
|
.bearer_auth(token);
|
||||||
|
let result = match LimitedRequester::new()
|
||||||
|
.await
|
||||||
|
.send_request(
|
||||||
|
request,
|
||||||
|
crate::api::limits::LimitType::Guild,
|
||||||
|
limits_instance,
|
||||||
|
limits_user,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(result) => result,
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
let stringed_response = match result.text().await {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(InstanceServerError::InvalidResponseError {
|
||||||
|
error: e.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _: Vec<Channel> = match from_str(&stringed_response) {
|
||||||
|
Ok(result) => return Ok(result),
|
||||||
|
Err(e) => {
|
||||||
|
return Err(InstanceServerError::InvalidResponseError {
|
||||||
|
error: e.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a `Result` containing a `Guild` struct if the request was successful, or an `InstanceServerError` if there was an error.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `url_api` - A string slice that holds the URL of the API.
|
||||||
|
/// * `guild_id` - A string slice that holds the ID of the guild.
|
||||||
|
/// * `token` - A string slice that holds the authorization token.
|
||||||
|
/// * `limits_user` - A mutable reference to a `Limits` struct containing the user's rate limits.
|
||||||
|
/// * `limits_instance` - A mutable reference to a `Limits` struct containing the instance's rate limits.
|
||||||
|
///
|
||||||
|
pub async fn get(
|
||||||
|
url_api: &str,
|
||||||
|
guild_id: &str,
|
||||||
|
token: &str,
|
||||||
|
limits_user: &mut Limits,
|
||||||
|
limits_instance: &mut Limits,
|
||||||
|
) -> Result<Guild, InstanceServerError> {
|
||||||
|
let request = Client::new()
|
||||||
|
.get(format!("{}/guilds/{}/", url_api, guild_id))
|
||||||
|
.bearer_auth(token);
|
||||||
|
let response = match LimitedRequester::new()
|
||||||
|
.await
|
||||||
|
.send_request(
|
||||||
|
request,
|
||||||
|
crate::api::limits::LimitType::Guild,
|
||||||
|
limits_instance,
|
||||||
|
limits_user,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(response) => response,
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
let guild: Guild = from_str(&response.text().await.unwrap()).unwrap();
|
||||||
|
Ok(guild)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
|
|
|
@ -26,30 +26,7 @@ impl UserMeta {
|
||||||
id: Option<&String>,
|
id: Option<&String>,
|
||||||
instance_limits: &mut Limits,
|
instance_limits: &mut Limits,
|
||||||
) -> Result<User, InstanceServerError> {
|
) -> Result<User, InstanceServerError> {
|
||||||
let url: String;
|
User::get(token, url_api, id, instance_limits).await
|
||||||
if id.is_none() {
|
|
||||||
url = format!("{}/users/@me/", url_api);
|
|
||||||
} else {
|
|
||||||
url = format!("{}/users/{}", url_api, id.unwrap());
|
|
||||||
}
|
|
||||||
let request = reqwest::Client::new().get(url).bearer_auth(token);
|
|
||||||
let mut requester = crate::limit::LimitedRequester::new().await;
|
|
||||||
let mut cloned_limits = instance_limits.clone();
|
|
||||||
match requester
|
|
||||||
.send_request(
|
|
||||||
request,
|
|
||||||
crate::api::limits::LimitType::Ip,
|
|
||||||
instance_limits,
|
|
||||||
&mut cloned_limits,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(result) => {
|
|
||||||
let result_text = result.text().await.unwrap();
|
|
||||||
Ok(serde_json::from_str::<User>(&result_text).unwrap())
|
|
||||||
}
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_settings(
|
pub async fn get_settings(
|
||||||
|
@ -57,23 +34,7 @@ impl UserMeta {
|
||||||
url_api: &String,
|
url_api: &String,
|
||||||
instance_limits: &mut Limits,
|
instance_limits: &mut Limits,
|
||||||
) -> Result<UserSettings, InstanceServerError> {
|
) -> Result<UserSettings, InstanceServerError> {
|
||||||
let request: reqwest::RequestBuilder = Client::new()
|
User::get_settings(token, url_api, instance_limits).await
|
||||||
.get(format!("{}/users/@me/settings/", url_api))
|
|
||||||
.bearer_auth(token);
|
|
||||||
let mut cloned_limits = instance_limits.clone();
|
|
||||||
let mut requester = crate::limit::LimitedRequester::new().await;
|
|
||||||
match requester
|
|
||||||
.send_request(
|
|
||||||
request,
|
|
||||||
crate::api::limits::LimitType::Ip,
|
|
||||||
instance_limits,
|
|
||||||
&mut cloned_limits,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(result) => Ok(serde_json::from_str(&result.text().await.unwrap()).unwrap()),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Modify the current user's `UserObject`.
|
/// Modify the current user's `UserObject`.
|
||||||
|
@ -153,6 +114,64 @@ impl UserMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl User {
|
||||||
|
pub async fn get(
|
||||||
|
token: &String,
|
||||||
|
url_api: &String,
|
||||||
|
id: Option<&String>,
|
||||||
|
instance_limits: &mut Limits,
|
||||||
|
) -> Result<User, InstanceServerError> {
|
||||||
|
let url: String;
|
||||||
|
if id.is_none() {
|
||||||
|
url = format!("{}/users/@me/", url_api);
|
||||||
|
} else {
|
||||||
|
url = format!("{}/users/{}", url_api, id.unwrap());
|
||||||
|
}
|
||||||
|
let request = reqwest::Client::new().get(url).bearer_auth(token);
|
||||||
|
let mut requester = crate::limit::LimitedRequester::new().await;
|
||||||
|
let mut cloned_limits = instance_limits.clone();
|
||||||
|
match requester
|
||||||
|
.send_request(
|
||||||
|
request,
|
||||||
|
crate::api::limits::LimitType::Ip,
|
||||||
|
instance_limits,
|
||||||
|
&mut cloned_limits,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(result) => {
|
||||||
|
let result_text = result.text().await.unwrap();
|
||||||
|
Ok(serde_json::from_str::<User>(&result_text).unwrap())
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_settings(
|
||||||
|
token: &String,
|
||||||
|
url_api: &String,
|
||||||
|
instance_limits: &mut Limits,
|
||||||
|
) -> Result<UserSettings, InstanceServerError> {
|
||||||
|
let request: reqwest::RequestBuilder = Client::new()
|
||||||
|
.get(format!("{}/users/@me/settings/", url_api))
|
||||||
|
.bearer_auth(token);
|
||||||
|
let mut cloned_limits = instance_limits.clone();
|
||||||
|
let mut requester = crate::limit::LimitedRequester::new().await;
|
||||||
|
match requester
|
||||||
|
.send_request(
|
||||||
|
request,
|
||||||
|
crate::api::limits::LimitType::Ip,
|
||||||
|
instance_limits,
|
||||||
|
&mut cloned_limits,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(result) => Ok(serde_json::from_str(&result.text().await.unwrap()).unwrap()),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
/**
|
/**
|
||||||
Get a user object by id, or get the current user.
|
Get a user object by id, or get the current user.
|
||||||
|
|
|
@ -23,6 +23,7 @@ custom_error! {
|
||||||
NoPermission = "You do not have the permissions needed to perform this action.",
|
NoPermission = "You do not have the permissions needed to perform this action.",
|
||||||
NotFound{error: String} = "The provided resource hasn't been found: {}",
|
NotFound{error: String} = "The provided resource hasn't been found: {}",
|
||||||
PasswordRequiredError = "You need to provide your current password to authenticate for this action.",
|
PasswordRequiredError = "You need to provide your current password to authenticate for this action.",
|
||||||
|
InvalidResponseError{error: String} = "The response is malformed and cannot be processed. Error: {}",
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_error! {
|
custom_error! {
|
||||||
|
|
449
src/gateway.rs
449
src/gateway.rs
File diff suppressed because it is too large
Load Diff
|
@ -15,7 +15,7 @@ use crate::types::{
|
||||||
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
pub created_at: chrono::DateTime<Utc>,
|
pub created_at: Option<chrono::DateTime<Utc>>,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub channel_type: ChannelType,
|
pub channel_type: ChannelType,
|
||||||
pub guild_id: Option<Snowflake>,
|
pub guild_id: Option<Snowflake>,
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub struct Guild {
|
||||||
pub splash: Option<String>,
|
pub splash: Option<String>,
|
||||||
pub discovery_splash: Option<String>,
|
pub discovery_splash: Option<String>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub owner: bool, // True if requesting user is owner
|
pub owner: Option<bool>, // True if requesting user is owner
|
||||||
pub owner_id: Option<Snowflake>,
|
pub owner_id: Option<Snowflake>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub permissions: Option<String>,
|
pub permissions: Option<String>,
|
||||||
|
@ -33,7 +33,7 @@ pub struct Guild {
|
||||||
pub default_message_notifications: Option<i32>,
|
pub default_message_notifications: Option<i32>,
|
||||||
pub explicit_content_filter: Option<i32>,
|
pub explicit_content_filter: Option<i32>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub roles: Vec<RoleObject>,
|
pub roles: Option<Vec<RoleObject>>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub emojis: Vec<Emoji>,
|
pub emojis: Vec<Emoji>,
|
||||||
//#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))]
|
//#[cfg_attr(feature = "sqlx", sqlx(try_from = "String"))]
|
||||||
|
@ -71,7 +71,7 @@ pub struct Guild {
|
||||||
pub stickers: Option<Vec<Sticker>>,
|
pub stickers: Option<Vec<Sticker>>,
|
||||||
pub premium_progress_bar_enabled: Option<bool>,
|
pub premium_progress_bar_enabled: Option<bool>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub joined_at: String,
|
pub joined_at: Option<String>,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub bans: Option<Vec<GuildBan>>,
|
pub bans: Option<Vec<GuildBan>>,
|
||||||
pub primary_category_id: Option<Snowflake>,
|
pub primary_category_id: Option<Snowflake>,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::entities::User;
|
use crate::types::entities::PublicUser;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Default, Serialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Deserialize, Default, Serialize, Clone, PartialEq, Eq)]
|
||||||
pub struct GuildMember {
|
pub struct GuildMember {
|
||||||
pub user: Option<User>,
|
pub user: Option<PublicUser>,
|
||||||
pub nick: Option<String>,
|
pub nick: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<String>,
|
||||||
pub roles: Vec<String>,
|
pub roles: Vec<String>,
|
||||||
|
|
|
@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
entities::{
|
entities::{
|
||||||
Application, Attachment, Channel, Emoji, GuildMember, RoleSubscriptionData, Sticker,
|
Application, Attachment, Channel, Emoji, GuildMember, PublicUser, RoleSubscriptionData,
|
||||||
StickerItem, User,
|
Sticker, StickerItem, User,
|
||||||
},
|
},
|
||||||
utils::Snowflake,
|
utils::Snowflake,
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ pub struct Message {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
pub channel_id: Snowflake,
|
pub channel_id: Snowflake,
|
||||||
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
#[cfg_attr(feature = "sqlx", sqlx(skip))]
|
||||||
pub author: User,
|
pub author: PublicUser,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub timestamp: String,
|
pub timestamp: String,
|
||||||
pub edited_timestamp: Option<String>,
|
pub edited_timestamp: Option<String>,
|
||||||
|
|
|
@ -38,11 +38,11 @@ pub struct User {
|
||||||
#[serde(deserialize_with = "deserialize_option_number_from_string")]
|
#[serde(deserialize_with = "deserialize_option_number_from_string")]
|
||||||
pub flags: Option<i32>,
|
pub flags: Option<i32>,
|
||||||
pub premium_since: Option<DateTime<Utc>>,
|
pub premium_since: Option<DateTime<Utc>>,
|
||||||
pub premium_type: u8,
|
pub premium_type: Option<u8>,
|
||||||
pub pronouns: Option<String>,
|
pub pronouns: Option<String>,
|
||||||
pub public_flags: Option<u16>,
|
pub public_flags: Option<u32>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
pub bio: 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: bool,
|
||||||
|
@ -52,29 +52,29 @@ pub struct User {
|
||||||
pub disabled: Option<bool>,
|
pub disabled: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct PublicUser {
|
pub struct PublicUser {
|
||||||
pub id: Snowflake,
|
pub id: Snowflake,
|
||||||
pub username: String,
|
pub username: Option<String>,
|
||||||
pub discriminator: String,
|
pub discriminator: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<String>,
|
||||||
pub accent_color: Option<u8>,
|
pub accent_color: Option<u8>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
pub theme_colors: Option<Vec<u8>>,
|
pub theme_colors: Option<Vec<u8>>,
|
||||||
pub pronouns: Option<String>,
|
pub pronouns: Option<String>,
|
||||||
pub bot: Option<bool>,
|
pub bot: Option<bool>,
|
||||||
pub bio: String,
|
pub bio: Option<String>,
|
||||||
pub premium_type: u8,
|
pub premium_type: Option<u8>,
|
||||||
pub premium_since: Option<DateTime<Utc>>,
|
pub premium_since: Option<DateTime<Utc>>,
|
||||||
pub public_flags: Option<u16>,
|
pub public_flags: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<User> for PublicUser {
|
impl From<User> for PublicUser {
|
||||||
fn from(value: User) -> Self {
|
fn from(value: User) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: value.id,
|
id: value.id,
|
||||||
username: value.username,
|
username: Some(value.username),
|
||||||
discriminator: value.discriminator,
|
discriminator: Some(value.discriminator),
|
||||||
avatar: value.avatar,
|
avatar: value.avatar,
|
||||||
accent_color: value.accent_color,
|
accent_color: value.accent_color,
|
||||||
banner: value.banner,
|
banner: value.banner,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::types::{
|
||||||
pub struct VoiceState {
|
pub struct VoiceState {
|
||||||
pub guild_id: Option<Snowflake>,
|
pub guild_id: Option<Snowflake>,
|
||||||
pub guild: Option<Guild>,
|
pub guild: Option<Guild>,
|
||||||
pub channel_id: Snowflake,
|
pub channel_id: Option<Snowflake>,
|
||||||
pub user_id: Snowflake,
|
pub user_id: Snowflake,
|
||||||
pub member: Option<GuildMember>,
|
pub member: Option<GuildMember>,
|
||||||
pub session_id: Snowflake,
|
pub session_id: Snowflake,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::types::entities::{Guild, UnavailableGuild, User};
|
use crate::types::entities::{Guild, PublicUser, UnavailableGuild};
|
||||||
use crate::types::events::WebSocketEvent;
|
use crate::types::events::WebSocketEvent;
|
||||||
use crate::types::{AuditLogEntry, Emoji, GuildMember, GuildScheduledEvent, RoleObject, Sticker};
|
use crate::types::{AuditLogEntry, Emoji, GuildMember, GuildScheduledEvent, RoleObject, Sticker};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
@ -32,7 +32,7 @@ impl WebSocketEvent for GuildCreate {}
|
||||||
/// See https://discord.com/developers/docs/topics/gateway-events#guild-ban-add-guild-ban-add-event-fields
|
/// See https://discord.com/developers/docs/topics/gateway-events#guild-ban-add-guild-ban-add-event-fields
|
||||||
pub struct GuildBanAdd {
|
pub struct GuildBanAdd {
|
||||||
pub guild_id: String,
|
pub guild_id: String,
|
||||||
pub user: User,
|
pub user: PublicUser,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for GuildBanAdd {}
|
impl WebSocketEvent for GuildBanAdd {}
|
||||||
|
@ -41,7 +41,7 @@ impl WebSocketEvent for GuildBanAdd {}
|
||||||
/// See https://discord.com/developers/docs/topics/gateway-events#guild-ban-remove
|
/// See https://discord.com/developers/docs/topics/gateway-events#guild-ban-remove
|
||||||
pub struct GuildBanRemove {
|
pub struct GuildBanRemove {
|
||||||
pub guild_id: String,
|
pub guild_id: String,
|
||||||
pub user: User,
|
pub user: PublicUser,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for GuildBanRemove {}
|
impl WebSocketEvent for GuildBanRemove {}
|
||||||
|
@ -113,7 +113,7 @@ impl WebSocketEvent for GuildMemberAdd {}
|
||||||
/// See https://discord.com/developers/docs/topics/gateway-events#guild-member-remove
|
/// See https://discord.com/developers/docs/topics/gateway-events#guild-member-remove
|
||||||
pub struct GuildMemberRemove {
|
pub struct GuildMemberRemove {
|
||||||
pub guild_id: String,
|
pub guild_id: String,
|
||||||
pub user: User,
|
pub user: PublicUser,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for GuildMemberRemove {}
|
impl WebSocketEvent for GuildMemberRemove {}
|
||||||
|
@ -123,7 +123,7 @@ impl WebSocketEvent for GuildMemberRemove {}
|
||||||
pub struct GuildMemberUpdate {
|
pub struct GuildMemberUpdate {
|
||||||
pub guild_id: String,
|
pub guild_id: String,
|
||||||
pub roles: Vec<String>,
|
pub roles: Vec<String>,
|
||||||
pub user: User,
|
pub user: PublicUser,
|
||||||
pub nick: Option<String>,
|
pub nick: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<String>,
|
||||||
pub joined_at: Option<DateTime<Utc>>,
|
pub joined_at: Option<DateTime<Utc>>,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::entities::{Emoji, GuildMember, Message, User};
|
use crate::types::entities::{Emoji, GuildMember, Message, PublicUser};
|
||||||
|
|
||||||
use super::WebSocketEvent;
|
use super::WebSocketEvent;
|
||||||
|
|
||||||
|
@ -29,31 +29,9 @@ pub struct MessageCreate {
|
||||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||||
/// See https://discord.com/developers/docs/topics/gateway-events#message-create-message-create-extra-fields
|
/// See https://discord.com/developers/docs/topics/gateway-events#message-create-message-create-extra-fields
|
||||||
pub struct MessageCreateUser {
|
pub struct MessageCreateUser {
|
||||||
pub id: String,
|
#[serde(flatten)]
|
||||||
username: String,
|
user: PublicUser,
|
||||||
discriminator: String,
|
member: Option<GuildMember>,
|
||||||
avatar: Option<String>,
|
|
||||||
bot: Option<bool>,
|
|
||||||
system: Option<bool>,
|
|
||||||
mfa_enabled: Option<bool>,
|
|
||||||
accent_color: Option<String>,
|
|
||||||
locale: Option<String>,
|
|
||||||
verified: Option<bool>,
|
|
||||||
email: Option<String>,
|
|
||||||
premium_since: Option<String>,
|
|
||||||
premium_type: Option<i8>,
|
|
||||||
pronouns: Option<String>,
|
|
||||||
public_flags: Option<i32>,
|
|
||||||
banner: Option<String>,
|
|
||||||
bio: Option<String>,
|
|
||||||
theme_colors: Option<Vec<i32>>,
|
|
||||||
phone: Option<String>,
|
|
||||||
nsfw_allowed: Option<bool>,
|
|
||||||
premium: Option<bool>,
|
|
||||||
purchased_flags: Option<i32>,
|
|
||||||
premium_usage_flags: Option<i32>,
|
|
||||||
disabled: Option<bool>,
|
|
||||||
member: GuildMember,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for MessageCreate {}
|
impl WebSocketEvent for MessageCreate {}
|
||||||
|
@ -64,7 +42,7 @@ pub struct MessageUpdate {
|
||||||
message: Message,
|
message: Message,
|
||||||
guild_id: Option<String>,
|
guild_id: Option<String>,
|
||||||
member: Option<GuildMember>,
|
member: Option<GuildMember>,
|
||||||
mentions: Option<Vec<(User, GuildMember)>>, // Not sure if this is correct: https://discord.com/developers/docs/topics/gateway-events#message-create
|
mentions: Option<Vec<MessageCreateUser>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for MessageUpdate {}
|
impl WebSocketEvent for MessageUpdate {}
|
||||||
|
@ -142,7 +120,9 @@ pub struct MessageACK {
|
||||||
/// ?
|
/// ?
|
||||||
pub version: u16,
|
pub version: u16,
|
||||||
pub message_id: String,
|
pub message_id: String,
|
||||||
pub last_viewed: Option<DateTime<Utc>>,
|
/// This is an integer???
|
||||||
|
/// Not even unix, see '3070'???
|
||||||
|
pub last_viewed: Option<u64>,
|
||||||
/// What flags?
|
/// What flags?
|
||||||
pub flags: Option<serde_json::Value>,
|
pub flags: Option<serde_json::Value>,
|
||||||
pub channel_id: String,
|
pub channel_id: String,
|
||||||
|
|
|
@ -60,11 +60,16 @@ pub trait WebSocketEvent {}
|
||||||
/// Similar to [GatewayReceivePayload], except we send a [Value] for d whilst we receive a [serde_json::value::RawValue]
|
/// Similar to [GatewayReceivePayload], except we send a [Value] for d whilst we receive a [serde_json::value::RawValue]
|
||||||
/// Also, we never need to send the event name
|
/// Also, we never need to send the event name
|
||||||
pub struct GatewaySendPayload {
|
pub struct GatewaySendPayload {
|
||||||
pub op: u8,
|
#[serde(rename = "op")]
|
||||||
|
pub op_code: u8,
|
||||||
|
|
||||||
|
#[serde(rename = "d")]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub d: Option<serde_json::Value>,
|
pub event_data: Option<serde_json::Value>,
|
||||||
|
|
||||||
|
#[serde(rename = "s")]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub s: Option<u64>,
|
pub sequence_number: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for GatewaySendPayload {}
|
impl WebSocketEvent for GatewaySendPayload {}
|
||||||
|
@ -76,11 +81,18 @@ impl WebSocketEvent for GatewaySendPayload {}
|
||||||
/// Also, we never need to sent the event name
|
/// Also, we never need to sent the event name
|
||||||
|
|
||||||
pub struct GatewayReceivePayload<'a> {
|
pub struct GatewayReceivePayload<'a> {
|
||||||
pub op: u8,
|
#[serde(rename = "op")]
|
||||||
|
pub op_code: u8,
|
||||||
|
|
||||||
#[serde(borrow)]
|
#[serde(borrow)]
|
||||||
pub d: Option<&'a serde_json::value::RawValue>,
|
#[serde(rename = "d")]
|
||||||
pub s: Option<u64>,
|
pub event_data: Option<&'a serde_json::value::RawValue>,
|
||||||
pub t: Option<String>,
|
|
||||||
|
#[serde(rename = "s")]
|
||||||
|
pub sequence_number: Option<u64>,
|
||||||
|
|
||||||
|
#[serde(rename = "t")]
|
||||||
|
pub event_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebSocketEvent for GatewayReceivePayload<'a> {}
|
impl<'a> WebSocketEvent for GatewayReceivePayload<'a> {}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::types::{GuildMember, VoiceState};
|
||||||
/// Seems to be passively set to update the client on guild details (though, why not just send the update events?)
|
/// Seems to be passively set to update the client on guild details (though, why not just send the update events?)
|
||||||
pub struct PassiveUpdateV1 {
|
pub struct PassiveUpdateV1 {
|
||||||
pub voice_states: Vec<VoiceState>,
|
pub voice_states: Vec<VoiceState>,
|
||||||
pub members: Vec<GuildMember>,
|
pub members: Option<Vec<GuildMember>>,
|
||||||
pub guild_id: String,
|
pub guild_id: String,
|
||||||
pub channels: Vec<ChannelUnreadUpdateObject>,
|
pub channels: Vec<ChannelUnreadUpdateObject>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub struct GatewayReadySupplemental {
|
||||||
pub merged_members: Vec<Vec<GuildMember>>,
|
pub merged_members: Vec<Vec<GuildMember>>,
|
||||||
// ?
|
// ?
|
||||||
pub lazy_private_channels: Vec<serde_json::Value>,
|
pub lazy_private_channels: Vec<serde_json::Value>,
|
||||||
pub guilds: Vec<SupplimentalGuild>,
|
pub guilds: Vec<SupplementalGuild>,
|
||||||
// ? pomelo
|
// ? pomelo
|
||||||
pub disclose: Vec<String>,
|
pub disclose: Vec<String>,
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ pub struct MergedPresenceGuild {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default)]
|
#[derive(Debug, Deserialize, Serialize, Default)]
|
||||||
pub struct SupplimentalGuild {
|
pub struct SupplementalGuild {
|
||||||
pub voice_states: Option<Vec<VoiceState>>,
|
pub voice_states: Option<Vec<VoiceState>>,
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub embedded_activities: Vec<serde_json::Value>,
|
pub embedded_activities: Vec<serde_json::Value>,
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub struct ThreadListSync {
|
||||||
pub guild_id: String,
|
pub guild_id: String,
|
||||||
pub channel_ids: Option<Vec<String>>,
|
pub channel_ids: Option<Vec<String>>,
|
||||||
pub threads: Vec<Channel>,
|
pub threads: Vec<Channel>,
|
||||||
pub members: Vec<ThreadMember>,
|
pub members: Option<Vec<ThreadMember>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for ThreadListSync {}
|
impl WebSocketEvent for ThreadListSync {}
|
||||||
|
|
|
@ -1,12 +1,54 @@
|
||||||
use crate::types::entities::User;
|
use crate::types::entities::PublicUser;
|
||||||
use crate::types::events::WebSocketEvent;
|
use crate::types::events::WebSocketEvent;
|
||||||
|
use crate::types::utils::Snowflake;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
/// See https://discord.com/developers/docs/topics/gateway-events#user-update
|
/// See https://discord.com/developers/docs/topics/gateway-events#user-update
|
||||||
pub struct UserUpdate {
|
pub struct UserUpdate {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub user: User,
|
pub user: PublicUser,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketEvent for UserUpdate {}
|
impl WebSocketEvent for UserUpdate {}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
|
/// Undocumented
|
||||||
|
///
|
||||||
|
/// Possibly an update for muted guild / channel settings for the current user
|
||||||
|
///
|
||||||
|
/// {"version":2,"suppress_roles":false,"suppress_everyone":false,"notify_highlights":0,"muted":false,"mute_scheduled_events":false,"mute_config":null,"mobile_push":true,"message_notifications":1,"hide_muted_channels":false,"guild_id":"848582562217590824","flags":0,"channel_overrides":[{"muted":false,"mute_config":null,"message_notifications":3,"flags":4096,"collapsed":false,"channel_id":"1042689182893604885"}]}
|
||||||
|
pub struct UserGuildSettingsUpdate {
|
||||||
|
pub version: u8,
|
||||||
|
pub suppress_roles: bool,
|
||||||
|
pub suppress_everyone: bool,
|
||||||
|
pub notify_highlights: u8,
|
||||||
|
pub muted: bool,
|
||||||
|
pub mute_scheduled_events: bool,
|
||||||
|
/// ??
|
||||||
|
pub mute_config: Option<serde_json::Value>,
|
||||||
|
pub mobile_push: bool,
|
||||||
|
pub message_notifications: u8,
|
||||||
|
pub hide_muted_channels: bool,
|
||||||
|
pub guild_id: Snowflake,
|
||||||
|
pub flags: i32,
|
||||||
|
pub channel_overrides: Vec<UserGuildSettingsChannelOverride>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WebSocketEvent for UserGuildSettingsUpdate {}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
|
/// Undocumented
|
||||||
|
///
|
||||||
|
/// Received in [UserGuildSettingsUpdate]
|
||||||
|
///
|
||||||
|
/// {"muted":false,"mute_config":null,"message_notifications":3,"flags":4096,"collapsed":false,"channel_id":"1042689182893604885"}
|
||||||
|
pub struct UserGuildSettingsChannelOverride {
|
||||||
|
pub muted: bool,
|
||||||
|
/// ??
|
||||||
|
pub mute_config: Option<serde_json::Value>,
|
||||||
|
pub message_notifications: u8,
|
||||||
|
pub flags: i32,
|
||||||
|
pub collapsed: bool,
|
||||||
|
pub channel_id: Snowflake,
|
||||||
|
}
|
||||||
|
|
|
@ -25,3 +25,25 @@ pub struct ChannelCreateSchema {
|
||||||
pub default_thread_rate_limit_per_user: Option<i32>,
|
pub default_thread_rate_limit_per_user: Option<i32>,
|
||||||
pub video_quality_mode: Option<i32>,
|
pub video_quality_mode: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub struct ChannelModifySchema {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub channel_type: Option<u8>,
|
||||||
|
pub topic: Option<String>,
|
||||||
|
pub icon: Option<String>,
|
||||||
|
pub bitrate: Option<i32>,
|
||||||
|
pub user_limit: Option<i32>,
|
||||||
|
pub rate_limit_per_user: Option<i32>,
|
||||||
|
pub position: Option<i32>,
|
||||||
|
pub permission_overwrites: Option<Vec<PermissionOverwrite>>,
|
||||||
|
pub parent_id: Option<String>,
|
||||||
|
pub nsfw: Option<bool>,
|
||||||
|
pub rtc_region: Option<String>,
|
||||||
|
pub default_auto_archive_duration: Option<i32>,
|
||||||
|
pub default_reaction_emoji: Option<String>,
|
||||||
|
pub flags: Option<i32>,
|
||||||
|
pub default_thread_rate_limit_per_user: Option<i32>,
|
||||||
|
pub video_quality_mode: Option<i32>,
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod common;
|
mod common;
|
||||||
use chorus::types::Channel;
|
use chorus::types::{self, Channel};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_channel() {
|
async fn get_channel() {
|
||||||
|
@ -21,3 +21,56 @@ async fn get_channel() {
|
||||||
);
|
);
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn delete_channel() {
|
||||||
|
let mut bundle = common::setup().await;
|
||||||
|
let result = bundle
|
||||||
|
.channel
|
||||||
|
.clone()
|
||||||
|
.delete(
|
||||||
|
&bundle.user.token,
|
||||||
|
bundle.instance.urls.get_api(),
|
||||||
|
&mut bundle.user.limits,
|
||||||
|
&mut bundle.instance.limits,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert!(result.is_none());
|
||||||
|
common::teardown(bundle).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn modify_channel() {
|
||||||
|
let mut bundle = common::setup().await;
|
||||||
|
let modify_data: types::ChannelModifySchema = types::ChannelModifySchema {
|
||||||
|
name: Some("beepboop".to_string()),
|
||||||
|
channel_type: None,
|
||||||
|
topic: None,
|
||||||
|
icon: None,
|
||||||
|
bitrate: None,
|
||||||
|
user_limit: None,
|
||||||
|
rate_limit_per_user: None,
|
||||||
|
position: None,
|
||||||
|
permission_overwrites: None,
|
||||||
|
parent_id: None,
|
||||||
|
nsfw: None,
|
||||||
|
rtc_region: None,
|
||||||
|
default_auto_archive_duration: None,
|
||||||
|
default_reaction_emoji: None,
|
||||||
|
flags: None,
|
||||||
|
default_thread_rate_limit_per_user: None,
|
||||||
|
video_quality_mode: None,
|
||||||
|
};
|
||||||
|
let result = Channel::modify(
|
||||||
|
modify_data,
|
||||||
|
&bundle.user.token,
|
||||||
|
bundle.instance.urls.get_api(),
|
||||||
|
&bundle.channel.id.to_string(),
|
||||||
|
&mut bundle.user.limits,
|
||||||
|
&mut bundle.instance.limits,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(result.name, Some("beepboop".to_string()));
|
||||||
|
common::teardown(bundle).await
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub struct TestBundle {
|
||||||
pub urls: URLBundle,
|
pub urls: URLBundle,
|
||||||
pub user: UserMeta,
|
pub user: UserMeta,
|
||||||
pub instance: Instance,
|
pub instance: Instance,
|
||||||
pub guild_id: String,
|
pub guild: Guild,
|
||||||
pub channel: Channel,
|
pub channel: Channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,13 +65,13 @@ pub async fn setup() -> TestBundle {
|
||||||
video_quality_mode: None,
|
video_quality_mode: None,
|
||||||
};
|
};
|
||||||
let mut user = instance.register_account(®).await.unwrap();
|
let mut user = instance.register_account(®).await.unwrap();
|
||||||
let guild_id = Guild::create(&mut user, urls.get_api(), guild_create_schema)
|
let guild = Guild::create(&mut user, urls.get_api(), guild_create_schema)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let channel = Channel::create(
|
let channel = Channel::create(
|
||||||
&user.token,
|
&user.token,
|
||||||
urls.get_api(),
|
urls.get_api(),
|
||||||
guild_id.as_str(),
|
&guild.id.to_string(),
|
||||||
channel_create_schema,
|
channel_create_schema,
|
||||||
&mut user.limits,
|
&mut user.limits,
|
||||||
&mut instance.limits,
|
&mut instance.limits,
|
||||||
|
@ -83,7 +83,7 @@ pub async fn setup() -> TestBundle {
|
||||||
urls,
|
urls,
|
||||||
user,
|
user,
|
||||||
instance,
|
instance,
|
||||||
guild_id,
|
guild,
|
||||||
channel,
|
channel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ pub async fn teardown(mut bundle: TestBundle) {
|
||||||
Guild::delete(
|
Guild::delete(
|
||||||
&mut bundle.user,
|
&mut bundle.user,
|
||||||
bundle.instance.urls.get_api(),
|
bundle.instance.urls.get_api(),
|
||||||
bundle.guild_id,
|
&bundle.guild.id.to_string(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
bundle.user.delete().await;
|
bundle.user.delete().await;
|
||||||
|
|
|
@ -19,11 +19,34 @@ async fn guild_creation_deletion() {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
println!("{}", guild);
|
match Guild::delete(
|
||||||
|
&mut bundle.user,
|
||||||
match Guild::delete(&mut bundle.user, bundle.urls.get_api(), guild).await {
|
bundle.urls.get_api(),
|
||||||
|
&guild.id.to_string(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
None => assert!(true),
|
None => assert!(true),
|
||||||
Some(_) => assert!(false),
|
Some(_) => assert!(false),
|
||||||
}
|
}
|
||||||
common::teardown(bundle).await
|
common::teardown(bundle).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn get_channels() {
|
||||||
|
let mut bundle = common::setup().await;
|
||||||
|
println!(
|
||||||
|
"{:?}",
|
||||||
|
bundle
|
||||||
|
.guild
|
||||||
|
.channels(
|
||||||
|
bundle.instance.urls.get_api(),
|
||||||
|
&bundle.user.token,
|
||||||
|
&mut bundle.user.limits,
|
||||||
|
&mut bundle.instance.limits,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
common::teardown(bundle).await;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue