mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-19 13:40:41 -05:00
More forgiving friend code input
This commit is contained in:
parent
bb4e0ee8d1
commit
f7a4ee0971
|
|
@ -4,13 +4,12 @@ import * as AdminRepository from "~/features/admin/AdminRepository.server";
|
|||
import { makeArtist } from "~/features/art/queries/makeArtist.server";
|
||||
import { requireUserId } from "~/features/auth/core/user.server";
|
||||
import { refreshBannedCache } from "~/features/ban/core/banned.server";
|
||||
import { FRIEND_CODE_REGEXP } from "~/features/sendouq/q-constants";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import { isAdmin, isMod } from "~/permissions";
|
||||
import { logger } from "~/utils/logger";
|
||||
import { parseRequestPayload, validate } from "~/utils/remix.server";
|
||||
import { assertUnreachable } from "~/utils/types";
|
||||
import { _action, actualNumber } from "~/utils/zod";
|
||||
import { _action, actualNumber, friendCode } from "~/utils/zod";
|
||||
import { plusTiersFromVotingAndLeaderboard } from "../core/plus-tier.server";
|
||||
|
||||
export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
|
|
@ -186,7 +185,7 @@ export const adminActionSchema = z.union([
|
|||
}),
|
||||
z.object({
|
||||
_action: _action("UPDATE_FRIEND_CODE"),
|
||||
friendCode: z.string().regex(FRIEND_CODE_REGEXP),
|
||||
friendCode,
|
||||
user: z.preprocess(actualNumber, z.number().positive()),
|
||||
}),
|
||||
]);
|
||||
|
|
|
|||
23
app/features/sendouq/q-constants.test.ts
Normal file
23
app/features/sendouq/q-constants.test.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { FRIEND_CODE_REGEXP } from "./q-constants";
|
||||
|
||||
describe("FRIEND_CODE_REGEXP", () => {
|
||||
it("should match valid friend codes", () => {
|
||||
const validCodes = ["SW-1234-5678-9012", "1234-5678-9012", "123456789012"];
|
||||
for (const code of validCodes) {
|
||||
expect(FRIEND_CODE_REGEXP.test(code)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("should not match invalid friend codes", () => {
|
||||
const invalidCodes = [
|
||||
"SW-1234-5678-901",
|
||||
"1234-5678-901",
|
||||
"12345678901",
|
||||
"hello",
|
||||
];
|
||||
for (const code of invalidCodes) {
|
||||
expect(FRIEND_CODE_REGEXP.test(code)).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -8,7 +8,8 @@ export const SENDOUQ = {
|
|||
PRIVATE_USER_NOTE_MAX_LENGTH: TWEET_LENGTH_MAX_LENGTH,
|
||||
} as const;
|
||||
|
||||
export const FRIEND_CODE_REGEXP_PATTERN = "^[0-9]{4}-[0-9]{4}-[0-9]{4}$";
|
||||
export const FRIEND_CODE_REGEXP_PATTERN =
|
||||
"^(SW-)?[0-9]{4}-?[0-9]{4}-?[0-9]{4}$";
|
||||
export const FRIEND_CODE_REGEXP = new RegExp(FRIEND_CODE_REGEXP_PATTERN);
|
||||
|
||||
export const FULL_GROUP_SIZE = 4;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
checkboxValueToBoolean,
|
||||
deduplicate,
|
||||
falsyToNull,
|
||||
friendCode,
|
||||
id,
|
||||
modeShort,
|
||||
safeJSONParse,
|
||||
|
|
@ -11,7 +12,7 @@ import {
|
|||
weaponSplId,
|
||||
} from "~/utils/zod";
|
||||
import { matchEndedAtIndex } from "./core/match";
|
||||
import { FRIEND_CODE_REGEXP, SENDOUQ, SENDOUQ_BEST_OF } from "./q-constants";
|
||||
import { SENDOUQ, SENDOUQ_BEST_OF } from "./q-constants";
|
||||
|
||||
export const frontPageSchema = z.union([
|
||||
z.object({
|
||||
|
|
@ -26,10 +27,7 @@ export const frontPageSchema = z.union([
|
|||
}),
|
||||
z.object({
|
||||
_action: _action("ADD_FRIEND_CODE"),
|
||||
friendCode: z.string().regex(FRIEND_CODE_REGEXP, {
|
||||
message:
|
||||
"Invalid friend code. Did you include dashes? Example: 1234-5678-9012",
|
||||
}),
|
||||
friendCode,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
|
|
|||
20
app/utils/zod.test.ts
Normal file
20
app/utils/zod.test.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { normalizeFriendCode } from "./zod";
|
||||
|
||||
describe("normalizeFriendCode", () => {
|
||||
it("returns well formatted friend code as is", () => {
|
||||
expect(normalizeFriendCode("1234-5678-9012")).toBe("1234-5678-9012");
|
||||
});
|
||||
|
||||
it("handles no dashes", () => {
|
||||
expect(normalizeFriendCode("123456789012")).toBe("1234-5678-9012");
|
||||
});
|
||||
|
||||
it("handles SW-suffix", () => {
|
||||
expect(normalizeFriendCode("SW-1234-5678-9012")).toBe("1234-5678-9012");
|
||||
});
|
||||
|
||||
it("handles a mix", () => {
|
||||
expect(normalizeFriendCode("SW-1234-56789012")).toBe("1234-5678-9012");
|
||||
});
|
||||
});
|
||||
|
|
@ -2,6 +2,7 @@ import type { ZodType } from "zod";
|
|||
import { z } from "zod";
|
||||
import type { abilitiesShort } from "~/modules/in-game-lists";
|
||||
import { abilities, mainWeaponIds, stageIds } from "~/modules/in-game-lists";
|
||||
import { FRIEND_CODE_REGEXP } from "../features/sendouq/q-constants";
|
||||
import type { Unpacked } from "./types";
|
||||
import { assertType } from "./types";
|
||||
|
||||
|
|
@ -33,6 +34,22 @@ export const stackableAbility = z
|
|||
.string()
|
||||
.refine((val) => abilityNameToType(val) === "STACKABLE");
|
||||
|
||||
export const normalizeFriendCode = (value: string) => {
|
||||
const onlyNumbers = value.replace(/\D/g, "");
|
||||
|
||||
const withDashes = onlyNumbers
|
||||
.split(/(\d{4})/)
|
||||
.filter(Boolean)
|
||||
.join("-");
|
||||
|
||||
return withDashes;
|
||||
};
|
||||
|
||||
export const friendCode = z
|
||||
.string()
|
||||
.regex(FRIEND_CODE_REGEXP)
|
||||
.transform(normalizeFriendCode);
|
||||
|
||||
export const ability = z.enum([
|
||||
"ISM",
|
||||
"ISS",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user