Skip to content

Instantly share code, notes, and snippets.

@giorgi-o
Last active March 23, 2023 10:49
Show Gist options
  • Save giorgi-o/9c7eede3b5c72c8b9f071b6dc8c8cd3c to your computer and use it in GitHub Desktop.
Save giorgi-o/9c7eede3b5c72c8b9f071b6dc8c8cd3c to your computer and use it in GitHub Desktop.
Discord Tic Tac Toe using Buttons (Components)
/**
* Tic Tac Toe using Discord's new components!
* https://reddit.com/r/discordapp/comments/nn733r
*
* Discord released their "components" feature yesterday,
* and I thought I might as well create something to
* try and learn how to use them, so here we go.
* This version doesn't even check for a winner lol.
*
* NOTE: As of 28/05, THIS WILL NOT WORK on the
* stable version of discord.js. You need to install
* monbrey's fork of discord.js, specifically the
* #message-components branch:
*
* npm install monbrey/discord.js#message-components
*
* A pull request has been submitted and the devs are
* going over it, but even then it will only be in
* master. For it to arrive in stable (the version
* you get using "npm install discord.js"), you
* need to wait until v13 is published, which won't
* happen for a long time, and this code will only
* work if they don't change anything between now
* and then, which is highly unlikely.
* Anyways, enjoy :)
*
* Made by u/giorgiocav123
*/
const Discord = require('discord.js');
const client = new Discord.Client({intents: Discord.Intents.NON_PRIVILEGED});
client.on("ready", async () => {
console.log(`Logged in as ${client.user.tag}!`);
for(const guild of client.guilds.cache.values())
await guild.commands.create({
name: "tictactoe",
description: "Play tic tac toe!"
}).catch(() => {});
});
/** @type interaction {Discord.CommandInteraction} */
client.on("interaction", async interaction => {
if(interaction.isCommand() && interaction.commandName === "tictactoe") {
interaction.reply("Here we go!", {
components: [
{type: 1, components: [
{type: 2, label: "_", style: 2, custom_id: "ttt11"},
{type: 2, label: "_", style: 2, custom_id: "ttt12"},
{type: 2, label: "_", style: 2, custom_id: "ttt13"},
]},
{type: 1, components: [
{type: 2, label: "_", style: 2, custom_id: "ttt21"},
{type: 2, label: "_", style: 2, custom_id: "ttt22"},
{type: 2, label: "_", style: 2, custom_id: "ttt23"},
]},
{type: 1, components: [
{type: 2, label: "_", style: 2, custom_id: "ttt31"},
{type: 2, label: "_", style: 2, custom_id: "ttt32"},
{type: 2, label: "_", style: 2, custom_id: "ttt33"},
]},
]
});
} else if(interaction.isMessageComponent() && interaction.customID.startsWith("ttt")) {
await updateGrid(interaction);
}
});
/**
*
* @param {Discord.MessageComponentInteraction} interaction
*/
async function updateGrid(interaction) {
/** @type {Discord.Message} message */
const message = interaction.message;
let xs = 0, os = 0;
for(let actionRow of message.components) {
for(let button of actionRow.components) {
if(button.label === 'X') xs++;
else if(button.label === 'O') os++;
}
}
const xs_turn = xs <= os;
const i = parseInt(interaction.customID[3]),
j = parseInt(interaction.customID[4]);
const buttonPressed = message.components[i-1].components[j-1];
if(buttonPressed.label !== '_')
return await interaction.reply("Someone already played there!", {ephemeral: true});
buttonPressed.label = xs_turn ? 'X' : 'O';
buttonPressed.style = xs_turn ? "SUCCESS" : "DANGER";
const styleToNumber = style => style === "SECONDARY" ? 2 : style === "SUCCESS" ? 3 : 4;
const components = [];
for(let actionRow of message.components) {
components.push({type: 1, components: []});
for (let button of actionRow.components) {
components[components.length - 1].components.push({type: 2, label: button.label, style: styleToNumber(button.style), custom_id: button.customID});
}
}
await message.edit({components: components});
await interaction.deferUpdate();
}
client.login("almost leaked my token there whoops");
@kyttarikos
Copy link

This is hella nice!

@AalbatrossGuy
Copy link

can i use this????

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment