diff --git a/backend/src/api/controllers/result.ts b/backend/src/api/controllers/result.ts index 43384df86..606395612 100644 --- a/backend/src/api/controllers/result.ts +++ b/backend/src/api/controllers/result.ts @@ -65,6 +65,7 @@ import { import { MonkeyRequest } from "../types"; import { getFunbox, checkCompatibility } from "@monkeytype/funbox"; import { tryCatch } from "@monkeytype/util/trycatch"; +import { getCachedConfiguration } from "../../init/configuration"; try { if (!anticheatImplemented()) throw new Error("undefined"); @@ -491,12 +492,18 @@ export async function addResult( const stopOnLetterTriggered = completedEvent.stopOnLetter && completedEvent.acc < 100; + const minTimeTyping = (await getCachedConfiguration(true)).leaderboards + .minTimeTyping; + + const userEligibleForLeaderboard = + user.banned !== true && + user.lbOptOut !== true && + (isDevEnvironment() || (user.timeTyping ?? 0) > minTimeTyping); + const validResultCriteria = canFunboxGetPb(completedEvent) && !completedEvent.bailedOut && - user.banned !== true && - user.lbOptOut !== true && - (isDevEnvironment() || (user.timeTyping ?? 0) > 7200) && + userEligibleForLeaderboard && !stopOnLetterTriggered; const selectedBadgeId = user.inventory?.badges?.find((b) => b.selected)?.id; @@ -579,19 +586,11 @@ export async function addResult( const weeklyXpLeaderboardConfig = req.ctx.configuration.leaderboards.weeklyXp; let weeklyXpLeaderboardRank = -1; - const eligibleForWeeklyXpLeaderboard = - user.banned !== true && - user.lbOptOut !== true && - (isDevEnvironment() || (user.timeTyping ?? 0) > 7200); const weeklyXpLeaderboard = WeeklyXpLeaderboard.get( weeklyXpLeaderboardConfig ); - if ( - eligibleForWeeklyXpLeaderboard && - xpGained.xp > 0 && - weeklyXpLeaderboard - ) { + if (userEligibleForLeaderboard && xpGained.xp > 0 && weeklyXpLeaderboard) { weeklyXpLeaderboardRank = await weeklyXpLeaderboard.addResult( weeklyXpLeaderboardConfig, { diff --git a/backend/src/dal/leaderboards.ts b/backend/src/dal/leaderboards.ts index a5da921b7..a724c4de1 100644 --- a/backend/src/dal/leaderboards.ts +++ b/backend/src/dal/leaderboards.ts @@ -121,6 +121,8 @@ export async function update( }> { const key = `lbPersonalBests.${mode}.${mode2}.${language}`; const lbCollectionName = `leaderboards.${language}.${mode}.${mode2}`; + const minTimeTyping = (await getCachedConfiguration(true)).leaderboards + .minTimeTyping; const lb = db.collection("users").aggregate( [ { @@ -144,7 +146,7 @@ export async function update( $ne: true, }, timeTyping: { - $gt: isDevEnvironment() ? 0 : 7200, + $gt: isDevEnvironment() ? 0 : minTimeTyping, }, }, }, diff --git a/frontend/src/ts/pages/leaderboards.ts b/frontend/src/ts/pages/leaderboards.ts index f3eed90e2..3addecd66 100644 --- a/frontend/src/ts/pages/leaderboards.ts +++ b/frontend/src/ts/pages/leaderboards.ts @@ -15,6 +15,8 @@ import { endOfDay, endOfWeek, format, + formatDuration, + intervalToDuration, startOfDay, startOfWeek, subDays, @@ -43,6 +45,7 @@ import { LanguageSchema, } from "@monkeytype/contracts/schemas/languages"; import { isSafeNumber } from "@monkeytype/util/numbers"; +import * as ServerConfiguration from "../ape/server-configuration"; const LeaderboardTypeSchema = z.enum(["allTime", "weekly", "daily"]); type LeaderboardType = z.infer; @@ -629,13 +632,18 @@ function fillUser(): void { return; } + const minTimeTyping = + ServerConfiguration.get()?.leaderboards.minTimeTyping ?? 7200; + if ( isAuthenticated() && !isDevEnvironment() && - (DB.getSnapshot()?.typingStats?.timeTyping ?? 0) < 7200 + (DB.getSnapshot()?.typingStats?.timeTyping ?? 0) < minTimeTyping ) { $(".page.pageLeaderboards .bigUser").html( - '
Your account must have 2 hours typed to be placed on the leaderboard.
' + `
Your account must have ${formatDuration( + intervalToDuration({ start: 0, end: minTimeTyping * 1000 }) + )} typed to be placed on the leaderboard.
` ); return; }