discord.jsで計算認証（コピペ）

## 前提
下記サイトを参考にして作成しました。

https://qiita.com/gx1285/items/aa8e0fba269931963b71

## 手順
index.js を作成して、ソースコードをコピーして貼り付け、必要な部分に必要な情報を入れる。

## 必要な環境
Node.js v16.9.0以上
discord.js v14.1.2以上

## パッケージのインストール
`npm init -y`
`npm i discord.js`
`npm i keyv @keyv/sqlite pify`

## コード
```js
const {
    Client,
    GatewayIntentBits,
    Events, EmbedBuilder,
    ActionRowBuilder,
    ButtonBuilder,
    ButtonStyle,
    ModalBuilder,
    TextInputBuilder,
    TextInputStyle
} = require('discord.js');

const client = new Client({
    intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildMembers,
        GatewayIntentBits.MessageContent,
        GatewayIntentBits.GuildMessages
    ],
});

const Keyv = require('keyv');
const verify_db = new Keyv('sqlite://db.sqlite', { table: 'verify' });

const token = '';
const admin_Id = '';
const add_roleId = '';

client.on(Events.ClientReady, async () => {
    console.log(`${client.user.username} でログイン中..`);
});

client.on(Events.MessageCreate, async message => {
    if (message.author.bot || !message.guild || message.author.id !== admin_Id) return;
    if (message.content === '!verify') {
        const row = new ActionRowBuilder()
            .addComponents(
                new ButtonBuilder()
                    .setCustomId('start_verify')
                    .setLabel('認証を開始')
                    .setEmoji('✅')
                    .setStyle(ButtonStyle.Secondary)
            );
        const embed = new EmbedBuilder()
            .setTitle('足し算認証')
            .setDescription('下のボタンを押して、認証してください。')
            .setColor('Green')
        await message.channel.send({ embeds: [embed], components: [row] });
        message.delete();
    }
});

client.on(Events.InteractionCreate, async interaction => {
    const { customId } = interaction;
    if (interaction.isButton()) {
        if (customId === 'start_verify') {
            const calc1 = Math.floor(Math.random() * 21);
            const calc2 = Math.floor(Math.random() * 21);
            await verify_db.set(interaction.user.id + '_kye', { one: calc1, two: calc2 });

            const role = interaction.guild.roles.cache.get(add_roleId);
            if (!role) {
                const err_embed = new EmbedBuilder()
                    .setAuthor({ name: '❌｜エラー' })
                    .setDescription(`設定されていたロールが見つかりませんでした。\n<@${interaction.guild.ownerId}> までご連絡ください。`)
                    .setColor('Red');
                return interaction.reply({ embeds: [err_embed], ephemeral: true });
            }
            const bot = interaction.guild.members.cache.get(interaction.client.user.id);
            const botrole = bot.roles.highest;
            if (role.position > botrole.position) {
                const err_embed = new EmbedBuilder()
                    .setAuthor({ name: '❌｜エラー' })
                    .setDescription(`設定されていたロールが ${client.user} より権限が高いため認証を進めることができません。\n<@${interaction.guild.ownerId}> までご連絡ください。`)
                    .setColor('Red');
                return interaction.reply({ embeds: [err_embed], ephemeral: true });
            }
            const modal = new ModalBuilder()
                .setCustomId('verify_modal')
                .setTitle('足し算認証');

            const add_row = new ActionRowBuilder().addComponents(
                new TextInputBuilder()
                    .setCustomId('q')
                    .setLabel(`${calc1} + ${calc2} の答えは？`)
                    .setStyle(TextInputStyle.Short)
                    .setPlaceholder('ここに入力して下さい。')
                    .setRequired(true),
            );
            modal.addComponents(add_row);
            await interaction.showModal(modal);
        }
    }
    if (interaction.isModalSubmit()) {
        if (customId === 'verify_modal') {
            const a = interaction.fields.getTextInputValue('q');
            const data = await verify_db.get(interaction.user.id + '_kye');
            const role = interaction.guild.roles.cache.get(add_roleId);
            if (Number(data.one) + Number(data.two) != a) {
                const embed = new EmbedBuilder()
                    .setAuthor({ name: '❌｜回答失敗' })
                    .setDescription(`回答が正しくないため、認証を終了しました。\n正解は \`${Number(data.one) + Number(data.two)}\` です。`)
                return interaction.reply({ embeds: [embed], ephemeral: true });
            }
            if (!role) {
                const err_embed = new EmbedBuilder()
                    .setAuthor({ name: '❌｜エラー' })
                    .setDescription(`設定されていたロールが見つかりませんでした。\n<@${interaction.guild.ownerId}> までご連絡ください。`)
                    .setColor('Red');
                return interaction.reply({ embeds: [err_embed], ephemeral: true });
            }
            try {
                await interaction.guild.members.resolve(interaction.user).roles.add(role);
                const embed = new EmbedBuilder()
                    .setAuthor({ name: '✅｜認証成功' })
                    .setDescription(`認証に成功しました。\nDiscord利用規約に反さないよう、十分に気を付けて **${interaction.guild.name}** をご利用ください。`)
                    .setColor('Green');
                await interaction.reply({ embeds: [embed], ephemeral: true })
            } catch (e) {
                console.log(e);
                if (e.code == 50013) {
                    const err_embed = new EmbedBuilder()
                        .setAuthor({ name: '❌｜エラー' })
                        .setDescription(`設定されていたロールが ${client.user} より権限が高いため認証を進めることができません。\n<@${interaction.guild.ownerId}> までご連絡ください。\n\`\`\`${e.message}\`\`\``)
                        .setColor('Red');
                    return interaction.reply({ embeds: [err_embed], ephemeral: true });
                } else {
                    const err_embed = new EmbedBuilder()
                        .setAuthor({ name: '❌｜エラー' })
                        .setDescription(`不明なエラーが発生しました。下記のエラーコードを <@${interaction.guild.ownerId}> までご連絡ください。\n\`\`\`${e.code}\`\`\``)
                        .setColor('Red');
                    return interaction.reply({ embeds: [err_embed], ephemeral: true });
                }
            }
        }
    }
});

client.login(token);
```
### Q.このコードを無断で使ったり、改造してBOTを公開してもいい？

完全オープンソースコードです、著作権は私にありますが、許可を取らずに使用していただいて構いません。（この投稿にいいねしてくれたらうれしいです）