diff --git a/src/api/routes/users/@me/pomelo-attempt.ts b/src/api/routes/users/@me/pomelo-attempt.ts new file mode 100644 index 00000000..d4327f61 --- /dev/null +++ b/src/api/routes/users/@me/pomelo-attempt.ts @@ -0,0 +1,35 @@ +import { route } from "@spacebar/api"; +import { Config, UniqueUsernameAttemptSchema, User } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +import { HTTPError } from "lambert-server"; +const router = Router(); + +// https://discord-userdoccers.vercel.app/resources/user#get-pomelo-eligibility +router.post( + "/", + route({ + requestBody: "UniqueUsernameAttemptSchema", + responses: { + 200: { body: "UniqueUsernameAttemptResponse" }, + 400: { body: "APIErrorResponse" }, + }, + description: + "Checks whether a unique username is available for the user to claim.", + }), + async (req: Request, res: Response) => { + const body = req.body as UniqueUsernameAttemptSchema; + const { uniqueUsernames } = Config.get().general; + if (!uniqueUsernames) { + throw new HTTPError( + "Unique Usernames feature is not enabled on this instance.", + 400, + ); + } + + res.json({ + taken: !(await User.isUsernameAvailable(body.username)), + }); + }, +); + +export default router; diff --git a/src/api/routes/users/@me/pomelo-suggestions.ts b/src/api/routes/users/@me/pomelo-suggestions.ts new file mode 100644 index 00000000..c70336bf --- /dev/null +++ b/src/api/routes/users/@me/pomelo-suggestions.ts @@ -0,0 +1,37 @@ +import { route } from "@spacebar/api"; +import { Config, User } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +import { HTTPError } from "lambert-server"; +const router = Router(); + +// https://discord-userdoccers.vercel.app/resources/user#get-pomelo-suggestions +router.get( + "/", + route({ + description: + "Returns a suggested unique username string based on the current user's username.", + responses: { + 400: { body: "APIErrorResponse" }, + }, + }), + async (req: Request, res: Response) => { + const { uniqueUsernames } = Config.get().general; + if (!uniqueUsernames) { + throw new HTTPError( + "Unique Usernames feature is not enabled on this instance.", + 400, + ); + } + + const user = await User.findOneOrFail({ + where: { + id: req.user_id, + }, + }); + + // TODO: return a suggestion based on the users current username + return res.json({ username: user.username.toString() }); + }, +); + +export default router; diff --git a/src/api/routes/users/@me/pomelo.ts b/src/api/routes/users/@me/pomelo.ts new file mode 100644 index 00000000..e10beaa4 --- /dev/null +++ b/src/api/routes/users/@me/pomelo.ts @@ -0,0 +1,61 @@ +import { route } from "@spacebar/api"; +import { + Config, + FieldErrors, + UniqueUsernameAttemptSchema, + User, +} from "@spacebar/util"; +import { Request, Response, Router } from "express"; +import { HTTPError } from "lambert-server"; +const router = Router(); + +// https://discord-userdoccers.vercel.app/resources/user#create-pomelo-migration +router.post( + "/", + route({ + description: + "Claims a unique username for the user. Returns the updated user object on success. Fires a User Update Gateway event.", + requestBody: "UniqueUsernameAttemptSchema", + responses: { + 200: { body: "PrivateUserResponse" }, + 400: { body: "APIErrorResponse" }, + }, + }), + async (req: Request, res: Response) => { + const body = req.body as UniqueUsernameAttemptSchema; + const { uniqueUsernames } = Config.get().general; + if (!uniqueUsernames) { + throw new HTTPError( + "Unique Usernames feature is not enabled on this instance.", + 400, + ); + } + + const isAvailable = await User.isUsernameAvailable(body.username); + + if (!isAvailable) { + throw FieldErrors({ + username: { + code: "USERNAME_TOO_MANY_USERS", + message: + req?.t("auth:register.USERNAME_TOO_MANY_USERS") || "", + }, + }); + } + + const user = await User.findOneOrFail({ + where: { + id: req.user_id, + }, + }); + + user.legacy_username = user.username; + user.username = body.username; + user.discriminator = "0"; + const newUser = await user.save(); + + res.json(newUser.toPrivateUser()); + }, +); + +export default router;