From b501a7c5f06ee2954ad11851110082f0e62d24b4 Mon Sep 17 00:00:00 2001 From: trisua Date: Sun, 29 Jun 2025 18:38:32 -0400 Subject: [PATCH] add: 4 more achievements --- crates/app/src/public/css/style.css | 3 ++- crates/app/src/routes/api/v1/auth/profile.rs | 11 ++++++++++- crates/app/src/routes/api/v1/notes.rs | 12 +++++++++++- crates/core/src/database/posts.rs | 13 +++++++++++-- crates/core/src/model/auth.rs | 20 ++++++++++++++++++-- 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/crates/app/src/public/css/style.css b/crates/app/src/public/css/style.css index 5533a96..24c41bd 100644 --- a/crates/app/src/public/css/style.css +++ b/crates/app/src/public/css/style.css @@ -582,6 +582,7 @@ input[type="checkbox"]:checked { font-size: 12px; border-radius: 6px; height: max-content; + font-weight: 600; } .notification.tr { @@ -670,7 +671,7 @@ nav .button:not(.title):not(.active):hover { margin-bottom: 0; backdrop-filter: none; bottom: 0; - position: absolute; + position: fixed; height: max-content; top: unset; } diff --git a/crates/app/src/routes/api/v1/auth/profile.rs b/crates/app/src/routes/api/v1/auth/profile.rs index 0d2bc49..1977d95 100644 --- a/crates/app/src/routes/api/v1/auth/profile.rs +++ b/crates/app/src/routes/api/v1/auth/profile.rs @@ -464,11 +464,20 @@ pub async fn enable_totp_request( Extension(data): Extension, ) -> impl IntoResponse { let data = &(data.read().await).0; - let user = match get_user_from_token!(jar, data) { + let mut user = match get_user_from_token!(jar, data) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; + // award achievement + if let Err(e) = data + .add_achievement(&mut user, AchievementName::Enable2fa.into()) + .await + { + return Json(e.into()); + } + + // ... match data.enable_totp(id, user).await { Ok(x) => Json(ApiReturn { ok: true, diff --git a/crates/app/src/routes/api/v1/notes.rs b/crates/app/src/routes/api/v1/notes.rs index b6bc986..ae67c4d 100644 --- a/crates/app/src/routes/api/v1/notes.rs +++ b/crates/app/src/routes/api/v1/notes.rs @@ -16,6 +16,7 @@ use crate::{ use tetratto_core::{ database::NAME_REGEX, model::{ + auth::AchievementName, journals::{JournalPrivacyPermission, Note}, oauth, permissions::FinePermission, @@ -190,11 +191,20 @@ pub async fn update_content_request( Json(props): Json, ) -> impl IntoResponse { let data = &(data.read().await).0; - let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageNotes) { + let mut user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageNotes) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; + // award achievement + if let Err(e) = data + .add_achievement(&mut user, AchievementName::EditNote.into()) + .await + { + return Json(e.into()); + } + + // ... match data.update_note_content(id, &user, &props.content).await { Ok(_) => { if let Err(e) = data diff --git a/crates/core/src/database/posts.rs b/crates/core/src/database/posts.rs index 011e653..f25e7ec 100644 --- a/crates/core/src/database/posts.rs +++ b/crates/core/src/database/posts.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; use crate::config::StringBan; -use crate::model::auth::Notification; +use crate::model::auth::{AchievementName, Notification}; use crate::model::communities::{CommunityMembership, CommunityReadAccess, Poll, Question}; use crate::model::communities_permissions::CommunityPermission; use crate::model::moderation::AuditLogEntry; @@ -1624,6 +1624,8 @@ impl DataManager { self.get_community_by_id(data.community).await? }; + let mut owner = self.get_user_by_id(data.owner).await?; + // check values (if this isn't reposting something else) let is_reposting = if let Some(ref repost) = data.context.repost { repost.reposting.is_some() @@ -1651,6 +1653,10 @@ impl DataManager { } else if data.title.len() > 128 { return Err(Error::DataTooLong("title".to_string())); } + + // award achievement + self.add_achievement(&mut owner, AchievementName::CreatePostWithTitle.into()) + .await?; } } @@ -1663,7 +1669,6 @@ impl DataManager { data.context.is_nsfw = community.context.is_nsfw; // remove request if we were answering a question - let owner = self.get_user_by_id(data.owner).await?; if data.context.answering != 0 { let question = self.get_question_by_id(data.context.answering).await?; @@ -1790,6 +1795,10 @@ impl DataManager { ) .await?; } + + // award achievement + self.add_achievement(&mut owner, AchievementName::CreateRepost.into()) + .await?; } // check if the post we're replying to allows commments diff --git a/crates/core/src/model/auth.rs b/crates/core/src/model/auth.rs index c91db34..4d332c7 100644 --- a/crates/core/src/model/auth.rs +++ b/crates/core/src/model/auth.rs @@ -490,7 +490,7 @@ pub struct ExternalConnectionData { } /// The total number of achievements needed to 100% Tetratto! -pub const ACHIEVEMENTS: usize = 24; +pub const ACHIEVEMENTS: usize = 28; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum AchievementName { @@ -518,6 +518,10 @@ pub enum AchievementName { JoinCommunity, CreateDraft, EditPost, + Enable2fa, + EditNote, + CreatePostWithTitle, + CreateRepost, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] @@ -554,6 +558,10 @@ impl AchievementName { Self::JoinCommunity => "A sense of community...", Self::CreateDraft => "Maybe later!", Self::EditPost => "Grammar police?", + Self::Enable2fa => "Locked in", + Self::EditNote => "I take it back!", + Self::CreatePostWithTitle => "Must declutter", + Self::CreateRepost => "More than a like or a comment...", } } @@ -575,7 +583,7 @@ impl AchievementName { Self::Get50Likes => "Get 50 likes on one post.", Self::Get100Likes => "Get 100 likes on one post.", Self::Get25Dislikes => "Get 25 dislikes on one post... :(", - Self::Get1Follower => "Get 1 follow. Cool!", + Self::Get1Follower => "Get 1 follower. Cool!", Self::Get10Followers => "Get 10 followers. You're getting popular!", Self::Get50Followers => "Get 50 followers. Okay, you're fairly popular!", Self::Get100Followers => "Get 100 followers. You might be famous..?", @@ -583,6 +591,10 @@ impl AchievementName { Self::JoinCommunity => "Join a community. Welcome!", Self::CreateDraft => "Save a post as a draft.", Self::EditPost => "Edit a post.", + Self::Enable2fa => "Enable TOTP 2FA.", + Self::EditNote => "Edit a note.", + Self::CreatePostWithTitle => "Create a post with a title.", + Self::CreateRepost => "Create a repost or quote.", } } @@ -614,6 +626,10 @@ impl AchievementName { Self::JoinCommunity => Common, Self::CreateDraft => Common, Self::EditPost => Common, + Self::Enable2fa => Rare, + Self::EditNote => Uncommon, + Self::CreatePostWithTitle => Common, + Self::CreateRepost => Common, } } }