mirror of
https://github.com/WorldEditAxe/eaglerproxy.git
synced 2024-12-21 14:54:13 -08:00
Added support for EasyMC auth
This commit is contained in:
parent
fed9ac786c
commit
2059fa8a44
108
src/plugins/EagProxyAAS/auth_easymc.ts
Normal file
108
src/plugins/EagProxyAAS/auth_easymc.ts
Normal file
|
@ -0,0 +1,108 @@
|
|||
import mc from "minecraft-protocol";
|
||||
import { Enums } from "../../proxy/Enums.js";
|
||||
|
||||
export async function getTokenProfileEasyMc(token: string): Promise<object> {
|
||||
const fetchOptions = {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
token,
|
||||
}),
|
||||
};
|
||||
const res = await fetch(
|
||||
"https://api.easymc.io/v1/token/redeem",
|
||||
fetchOptions
|
||||
);
|
||||
const resJson = await res.json();
|
||||
|
||||
if (resJson.error)
|
||||
throw new Error(Enums.ChatColor.RED + `EasyMC: ${resJson.error}`);
|
||||
if (!resJson)
|
||||
throw new Error(
|
||||
Enums.ChatColor.RED + "EasyMC replied with an empty response!?"
|
||||
);
|
||||
if (
|
||||
resJson.session?.length !== 43 ||
|
||||
resJson.mcName?.length < 3 ||
|
||||
resJson.uuid?.length !== 36
|
||||
)
|
||||
throw new Error(
|
||||
Enums.ChatColor.RED + "Invalid response from EasyMC received!"
|
||||
);
|
||||
return {
|
||||
auth: "mojang",
|
||||
sessionServer: "https://sessionserver.easymc.io",
|
||||
username: resJson.mcName,
|
||||
haveCredentials: true,
|
||||
session: {
|
||||
accessToken: resJson.session,
|
||||
selectedProfile: {
|
||||
name: resJson.mcName,
|
||||
id: resJson.uuid,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function easyMcAuth(client, options) {
|
||||
const fetchOptions = {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
token: options.easyMcToken,
|
||||
}),
|
||||
};
|
||||
try {
|
||||
const res = await fetch(
|
||||
"https://api.easymc.io/v1/token/redeem",
|
||||
fetchOptions
|
||||
);
|
||||
const resJson = await res.json();
|
||||
if (resJson.error)
|
||||
throw new Error(Enums.ChatColor.RED + `EasyMC: ${resJson.error}`);
|
||||
if (!resJson)
|
||||
throw new Error(
|
||||
Enums.ChatColor.RED + "EasyMC replied with an empty response!?"
|
||||
);
|
||||
if (
|
||||
resJson.session?.length !== 43 ||
|
||||
resJson.mcName?.length < 3 ||
|
||||
resJson.uuid?.length !== 36
|
||||
)
|
||||
throw new Error(
|
||||
Enums.ChatColor.RED + "Invalid response from EasyMC received!"
|
||||
);
|
||||
const session = {
|
||||
accessToken: resJson.session,
|
||||
selectedProfile: {
|
||||
name: resJson.mcName,
|
||||
id: resJson.uuid,
|
||||
},
|
||||
};
|
||||
options.haveCredentials = true;
|
||||
client.session = session;
|
||||
options.username = client.username = session.selectedProfile.name;
|
||||
options.accessToken = session.accessToken;
|
||||
client.emit("session", session);
|
||||
} catch (error) {
|
||||
client.emit("error", error);
|
||||
return;
|
||||
}
|
||||
options.connect(client);
|
||||
}
|
||||
|
||||
function getEasyMcClientOptions(token: string) {
|
||||
if (token.length !== 20) {
|
||||
throw new Error(
|
||||
Enums.ChatColor.RED +
|
||||
"EasyMC authentication requires an alt token. See https://easymc.io/get ."
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
auth: easyMcAuth,
|
||||
easyMcToken: token,
|
||||
sessionServer: "https://sessionserver.easymc.io",
|
||||
username: Buffer.alloc(0),
|
||||
};
|
||||
}
|
338
src/plugins/EagProxyAAS/commands.ts
Normal file
338
src/plugins/EagProxyAAS/commands.ts
Normal file
|
@ -0,0 +1,338 @@
|
|||
import { dirname, join } from "path";
|
||||
import { Enums } from "../../proxy/Enums.js";
|
||||
import { Player } from "../../proxy/Player.js";
|
||||
import { config } from "./config.js";
|
||||
import { ConnectType } from "./types.js";
|
||||
import fs from "fs/promises";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const SEPARATOR = "======================================";
|
||||
const METADATA: {
|
||||
name: string;
|
||||
id: string;
|
||||
version: string;
|
||||
entry_point: string;
|
||||
requirements: any[];
|
||||
load_after: any[];
|
||||
incompatibilities: any[];
|
||||
} = JSON.parse(
|
||||
(
|
||||
await fs.readFile(
|
||||
join(dirname(fileURLToPath(import.meta.url)), "metadata.json")
|
||||
)
|
||||
).toString()
|
||||
);
|
||||
|
||||
export function sendPluginChatMessage(
|
||||
client: Player,
|
||||
...components: { text: string; color: string; [otherFields: string]: any }[]
|
||||
) {
|
||||
if (components.length == 0)
|
||||
throw new Error("There must be one or more passed components!");
|
||||
else {
|
||||
client.ws.send(
|
||||
client.serializer.createPacketBuffer({
|
||||
name: "chat",
|
||||
params: {
|
||||
message: JSON.stringify({
|
||||
text: "[EagPAAS] ",
|
||||
color: "gold",
|
||||
extra: components,
|
||||
}),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function handleCommand(sender: Player, cmd: string): void {
|
||||
switch (cmd.toLowerCase().split(/ /gim)[0]) {
|
||||
default:
|
||||
sendPluginChatMessage(sender, {
|
||||
text: `"${cmd.split(/ /gim, 1)[0]}" is not a valid command!`,
|
||||
color: "red",
|
||||
});
|
||||
break;
|
||||
case "/eag-help":
|
||||
helpCommand(sender);
|
||||
break;
|
||||
case "/eag-toggleparticles":
|
||||
toggleParticles(sender);
|
||||
break;
|
||||
case "/eag-switchservers":
|
||||
switchServer(cmd, sender);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function helpCommand(sender: Player) {
|
||||
sendPluginChatMessage(sender, {
|
||||
text: SEPARATOR,
|
||||
color: "yellow",
|
||||
});
|
||||
sendPluginChatMessage(sender, {
|
||||
text: "Available Commands:",
|
||||
color: "aqua",
|
||||
});
|
||||
sendPluginChatMessage(sender, {
|
||||
text: "/eag-help",
|
||||
color: "light_green",
|
||||
hoverEvent: {
|
||||
action: "show_text",
|
||||
value: Enums.ChatColor.GOLD + "Click me to run this command!",
|
||||
},
|
||||
clickEvent: {
|
||||
action: "run_command",
|
||||
value: "/eag-help",
|
||||
},
|
||||
extra: [
|
||||
{
|
||||
text: " - Prints out a list of commmands",
|
||||
color: "aqua",
|
||||
},
|
||||
],
|
||||
});
|
||||
sendPluginChatMessage(sender, {
|
||||
text: "/eag-toggleparticles",
|
||||
color: "light_green",
|
||||
hoverEvent: {
|
||||
action: "show_text",
|
||||
value: Enums.ChatColor.GOLD + "Click me to run this command!",
|
||||
},
|
||||
clickEvent: {
|
||||
action: "run_command",
|
||||
value: "/eag-toggleparticles",
|
||||
},
|
||||
extra: [
|
||||
{
|
||||
text: " - Toggles whether or not particles should be rendered/shown on the client. Turning this on can potentially boost FPS.",
|
||||
color: "aqua",
|
||||
},
|
||||
],
|
||||
});
|
||||
sendPluginChatMessage(sender, {
|
||||
text: `/eag-switchservers <mode: online|offline> <ip>${
|
||||
config.allowCustomPorts ? " [port]" : ""
|
||||
}`,
|
||||
color: "light_green",
|
||||
hoverEvent: {
|
||||
action: "show_text",
|
||||
value: Enums.ChatColor.GOLD + "Click me to paste this command to chat!",
|
||||
},
|
||||
clickEvent: {
|
||||
action: "suggest_command",
|
||||
value: `/eag-switchservers <mode: online|offline> <ip>${
|
||||
config.allowCustomPorts ? " [port]" : ""
|
||||
}`,
|
||||
},
|
||||
extra: [
|
||||
{
|
||||
text: " - Switch between servers on-the-fly. Switching to servers in online mode requires logging in via online mode or EasyMC!",
|
||||
color: "aqua",
|
||||
},
|
||||
],
|
||||
});
|
||||
sendPluginChatMessage(sender, {
|
||||
text: `Running ${METADATA.name} on version v${METADATA.version}.`,
|
||||
color: "gray",
|
||||
});
|
||||
sendPluginChatMessage(sender, {
|
||||
text: SEPARATOR,
|
||||
color: "yellow",
|
||||
});
|
||||
}
|
||||
|
||||
export function toggleParticles(sender: Player) {
|
||||
const listener = (sender as any)._particleListener;
|
||||
if (listener != null) {
|
||||
sender.removeListener("vanillaPacket", listener);
|
||||
(sender as any)._particleListener = undefined;
|
||||
sendPluginChatMessage(sender, {
|
||||
text: "Disabled particle hider!",
|
||||
color: "red",
|
||||
});
|
||||
} else {
|
||||
(sender as any)._particleListener = (
|
||||
packet: { name: string; params: any; cancel: boolean },
|
||||
origin: "SERVER" | "CLIENT"
|
||||
) => {
|
||||
if (origin == "SERVER") {
|
||||
if (packet.name == "world_particles") {
|
||||
packet.cancel = true;
|
||||
} else if (packet.name == "world_event") {
|
||||
if (packet.params.effectId >= 2000) {
|
||||
packet.cancel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
sender.on("vanillaPacket", (sender as any)._particleListener);
|
||||
sendPluginChatMessage(sender, {
|
||||
text: "Enabled particle hider!",
|
||||
color: "green",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function switchServer(cmd: string, sender: Player) {
|
||||
if ((sender as any)._serverSwitchLock) {
|
||||
return sendPluginChatMessage(sender, {
|
||||
text: `There is already a pending server switch - please wait, and be patient!`,
|
||||
color: "red",
|
||||
});
|
||||
}
|
||||
let split = cmd.split(/ /gim).slice(1),
|
||||
mode = split[0]?.toLowerCase(),
|
||||
ip = split[1],
|
||||
port = split[2];
|
||||
if (mode != "online" && mode != "offline") {
|
||||
return sendPluginChatMessage(sender, {
|
||||
text: `Invalid command usage - please provide a valid mode! `,
|
||||
color: "red",
|
||||
extra: [
|
||||
{
|
||||
text: `/eag-switchservers <mode: online|offline> <ip>${
|
||||
config.allowCustomPorts ? " [port]" : ""
|
||||
}.`,
|
||||
color: "gold",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
if (ip == null) {
|
||||
return sendPluginChatMessage(sender, {
|
||||
text: `Invalid command usage - please provide a valid IP or hostname (like example.com, 1.2.3.4, etc.)! `,
|
||||
color: "red",
|
||||
extra: [
|
||||
{
|
||||
text: `/eag-switchservers <mode: online|offline> <ip>${
|
||||
config.allowCustomPorts ? " [port]" : ""
|
||||
}.`,
|
||||
color: "gold",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
if (
|
||||
port != null &&
|
||||
(isNaN(Number(port)) || Number(port) < 1 || Number(port) > 65535)
|
||||
) {
|
||||
return sendPluginChatMessage(sender, {
|
||||
text: `Invalid command usage - a port must be a number above 0 and below 65536! `,
|
||||
color: "red",
|
||||
extra: [
|
||||
{
|
||||
text: `/eag-switchservers <mode: online|offline> <ip>${
|
||||
config.allowCustomPorts ? " [port]" : ""
|
||||
}.`,
|
||||
color: "gold",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
if (port != null && !config.allowCustomPorts) {
|
||||
return sendPluginChatMessage(sender, {
|
||||
text: `Invalid command usage - custom server ports are disabled on this proxy instance! `,
|
||||
color: "red",
|
||||
extra: [
|
||||
{
|
||||
text: `/eag-switchservers <mode: online|offline> <ip>${
|
||||
config.allowCustomPorts ? " [port]" : ""
|
||||
}.`,
|
||||
color: "gold",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
let connectionType =
|
||||
mode == "offline" ? ConnectType.OFFLINE : ConnectType.ONLINE,
|
||||
addr = ip,
|
||||
addrPort = Number(port);
|
||||
if (connectionType == ConnectType.ONLINE) {
|
||||
if ((sender as any)._onlineSession == null) {
|
||||
sendPluginChatMessage(sender, {
|
||||
text: `You either connected to this proxy under offline mode, or your online/EasyMC session has timed out and has become invalid.`,
|
||||
color: "red",
|
||||
});
|
||||
return sendPluginChatMessage(sender, {
|
||||
text: `To switch to online servers, please reconnect and log-in through online/EasyMC mode.`,
|
||||
color: "red",
|
||||
});
|
||||
} else {
|
||||
const savedAuth = (sender as any)._onlineSession;
|
||||
sendPluginChatMessage(sender, {
|
||||
text: `(joining server under ${savedAuth.username}/your ${
|
||||
savedAuth.isEasyMC ? "EasyMC" : "Minecraft"
|
||||
} account's username)`,
|
||||
color: "aqua",
|
||||
});
|
||||
sendPluginChatMessage(sender, {
|
||||
text: "Attempting to switch servers, please wait... (if you don't get connected to the target server after a while, the server might not be a Minecraft server at all. Reconnect and try again.)",
|
||||
color: "gray",
|
||||
});
|
||||
(sender as any)._serverSwitchLock = true;
|
||||
try {
|
||||
await sender.switchServers({
|
||||
host: addr,
|
||||
port: addrPort,
|
||||
version: "1.8.8",
|
||||
keepAlive: false,
|
||||
skipValidation: true,
|
||||
hideErrors: true,
|
||||
...savedAuth,
|
||||
});
|
||||
(sender as any)._serverSwitchLock = false;
|
||||
} catch (err) {
|
||||
if (sender.state! != Enums.ClientState.DISCONNECTED) {
|
||||
sender.disconnect(
|
||||
Enums.ChatColor.RED +
|
||||
`Something went wrong whilst switching servers: ${err.message}${
|
||||
err.code == "ENOTFOUND"
|
||||
? addr.includes(":")
|
||||
? `\n${Enums.ChatColor.GRAY}Suggestion: Replace the : in your IP with a space.`
|
||||
: "\nIs that IP valid?"
|
||||
: ""
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sendPluginChatMessage(sender, {
|
||||
text: `(joining server under ${sender.username}/Eaglercraft username)`,
|
||||
color: "aqua",
|
||||
});
|
||||
sendPluginChatMessage(sender, {
|
||||
text: "Attempting to switch servers, please wait... (if you don't get connected to the target server for a while, the server might be online only)",
|
||||
color: "gray",
|
||||
});
|
||||
try {
|
||||
(sender as any)._serverSwitchLock = true;
|
||||
await sender.switchServers({
|
||||
host: addr,
|
||||
port: addrPort,
|
||||
version: "1.8.8",
|
||||
username: sender.username,
|
||||
auth: "offline",
|
||||
keepAlive: false,
|
||||
skipValidation: true,
|
||||
hideErrors: true,
|
||||
});
|
||||
(sender as any)._serverSwitchLock = false;
|
||||
} catch (err) {
|
||||
if (sender.state! != Enums.ClientState.DISCONNECTED) {
|
||||
sender.disconnect(
|
||||
Enums.ChatColor.RED +
|
||||
`Something went wrong whilst switching servers: ${err.message}${
|
||||
err.code == "ENOTFOUND"
|
||||
? addr.includes(":")
|
||||
? `\n${Enums.ChatColor.GRAY}Suggestion: Replace the : in your IP with a space.`
|
||||
: "\nIs that IP valid?"
|
||||
: ""
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user