From 5df3430242c820fbe659c85bf251a3c10a17229f Mon Sep 17 00:00:00 2001 From: DeSqBlocki Date: Sat, 15 Aug 2026 00:38:21 +0200 Subject: [PATCH] fuk you rai <3 --- commands/miscellaneous/poke.js | 365 +++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 commands/miscellaneous/poke.js diff --git a/commands/miscellaneous/poke.js b/commands/miscellaneous/poke.js new file mode 100644 index 0000000..ec456bc --- /dev/null +++ b/commands/miscellaneous/poke.js @@ -0,0 +1,365 @@ +const { + SlashCommandBuilder, + MessageFlags +} = require("discord.js"); + + +/* + * CONFIG + */ + +const POKE_MAX_TIMES = 5; +const POKE_DELAY_MS = 750; +const POKE_COOLDOWN_MS = 30_000; + + +/* + * In-memory cooldowns. + * + * Key: + * Discord user ID of the person sending the poke. + * + * Value: + * Timestamp when they may poke again. + */ + +const pokeCooldowns = new Map(); + + +module.exports = { + data: new SlashCommandBuilder() + .setName("fun") + .setDescription("Fun commands.") + + .addSubcommand(subcommand => + subcommand + .setName("poke") + .setDescription( + "Poke another server member in DMs." + ) + + .addUserOption(option => + option + .setName("member") + .setDescription( + "The member you want to poke." + ) + .setRequired(true) + ) + + .addIntegerOption(option => + option + .setName("times") + .setDescription( + `How many times to poke them. Max ${POKE_MAX_TIMES}.` + ) + .setMinValue(1) + .setMaxValue( + POKE_MAX_TIMES + ) + .setRequired(false) + ) + ), + + + async execute(interaction) { + switch ( + interaction.options.getSubcommand() + ) { + case "poke": + return poke( + interaction + ); + } + } +}; + + +/* + * POKE + */ + +async function poke(interaction) { + + /* + * Guild only. + */ + + if (!interaction.guild) { + return interaction.reply({ + content: + "This command can only be used inside a server.", + + flags: + MessageFlags.Ephemeral + }); + } + + + /* + * Options + */ + + const user = + interaction.options.getUser( + "member", + true + ); + + + const times = + interaction.options.getInteger( + "times" + ) + ?? 1; + + + /* + * Don't poke yourself. + */ + + if ( + user.id === + interaction.user.id + ) { + return interaction.reply({ + content: + "You can't poke yourself! 👉", + + flags: + MessageFlags.Ephemeral + }); + } + + + /* + * Don't poke bots. + */ + + if (user.bot) { + return interaction.reply({ + content: + "You can't poke a bot!", + + flags: + MessageFlags.Ephemeral + }); + } + + + /* + * Make sure the target is actually + * a member of this guild. + */ + + let member; + + + try { + member = + await interaction.guild + .members + .fetch( + user.id + ); + + } catch { + return interaction.reply({ + content: + "I couldn't find that member in this server.", + + flags: + MessageFlags.Ephemeral + }); + } + + + /* + * COOLDOWN + */ + + const now = + Date.now(); + + + const cooldownUntil = + pokeCooldowns.get( + interaction.user.id + ); + + + if ( + cooldownUntil && + cooldownUntil > now + ) { + const remaining = + Math.ceil( + ( + cooldownUntil - + now + ) + / + 1000 + ); + + + return interaction.reply({ + content: + `You need to wait **${remaining}s** before poking someone again.`, + + flags: + MessageFlags.Ephemeral + }); + } + + + /* + * Defer before sending DMs. + */ + + await interaction.deferReply({ + flags: + MessageFlags.Ephemeral + }); + + + /* + * Set cooldown before sending. + * + * This prevents repeated invocations + * while the DM loop is running. + */ + + pokeCooldowns.set( + interaction.user.id, + now + POKE_COOLDOWN_MS + ); + + + /* + * Sender name. + * + * Prefer their server display name. + */ + + let senderName = + interaction.user.displayName; + + + try { + const senderMember = + await interaction.guild + .members + .fetch( + interaction.user.id + ); + + + senderName = + senderMember.displayName; + + } catch { + /* + * interaction.user.displayName + * remains the fallback. + */ + } + + + /* + * SEND POKES + */ + + let sent = + 0; + + + try { + for ( + let i = 0; + i < times; + i++ + ) { + + await member.send({ + content: + `👉 **${senderName} poked you!**\n` + + `From **${interaction.guild.name}**` + }); + + + sent++; + + + /* + * Don't sleep after the final DM. + */ + + if ( + i < + times - 1 + ) { + await sleep( + POKE_DELAY_MS + ); + } + } + + } catch (error) { + console.error( + `Failed to poke ${user.tag}:`, + error + ); + + + /* + * If no messages made it through, + * this is most likely closed DMs. + */ + + if (sent === 0) { + return interaction.editReply({ + content: + `I couldn't poke ${user}. They may have DMs disabled.` + }); + } + + + /* + * Some messages succeeded before + * Discord rejected a later one. + */ + + return interaction.editReply({ + content: + `I poked ${user} **${sent}/${times}** times before I couldn't send any more.` + }); + } + + + /* + * SUCCESS + */ + + return interaction.editReply({ + content: + times === 1 + ? `👉 Poked ${user}!` + : `👉 Poked ${user} **${times} times!**` + }); +} + + +/* + * SLEEP + */ + +function sleep(ms) { + return new Promise( + resolve => + setTimeout( + resolve, + ms + ) + ); +} \ No newline at end of file