This repository has been archived by the owner on Oct 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
557037a
commit d0d8411
Showing
5 changed files
with
196 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { SlashCommandBuilder } from "discord.js"; | ||
import type { MeteoriumCommand } from ".."; | ||
import { MeteoriumEmbedBuilder } from "../../util/MeteoriumEmbedBuilder"; | ||
import * as MojangAPI from "../../util/MojangAPI"; | ||
|
||
export const Command: MeteoriumCommand = { | ||
InteractionData: new SlashCommandBuilder() | ||
.setName("mojangapi") | ||
.setDescription("Get Minecraft information from Mojang APIs") | ||
.addSubcommandGroup((group) => | ||
group | ||
.setName("profile") | ||
.setDescription("Get a user's profile information") | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName("username") | ||
.setDescription("By username") | ||
.addStringOption((option) => | ||
option.setName("username").setDescription("The username of the player").setRequired(true), | ||
) | ||
.addBooleanOption((option) => | ||
option | ||
.setName("ephemeral") | ||
.setDescription("If true, the response will only be shown to you") | ||
.setRequired(false), | ||
), | ||
) | ||
.addSubcommand((subcommand) => | ||
subcommand | ||
.setName("uuid") | ||
.setDescription("By uuid") | ||
.addStringOption((option) => | ||
option.setName("uuid").setDescription("The uuid of the player").setRequired(true), | ||
) | ||
.addBooleanOption((option) => | ||
option | ||
.setName("ephemeral") | ||
.setDescription("If true, the response will only be shown to you") | ||
.setRequired(false), | ||
), | ||
), | ||
), | ||
async Callback(interaction, _) { | ||
const Ephemeral = interaction.options.getBoolean("ephemeral", false) ? true : false; | ||
await interaction.deferReply({ ephemeral: Ephemeral }); | ||
|
||
const SubcommandGroup = interaction.options.getSubcommandGroup(); | ||
const Subcommand = interaction.options.getSubcommand(); | ||
|
||
switch (SubcommandGroup) { | ||
case "profile": { | ||
let UUID: string; | ||
if (Subcommand == "uuid") UUID = interaction.options.getString("uuid", true); | ||
else { | ||
const res = await MojangAPI.getUUIDFromName(interaction.options.getString("name", true)); | ||
if (res.code == 204 || res.code == 404) | ||
return await interaction.editReply("The username/profiile doesn't exist."); | ||
if (res.code != 200) | ||
return await interaction.editReply( | ||
"Failed while fetching information from Mojang's API (username to uuid status code not 200)", | ||
); | ||
UUID = res.data.id; | ||
} | ||
|
||
const Profile = await MojangAPI.getProfile(UUID); | ||
if (Profile.code != 200) | ||
return await interaction.editReply( | ||
"Failed while fetching information from Mojang's API (username to uuid status code not 200)", | ||
); | ||
const ProfileTextures = MojangAPI.decodeTexturesB64(Profile.data.properties[0].value); | ||
|
||
const Embed = new MeteoriumEmbedBuilder() | ||
.setNormalColor() | ||
.setTitle(Profile.data.name) | ||
.addFields([ | ||
{ name: "UUID", value: Profile.data.id }, | ||
{ | ||
name: "Profile actions", | ||
value: | ||
Profile.data.profileActions.length == 0 | ||
? "N/A" | ||
: Profile.data.profileActions.toString(), | ||
}, | ||
{ | ||
name: "Skin url", | ||
value: | ||
ProfileTextures.textures.SKIN == undefined | ||
? `Default (${MojangAPI.decodeDefaultSkin(UUID)})` | ||
: ProfileTextures.textures.SKIN.url, | ||
}, | ||
{ | ||
name: "Skin type", | ||
value: | ||
ProfileTextures.textures.SKIN == undefined | ||
? "N/A" | ||
: ProfileTextures.textures.SKIN.metadata == undefined | ||
? "Classic" | ||
: "Slim", | ||
}, | ||
{ | ||
name: "Cape url", | ||
value: | ||
ProfileTextures.textures.CAPE == undefined ? "N/A" : ProfileTextures.textures.CAPE.url, | ||
}, | ||
]); | ||
|
||
return await interaction.editReply({ embeds: [ Embed ] }); | ||
} | ||
} | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
export interface Textures { | ||
timestamp: string; | ||
profileId: string; | ||
profileName: string; | ||
signatureRequired?: true; | ||
textures: { | ||
SKIN?: { | ||
url: string; | ||
metadata?: { model: string }; | ||
}; | ||
CAPE?: { url: string }; | ||
}; | ||
} | ||
|
||
export interface ProfileResponse { | ||
id: string; | ||
name: string; | ||
properties: [ | ||
{ | ||
name: "textures"; | ||
value: string; | ||
signature?: string; | ||
}, | ||
]; | ||
profileActions: string[]; | ||
legacy?: true; | ||
} | ||
|
||
export interface UUIDFromNameResponse { | ||
name: string; | ||
id: string; | ||
legacy?: true; | ||
demo?: true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import axios from "axios"; | ||
|
||
import * as proto from "./Proto"; | ||
|
||
export async function getUUIDFromName(name: string) { | ||
const res = await axios.get(`https://api.mojang.com/users/profiles/minecraft/${name}`); | ||
return { code: res.status, data: res.data as proto.UUIDFromNameResponse }; | ||
} | ||
|
||
export async function getProfile(uuid: string) { | ||
const res = await axios.get(`https://sessionserver.mojang.com/session/minecraft/profile/${encodeURIComponent(uuid)}`); | ||
return { code: res.status, data: res.data as proto.ProfileResponse }; | ||
} | ||
|
||
export function decodeTexturesB64(texturesb64: string) { | ||
const bf = Buffer.from(texturesb64, "base64"); | ||
return JSON.parse(bf.toString()) as proto.Textures; | ||
} | ||
|
||
export function decodeDefaultSkin(uuid: string): "steve" | "alex" { | ||
const chars = uuid.split(""); | ||
// @ts-ignore | ||
const lsbs_even = parseInt(chars[ 7], 16) ^ parseInt(chars[15], 16) ^ parseInt(chars[23], 16) ^ parseInt(chars[31], 16); | ||
return lsbs_even ? "alex" : "steve"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters