fuk you rai <3
This commit is contained in:
@@ -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
|
||||
)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user