apps/bot/src/feats/link/index.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 |
import { editActor, getActor } from "@stealth-developers/db";
import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
import { logger } from "@/lib";
import { useGetData } from "@/middleware";
import { getUser } from "../roblox/lib";
export const syncCommand = useGetData.command("sync", {
description: "Link your Roblox account to your Discord account",
});
syncCommand.subcommand("pair", {
description: "Link your Roblox account to your Discord account",
run: async (interaction, _, { actor }) => {
if (!actor)
return interaction.reply({ content: "Failed to fetch your data.", ephemeral: true });
const pin = Math.floor(100000 + Math.random() * 900000);
const pinExpiryMs = 5 * 60 * 1000;
await editActor(actor.id, {
pin: String(pin),
pinExpiresIn: new Date(Date.now() + pinExpiryMs),
});
interaction.reply({
content: [
`Your pin is: **${pin}**.`,
"Input this pin in Ground War or Warfare Tycoon to link your account.",
].join(" "),
flags: ["Ephemeral"],
});
const pollIntervalMs = 5000;
const startTime = Date.now();
const interval = setInterval(async () => {
try {
if (Date.now() - startTime > pinExpiryMs) {
clearInterval(interval);
await interaction
.editReply({
content:
"Your verification pin has expired. Please run the command again to generate a new one.",
})
.catch(() => {});
return;
}
const updatedActor = await getActor(actor.id);
if (updatedActor && updatedActor.robloxId) {
clearInterval(interval);
const oauthButton = new ButtonBuilder()
.setLabel("Finalize Profile Sync")
.setStyle(ButtonStyle.Link)
.setURL(`http://127.0.0.1:3000/auth/login?actorId=${actor.id}`);
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(oauthButton);
await interaction
.editReply({
content:
"Successfully linked your Roblox account! Click the button below to authorize game widgets on your Discord profile.",
components: [row],
})
.catch(() => {});
}
} catch (error) {
logger.error(error, "Error during pin verification polling");
}
}, pollIntervalMs);
},
});
syncCommand.subcommand("unlink", {
description: "Unlink your Roblox account from your Discord account",
run: async (interaction, _, { actor }) => {
if (!actor)
return interaction.reply({ content: "Failed to fetch your data.", flags: ["Ephemeral"] });
await editActor(actor.id, {
pin: null,
pinExpiresIn: null,
robloxId: null,
});
interaction.reply({ content: "Your account has been unlinked.", flags: ["Ephemeral"] });
},
});
syncCommand.subcommand("status", {
description: "Check your linked Roblox account",
run: async (interaction, _, { actor }) => {
if (!actor)
return interaction.reply({ content: "Failed to fetch your data.", flags: ["Ephemeral"] });
if (!actor.robloxId)
return interaction.reply({
content: "You are not linked to a Roblox account.",
flags: ["Ephemeral"],
});
const [account, accountError] = await getUser(actor.robloxId);
if (accountError)
return interaction.reply({
content: "Failed to fetch your Roblox account.",
flags: ["Ephemeral"],
});
interaction.reply({
content: `You are linked to Roblox account **@${account.name}**.`,
flags: ["Ephemeral"],
});
},
});
|