Compare commits
8 Commits
9791b13921
...
8e393b4b92
Author | SHA1 | Date |
---|---|---|
kozabrada123 | 8e393b4b92 | |
kozabrada123 | 6c6a87ce5b | |
kozabrada123 | 1dfbd216a4 | |
kozabrada123 | 87aad461fd | |
kozabrada123 | 9d847906be | |
kozabrada123 | fa70c55944 | |
kozabrada123 | 754c212b39 | |
kozabrada123 | ec9541f38e |
|
@ -0,0 +1,35 @@
|
||||||
|
name: cargo doc lints
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main", "preserve/*" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main", "dev" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
cargo-doc-lints:
|
||||||
|
name: Run cargo doc for doc lints
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Rust toolchain
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: Install aditional components for sarif
|
||||||
|
run: cargo install clippy-sarif sarif-fmt
|
||||||
|
|
||||||
|
- name: Run cargo doc
|
||||||
|
run: cargo doc --no-deps --all-features --locked --message-format=json | clippy-sarif | sed 's/rust-lang.github.io\/rust-clippy/doc.rust-lang.org\/rustdoc\/lints.html/g' | sed 's/clippy/rustdoc/g' | tee cargo-doc-results.sarif | sarif-fmt
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Upload analysis results to GitHub
|
||||||
|
uses: github/codeql-action/upload-sarif@v3
|
||||||
|
with:
|
||||||
|
sarif_file: cargo-doc-results.sarif
|
||||||
|
wait-for-processing: true
|
|
@ -2,7 +2,10 @@
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
@ -12,10 +15,11 @@ use crate::{
|
||||||
instance::{ChorusUser, Instance},
|
instance::{ChorusUser, Instance},
|
||||||
ratelimiter::ChorusRequest,
|
ratelimiter::ChorusRequest,
|
||||||
types::{
|
types::{
|
||||||
DeleteDisableUserSchema, GetPomeloEligibilityReturn, GetPomeloSuggestionsReturn,
|
CreateUserHarvestSchema, DeleteDisableUserSchema, GetPomeloEligibilityReturn,
|
||||||
GetUserProfileSchema, LimitType, PublicUser, Snowflake, User, UserModifyProfileSchema,
|
GetPomeloSuggestionsReturn, GetRecentMentionsSchema, GetUserProfileSchema, Harvest,
|
||||||
UserModifySchema, UserProfile, UserProfileMetadata, UserSettings,
|
HarvestBackendType, LimitType, ModifyUserNoteSchema, PublicUser, Snowflake, User,
|
||||||
VerifyUserEmailChangeResponse, VerifyUserEmailChangeSchema,
|
UserModifyProfileSchema, UserModifySchema, UserNote, UserProfile, UserProfileMetadata,
|
||||||
|
UserSettings, VerifyUserEmailChangeResponse, VerifyUserEmailChangeSchema,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -223,11 +227,12 @@ impl ChorusUser {
|
||||||
|
|
||||||
/// Verifies a code sent to change the current user's email.
|
/// Verifies a code sent to change the current user's email.
|
||||||
///
|
///
|
||||||
/// Should be the follow-up to [Self::initiate_email_change]
|
|
||||||
///
|
|
||||||
/// This endpoint returns a token which can be used with [Self::modify]
|
/// This endpoint returns a token which can be used with [Self::modify]
|
||||||
/// to set a new email address (email_token).
|
/// to set a new email address (email_token).
|
||||||
///
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// Should be the follow-up to [Self::initiate_email_change]
|
||||||
|
///
|
||||||
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
|
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
|
||||||
// FIXME: Does this mean PUT users/@me/email is different?
|
// FIXME: Does this mean PUT users/@me/email is different?
|
||||||
///
|
///
|
||||||
|
@ -255,8 +260,7 @@ impl ChorusUser {
|
||||||
|
|
||||||
/// Returns a suggested unique username based on the current user's username.
|
/// Returns a suggested unique username based on the current user's username.
|
||||||
///
|
///
|
||||||
/// Note:
|
/// # Notes:
|
||||||
///
|
|
||||||
/// "This endpoint is used during the pomelo migration flow.
|
/// "This endpoint is used during the pomelo migration flow.
|
||||||
///
|
///
|
||||||
/// The user must be in the rollout to use this endpoint."
|
/// The user must be in the rollout to use this endpoint."
|
||||||
|
@ -266,6 +270,7 @@ impl ChorusUser {
|
||||||
///
|
///
|
||||||
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
|
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
|
||||||
///
|
///
|
||||||
|
/// # Reference
|
||||||
/// See <https://docs.discord.sex/resources/user#get-pomelo-suggestions>
|
/// See <https://docs.discord.sex/resources/user#get-pomelo-suggestions>
|
||||||
pub async fn get_pomelo_suggestions(&mut self) -> ChorusResult<String> {
|
pub async fn get_pomelo_suggestions(&mut self) -> ChorusResult<String> {
|
||||||
let request = Client::new()
|
let request = Client::new()
|
||||||
|
@ -289,8 +294,10 @@ impl ChorusUser {
|
||||||
///
|
///
|
||||||
/// Returns whether the username is not taken yet.
|
/// Returns whether the username is not taken yet.
|
||||||
///
|
///
|
||||||
|
/// # Notes
|
||||||
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
|
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
|
||||||
///
|
///
|
||||||
|
/// # Reference
|
||||||
/// See <https://docs.discord.sex/resources/user#get-pomelo-eligibility>
|
/// See <https://docs.discord.sex/resources/user#get-pomelo-eligibility>
|
||||||
pub async fn get_pomelo_eligibility(&mut self, username: &String) -> ChorusResult<bool> {
|
pub async fn get_pomelo_eligibility(&mut self, username: &String) -> ChorusResult<bool> {
|
||||||
let request = Client::new()
|
let request = Client::new()
|
||||||
|
@ -320,8 +327,7 @@ impl ChorusUser {
|
||||||
/// Updates [Self::object] to an updated representation returned by the server.
|
/// Updates [Self::object] to an updated representation returned by the server.
|
||||||
// FIXME: Is this appropriate behaviour?
|
// FIXME: Is this appropriate behaviour?
|
||||||
///
|
///
|
||||||
/// Note:
|
/// # Notes
|
||||||
///
|
|
||||||
/// "This endpoint is used during the pomelo migration flow.
|
/// "This endpoint is used during the pomelo migration flow.
|
||||||
///
|
///
|
||||||
/// The user must be in the rollout to use this endpoint."
|
/// The user must be in the rollout to use this endpoint."
|
||||||
|
@ -331,6 +337,7 @@ impl ChorusUser {
|
||||||
//
|
//
|
||||||
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
|
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
|
||||||
///
|
///
|
||||||
|
/// # Reference
|
||||||
/// See <https://docs.discord.sex/resources/user#create-pomelo-migration>
|
/// See <https://docs.discord.sex/resources/user#create-pomelo-migration>
|
||||||
pub async fn create_pomelo_migration(&mut self, username: &String) -> ChorusResult<()> {
|
pub async fn create_pomelo_migration(&mut self, username: &String) -> ChorusResult<()> {
|
||||||
let request = Client::new()
|
let request = Client::new()
|
||||||
|
@ -358,6 +365,211 @@ impl ChorusUser {
|
||||||
|
|
||||||
ChorusResult::Err(result.err().unwrap())
|
ChorusResult::Err(result.err().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches a list of [Message](crate::types::Message)s that the current user has been
|
||||||
|
/// mentioned in during the last 7 days.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// As of 2024/08/09, Spacebar does not yet implement this endpoint.
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#get-recent-mentions>
|
||||||
|
pub async fn get_recent_mentions(
|
||||||
|
&mut self,
|
||||||
|
query_parameters: GetRecentMentionsSchema,
|
||||||
|
) -> ChorusResult<Vec<crate::types::Message>> {
|
||||||
|
let request = Client::new()
|
||||||
|
.get(format!(
|
||||||
|
"{}/users/@me/mentions",
|
||||||
|
self.belongs_to.read().unwrap().urls.api
|
||||||
|
))
|
||||||
|
.header("Authorization", self.token())
|
||||||
|
.query(&query_parameters);
|
||||||
|
|
||||||
|
let chorus_request = ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
chorus_request
|
||||||
|
.deserialize_response::<Vec<crate::types::Message>>(self)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Acknowledges a message the current user has been mentioned in.
|
||||||
|
///
|
||||||
|
/// Fires a `RecentMentionDelete` gateway event. (Note: yet to be implemented in chorus, see [#545](https://github.com/polyphony-chat/chorus/issues/545))
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// As of 2024/08/09, Spacebar does not yet implement this endpoint.
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#delete-recent-mention>
|
||||||
|
pub async fn delete_recent_mention(&mut self, message_id: Snowflake) -> ChorusResult<()> {
|
||||||
|
let request = Client::new()
|
||||||
|
.delete(format!(
|
||||||
|
"{}/users/@me/mentions/{}",
|
||||||
|
self.belongs_to.read().unwrap().urls.api,
|
||||||
|
message_id
|
||||||
|
))
|
||||||
|
.header("Authorization", self.token());
|
||||||
|
|
||||||
|
let chorus_request = ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
chorus_request.handle_request_as_result(self).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If it exists, returns the most recent [Harvest] (personal data harvest request).
|
||||||
|
///
|
||||||
|
/// To create a new [Harvest], see [Self::create_harvest].
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// As of 2024/08/09, Spacebar does not yet implement this endpoint. (Or data harvesting)
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#get-user-harvest>
|
||||||
|
pub async fn get_harvest(&mut self) -> ChorusResult<Option<Harvest>> {
|
||||||
|
let request = Client::new()
|
||||||
|
.get(format!(
|
||||||
|
"{}/users/@me/harvest",
|
||||||
|
self.belongs_to.read().unwrap().urls.api,
|
||||||
|
))
|
||||||
|
.header("Authorization", self.token());
|
||||||
|
|
||||||
|
let chorus_request = ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Manual handling, because a 204 with no harvest is a success state
|
||||||
|
// TODO: Maybe make this a method on ChorusRequest if we need it a lot
|
||||||
|
let response = chorus_request.send_request(self).await?;
|
||||||
|
log::trace!("Got response: {:?}", response);
|
||||||
|
|
||||||
|
if response.status() == http::StatusCode::NO_CONTENT {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let response_text = match response.text().await {
|
||||||
|
Ok(string) => string,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(ChorusError::InvalidResponse {
|
||||||
|
error: format!(
|
||||||
|
"Error while trying to process the HTTP response into a String: {}",
|
||||||
|
e
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let object = match serde_json::from_str::<Harvest>(&response_text) {
|
||||||
|
Ok(object) => object,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(ChorusError::InvalidResponse {
|
||||||
|
error: format!(
|
||||||
|
"Error while trying to deserialize the JSON response into requested type T: {}. JSON Response: {}",
|
||||||
|
e, response_text
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(Some(object))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a personal data harvest request ([Harvest]) for the current user.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// To fetch the latest existing harvest, see [Self::get_harvest].
|
||||||
|
///
|
||||||
|
/// Invalid options in the backends array are ignored.
|
||||||
|
///
|
||||||
|
/// If the array is empty (after ignoring), it requests all [HarvestBackendType]s.
|
||||||
|
///
|
||||||
|
/// As of 2024/08/09, Spacebar does not yet implement this endpoint. (Or data harvesting)
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#create-user-harvest>
|
||||||
|
pub async fn create_harvest(
|
||||||
|
&mut self,
|
||||||
|
backends: Vec<HarvestBackendType>,
|
||||||
|
) -> ChorusResult<Harvest> {
|
||||||
|
let schema = if backends.is_empty() {
|
||||||
|
CreateUserHarvestSchema { backends: None }
|
||||||
|
} else {
|
||||||
|
CreateUserHarvestSchema {
|
||||||
|
backends: Some(backends),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let request = Client::new()
|
||||||
|
.post(format!(
|
||||||
|
"{}/users/@me/harvest",
|
||||||
|
self.belongs_to.read().unwrap().urls.api,
|
||||||
|
))
|
||||||
|
.header("Authorization", self.token())
|
||||||
|
.json(&schema);
|
||||||
|
|
||||||
|
let chorus_request = ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
chorus_request.deserialize_response(self).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mapping of user IDs ([Snowflake]s) to notes ([String]s) for the current user.
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#get-user-notes>
|
||||||
|
pub async fn get_user_notes(&mut self) -> ChorusResult<HashMap<Snowflake, String>> {
|
||||||
|
let request = Client::new()
|
||||||
|
.get(format!(
|
||||||
|
"{}/users/@me/notes",
|
||||||
|
self.belongs_to.read().unwrap().urls.api,
|
||||||
|
))
|
||||||
|
.header("Authorization", self.token());
|
||||||
|
|
||||||
|
let chorus_request = ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
chorus_request.deserialize_response(self).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetches the note ([UserNote]) for the given user.
|
||||||
|
///
|
||||||
|
/// If the current user has no note for the target, this endpoint
|
||||||
|
/// returns `Err(NotFound { error: "{\"message\": \"Unknown User\", \"code\": 10013}" })`
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// This function is a wrapper around [`User::get_note`].
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#get-user-note>
|
||||||
|
pub async fn get_user_note(&mut self, target_user_id: Snowflake) -> ChorusResult<UserNote> {
|
||||||
|
User::get_note(self, target_user_id).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the note for the given user.
|
||||||
|
///
|
||||||
|
/// Fires a `UserNoteUpdate` gateway event. (Note: yet to be implemented in chorus, see [#546](https://github.com/polyphony-chat/chorus/issues/546))
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
/// This function is a wrapper around [`User::set_note`].
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#modify-user-note>
|
||||||
|
pub async fn set_user_note(
|
||||||
|
&mut self,
|
||||||
|
target_user_id: Snowflake,
|
||||||
|
note: Option<String>,
|
||||||
|
) -> ChorusResult<()> {
|
||||||
|
User::set_note(self, target_user_id, note).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
|
@ -512,4 +724,61 @@ impl User {
|
||||||
.deserialize_response::<UserProfileMetadata>(user)
|
.deserialize_response::<UserProfileMetadata>(user)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches the note ([UserNote]) for the given user.
|
||||||
|
///
|
||||||
|
/// If the current user has no note for the target, this endpoint
|
||||||
|
/// returns `Err(NotFound { error: "{\"message\": \"Unknown User\", \"code\": 10013}" })`
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#get-user-note>
|
||||||
|
pub async fn get_note(
|
||||||
|
user: &mut ChorusUser,
|
||||||
|
target_user_id: Snowflake,
|
||||||
|
) -> ChorusResult<UserNote> {
|
||||||
|
let request = Client::new()
|
||||||
|
.get(format!(
|
||||||
|
"{}/users/@me/notes/{}",
|
||||||
|
user.belongs_to.read().unwrap().urls.api,
|
||||||
|
target_user_id
|
||||||
|
))
|
||||||
|
.header("Authorization", user.token());
|
||||||
|
|
||||||
|
let chorus_request = ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
chorus_request.deserialize_response(user).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the note for the given user.
|
||||||
|
///
|
||||||
|
/// Fires a `UserNoteUpdate` gateway event. (Note: yet to be implemented in chorus, see [#546](https://github.com/polyphony-chat/chorus/issues/546))
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#modify-user-note>
|
||||||
|
pub async fn set_note(
|
||||||
|
user: &mut ChorusUser,
|
||||||
|
target_user_id: Snowflake,
|
||||||
|
note: Option<String>,
|
||||||
|
) -> ChorusResult<()> {
|
||||||
|
let schema = ModifyUserNoteSchema { note };
|
||||||
|
|
||||||
|
let request = Client::new()
|
||||||
|
.put(format!(
|
||||||
|
"{}/users/@me/notes/{}",
|
||||||
|
user.belongs_to.read().unwrap().urls.api,
|
||||||
|
target_user_id
|
||||||
|
))
|
||||||
|
.header("Authorization", user.token())
|
||||||
|
.json(&schema);
|
||||||
|
|
||||||
|
let chorus_request = ChorusRequest {
|
||||||
|
request,
|
||||||
|
limit_type: LimitType::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
chorus_request.handle_request_as_result(user).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,12 +69,14 @@ pub struct Message {
|
||||||
pub reaction_remove: Publisher<types::MessageReactionRemove>,
|
pub reaction_remove: Publisher<types::MessageReactionRemove>,
|
||||||
pub reaction_remove_all: Publisher<types::MessageReactionRemoveAll>,
|
pub reaction_remove_all: Publisher<types::MessageReactionRemoveAll>,
|
||||||
pub reaction_remove_emoji: Publisher<types::MessageReactionRemoveEmoji>,
|
pub reaction_remove_emoji: Publisher<types::MessageReactionRemoveEmoji>,
|
||||||
|
pub recent_mention_delete: Publisher<types::RecentMentionDelete>,
|
||||||
pub ack: Publisher<types::MessageACK>,
|
pub ack: Publisher<types::MessageACK>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub update: Publisher<types::UserUpdate>,
|
pub update: Publisher<types::UserUpdate>,
|
||||||
|
pub note_update: Publisher<types::UserNoteUpdate>,
|
||||||
pub guild_settings_update: Publisher<types::UserGuildSettingsUpdate>,
|
pub guild_settings_update: Publisher<types::UserGuildSettingsUpdate>,
|
||||||
pub presence_update: Publisher<types::PresenceUpdate>,
|
pub presence_update: Publisher<types::PresenceUpdate>,
|
||||||
pub typing_start: Publisher<types::TypingStartEvent>,
|
pub typing_start: Publisher<types::TypingStartEvent>,
|
||||||
|
|
|
@ -404,6 +404,7 @@ impl Gateway {
|
||||||
"MESSAGE_REACTION_REMOVE" => message.reaction_remove, // TODO
|
"MESSAGE_REACTION_REMOVE" => message.reaction_remove, // TODO
|
||||||
"MESSAGE_REACTION_REMOVE_ALL" => message.reaction_remove_all, // TODO
|
"MESSAGE_REACTION_REMOVE_ALL" => message.reaction_remove_all, // TODO
|
||||||
"MESSAGE_REACTION_REMOVE_EMOJI" => message.reaction_remove_emoji, // TODO
|
"MESSAGE_REACTION_REMOVE_EMOJI" => message.reaction_remove_emoji, // TODO
|
||||||
|
"RECENT_MENTION_DELETE" => message.recent_mention_delete,
|
||||||
"MESSAGE_ACK" => message.ack,
|
"MESSAGE_ACK" => message.ack,
|
||||||
"PRESENCE_UPDATE" => user.presence_update, // TODO
|
"PRESENCE_UPDATE" => user.presence_update, // TODO
|
||||||
"RELATIONSHIP_ADD" => relationship.add,
|
"RELATIONSHIP_ADD" => relationship.add,
|
||||||
|
@ -413,6 +414,7 @@ impl Gateway {
|
||||||
"STAGE_INSTANCE_DELETE" => stage_instance.delete,
|
"STAGE_INSTANCE_DELETE" => stage_instance.delete,
|
||||||
"TYPING_START" => user.typing_start,
|
"TYPING_START" => user.typing_start,
|
||||||
"USER_UPDATE" => user.update, // TODO
|
"USER_UPDATE" => user.update, // TODO
|
||||||
|
"USER_NOTE_UPDATE" => user.note_update,
|
||||||
"USER_GUILD_SETTINGS_UPDATE" => user.guild_settings_update,
|
"USER_GUILD_SETTINGS_UPDATE" => user.guild_settings_update,
|
||||||
"VOICE_STATE_UPDATE" => voice.state_update, // TODO
|
"VOICE_STATE_UPDATE" => voice.state_update, // TODO
|
||||||
"VOICE_SERVER_UPDATE" => voice.server_update,
|
"VOICE_SERVER_UPDATE" => voice.server_update,
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
|
||||||
|
use crate::types::Snowflake;
|
||||||
|
|
||||||
|
#[cfg(feature = "client")]
|
||||||
|
use crate::gateway::Updateable;
|
||||||
|
|
||||||
|
// FIXME: Should this type be Composite?
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
|
/// A user's data harvest.
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
///
|
||||||
|
/// See <https://docs.discord.sex/resources/user#harvest-object>
|
||||||
|
pub struct Harvest {
|
||||||
|
pub harvest_id: Snowflake,
|
||||||
|
/// The id of the user being harvested
|
||||||
|
pub user_id: Snowflake,
|
||||||
|
pub status: HarvestStatus,
|
||||||
|
/// The time the harvest was created
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
/// The time the harvest was last polled
|
||||||
|
pub polled_at: Option<DateTime<Utc>>,
|
||||||
|
/// The time the harvest was completed
|
||||||
|
pub completed_at: Option<DateTime<Utc>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "client")]
|
||||||
|
impl Updateable for Harvest {
|
||||||
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
fn id(&self) -> Snowflake {
|
||||||
|
self.harvest_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Serialize_repr,
|
||||||
|
Deserialize_repr,
|
||||||
|
Debug,
|
||||||
|
Default,
|
||||||
|
Clone,
|
||||||
|
Eq,
|
||||||
|
PartialEq,
|
||||||
|
Hash,
|
||||||
|
Copy,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
)]
|
||||||
|
#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
/// Current status of a [Harvest]
|
||||||
|
///
|
||||||
|
/// See <https://docs.discord.sex/resources/user#harvest-status> and <https://docs.discord.sex/resources/user#harvest-object>
|
||||||
|
pub enum HarvestStatus {
|
||||||
|
/// The harvest is queued and has not been started
|
||||||
|
Queued = 0,
|
||||||
|
/// The harvest is currently running / being processed
|
||||||
|
Running = 1,
|
||||||
|
/// The harvest has failed
|
||||||
|
Failed = 2,
|
||||||
|
/// The harvest has been completed successfully
|
||||||
|
Completed = 3,
|
||||||
|
#[default]
|
||||||
|
Unknown = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Hash, Copy, PartialOrd, Ord)]
|
||||||
|
#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
|
||||||
|
/// A type of backend / service a harvest can be requested for.
|
||||||
|
///
|
||||||
|
/// See <https://docs.discord.sex/resources/user#harvest-backend-type> and <https://support.discord.com/hc/en-us/articles/360004957991-Your-Discord-Data-Package>
|
||||||
|
pub enum HarvestBackendType {
|
||||||
|
/// All account information;
|
||||||
|
Accounts,
|
||||||
|
/// Actions the user has taken;
|
||||||
|
///
|
||||||
|
/// Represented as "Your Activity" in the discord client
|
||||||
|
Analytics,
|
||||||
|
/// First-party embedded activity information;
|
||||||
|
///
|
||||||
|
/// e.g.: Chess in the Park, Checkers in the Park, Poker Night 2.0;
|
||||||
|
/// Sketch Heads, Watch Together, Letter League, Land-io, Know What I Meme
|
||||||
|
Activities,
|
||||||
|
/// The user's messages
|
||||||
|
Messages,
|
||||||
|
/// Official Discord programes;
|
||||||
|
///
|
||||||
|
/// e.g.: Partner, HypeSquad, Verified Server
|
||||||
|
Programs,
|
||||||
|
/// Guilds the user is a member of;
|
||||||
|
Servers,
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ pub use config::*;
|
||||||
pub use emoji::*;
|
pub use emoji::*;
|
||||||
pub use guild::*;
|
pub use guild::*;
|
||||||
pub use guild_member::*;
|
pub use guild_member::*;
|
||||||
|
pub use harvest::*;
|
||||||
pub use integration::*;
|
pub use integration::*;
|
||||||
pub use invite::*;
|
pub use invite::*;
|
||||||
pub use message::*;
|
pub use message::*;
|
||||||
|
@ -52,6 +53,7 @@ mod config;
|
||||||
mod emoji;
|
mod emoji;
|
||||||
mod guild;
|
mod guild;
|
||||||
mod guild_member;
|
mod guild_member;
|
||||||
|
mod harvest;
|
||||||
mod integration;
|
mod integration;
|
||||||
mod invite;
|
mod invite;
|
||||||
mod message;
|
mod message;
|
||||||
|
|
|
@ -331,8 +331,8 @@ pub struct ProfileBadge {
|
||||||
/// A link (potentially used for href) for the badge.
|
/// A link (potentially used for href) for the badge.
|
||||||
///
|
///
|
||||||
/// e.g.:
|
/// e.g.:
|
||||||
/// "staff" badge links to "https://discord.com/company"
|
/// `"staff"` badge links to `"https://discord.com/company"`
|
||||||
/// "certified_moderator" links to "https://discord.com/safety"
|
/// `"certified_moderator"` links to `"https://discord.com/safety"`
|
||||||
pub link: Option<String>,
|
pub link: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,3 +765,22 @@ pub struct MutualGuild {
|
||||||
/// The user's nickname in the guild, if any
|
/// The user's nickname in the guild, if any
|
||||||
pub nick: Option<String>,
|
pub nick: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Structure which is returned by the [crate::instance::ChorusUser::get_user_note] endpoint.
|
||||||
|
///
|
||||||
|
/// Note that [crate::instance::ChorusUser::get_user_notes] endpoint
|
||||||
|
/// returns a completely different structure;
|
||||||
|
// Specualation: this is probably how Discord stores notes internally
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/resources/user#get-user-note>
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
|
||||||
|
pub struct UserNote {
|
||||||
|
/// Actual note contents; max 256 characters
|
||||||
|
pub note: String,
|
||||||
|
/// The ID of the user the note is on
|
||||||
|
pub note_user_id: Snowflake,
|
||||||
|
/// The ID of the user who created the note (always the current user)
|
||||||
|
pub user_id: Snowflake,
|
||||||
|
}
|
||||||
|
|
|
@ -149,6 +149,15 @@ pub struct MessageReactionRemoveEmoji {
|
||||||
pub emoji: Emoji,
|
pub emoji: Emoji,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Default, Clone, Copy, WebSocketEvent)]
|
||||||
|
/// Sent when a message that mentioned the current user in the last week is acknowledged and deleted.
|
||||||
|
///
|
||||||
|
/// # Reference
|
||||||
|
/// See <https://docs.discord.sex/topics/gateway-events#recent-mention-delete>
|
||||||
|
pub struct RecentMentionDelete {
|
||||||
|
pub message_id: Snowflake,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone, WebSocketEvent)]
|
||||||
/// Officially Undocumented
|
/// Officially Undocumented
|
||||||
///
|
///
|
||||||
|
|
|
@ -16,6 +16,18 @@ pub struct UserUpdate {
|
||||||
pub user: PublicUser,
|
pub user: PublicUser,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, WebSocketEvent)]
|
||||||
|
/// See <https://docs.discord.sex/topics/gateway-events#user-note-update-structure>;
|
||||||
|
///
|
||||||
|
/// Sent when a note the current user has on another user is modified;
|
||||||
|
///
|
||||||
|
/// If the field "note" is an empty string, the note was removed.
|
||||||
|
pub struct UserNoteUpdate {
|
||||||
|
/// Id of the user the note is for
|
||||||
|
pub id: Snowflake,
|
||||||
|
pub note: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, WebSocketEvent)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq, WebSocketEvent)]
|
||||||
/// Undocumented;
|
/// Undocumented;
|
||||||
///
|
///
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::collections::HashMap;
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::{Snowflake, ThemeColors};
|
use crate::types::{HarvestBackendType, Snowflake, ThemeColors};
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
|
@ -218,7 +218,7 @@ pub struct GetUserProfileSchema {
|
||||||
///
|
///
|
||||||
/// See <https://docs.discord.sex/resources/user#get-pomelo-suggestions>
|
/// See <https://docs.discord.sex/resources/user#get-pomelo-suggestions>
|
||||||
pub(crate) struct GetPomeloSuggestionsReturn {
|
pub(crate) struct GetPomeloSuggestionsReturn {
|
||||||
pub username: String
|
pub username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
|
@ -226,5 +226,52 @@ pub(crate) struct GetPomeloSuggestionsReturn {
|
||||||
///
|
///
|
||||||
/// See <https://docs.discord.sex/resources/user#get-pomelo-eligibility>
|
/// See <https://docs.discord.sex/resources/user#get-pomelo-eligibility>
|
||||||
pub(crate) struct GetPomeloEligibilityReturn {
|
pub(crate) struct GetPomeloEligibilityReturn {
|
||||||
pub taken: bool
|
pub taken: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
|
||||||
|
/// Query string parameters for the route GET /users/@me/mentions
|
||||||
|
/// ([crate::instance::ChorusUser::get_recent_mentions])
|
||||||
|
///
|
||||||
|
/// See <https://docs.discord.sex/resources/user#get-recent-mentions>
|
||||||
|
pub struct GetRecentMentionsSchema {
|
||||||
|
/// Only fetch messages before this message id
|
||||||
|
///
|
||||||
|
/// Due to the nature of snowflakes, this can be easily used to fetch
|
||||||
|
/// messages before a certain timestamp
|
||||||
|
pub before: Option<Snowflake>,
|
||||||
|
/// Max number of messages to return
|
||||||
|
///
|
||||||
|
/// Should be between 1 and 100.
|
||||||
|
///
|
||||||
|
/// If unset the limit is 25 messages
|
||||||
|
pub limit: Option<u8>,
|
||||||
|
/// Limit messages to a specific guild
|
||||||
|
pub guild_id: Option<Snowflake>,
|
||||||
|
/// Whether to include role mentions.
|
||||||
|
///
|
||||||
|
/// If unset the server assumes true
|
||||||
|
pub roles: Option<bool>,
|
||||||
|
/// Whether to include @everyone and @here mentions.
|
||||||
|
///
|
||||||
|
/// If unset the server assumes true
|
||||||
|
pub everyone: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
|
/// Internal type for the [crate::instance::ChorusUser::create_harvest] endpoint.
|
||||||
|
// (koza): imo it's nicer if the user can just pass a vec, instead of having to bother with
|
||||||
|
// a specific type
|
||||||
|
///
|
||||||
|
/// See <https://docs.discord.sex/resources/user#create-user-harvest>
|
||||||
|
pub(crate) struct CreateUserHarvestSchema {
|
||||||
|
pub backends: Option<Vec<HarvestBackendType>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
|
/// Internal type for the [crate::instance::ChorusUser::set_user_note] endpoint.
|
||||||
|
///
|
||||||
|
/// See <https://docs.discord.sex/resources/user#modify-user-note>
|
||||||
|
pub(crate) struct ModifyUserNoteSchema {
|
||||||
|
pub note: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue