add: 8 more achievements
This commit is contained in:
parent
8d70f65863
commit
a799c777ea
11 changed files with 121 additions and 18 deletions
|
@ -1084,10 +1084,12 @@
|
||||||
("href" "/journals/0/0")
|
("href" "/journals/0/0")
|
||||||
(icon (text "notebook"))
|
(icon (text "notebook"))
|
||||||
(str (text "general:link.journals")))
|
(str (text "general:link.journals")))
|
||||||
|
(text "{% if not user.settings.disable_achievements -%}")
|
||||||
(a
|
(a
|
||||||
("href" "/achievements")
|
("href" "/achievements")
|
||||||
(icon (text "award"))
|
(icon (text "award"))
|
||||||
(str (text "general:link.achievements")))
|
(str (text "general:link.achievements")))
|
||||||
|
(text "{%- endif %}")
|
||||||
(a
|
(a
|
||||||
("href" "/settings")
|
("href" "/settings")
|
||||||
(text "{{ icon \"settings\" }}")
|
(text "{{ icon \"settings\" }}")
|
||||||
|
|
|
@ -1553,6 +1553,11 @@
|
||||||
\"{{ profile.settings.disable_gpa_fun }}\",
|
\"{{ profile.settings.disable_gpa_fun }}\",
|
||||||
\"checkbox\",
|
\"checkbox\",
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
[\"disable_achievements\", \"Disable achievements\"],
|
||||||
|
\"{{ profile.settings.disable_achievements }}\",
|
||||||
|
\"checkbox\",
|
||||||
|
],
|
||||||
],
|
],
|
||||||
settings,
|
settings,
|
||||||
);
|
);
|
||||||
|
|
|
@ -979,7 +979,13 @@
|
||||||
|
|
||||||
self.define(
|
self.define(
|
||||||
"timestamp",
|
"timestamp",
|
||||||
({ $ }, updated_, progress_ms_, duration_ms_, display = "full") => {
|
async (
|
||||||
|
{ $ },
|
||||||
|
updated_,
|
||||||
|
progress_ms_,
|
||||||
|
duration_ms_,
|
||||||
|
display = "full",
|
||||||
|
) => {
|
||||||
if (duration_ms_ === "0") {
|
if (duration_ms_ === "0") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1003,7 +1009,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display === "full") {
|
if (display === "full") {
|
||||||
return `${$.ms_time_text(progress_ms)}/${$.ms_time_text(duration_ms)} <span class="fade">(${Math.floor((progress_ms / duration_ms) * 100)}%)</span>`;
|
return `${await $.ms_time_text(progress_ms)}/${await $.ms_time_text(duration_ms)} <span class="fade">(${Math.floor((progress_ms / duration_ms) * 100)}%)</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display === "left") {
|
if (display === "left") {
|
||||||
|
|
|
@ -292,11 +292,10 @@ pub async fn create_membership(
|
||||||
};
|
};
|
||||||
|
|
||||||
match data
|
match data
|
||||||
.create_membership(CommunityMembership::new(
|
.create_membership(
|
||||||
user.id,
|
CommunityMembership::new(user.id, id, CommunityPermission::default()),
|
||||||
id,
|
&user,
|
||||||
CommunityPermission::default(),
|
)
|
||||||
))
|
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(m) => Json(ApiReturn {
|
Ok(m) => Json(ApiReturn {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use axum::{
|
||||||
Extension, Json,
|
Extension, Json,
|
||||||
};
|
};
|
||||||
use axum_extra::extract::CookieJar;
|
use axum_extra::extract::CookieJar;
|
||||||
use tetratto_core::model::{communities::PostDraft, oauth, ApiReturn, Error};
|
use tetratto_core::model::{auth::AchievementName, communities::PostDraft, oauth, ApiReturn, Error};
|
||||||
use crate::{
|
use crate::{
|
||||||
get_user_from_token,
|
get_user_from_token,
|
||||||
routes::{
|
routes::{
|
||||||
|
@ -20,11 +20,20 @@ pub async fn create_request(
|
||||||
Json(req): Json<CreatePostDraft>,
|
Json(req): Json<CreatePostDraft>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let data = &(data.read().await).0;
|
let data = &(data.read().await).0;
|
||||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserCreateDrafts) {
|
let mut user = match get_user_from_token!(jar, data, oauth::AppScope::UserCreateDrafts) {
|
||||||
Some(ua) => ua,
|
Some(ua) => ua,
|
||||||
None => return Json(Error::NotAllowed.into()),
|
None => return Json(Error::NotAllowed.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// award achievement
|
||||||
|
if let Err(e) = data
|
||||||
|
.add_achievement(&mut user, AchievementName::CreateDraft.into())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
return Json(e.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
match data
|
match data
|
||||||
.create_draft(PostDraft::new(req.content, user.id))
|
.create_draft(PostDraft::new(req.content, user.id))
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -341,11 +341,20 @@ pub async fn update_content_request(
|
||||||
Json(req): Json<UpdatePostContent>,
|
Json(req): Json<UpdatePostContent>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let data = &(data.read().await).0;
|
let data = &(data.read().await).0;
|
||||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserEditPosts) {
|
let mut user = match get_user_from_token!(jar, data, oauth::AppScope::UserEditPosts) {
|
||||||
Some(ua) => ua,
|
Some(ua) => ua,
|
||||||
None => return Json(Error::NotAllowed.into()),
|
None => return Json(Error::NotAllowed.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// award achievement
|
||||||
|
if let Err(e) = data
|
||||||
|
.add_achievement(&mut user, AchievementName::EditPost.into())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
return Json(e.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
match data.update_post_content(id, user, req.content).await {
|
match data.update_post_content(id, user, req.content).await {
|
||||||
Ok(_) => Json(ApiReturn {
|
Ok(_) => Json(ApiReturn {
|
||||||
ok: true,
|
ok: true,
|
||||||
|
|
|
@ -713,6 +713,10 @@ impl DataManager {
|
||||||
///
|
///
|
||||||
/// Still returns `Ok` if the user already has the achievement.
|
/// Still returns `Ok` if the user already has the achievement.
|
||||||
pub async fn add_achievement(&self, user: &mut User, achievement: Achievement) -> Result<()> {
|
pub async fn add_achievement(&self, user: &mut User, achievement: Achievement) -> Result<()> {
|
||||||
|
if user.settings.disable_achievements {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
if user
|
if user
|
||||||
.achievements
|
.achievements
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -299,11 +299,10 @@ impl DataManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add community owner as admin
|
// add community owner as admin
|
||||||
self.create_membership(CommunityMembership::new(
|
self.create_membership(
|
||||||
data.owner,
|
CommunityMembership::new(data.owner, data.id, CommunityPermission::ADMINISTRATOR),
|
||||||
data.id,
|
&owner,
|
||||||
CommunityPermission::ADMINISTRATOR,
|
)
|
||||||
))
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use oiseau::cache::Cache;
|
use oiseau::cache::Cache;
|
||||||
|
use crate::model::auth::AchievementName;
|
||||||
use crate::model::communities::Community;
|
use crate::model::communities::Community;
|
||||||
use crate::model::requests::{ActionRequest, ActionType};
|
use crate::model::requests::{ActionRequest, ActionType};
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
|
@ -169,7 +170,11 @@ impl DataManager {
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `data` - a mock [`CommunityMembership`] object to insert
|
/// * `data` - a mock [`CommunityMembership`] object to insert
|
||||||
#[async_recursion::async_recursion]
|
#[async_recursion::async_recursion]
|
||||||
pub async fn create_membership(&self, data: CommunityMembership) -> Result<String> {
|
pub async fn create_membership(
|
||||||
|
&self,
|
||||||
|
data: CommunityMembership,
|
||||||
|
user: &User,
|
||||||
|
) -> Result<String> {
|
||||||
// make sure membership doesn't already exist
|
// make sure membership doesn't already exist
|
||||||
if self
|
if self
|
||||||
.get_membership_by_owner_community_no_void(data.owner, data.community)
|
.get_membership_by_owner_community_no_void(data.owner, data.community)
|
||||||
|
@ -199,7 +204,7 @@ impl DataManager {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
return self.create_membership(data).await;
|
return self.create_membership(data, user).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -237,6 +242,9 @@ impl DataManager {
|
||||||
Ok(if data.role.check(CommunityPermission::REQUESTED) {
|
Ok(if data.role.check(CommunityPermission::REQUESTED) {
|
||||||
"Join request sent".to_string()
|
"Join request sent".to_string()
|
||||||
} else {
|
} else {
|
||||||
|
self.add_achievement(&mut user.clone(), AchievementName::JoinCommunity.into())
|
||||||
|
.await?;
|
||||||
|
|
||||||
"Community joined".to_string()
|
"Community joined".to_string()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,6 +265,33 @@ impl DataManager {
|
||||||
self.add_achievement(&mut other_user, AchievementName::FollowedByStaff.into())
|
self.add_achievement(&mut other_user, AchievementName::FollowedByStaff.into())
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// other achivements
|
||||||
|
self.add_achievement(&mut other_user, AchievementName::Get1Follower.into())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if other_user.follower_count >= 9 {
|
||||||
|
self.add_achievement(&mut other_user, AchievementName::Get10Followers.into())
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if other_user.follower_count >= 49 {
|
||||||
|
self.add_achievement(&mut other_user, AchievementName::Get50Followers.into())
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if other_user.follower_count >= 99 {
|
||||||
|
self.add_achievement(&mut other_user, AchievementName::Get100Followers.into())
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if initiator.following_count >= 9 {
|
||||||
|
self.add_achievement(
|
||||||
|
&mut initiator.clone(),
|
||||||
|
AchievementName::Follow10Users.into(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -261,6 +261,9 @@ pub struct UserSettings {
|
||||||
/// Increase the text size of buttons and paragraphs.
|
/// Increase the text size of buttons and paragraphs.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub large_text: bool,
|
pub large_text: bool,
|
||||||
|
/// Disable achievements.
|
||||||
|
#[serde(default)]
|
||||||
|
pub disable_achievements: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mime_avif() -> String {
|
fn mime_avif() -> String {
|
||||||
|
@ -478,7 +481,7 @@ pub struct ExternalConnectionData {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The total number of achievements needed to 100% Tetratto!
|
/// The total number of achievements needed to 100% Tetratto!
|
||||||
pub const ACHIEVEMENTS: usize = 16;
|
pub const ACHIEVEMENTS: usize = 24;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum AchievementName {
|
pub enum AchievementName {
|
||||||
|
@ -498,6 +501,14 @@ pub enum AchievementName {
|
||||||
Get50Likes,
|
Get50Likes,
|
||||||
Get100Likes,
|
Get100Likes,
|
||||||
Get25Dislikes,
|
Get25Dislikes,
|
||||||
|
Get1Follower,
|
||||||
|
Get10Followers,
|
||||||
|
Get50Followers,
|
||||||
|
Get100Followers,
|
||||||
|
Follow10Users,
|
||||||
|
JoinCommunity,
|
||||||
|
CreateDraft,
|
||||||
|
EditPost,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
@ -526,6 +537,14 @@ impl AchievementName {
|
||||||
Self::Get50Likes => "banger post follow for more",
|
Self::Get50Likes => "banger post follow for more",
|
||||||
Self::Get100Likes => "everyone liked that",
|
Self::Get100Likes => "everyone liked that",
|
||||||
Self::Get25Dislikes => "Sorry...",
|
Self::Get25Dislikes => "Sorry...",
|
||||||
|
Self::Get1Follower => "Friends?",
|
||||||
|
Self::Get10Followers => "Friends!",
|
||||||
|
Self::Get50Followers => "50 WHOLE FOLLOWERS??",
|
||||||
|
Self::Get100Followers => "Everyone is my friend!",
|
||||||
|
Self::Follow10Users => "Big fan",
|
||||||
|
Self::JoinCommunity => "A sense of community...",
|
||||||
|
Self::CreateDraft => "Maybe later!",
|
||||||
|
Self::EditPost => "Grammar police?",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,6 +566,14 @@ impl AchievementName {
|
||||||
Self::Get50Likes => "Get 50 likes on one post.",
|
Self::Get50Likes => "Get 50 likes on one post.",
|
||||||
Self::Get100Likes => "Get 100 likes on one post.",
|
Self::Get100Likes => "Get 100 likes on one post.",
|
||||||
Self::Get25Dislikes => "Get 25 dislikes on one post... :(",
|
Self::Get25Dislikes => "Get 25 dislikes on one post... :(",
|
||||||
|
Self::Get1Follower => "Get 1 follow. 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..?",
|
||||||
|
Self::Follow10Users => "Follow 10 other users. I'm sure people appreciate it!",
|
||||||
|
Self::JoinCommunity => "Join a community. Welcome!",
|
||||||
|
Self::CreateDraft => "Save a post as a draft.",
|
||||||
|
Self::EditPost => "Edit a post.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,6 +597,14 @@ impl AchievementName {
|
||||||
Self::Get50Likes => Uncommon,
|
Self::Get50Likes => Uncommon,
|
||||||
Self::Get100Likes => Rare,
|
Self::Get100Likes => Rare,
|
||||||
Self::Get25Dislikes => Uncommon,
|
Self::Get25Dislikes => Uncommon,
|
||||||
|
Self::Get1Follower => Common,
|
||||||
|
Self::Get10Followers => Common,
|
||||||
|
Self::Get50Followers => Uncommon,
|
||||||
|
Self::Get100Followers => Rare,
|
||||||
|
Self::Follow10Users => Common,
|
||||||
|
Self::JoinCommunity => Common,
|
||||||
|
Self::CreateDraft => Common,
|
||||||
|
Self::EditPost => Common,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue