all repos — stealth-developers @ 7f079d8ff07713cc317b566bceb3fe34b42c4ce0

src/utils/roblox.ts (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
import config from "@/config";
import type {
	AvatarSize,
	BLApiResponse,
	GetUserResponse,
	RobloxSearchResponse,
	RobloxSearchUser,
	ThumbnailResponse,
} from "@/types/roblox";

export async function getRobloxUser(
	userId: string,
	size: AvatarSize = 420,
): Promise<{
	user: GetUserResponse;
	thumbnail: ThumbnailResponse;
}> {
	if (!config.data.roblox) throw new Error("roblox API key is not configured");

	const getUserUrl = `https://apis.roblox.com/cloud/v2/users/${userId}`;
	const getThumbnailUrl = `https://apis.roblox.com/cloud/v2/users/${userId}:generateThumbnail?size=${size}`;
	const [userRes, thumbnailRes] = await Promise.all([
		fetch(getUserUrl, {
			headers: {
				"Content-Type": "application/json",
				"x-api-key": config.data.roblox.apiKey,
			},
		}),
		fetch(getThumbnailUrl, {
			headers: {
				"Content-Type": "application/json",
				"x-api-key": config.data.roblox.apiKey,
			},
		}),
	]);

	const [userData, thumbnailData] = await Promise.all([
		userRes.json(),
		thumbnailRes.json(),
	]);

	return { user: userData, thumbnail: thumbnailData };
}

export async function getConnectedRobloxUser(
	discordId: string,
): Promise<BLApiResponse> {
	if (!config.data.bloxlink)
		throw new Error("bloxlink token is not configured");

	const response = await fetch(
		`https://api.blox.link/v4/public/discord-to-roblox/${discordId}`,
		{
			headers: {
				Authorization: config.data.bloxlink.token,
			},
		},
	);

	return await response.json();
}

export async function getRobloxIdFromUsername(
	username: string,
): Promise<string | null> {
	try {
		const response = await fetch(
			"https://users.roblox.com/v1/usernames/users",
			{
				method: "POST",
				headers: {
					"Content-Type": "application/json",
				},
				body: JSON.stringify({
					usernames: [username],
					excludeBannedUsers: true,
				}),
			},
		);

		if (!response.ok) {
			return null;
		}

		const data = await response.json();

		if (data.data && data.data.length > 0 && data.data[0].id) {
			return data.data[0].id.toString();
		}

		return null;
	} catch (error) {
		return null;
	}
}

export async function searchRobloxUsers(
	keyword: string,
	limit = 10,
): Promise<{ users: RobloxSearchUser[]; error?: string; code?: number }> {
	try {
		const response = await fetch(
			`https://users.roblox.com/v1/users/search?keyword=${encodeURIComponent(keyword)}&limit=${limit}`,
			{
				method: "GET",
				headers: {
					"Content-Type": "application/json",
					...(config.data.roblox?.cookie
						? { Cookie: config.data.roblox.cookie }
						: {}),
				},
			},
		);

		if (!response.ok) {
			return { users: [], error: response.statusText, code: response.status };
		}

		const data: RobloxSearchResponse = await response.json();
		return { users: data.data || [] };
	} catch (error) {
		return { users: [], error: "failed to search users" };
	}
}