feat: user notes endpoints

Adds: get_user_notes, get_user_note, set_user_note
This commit is contained in:
kozabrada123 2024-08-09 11:10:25 +02:00
parent 87aad461fd
commit 1dfbd216a4
3 changed files with 160 additions and 11 deletions

View File

@ -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;
@ -14,9 +17,9 @@ use crate::{
types::{ types::{
CreateUserHarvestSchema, DeleteDisableUserSchema, GetPomeloEligibilityReturn, CreateUserHarvestSchema, DeleteDisableUserSchema, GetPomeloEligibilityReturn,
GetPomeloSuggestionsReturn, GetRecentMentionsSchema, GetUserProfileSchema, Harvest, GetPomeloSuggestionsReturn, GetRecentMentionsSchema, GetUserProfileSchema, Harvest,
HarvestBackendType, LimitType, PublicUser, Snowflake, User, UserModifyProfileSchema, HarvestBackendType, LimitType, ModifyUserNoteSchema, PublicUser, Snowflake, User,
UserModifySchema, UserProfile, UserProfileMetadata, UserSettings, UserModifyProfileSchema, UserModifySchema, UserNote, UserProfile, UserProfileMetadata,
VerifyUserEmailChangeResponse, VerifyUserEmailChangeSchema, UserSettings, VerifyUserEmailChangeResponse, VerifyUserEmailChangeSchema,
}, },
}; };
@ -224,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?
/// ///
@ -256,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."
@ -267,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()
@ -290,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()
@ -321,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."
@ -332,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()
@ -363,8 +369,10 @@ impl ChorusUser {
/// Fetches a list of [Message](crate::types::Message)s that the current user has been /// Fetches a list of [Message](crate::types::Message)s that the current user has been
/// mentioned in during the last 7 days. /// mentioned in during the last 7 days.
/// ///
/// # Notes
/// As of 2024/08/09, Spacebar does not yet implement this endpoint. /// As of 2024/08/09, Spacebar does not yet implement this endpoint.
/// ///
/// # Reference
/// See <https://docs.discord.sex/resources/user#get-recent-mentions> /// See <https://docs.discord.sex/resources/user#get-recent-mentions>
pub async fn get_recent_mentions( pub async fn get_recent_mentions(
&mut self, &mut self,
@ -390,10 +398,12 @@ impl ChorusUser {
/// Acknowledges a message the current user has been mentioned in. /// 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)) /// 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. /// As of 2024/08/09, Spacebar does not yet implement this endpoint.
/// ///
/// # Reference
/// See <https://docs.discord.sex/resources/user#delete-recent-mention> /// See <https://docs.discord.sex/resources/user#delete-recent-mention>
pub async fn delete_recent_mention(&mut self, message_id: Snowflake) -> ChorusResult<()> { pub async fn delete_recent_mention(&mut self, message_id: Snowflake) -> ChorusResult<()> {
let request = Client::new() let request = Client::new()
@ -416,8 +426,10 @@ impl ChorusUser {
/// ///
/// To create a new [Harvest], see [Self::create_harvest]. /// 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) /// 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> /// See <https://docs.discord.sex/resources/user#get-user-harvest>
pub async fn get_harvest(&mut self) -> ChorusResult<Option<Harvest>> { pub async fn get_harvest(&mut self) -> ChorusResult<Option<Harvest>> {
let request = Client::new() let request = Client::new()
@ -469,6 +481,7 @@ impl ChorusUser {
/// Creates a personal data harvest request ([Harvest]) for the current user. /// Creates a personal data harvest request ([Harvest]) for the current user.
/// ///
/// # Notes
/// To fetch the latest existing harvest, see [Self::get_harvest]. /// To fetch the latest existing harvest, see [Self::get_harvest].
/// ///
/// Invalid options in the backends array are ignored. /// Invalid options in the backends array are ignored.
@ -477,6 +490,7 @@ impl ChorusUser {
/// ///
/// As of 2024/08/09, Spacebar does not yet implement this endpoint. (Or data harvesting) /// 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> /// See <https://docs.discord.sex/resources/user#create-user-harvest>
pub async fn create_harvest( pub async fn create_harvest(
&mut self, &mut self,
@ -505,6 +519,57 @@ impl ChorusUser {
chorus_request.deserialize_response(self).await 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 {
@ -659,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
}
} }

View File

@ -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,
}

View File

@ -267,3 +267,11 @@ pub struct GetRecentMentionsSchema {
pub(crate) struct CreateUserHarvestSchema { pub(crate) struct CreateUserHarvestSchema {
pub backends: Option<Vec<HarvestBackendType>>, 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>,
}