153 lines
5.2 KiB
TypeScript
153 lines
5.2 KiB
TypeScript
import discord, {
|
|
CommandInteraction,
|
|
CommandInteractionOptionResolver,
|
|
SlashCommandBuilder,
|
|
SlashCommandRoleOption,
|
|
SlashCommandStringOption,
|
|
SlashCommandIntegerOption,
|
|
SlashCommandSubcommandBuilder,
|
|
EmbedBuilder,
|
|
InteractionResponse,
|
|
SlashCommandSubcommandsOnlyBuilder,
|
|
} from 'discord.js';
|
|
import {HydratedDocument} from 'mongoose';
|
|
|
|
import {Command} from '../../classes/command';
|
|
import {logger} from '../../logger';
|
|
import {config} from '../../config';
|
|
import {Guild, guildModel} from '../../models/Guild';
|
|
import {GiveawayMsg, giveawayMsgModel} from '../../models/GiveawayMsg';
|
|
|
|
type CIOR = CommandInteractionOptionResolver;
|
|
|
|
async function add(interaction: CommandInteraction): Promise<void>{
|
|
const message: string | null =
|
|
(interaction.options as CIOR).getString('message');
|
|
if(!message)
|
|
throw Error('message not exist');
|
|
const embed = new EmbedBuilder()
|
|
.setTitle('New Giveaway')
|
|
.setDescription(`@everyone\n${message}`);
|
|
|
|
if(!interaction.guildId)
|
|
throw Error('guildId not exist');
|
|
if(!interaction.channelId)
|
|
throw Error('channelId not exist');
|
|
|
|
let msg: discord.Message =
|
|
await (await interaction.reply({embeds: [embed]})).fetch();
|
|
await msg.react(config.giveaway.emoji);
|
|
if(!interaction.guild || !interaction.guild.id)
|
|
throw Error('guild not exist');
|
|
const guild: HydratedDocument<Guild> | null =
|
|
await guildModel.findOneAndUpdate(
|
|
{id: interaction.guild.id},
|
|
{$set: {name: interaction.guild.name}},
|
|
{upsert: true, new: true}
|
|
);
|
|
if(!guild)
|
|
throw Error('guild not exist');
|
|
const giveawayMsg: HydratedDocument<GiveawayMsg> | null =
|
|
await giveawayMsgModel.findOneAndUpdate(
|
|
{guild: guild, messageId: msg.id, authorId: interaction.user.id},
|
|
{}, {upsert: true, new: true}
|
|
);
|
|
if(!giveawayMsg)
|
|
throw Error('giveawayMsg not exist');
|
|
|
|
await msg.edit({embeds: [new EmbedBuilder()
|
|
.setColor(Math.floor(Math.random()*16777215))
|
|
.setTitle('Giveaway')
|
|
.setDescription(message)
|
|
.setFooter({text: `id: ${msg.id}`})
|
|
]});
|
|
}
|
|
|
|
async function pick(interaction: CommandInteraction): Promise<void>{
|
|
const messageId: string | null =
|
|
(interaction.options as CIOR).getString('message');
|
|
if(!messageId)
|
|
throw Error('message not exist');
|
|
const num: number | null =
|
|
(interaction.options as CIOR).getInteger('number');
|
|
if(!num)
|
|
throw Error('number not exist');
|
|
|
|
const dbGiveawayMsg: HydratedDocument<GiveawayMsg> | null =
|
|
await giveawayMsgModel.findOneAndDelete({
|
|
messageId: messageId, authorId: interaction.user.id
|
|
});
|
|
if(!dbGiveawayMsg){
|
|
await interaction.reply({
|
|
content: logger.log(`Giveaway didn't exist or the author didn't match.`),
|
|
ephemeral: true
|
|
});
|
|
return;
|
|
}
|
|
for(let i = dbGiveawayMsg.userIds.length - 1; i > 0; i--){
|
|
let j = Math.floor(Math.random() * (i + 1));
|
|
[dbGiveawayMsg.userIds[i], dbGiveawayMsg.userIds[j]]
|
|
= [dbGiveawayMsg.userIds[j], dbGiveawayMsg.userIds[i]];
|
|
}
|
|
let content: string = '### Giveaway Result\n';
|
|
for(let i = 0; i < num; i++)
|
|
content += `1. ${await interaction.client.users.fetch(dbGiveawayMsg.userIds[i])}\n`;
|
|
content += `will obtain the prize for giveaway, id: ${dbGiveawayMsg.messageId}`;
|
|
await interaction.reply({content: content});
|
|
}
|
|
|
|
class Giveaway extends Command{
|
|
get name(){return 'giveaway';}
|
|
get description(){return 'Setup a Giveaway message.';}
|
|
async execute(interaction: CommandInteraction): Promise<void>{
|
|
try{
|
|
const subcommand: string | null =
|
|
(interaction.options as CIOR).getSubcommand();
|
|
switch(subcommand){
|
|
case 'add':
|
|
await add(interaction); break;
|
|
case 'pick':
|
|
await pick(interaction); break;
|
|
default:
|
|
throw Error('subcommand not exist');
|
|
}
|
|
}catch(err: unknown){
|
|
let message;
|
|
if(err instanceof Error) message = err.message;
|
|
else message = String(message);
|
|
logger.error(`While executing "/giveaway", ${message}`);
|
|
await interaction.reply({content: `While executing "/giveaway", ${message}`});
|
|
}
|
|
}
|
|
override build(): SlashCommandSubcommandsOnlyBuilder{
|
|
return new SlashCommandBuilder()
|
|
.setName(this.name)
|
|
.setDescription(this.description)
|
|
.addSubcommand((subcommand: SlashCommandSubcommandBuilder) => subcommand
|
|
.setName('add')
|
|
.setDescription('Construct a giveaway')
|
|
.addStringOption((option: SlashCommandStringOption) => option
|
|
.setName('message')
|
|
.setDescription('The message displayed with the giveaway message.')
|
|
.setRequired(true)
|
|
)
|
|
)
|
|
.addSubcommand((subcommand: SlashCommandSubcommandBuilder) => subcommand
|
|
.setName('pick')
|
|
.setDescription('Random pick a number of user in a giveaway')
|
|
.addStringOption((option: SlashCommandStringOption) => option
|
|
.setName('message')
|
|
.setDescription('The message id of the giveaway (Shown in the footer)')
|
|
.setRequired(true)
|
|
)
|
|
.addIntegerOption((option: SlashCommandIntegerOption) => option
|
|
.setName('number')
|
|
.setDescription('The number of member to choose.')
|
|
.setRequired(true)
|
|
)
|
|
)
|
|
}
|
|
};
|
|
|
|
export const command = new Giveaway();
|