mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-01-11 01:44:50 +08:00
refactor: Import shared types back into MonkeyTypes namespace (fehmer) (#4800)
* impr: Import shared types back into MonkeyTypes namespace, partially reverts #4769 * down to 6 errors * fixes * cleanup
This commit is contained in:
parent
cb6d61e1ca
commit
4b3059bdc7
16 changed files with 1776 additions and 483 deletions
1383
backend/package-lock.json
generated
1383
backend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -32,7 +32,7 @@
|
|||
"lodash": "4.17.21",
|
||||
"lru-cache": "7.10.1",
|
||||
"mjml": "4.13.0",
|
||||
"mongodb": "4.4.0",
|
||||
"mongodb": "4.17.1",
|
||||
"mustache": "4.2.0",
|
||||
"node-fetch": "2.6.7",
|
||||
"nodemailer": "6.9.1",
|
||||
|
|
@ -54,6 +54,7 @@
|
|||
"@types/bcrypt": "5.0.0",
|
||||
"@types/cors": "2.8.12",
|
||||
"@types/cron": "1.7.3",
|
||||
"@types/express": "4.17.21",
|
||||
"@types/ioredis": "4.28.10",
|
||||
"@types/jest": "27.5.0",
|
||||
"@types/lodash": "4.14.178",
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ import _ from "lodash";
|
|||
import * as WeeklyXpLeaderboard from "../../services/weekly-xp-leaderboard";
|
||||
import { UAParser } from "ua-parser-js";
|
||||
import { canFunboxGetPb } from "../../utils/pb";
|
||||
import { Configuration } from "../../types/shared";
|
||||
|
||||
try {
|
||||
if (anticheatImplemented() === false) throw new Error("undefined");
|
||||
|
|
@ -618,7 +617,7 @@ interface XpResult {
|
|||
|
||||
async function calculateXp(
|
||||
result,
|
||||
xpConfiguration: Configuration["users"]["xp"],
|
||||
xpConfiguration: MonkeyTypes.Configuration["users"]["xp"],
|
||||
uid: string,
|
||||
currentTotalXp: number,
|
||||
streak: number
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { Configuration } from "../types/shared";
|
||||
|
||||
/**
|
||||
* This is the base schema for the configuration of the API backend.
|
||||
* To add a new configuration. Simply add it to this object.
|
||||
* When changing this template, please follow the principle of "Secure by default" (https://en.wikipedia.org/wiki/Secure_by_default).
|
||||
*/
|
||||
export const BASE_CONFIGURATION: Configuration = {
|
||||
export const BASE_CONFIGURATION: MonkeyTypes.Configuration = {
|
||||
maintenance: false,
|
||||
results: {
|
||||
savingEnabled: false,
|
||||
|
|
@ -139,421 +137,423 @@ type Schema<T> = {
|
|||
: never;
|
||||
};
|
||||
|
||||
export const CONFIGURATION_FORM_SCHEMA: ObjectSchema<Configuration> = {
|
||||
type: "object",
|
||||
label: "Server Configuration",
|
||||
fields: {
|
||||
maintenance: {
|
||||
type: "boolean",
|
||||
label: "In Maintenance",
|
||||
},
|
||||
results: {
|
||||
type: "object",
|
||||
label: "Results",
|
||||
fields: {
|
||||
savingEnabled: {
|
||||
type: "boolean",
|
||||
label: "Saving Results",
|
||||
},
|
||||
objectHashCheckEnabled: {
|
||||
type: "boolean",
|
||||
label: "Object Hash Check",
|
||||
},
|
||||
filterPresets: {
|
||||
type: "object",
|
||||
label: "Filter Presets",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxPresetsPerUser: {
|
||||
type: "number",
|
||||
label: "Max Presets Per User",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
limits: {
|
||||
type: "object",
|
||||
label: "maximum results",
|
||||
fields: {
|
||||
regularUser: {
|
||||
type: "number",
|
||||
label: "for regular users",
|
||||
min: 0,
|
||||
},
|
||||
premiumUser: {
|
||||
type: "number",
|
||||
label: "for premium users",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
export const CONFIGURATION_FORM_SCHEMA: ObjectSchema<MonkeyTypes.Configuration> =
|
||||
{
|
||||
type: "object",
|
||||
label: "Server Configuration",
|
||||
fields: {
|
||||
maintenance: {
|
||||
type: "boolean",
|
||||
label: "In Maintenance",
|
||||
},
|
||||
},
|
||||
quotes: {
|
||||
type: "object",
|
||||
label: "Quotes",
|
||||
fields: {
|
||||
reporting: {
|
||||
type: "object",
|
||||
label: "Reporting",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxReports: {
|
||||
type: "number",
|
||||
label: "Max Reports",
|
||||
},
|
||||
contentReportLimit: {
|
||||
type: "number",
|
||||
label: "Content Report Limit",
|
||||
},
|
||||
results: {
|
||||
type: "object",
|
||||
label: "Results",
|
||||
fields: {
|
||||
savingEnabled: {
|
||||
type: "boolean",
|
||||
label: "Saving Results",
|
||||
},
|
||||
},
|
||||
submissionsEnabled: {
|
||||
type: "boolean",
|
||||
label: "Submissions Enabled",
|
||||
},
|
||||
maxFavorites: {
|
||||
type: "number",
|
||||
label: "Max Favorites",
|
||||
},
|
||||
},
|
||||
},
|
||||
admin: {
|
||||
type: "object",
|
||||
label: "Admin",
|
||||
fields: {
|
||||
endpointsEnabled: {
|
||||
type: "boolean",
|
||||
label: "Endpoints Enabled",
|
||||
},
|
||||
},
|
||||
},
|
||||
apeKeys: {
|
||||
type: "object",
|
||||
label: "Ape Keys",
|
||||
fields: {
|
||||
endpointsEnabled: {
|
||||
type: "boolean",
|
||||
label: "Endpoints Enabled",
|
||||
},
|
||||
acceptKeys: {
|
||||
type: "boolean",
|
||||
label: "Accept Keys",
|
||||
},
|
||||
maxKeysPerUser: {
|
||||
type: "number",
|
||||
label: "Max Keys Per User",
|
||||
min: 0,
|
||||
},
|
||||
apeKeyBytes: {
|
||||
type: "number",
|
||||
label: "Ape Key Bytes",
|
||||
min: 24,
|
||||
},
|
||||
apeKeySaltRounds: {
|
||||
type: "number",
|
||||
label: "Ape Key Salt Rounds",
|
||||
min: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
users: {
|
||||
type: "object",
|
||||
label: "Users",
|
||||
fields: {
|
||||
signUp: {
|
||||
type: "boolean",
|
||||
label: "Sign Up Enabled",
|
||||
},
|
||||
lastHashesCheck: {
|
||||
type: "object",
|
||||
label: "Last Hashes Check",
|
||||
fields: {
|
||||
enabled: { type: "boolean", label: "Enabled" },
|
||||
maxHashes: { type: "number", label: "Hashes to store" },
|
||||
objectHashCheckEnabled: {
|
||||
type: "boolean",
|
||||
label: "Object Hash Check",
|
||||
},
|
||||
},
|
||||
xp: {
|
||||
type: "object",
|
||||
label: "XP",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
gainMultiplier: {
|
||||
type: "number",
|
||||
label: "Gain Multiplier",
|
||||
},
|
||||
funboxBonus: {
|
||||
type: "number",
|
||||
label: "Funbox Bonus",
|
||||
},
|
||||
maxDailyBonus: {
|
||||
type: "number",
|
||||
label: "Max Daily Bonus",
|
||||
},
|
||||
minDailyBonus: {
|
||||
type: "number",
|
||||
label: "Min Daily Bonus",
|
||||
},
|
||||
streak: {
|
||||
type: "object",
|
||||
label: "Streak",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxStreakDays: {
|
||||
type: "number",
|
||||
label: "Max Streak Days",
|
||||
},
|
||||
maxStreakMultiplier: {
|
||||
type: "number",
|
||||
label: "Max Streak Multiplier",
|
||||
},
|
||||
filterPresets: {
|
||||
type: "object",
|
||||
label: "Filter Presets",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxPresetsPerUser: {
|
||||
type: "number",
|
||||
label: "Max Presets Per User",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
discordIntegration: {
|
||||
type: "object",
|
||||
label: "Discord Integration",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
},
|
||||
},
|
||||
autoBan: {
|
||||
type: "object",
|
||||
label: "Auto Ban",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxCount: {
|
||||
type: "number",
|
||||
label: "Max Count",
|
||||
min: 0,
|
||||
},
|
||||
maxHours: {
|
||||
type: "number",
|
||||
label: "Max Hours",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
inbox: {
|
||||
type: "object",
|
||||
label: "Inbox",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxMail: {
|
||||
type: "number",
|
||||
label: "Max Messages",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
profiles: {
|
||||
type: "object",
|
||||
label: "User Profiles",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rateLimiting: {
|
||||
type: "object",
|
||||
label: "Rate Limiting",
|
||||
fields: {
|
||||
badAuthentication: {
|
||||
type: "object",
|
||||
label: "Bad Authentication Rate Limiter",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
penalty: {
|
||||
type: "number",
|
||||
label: "Penalty",
|
||||
min: 0,
|
||||
},
|
||||
flaggedStatusCodes: {
|
||||
type: "array",
|
||||
label: "Flagged Status Codes",
|
||||
items: {
|
||||
label: "Status Code",
|
||||
limits: {
|
||||
type: "object",
|
||||
label: "maximum results",
|
||||
fields: {
|
||||
regularUser: {
|
||||
type: "number",
|
||||
label: "for regular users",
|
||||
min: 0,
|
||||
},
|
||||
premiumUser: {
|
||||
type: "number",
|
||||
label: "for premium users",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
dailyLeaderboards: {
|
||||
type: "object",
|
||||
label: "Daily Leaderboards",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxResults: {
|
||||
type: "number",
|
||||
label: "Max Results",
|
||||
min: 0,
|
||||
},
|
||||
leaderboardExpirationTimeInDays: {
|
||||
type: "number",
|
||||
label: "Leaderboard Expiration Time In Days",
|
||||
min: 0,
|
||||
},
|
||||
validModeRules: {
|
||||
type: "array",
|
||||
label: "Valid Mode Rules",
|
||||
items: {
|
||||
quotes: {
|
||||
type: "object",
|
||||
label: "Quotes",
|
||||
fields: {
|
||||
reporting: {
|
||||
type: "object",
|
||||
label: "Rule",
|
||||
label: "Reporting",
|
||||
fields: {
|
||||
language: {
|
||||
type: "string",
|
||||
label: "Language",
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
mode: {
|
||||
type: "string",
|
||||
label: "Mode",
|
||||
maxReports: {
|
||||
type: "number",
|
||||
label: "Max Reports",
|
||||
},
|
||||
mode2: {
|
||||
type: "string",
|
||||
label: "Secondary Mode",
|
||||
contentReportLimit: {
|
||||
type: "number",
|
||||
label: "Content Report Limit",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
scheduleRewardsModeRules: {
|
||||
type: "array",
|
||||
label: "Schedule Rewards Mode Rules",
|
||||
items: {
|
||||
type: "object",
|
||||
label: "Rule",
|
||||
fields: {
|
||||
language: {
|
||||
type: "string",
|
||||
label: "Language",
|
||||
},
|
||||
mode: {
|
||||
type: "string",
|
||||
label: "Mode",
|
||||
},
|
||||
mode2: {
|
||||
type: "string",
|
||||
label: "Secondary Mode",
|
||||
},
|
||||
},
|
||||
submissionsEnabled: {
|
||||
type: "boolean",
|
||||
label: "Submissions Enabled",
|
||||
},
|
||||
},
|
||||
topResultsToAnnounce: {
|
||||
type: "number",
|
||||
label: "Top Results To Announce",
|
||||
min: 1,
|
||||
hint: "This should atleast be 1. Setting to zero is very bad.",
|
||||
},
|
||||
xpRewardBrackets: {
|
||||
type: "array",
|
||||
label: "XP Reward Brackets",
|
||||
items: {
|
||||
type: "object",
|
||||
label: "Bracket",
|
||||
fields: {
|
||||
minRank: {
|
||||
type: "number",
|
||||
label: "Min Rank",
|
||||
min: 1,
|
||||
},
|
||||
maxRank: {
|
||||
type: "number",
|
||||
label: "Max Rank",
|
||||
min: 1,
|
||||
},
|
||||
minReward: {
|
||||
type: "number",
|
||||
label: "Min Reward",
|
||||
min: 0,
|
||||
},
|
||||
maxReward: {
|
||||
type: "number",
|
||||
label: "Max Reward",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
maxFavorites: {
|
||||
type: "number",
|
||||
label: "Max Favorites",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
leaderboards: {
|
||||
type: "object",
|
||||
label: "Leaderboards",
|
||||
fields: {
|
||||
weeklyXp: {
|
||||
type: "object",
|
||||
label: "Weekly XP",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
admin: {
|
||||
type: "object",
|
||||
label: "Admin",
|
||||
fields: {
|
||||
endpointsEnabled: {
|
||||
type: "boolean",
|
||||
label: "Endpoints Enabled",
|
||||
},
|
||||
},
|
||||
},
|
||||
apeKeys: {
|
||||
type: "object",
|
||||
label: "Ape Keys",
|
||||
fields: {
|
||||
endpointsEnabled: {
|
||||
type: "boolean",
|
||||
label: "Endpoints Enabled",
|
||||
},
|
||||
acceptKeys: {
|
||||
type: "boolean",
|
||||
label: "Accept Keys",
|
||||
},
|
||||
maxKeysPerUser: {
|
||||
type: "number",
|
||||
label: "Max Keys Per User",
|
||||
min: 0,
|
||||
},
|
||||
apeKeyBytes: {
|
||||
type: "number",
|
||||
label: "Ape Key Bytes",
|
||||
min: 24,
|
||||
},
|
||||
apeKeySaltRounds: {
|
||||
type: "number",
|
||||
label: "Ape Key Salt Rounds",
|
||||
min: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
users: {
|
||||
type: "object",
|
||||
label: "Users",
|
||||
fields: {
|
||||
signUp: {
|
||||
type: "boolean",
|
||||
label: "Sign Up Enabled",
|
||||
},
|
||||
lastHashesCheck: {
|
||||
type: "object",
|
||||
label: "Last Hashes Check",
|
||||
fields: {
|
||||
enabled: { type: "boolean", label: "Enabled" },
|
||||
maxHashes: { type: "number", label: "Hashes to store" },
|
||||
},
|
||||
expirationTimeInDays: {
|
||||
type: "number",
|
||||
label: "Expiration time in days",
|
||||
min: 0,
|
||||
hint: "This should atleast be 15, to allow for past week queries.",
|
||||
},
|
||||
xpRewardBrackets: {
|
||||
type: "array",
|
||||
label: "XP Reward Brackets",
|
||||
items: {
|
||||
},
|
||||
xp: {
|
||||
type: "object",
|
||||
label: "XP",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
gainMultiplier: {
|
||||
type: "number",
|
||||
label: "Gain Multiplier",
|
||||
},
|
||||
funboxBonus: {
|
||||
type: "number",
|
||||
label: "Funbox Bonus",
|
||||
},
|
||||
maxDailyBonus: {
|
||||
type: "number",
|
||||
label: "Max Daily Bonus",
|
||||
},
|
||||
minDailyBonus: {
|
||||
type: "number",
|
||||
label: "Min Daily Bonus",
|
||||
},
|
||||
streak: {
|
||||
type: "object",
|
||||
label: "Bracket",
|
||||
label: "Streak",
|
||||
fields: {
|
||||
minRank: {
|
||||
type: "number",
|
||||
label: "Min Rank",
|
||||
min: 1,
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxRank: {
|
||||
maxStreakDays: {
|
||||
type: "number",
|
||||
label: "Max Rank",
|
||||
min: 1,
|
||||
label: "Max Streak Days",
|
||||
},
|
||||
minReward: {
|
||||
maxStreakMultiplier: {
|
||||
type: "number",
|
||||
label: "Min Reward",
|
||||
min: 0,
|
||||
label: "Max Streak Multiplier",
|
||||
},
|
||||
maxReward: {
|
||||
type: "number",
|
||||
label: "Max Reward",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
discordIntegration: {
|
||||
type: "object",
|
||||
label: "Discord Integration",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
},
|
||||
},
|
||||
autoBan: {
|
||||
type: "object",
|
||||
label: "Auto Ban",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxCount: {
|
||||
type: "number",
|
||||
label: "Max Count",
|
||||
min: 0,
|
||||
},
|
||||
maxHours: {
|
||||
type: "number",
|
||||
label: "Max Hours",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
inbox: {
|
||||
type: "object",
|
||||
label: "Inbox",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxMail: {
|
||||
type: "number",
|
||||
label: "Max Messages",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
profiles: {
|
||||
type: "object",
|
||||
label: "User Profiles",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rateLimiting: {
|
||||
type: "object",
|
||||
label: "Rate Limiting",
|
||||
fields: {
|
||||
badAuthentication: {
|
||||
type: "object",
|
||||
label: "Bad Authentication Rate Limiter",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
penalty: {
|
||||
type: "number",
|
||||
label: "Penalty",
|
||||
min: 0,
|
||||
},
|
||||
flaggedStatusCodes: {
|
||||
type: "array",
|
||||
label: "Flagged Status Codes",
|
||||
items: {
|
||||
label: "Status Code",
|
||||
type: "number",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
dailyLeaderboards: {
|
||||
type: "object",
|
||||
label: "Daily Leaderboards",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
maxResults: {
|
||||
type: "number",
|
||||
label: "Max Results",
|
||||
min: 0,
|
||||
},
|
||||
leaderboardExpirationTimeInDays: {
|
||||
type: "number",
|
||||
label: "Leaderboard Expiration Time In Days",
|
||||
min: 0,
|
||||
},
|
||||
validModeRules: {
|
||||
type: "array",
|
||||
label: "Valid Mode Rules",
|
||||
items: {
|
||||
type: "object",
|
||||
label: "Rule",
|
||||
fields: {
|
||||
language: {
|
||||
type: "string",
|
||||
label: "Language",
|
||||
},
|
||||
mode: {
|
||||
type: "string",
|
||||
label: "Mode",
|
||||
},
|
||||
mode2: {
|
||||
type: "string",
|
||||
label: "Secondary Mode",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
scheduleRewardsModeRules: {
|
||||
type: "array",
|
||||
label: "Schedule Rewards Mode Rules",
|
||||
items: {
|
||||
type: "object",
|
||||
label: "Rule",
|
||||
fields: {
|
||||
language: {
|
||||
type: "string",
|
||||
label: "Language",
|
||||
},
|
||||
mode: {
|
||||
type: "string",
|
||||
label: "Mode",
|
||||
},
|
||||
mode2: {
|
||||
type: "string",
|
||||
label: "Secondary Mode",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
topResultsToAnnounce: {
|
||||
type: "number",
|
||||
label: "Top Results To Announce",
|
||||
min: 1,
|
||||
hint: "This should atleast be 1. Setting to zero is very bad.",
|
||||
},
|
||||
xpRewardBrackets: {
|
||||
type: "array",
|
||||
label: "XP Reward Brackets",
|
||||
items: {
|
||||
type: "object",
|
||||
label: "Bracket",
|
||||
fields: {
|
||||
minRank: {
|
||||
type: "number",
|
||||
label: "Min Rank",
|
||||
min: 1,
|
||||
},
|
||||
maxRank: {
|
||||
type: "number",
|
||||
label: "Max Rank",
|
||||
min: 1,
|
||||
},
|
||||
minReward: {
|
||||
type: "number",
|
||||
label: "Min Reward",
|
||||
min: 0,
|
||||
},
|
||||
maxReward: {
|
||||
type: "number",
|
||||
label: "Max Reward",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
leaderboards: {
|
||||
type: "object",
|
||||
label: "Leaderboards",
|
||||
fields: {
|
||||
weeklyXp: {
|
||||
type: "object",
|
||||
label: "Weekly XP",
|
||||
fields: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
label: "Enabled",
|
||||
},
|
||||
expirationTimeInDays: {
|
||||
type: "number",
|
||||
label: "Expiration time in days",
|
||||
min: 0,
|
||||
hint: "This should atleast be 15, to allow for past week queries.",
|
||||
},
|
||||
xpRewardBrackets: {
|
||||
type: "array",
|
||||
label: "XP Reward Brackets",
|
||||
items: {
|
||||
type: "object",
|
||||
label: "Bracket",
|
||||
fields: {
|
||||
minRank: {
|
||||
type: "number",
|
||||
label: "Min Rank",
|
||||
min: 1,
|
||||
},
|
||||
maxRank: {
|
||||
type: "number",
|
||||
label: "Max Rank",
|
||||
min: 1,
|
||||
},
|
||||
minReward: {
|
||||
type: "number",
|
||||
label: "Min Reward",
|
||||
min: 0,
|
||||
},
|
||||
maxReward: {
|
||||
type: "number",
|
||||
label: "Max Reward",
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -562,5 +562,4 @@ export const CONFIGURATION_FORM_SCHEMA: ObjectSchema<Configuration> = {
|
|||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import MonkeyError from "../utils/error";
|
|||
import { Collection, ObjectId, WithId, Long, UpdateFilter } from "mongodb";
|
||||
import Logger from "../utils/logger";
|
||||
import { flattenObjectDeep, isToday, isYesterday } from "../utils/misc";
|
||||
import { Configuration } from "../types/shared";
|
||||
|
||||
const SECONDS_PER_HOUR = 3600;
|
||||
|
||||
|
|
@ -20,7 +19,7 @@ export async function addUser(
|
|||
email: string,
|
||||
uid: string
|
||||
): Promise<void> {
|
||||
const newUserDocument: MonkeyTypes.User = {
|
||||
const newUserDocument: Partial<MonkeyTypes.User> = {
|
||||
name,
|
||||
email,
|
||||
uid,
|
||||
|
|
@ -549,7 +548,10 @@ export async function linkDiscord(
|
|||
discordId: string,
|
||||
discordAvatar?: string
|
||||
): Promise<void> {
|
||||
const updates = _.pickBy({ discordId, discordAvatar }, _.identity);
|
||||
const updates: Partial<MonkeyTypes.User> = _.pickBy(
|
||||
{ discordId, discordAvatar },
|
||||
_.identity
|
||||
);
|
||||
const result = await getUsersCollection().updateOne(
|
||||
{ uid },
|
||||
{ $set: updates }
|
||||
|
|
@ -845,7 +847,7 @@ interface AddToInboxBulkEntry {
|
|||
|
||||
export async function addToInboxBulk(
|
||||
entries: AddToInboxBulkEntry[],
|
||||
inboxConfig: Configuration["users"]["inbox"]
|
||||
inboxConfig: MonkeyTypes.Configuration["users"]["inbox"]
|
||||
): Promise<void> {
|
||||
const { enabled, maxMail } = inboxConfig;
|
||||
|
||||
|
|
@ -873,7 +875,7 @@ export async function addToInboxBulk(
|
|||
export async function addToInbox(
|
||||
uid: string,
|
||||
mail: MonkeyTypes.MonkeyMail[],
|
||||
inboxConfig: Configuration["users"]["inbox"]
|
||||
inboxConfig: MonkeyTypes.Configuration["users"]["inbox"]
|
||||
): Promise<void> {
|
||||
const { enabled, maxMail } = inboxConfig;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@ import { ObjectId } from "mongodb";
|
|||
import Logger from "../utils/logger";
|
||||
import { identity } from "../utils/misc";
|
||||
import { BASE_CONFIGURATION } from "../constants/base-configuration";
|
||||
import { Configuration } from "../types/shared";
|
||||
|
||||
const CONFIG_UPDATE_INTERVAL = 10 * 60 * 1000; // 10 Minutes
|
||||
|
||||
function mergeConfigurations(
|
||||
baseConfiguration: Configuration,
|
||||
liveConfiguration: Partial<Configuration>
|
||||
baseConfiguration: MonkeyTypes.Configuration,
|
||||
liveConfiguration: Partial<MonkeyTypes.Configuration>
|
||||
): void {
|
||||
if (
|
||||
!_.isPlainObject(baseConfiguration) ||
|
||||
|
|
@ -46,7 +45,7 @@ let serverConfigurationUpdated = false;
|
|||
|
||||
export async function getCachedConfiguration(
|
||||
attemptCacheUpdate = false
|
||||
): Promise<Configuration> {
|
||||
): Promise<MonkeyTypes.Configuration> {
|
||||
if (
|
||||
attemptCacheUpdate &&
|
||||
lastFetchTime < Date.now() - CONFIG_UPDATE_INTERVAL
|
||||
|
|
@ -58,7 +57,7 @@ export async function getCachedConfiguration(
|
|||
return configuration;
|
||||
}
|
||||
|
||||
export async function getLiveConfiguration(): Promise<Configuration> {
|
||||
export async function getLiveConfiguration(): Promise<MonkeyTypes.Configuration> {
|
||||
lastFetchTime = Date.now();
|
||||
|
||||
const configurationCollection = db.collection("configuration");
|
||||
|
|
@ -72,7 +71,7 @@ export async function getLiveConfiguration(): Promise<Configuration> {
|
|||
const liveConfigurationWithoutId = _.omit(
|
||||
liveConfiguration,
|
||||
"_id"
|
||||
) as Configuration;
|
||||
) as MonkeyTypes.Configuration;
|
||||
mergeConfigurations(baseConfiguration, liveConfigurationWithoutId);
|
||||
|
||||
pushConfiguration(baseConfiguration);
|
||||
|
|
@ -93,7 +92,9 @@ export async function getLiveConfiguration(): Promise<Configuration> {
|
|||
return configuration;
|
||||
}
|
||||
|
||||
async function pushConfiguration(configuration: Configuration): Promise<void> {
|
||||
async function pushConfiguration(
|
||||
configuration: MonkeyTypes.Configuration
|
||||
): Promise<void> {
|
||||
if (serverConfigurationUpdated) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -110,7 +111,7 @@ async function pushConfiguration(configuration: Configuration): Promise<void> {
|
|||
}
|
||||
|
||||
export async function patchConfiguration(
|
||||
configurationUpdates: Partial<Configuration>
|
||||
configurationUpdates: Partial<MonkeyTypes.Configuration>
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const currentConfiguration = _.cloneDeep(configuration);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { Response, NextFunction, RequestHandler } from "express";
|
|||
import { handleMonkeyResponse, MonkeyResponse } from "../utils/monkey-response";
|
||||
import { getUser } from "../dal/user";
|
||||
import { isAdmin } from "../dal/admin-uids";
|
||||
import { Configuration } from "../types/shared";
|
||||
|
||||
interface ValidationOptions<T> {
|
||||
criteria: (data: T) => boolean;
|
||||
|
|
@ -23,7 +22,7 @@ const emptyMiddleware = (
|
|||
* the criteria.
|
||||
*/
|
||||
function validateConfiguration(
|
||||
options: ValidationOptions<Configuration>
|
||||
options: ValidationOptions<MonkeyTypes.Configuration>
|
||||
): RequestHandler {
|
||||
const {
|
||||
criteria,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import {
|
|||
} from "../utils/prometheus";
|
||||
import crypto from "crypto";
|
||||
import { performance } from "perf_hooks";
|
||||
import { Configuration } from "../types/shared";
|
||||
|
||||
interface RequestAuthenticationOptions {
|
||||
isPublic?: boolean;
|
||||
|
|
@ -127,7 +126,7 @@ function authenticateWithBody(
|
|||
|
||||
async function authenticateWithAuthHeader(
|
||||
authHeader: string,
|
||||
configuration: Configuration,
|
||||
configuration: MonkeyTypes.Configuration,
|
||||
options: RequestAuthenticationOptions
|
||||
): Promise<MonkeyTypes.DecodedToken> {
|
||||
const [authScheme, token] = authHeader.split(" ");
|
||||
|
|
@ -210,7 +209,7 @@ async function authenticateWithBearerToken(
|
|||
|
||||
async function authenticateWithApeKey(
|
||||
key: string,
|
||||
configuration: Configuration,
|
||||
configuration: MonkeyTypes.Configuration,
|
||||
options: RequestAuthenticationOptions
|
||||
): Promise<MonkeyTypes.DecodedToken> {
|
||||
if (!configuration.apeKeys.acceptKeys) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import LRUCache from "lru-cache";
|
|||
import Logger from "../utils/logger";
|
||||
import { MonkeyQueue } from "./monkey-queue";
|
||||
import { getCurrentDayTimestamp, getCurrentWeekTimestamp } from "../utils/misc";
|
||||
import { ValidModeRule } from "../types/shared";
|
||||
|
||||
const QUEUE_NAME = "later";
|
||||
|
||||
|
|
@ -18,7 +17,7 @@ export interface LaterTask<T extends LaterTaskType> {
|
|||
export type LaterTaskContexts = {
|
||||
"daily-leaderboard-results": {
|
||||
yesterdayTimestamp: number;
|
||||
modeRule: ValidModeRule;
|
||||
modeRule: MonkeyTypes.ValidModeRule;
|
||||
};
|
||||
"weekly-xp-leaderboard-results": {
|
||||
lastWeekTimestamp: number;
|
||||
|
|
@ -83,7 +82,7 @@ class LaterQueue extends MonkeyQueue<LaterTask<LaterTaskType>> {
|
|||
async scheduleForTomorrow(
|
||||
taskName: LaterTaskType,
|
||||
taskId: string,
|
||||
modeRule: ValidModeRule
|
||||
modeRule: MonkeyTypes.ValidModeRule
|
||||
): Promise<void> {
|
||||
const currentDayTimestamp = getCurrentDayTimestamp();
|
||||
const jobId = `${taskName}:${currentDayTimestamp}:${taskId}`;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import * as RedisClient from "../init/redis";
|
||||
import LaterQueue from "../queues/later-queue";
|
||||
import { Configuration } from "../types/shared";
|
||||
import { getCurrentWeekTimestamp } from "../utils/misc";
|
||||
|
||||
interface InternalWeeklyXpLeaderboardEntry {
|
||||
|
|
@ -60,7 +59,7 @@ export class WeeklyXpLeaderboard {
|
|||
}
|
||||
|
||||
public async addResult(
|
||||
weeklyXpLeaderboardConfig: Configuration["leaderboards"]["weeklyXp"],
|
||||
weeklyXpLeaderboardConfig: MonkeyTypes.Configuration["leaderboards"]["weeklyXp"],
|
||||
opts: AddResultOpts
|
||||
): Promise<number> {
|
||||
const { entry, xpGained, timeTypedSeconds } = opts;
|
||||
|
|
@ -117,7 +116,7 @@ export class WeeklyXpLeaderboard {
|
|||
public async getResults(
|
||||
minRank: number,
|
||||
maxRank: number,
|
||||
weeklyXpLeaderboardConfig: Configuration["leaderboards"]["weeklyXp"]
|
||||
weeklyXpLeaderboardConfig: MonkeyTypes.Configuration["leaderboards"]["weeklyXp"]
|
||||
): Promise<WeeklyXpLeaderboardEntry[]> {
|
||||
const connection = RedisClient.getConnection();
|
||||
if (!connection || !weeklyXpLeaderboardConfig.enabled) {
|
||||
|
|
@ -150,7 +149,7 @@ export class WeeklyXpLeaderboard {
|
|||
|
||||
public async getRank(
|
||||
uid: string,
|
||||
weeklyXpLeaderboardConfig: Configuration["leaderboards"]["weeklyXp"]
|
||||
weeklyXpLeaderboardConfig: MonkeyTypes.Configuration["leaderboards"]["weeklyXp"]
|
||||
): Promise<WeeklyXpLeaderboardEntry | null> {
|
||||
const connection = RedisClient.getConnection();
|
||||
if (!connection || !weeklyXpLeaderboardConfig.enabled) {
|
||||
|
|
@ -184,7 +183,7 @@ export class WeeklyXpLeaderboard {
|
|||
}
|
||||
|
||||
export function get(
|
||||
weeklyXpLeaderboardConfig: Configuration["leaderboards"]["weeklyXp"],
|
||||
weeklyXpLeaderboardConfig: MonkeyTypes.Configuration["leaderboards"]["weeklyXp"],
|
||||
customTimestamp?: number
|
||||
): WeeklyXpLeaderboard | null {
|
||||
const { enabled } = weeklyXpLeaderboardConfig;
|
||||
|
|
|
|||
10
backend/src/types/types.d.ts
vendored
10
backend/src/types/types.d.ts
vendored
|
|
@ -3,6 +3,9 @@ type ObjectId = import("mongodb").ObjectId;
|
|||
type ExpressRequest = import("express").Request;
|
||||
|
||||
declare namespace MonkeyTypes {
|
||||
type Configuration = import("./shared").Configuration;
|
||||
type ValidModeRule = import("./shared").ValidModeRule;
|
||||
type RewardBracket = import("./shared").RewardBracket;
|
||||
interface DecodedToken {
|
||||
type: "Bearer" | "ApeKey" | "None";
|
||||
uid: string;
|
||||
|
|
@ -168,7 +171,7 @@ declare namespace MonkeyTypes {
|
|||
[language: string]: boolean;
|
||||
};
|
||||
funbox: {
|
||||
none?: boolean;
|
||||
none: boolean;
|
||||
[funbox: string]: boolean;
|
||||
};
|
||||
}
|
||||
|
|
@ -361,9 +364,12 @@ declare namespace MonkeyTypes {
|
|||
type: string;
|
||||
}
|
||||
|
||||
interface PublicSpeedStats {
|
||||
type PublicSpeedStats = TypedMongoEntry & PublicSpeedStatsByLanguage;
|
||||
interface TypedMongoEntry {
|
||||
_id: string;
|
||||
type: "speedStats";
|
||||
}
|
||||
interface PublicSpeedStatsByLanguage {
|
||||
[language_mode_mode2: string]: Record<string, number>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import _ from "lodash";
|
|||
import * as RedisClient from "../init/redis";
|
||||
import LaterQueue from "../queues/later-queue";
|
||||
import { getCurrentDayTimestamp, matchesAPattern, kogascore } from "./misc";
|
||||
import { Configuration, ValidModeRule } from "../types/shared";
|
||||
|
||||
interface DailyLeaderboardEntry {
|
||||
uid: string;
|
||||
|
|
@ -37,9 +36,9 @@ export class DailyLeaderboard {
|
|||
private leaderboardScoresKeyName: string;
|
||||
private leaderboardModeKey: string;
|
||||
private customTime: number;
|
||||
private modeRule: ValidModeRule;
|
||||
private modeRule: MonkeyTypes.ValidModeRule;
|
||||
|
||||
constructor(modeRule: ValidModeRule, customTime = -1) {
|
||||
constructor(modeRule: MonkeyTypes.ValidModeRule, customTime = -1) {
|
||||
const { language, mode, mode2 } = modeRule;
|
||||
|
||||
this.leaderboardModeKey = `${language}:${mode}:${mode2}`;
|
||||
|
|
@ -68,7 +67,7 @@ export class DailyLeaderboard {
|
|||
|
||||
public async addResult(
|
||||
entry: DailyLeaderboardEntry,
|
||||
dailyLeaderboardsConfig: Configuration["dailyLeaderboards"]
|
||||
dailyLeaderboardsConfig: MonkeyTypes.Configuration["dailyLeaderboards"]
|
||||
): Promise<number> {
|
||||
const connection = RedisClient.getConnection();
|
||||
if (!connection || !dailyLeaderboardsConfig.enabled) {
|
||||
|
|
@ -124,7 +123,7 @@ export class DailyLeaderboard {
|
|||
public async getResults(
|
||||
minRank: number,
|
||||
maxRank: number,
|
||||
dailyLeaderboardsConfig: Configuration["dailyLeaderboards"]
|
||||
dailyLeaderboardsConfig: MonkeyTypes.Configuration["dailyLeaderboards"]
|
||||
): Promise<LbEntryWithRank[]> {
|
||||
const connection = RedisClient.getConnection();
|
||||
if (!connection || !dailyLeaderboardsConfig.enabled) {
|
||||
|
|
@ -156,7 +155,7 @@ export class DailyLeaderboard {
|
|||
|
||||
public async getRank(
|
||||
uid: string,
|
||||
dailyLeaderboardsConfig: Configuration["dailyLeaderboards"]
|
||||
dailyLeaderboardsConfig: MonkeyTypes.Configuration["dailyLeaderboards"]
|
||||
): Promise<GetRankResponse | null> {
|
||||
const connection = RedisClient.getConnection();
|
||||
if (!connection || !dailyLeaderboardsConfig.enabled) {
|
||||
|
|
@ -198,7 +197,7 @@ export class DailyLeaderboard {
|
|||
|
||||
export async function purgeUserFromDailyLeaderboards(
|
||||
uid: string,
|
||||
configuration: Configuration["dailyLeaderboards"]
|
||||
configuration: MonkeyTypes.Configuration["dailyLeaderboards"]
|
||||
): Promise<void> {
|
||||
const connection = RedisClient.getConnection();
|
||||
if (!connection || !configuration.enabled) {
|
||||
|
|
@ -210,8 +209,8 @@ export async function purgeUserFromDailyLeaderboards(
|
|||
}
|
||||
|
||||
function isValidModeRule(
|
||||
modeRule: ValidModeRule,
|
||||
modeRules: ValidModeRule[]
|
||||
modeRule: MonkeyTypes.ValidModeRule,
|
||||
modeRules: MonkeyTypes.ValidModeRule[]
|
||||
): boolean {
|
||||
const { language, mode, mode2 } = modeRule;
|
||||
|
||||
|
|
@ -227,7 +226,7 @@ export function getDailyLeaderboard(
|
|||
language: string,
|
||||
mode: string,
|
||||
mode2: string,
|
||||
dailyLeaderboardsConfig: Configuration["dailyLeaderboards"],
|
||||
dailyLeaderboardsConfig: MonkeyTypes.Configuration["dailyLeaderboards"],
|
||||
customTimestamp = -1
|
||||
): DailyLeaderboard | null {
|
||||
const { validModeRules, enabled } = dailyLeaderboardsConfig;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"strictNullChecks": true,
|
||||
"skipLibCheck": true
|
||||
"skipLibCheck": false
|
||||
},
|
||||
"ts-node": {
|
||||
"files": true
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import Ape from ".";
|
||||
import * as SharedMonkeyTypes from "@backend/types/shared";
|
||||
|
||||
let config: SharedMonkeyTypes.Configuration | undefined = undefined;
|
||||
let config: MonkeyTypes.Configuration | undefined = undefined;
|
||||
|
||||
export function get(): SharedMonkeyTypes.Configuration | undefined {
|
||||
export function get(): MonkeyTypes.Configuration | undefined {
|
||||
return config;
|
||||
}
|
||||
|
||||
|
|
@ -14,6 +13,6 @@ export async function sync(): Promise<void> {
|
|||
console.error("Could not fetch configuration", response.message);
|
||||
return;
|
||||
} else {
|
||||
config = response.data as SharedMonkeyTypes.Configuration;
|
||||
config = response.data as MonkeyTypes.Configuration;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
frontend/src/ts/types/types.d.ts
vendored
4
frontend/src/ts/types/types.d.ts
vendored
|
|
@ -1,6 +1,10 @@
|
|||
type typesSeparatedWithHash<T> = T | `${T}#${typesSeparatedWithHash<T>}`;
|
||||
|
||||
declare namespace MonkeyTypes {
|
||||
type Configuration = import("@backend/types/shared").Configuration;
|
||||
type ValidModeRule = import("@backend/types/shared").ValidModeRule;
|
||||
type RewardBracket = import("@backend/types/shared").RewardBracket;
|
||||
|
||||
type PageName =
|
||||
| "loading"
|
||||
| "test"
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
"noPropertyAccessFromIndexSignature": true,
|
||||
"allowUnusedLabels": false,
|
||||
"allowUnreachableCode": false,
|
||||
"skipLibCheck": true,
|
||||
"skipLibCheck": false,
|
||||
"paths": {
|
||||
"@backend/*": ["../backend/src/*"]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue