feat: extra api functions
vi did:web:vt3e.cat
Mon, 25 May 2026 09:35:59 +0100
2 files changed,
76 insertions(+),
1 deletions(-)
M
src/roblox/index.ts
→
src/roblox/index.ts
@@ -1,6 +1,6 @@
import { container } from "@sapphire/framework"; import config from "@/config"; -import type { BanResponse, RobloxUser } from "./types"; +import type { BanResponse, FriendsResponse, RestrictionsResponse, RobloxUser } from "./types"; const COOKIE = config.roblox.cookie; let CSRF_TOKEN: string | undefined;@@ -13,11 +13,63 @@ },
...options, }); +export async function batchUsers(ids: number[]): Promise<RobloxUser[]> { + const url = new URL("https://apis.roblox.com/user-profile-api/v1/user/profiles/get-profiles"); + const fields = ["names.combinedName", "names.username"]; + + const response = await request(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ userIds: ids, fields }), + }); + + type Profile = { + userId: number; + names: { + combinedName: string; + username: string; + }; + }; + type BatchResponse = { + profileDetails: Profile[]; + }; + + const res = (await response.json()) as BatchResponse; + + return res.profileDetails.map( + (detail) => + ({ + id: detail.userId, + displayName: detail.names.combinedName, + name: detail.names.username, + }) as RobloxUser, + ); +} + export async function getUser(id: string): Promise<RobloxUser> { const url = new URL(`https://users.roblox.com/v1/users/${id}`); const response = await request(url); return (await response.json()) as RobloxUser; +} + +export async function getFriends(id: string, options: { cursor: string | null; page: number }) { + const url = new URL(`https://friends.roblox.com/v1/users/${id}/friends/find`); + if (options.cursor) url.searchParams.set("cursor", options.cursor); + url.searchParams.set("limit", "20"); + + const response = await request(url); + const data = (await response.json()) as FriendsResponse; + + return { cursor: data.NextCursor, ids: data.PageItems.map((item) => item.id) }; +} + +export async function fetchRestriction(id: string): Promise<RestrictionsResponse> { + const url = new URL( + `https://apis.roblox.com/user/cloud/v2/universes/21449357/user-restrictions/${id}`, + ); + const response = await request(url); + return (await response.json()) as RestrictionsResponse; } export async function ban(
M
src/roblox/types.ts
→
src/roblox/types.ts
@@ -17,3 +17,26 @@ excludeAltAccounts: boolean;
inherited: boolean; }; }; + +export type Restriction = { + active: boolean; + startTime: string; + privateReason: string | null; + displayReason: string | null; + excludeAltAccounts: boolean; + inherited: boolean; +}; + +export type RestrictionsResponse = { + path: string; + user: string; + gameJoinRestriction: Restriction; +}; + +export type FriendsResponse = { + PreviousCursor: string | null; + NextCursor: string | null; + PageItems: { id: number }[]; + /** this parameter seems to return null even if there are more, we will assume it will return `false` if there are no more */ + HasMore: null | boolean; +};