Files
amane-tanikaze-dcbot/commands/giveaway/giveaway.ts
2024-10-13 14:50:19 +00:00

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();