diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 44eca1c..7544372 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ yarn@3.6.1を使用してください。 1. その内容の Pull request が既に存在していないかを確認して下さい。(マージ済み、クローズ済みのものも) 2. もう実装されていないか確認して下さい。 3. Fork し、コードを書いて、内容を書き込みます。 -4. Pull request を作成します。(developブランチによろしくお願いいたします。) +4. Pull request を作成します。(develop ブランチによろしくお願いいたします。) ## コミットメッセージ diff --git a/config.example.json b/config.example.json index eac2bed..eb06cc1 100644 --- a/config.example.json +++ b/config.example.json @@ -1,18 +1,24 @@ { - "token": "Discord Bot Token", - "owners": ["user id"], - "mods": ["user id"], + "token": "", + "owners": [ + "" + ], + "mods": [ + "" + ], "channelIds": { - "error": "channel id", - "botLog": "channel id", - "commandLog": "channel id" + "error": "", + "botLog": "", + "commandLog": "" }, - "clientId": "user id", + "clientId": "", + "mongoDBUrl": "", "load": { "chatinput": true, "messagecotextmenu": true, "usercotextmenu": true }, - "mongoDBUrl": "mongoDBUrl", - "key": "key" -} + "sgcJsonChannelId": "", + "sgcJsonChannelIdv2": "", + "key": "" +} \ No newline at end of file diff --git a/package.json b/package.json index ac18b73..f7fe554 100644 --- a/package.json +++ b/package.json @@ -13,18 +13,22 @@ "start": "node dist/src/index.js" }, "dependencies": { - "@discordjs/rest": "^1.7.2-dev.1689034321-09b0382.0", - "discord.js": "^14.11.1-dev.1689034320-09b0382.0", - "enka-network-api": "^3.7.0", + "@discordjs/rest": "^1.7.2-dev.1689249890-ceab07b.0", + "discord.js": "^14.11.1-dev.1689249910-ceab07b.0", + "enka-network-api": "^3.7.1", "json-bigint": "^1.0.0", - "mongoose": "^7.3.2", - "typescript": "^5.1.6" + "mongoose": "^7.3.4", + "typescript": "^5.1.6", + "ws": "^8.13.0", + "xml2js": "^0.6.0" }, "devDependencies": { "@commitlint/cli": "^17.6.6", "@commitlint/config-conventional": "^17.6.6", "@types/json-bigint": "^1.0.1", - "@types/node": "20.4.1", + "@types/node": "20.4.2", + "@types/ws": "^8.5.5", + "@types/xml2js": "^0.4.11", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "@yarnpkg/pnpify": "3.1.6", @@ -34,7 +38,7 @@ "eslint-formatter-pretty": "^5.0.0", "eslint-plugin-unicorn": "^47.0.0", "husky": "^8.0.3", - "prettier": "^3.0.0", + "prettier": "2.8.8", "rimraf": "^5.0.1" }, "engines": { diff --git a/src/command/chatinput/afk.ts b/src/command/chatinput/afk.ts new file mode 100644 index 0000000..31454f6 --- /dev/null +++ b/src/command/chatinput/afk.ts @@ -0,0 +1,33 @@ +import { ChatInputCommandInteraction, Colors, EmbedBuilder, SlashCommandBuilder } from 'discord.js'; + +export default { + command: new SlashCommandBuilder() + .setName('afk') + .setDescription('afkが設定または解除されます。') + .addStringOption((input) => input.setName('reason').setDescription('理由').setRequired(false)), + ownersOnly: false, + modOnly: false, + permissions: false, + async execute(interaction: ChatInputCommandInteraction) { + const { afk, mention } = interaction.client.botData.afk; + const mentions: string[] | undefined = await mention.get(interaction.user.id); + if (await afk.get(interaction.user.id)) { + await afk.delete(interaction.user.id); + const embed = new EmbedBuilder() + .setColor(Colors.Blue) + .setTitle('✅ afkを解除しました。') + .setDescription('解除に成功しました。'); + if (mentions) { + embed.addFields({ name: 'メンション: ', value: mentions.join('\n') }); + await mention.delete(interaction.user.id); + } + await interaction.reply({ + ephemeral: false, + embeds: [embed], + }); + } else { + await afk.set(interaction.user.id, interaction.options.getString('reason') || true); + await interaction.ok('afkを設定しました。', 'afkになりました。', false); + } + }, +}; diff --git a/src/command/chatinput/bot_invite.ts b/src/command/chatinput/bot_invite.ts new file mode 100644 index 0000000..d98185f --- /dev/null +++ b/src/command/chatinput/bot_invite.ts @@ -0,0 +1,95 @@ +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + ChatInputCommandInteraction, + Colors, + EmbedBuilder, + PermissionsBitField, + SlashCommandBuilder, +} from 'discord.js'; + +export default { + command: new SlashCommandBuilder() + .setName('bot_invite') + .setDescription('指定したbotの招待リンクを生成します。') + .addUserOption((input) => input.setName('bot').setDescription('bot').setRequired(false)), + ownersOnly: false, + modOnly: false, + permissions: false, + async execute(interaction: ChatInputCommandInteraction) { + const bot = interaction.options.getUser('bot'); + if (!bot) + return await interaction.reply({ + embeds: [ + new EmbedBuilder() + .setTitle(`${interaction.client.user.tag}を招待する。`) + .setColor(Colors.Blue) + .setDescription('下のボタンから招待できます。') + .setThumbnail(interaction.client.user.extDefaultAvatarURL({ extension: 'webp' })), + ], + components: [ + new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel('管理者権限') + .setURL( + `https://discord.com/api/oauth2/authorize?client_id=${ + interaction.client.user.id + }&permissions=${PermissionsBitField.Flags.Administrator.toString()}&scope=bot%20applications.commands`, + ), + new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel('権限選択') + .setURL( + `https://discord.com/api/oauth2/authorize?client_id=${ + interaction.client.user.id + }&permissions=${PermissionsBitField.All.toString()}&scope=bot%20applications.commands`, + ), + new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel('権限なし') + .setURL( + `https://discord.com/api/oauth2/authorize?client_id=${interaction.client.user.id}&permissions=0&scope=bot%20applications.commands`, + ), + ), + ], + }); + if (!bot.bot) return await interaction.error('指定されたものはbotではありません', 'botを指定してください。', true); + await interaction.reply({ + embeds: [ + new EmbedBuilder() + .setTitle(`${bot.tag}を招待する。`) + .setColor(Colors.Blue) + .setDescription('下のボタンから招待できます。') + .setThumbnail(bot.extDefaultAvatarURL({ extension: 'webp' })), + ], + components: [ + new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel('管理者権限') + .setURL( + `https://discord.com/api/oauth2/authorize?client_id=${ + bot.id + }&permissions=${PermissionsBitField.Flags.Administrator.toString()}&scope=bot%20applications.commands`, + ), + new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel('権限選択') + .setURL( + `https://discord.com/api/oauth2/authorize?client_id=${ + bot.id + }&permissions=${PermissionsBitField.All.toString()}&scope=bot%20applications.commands`, + ), + new ButtonBuilder() + .setStyle(ButtonStyle.Link) + .setLabel('権限なし') + .setURL( + `https://discord.com/api/oauth2/authorize?client_id=${bot.id}&permissions=0&scope=bot%20applications.commands`, + ), + ), + ], + }); + }, +}; diff --git a/src/command/chatinput/globalchat.ts b/src/command/chatinput/globalchat.ts index 21ce18a..f56a854 100644 --- a/src/command/chatinput/globalchat.ts +++ b/src/command/chatinput/globalchat.ts @@ -7,6 +7,7 @@ import { SlashCommandBuilder, Webhook, } from 'discord.js'; +import { translatePermission } from '../../utils/permission.js'; export default { command: new SlashCommandBuilder() @@ -18,9 +19,32 @@ export default { ), ownersOnly: false, modOnly: false, - permissions: [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.ManageWebhooks], + permissions: false, async execute(interaction: ChatInputCommandInteraction) { + const permissions = [PermissionFlagsBits.ManageChannels]; + const authorPerms = interaction.channel.permissionsFor(interaction.guild.members.cache.get(interaction.user.id)); + if (!authorPerms || !permissions.every((permission) => authorPerms.has(permission))) { + const permission: bigint[] = permissions; + return await interaction.error( + '権限不足', + 'このコマンドを実行するためには、あなたに`' + + translatePermission(permission).join(', ') + + '`の権限が必要です。', + true, + ); + } + const botPerms = interaction.channel.permissionsFor( + interaction.guild.members.cache.get(interaction.client.user.id), + ); + if (!botPerms || !permissions.every((permission) => botPerms.has(permission))) { + const permission: bigint[] = permissions; + return await interaction.error( + '権限不足', + 'このコマンドを実行するためには、Botに`' + translatePermission(permission).join(', ') + '`の権限が必要です。', + true, + ); + } const { register, blocks } = interaction.client.botData.globalChat; const optionsChannel = interaction.options.getChannel('channel', true, [ChannelType.GuildText]); diff --git a/src/command/chatinput/slot.ts b/src/command/chatinput/slot.ts new file mode 100644 index 0000000..9418560 --- /dev/null +++ b/src/command/chatinput/slot.ts @@ -0,0 +1,65 @@ +import { ChatInputCommandInteraction, SlashCommandBuilder, PermissionFlagsBits } from 'discord.js'; +import { setTimeout } from 'node:timers/promises'; +export default { + command: new SlashCommandBuilder().setName('slot').setDescription('スロットができます。').setGuildOnly(), + ownersOnly: false, + modOnly: false, + permissions: [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.MentionEveryone], + async execute(interaction: ChatInputCommandInteraction) { + const array = [ + '🍏', + '🍎', + '🍐', + '🍊', + '🍋', + '🍉', + '🍇', + '🫐', + '🍅', + '🥝', + '🍍', + '🍒', + '🍈', + '🍓', + '🍏', + '🍎', + '🍐', + '🍊', + '🍋', + '🍉', + '🍇', + '🫐', + '🍅', + '🥝', + '🍍', + '🍒', + '🍈', + '🍓', + ]; + + const random = Math.floor(Math.random() * array.length); + const result = array[random]; + const random2 = Math.floor(Math.random() * array.length); + const result2 = array[random2]; + const random3 = Math.floor(Math.random() * array.length); + const result3 = array[random3]; + await interaction.reply(result + result2 + result3); + let x = 0; + while (x < 10) { + x++; + await setTimeout(1000); + const random = Math.floor(Math.random() * array.length); + const result = array[random]; + const random2 = Math.floor(Math.random() * array.length); + const result2 = array[random2]; + const random3 = Math.floor(Math.random() * array.length); + const result3 = array[random3]; + await interaction.editReply(result + result2 + result3); + if (x == 10) { + await (result === result2 && result2 === result3 + ? interaction.followUp('あなたは勝利しました。') + : interaction.followUp('あなたは負けました。')); + } + } + }, +}; diff --git a/src/command/chatinput/superglobalchat.ts b/src/command/chatinput/superglobalchat.ts new file mode 100644 index 0000000..7b94e76 --- /dev/null +++ b/src/command/chatinput/superglobalchat.ts @@ -0,0 +1,51 @@ +import { ChannelType, ChatInputCommandInteraction, PermissionFlagsBits, SlashCommandBuilder } from 'discord.js'; +import { translatePermission } from '../../utils/permission.js'; + +export default { + command: new SlashCommandBuilder() + .setName('superglobalchat') + .setDescription('スーパーグローバルチャットに参加/退出します。') + .setGuildOnly() + .addChannelOption((input) => + input.addChannelTypes(ChannelType.GuildText).setName('channel').setDescription('チャンネル').setRequired(true), + ), + ownersOnly: true, + modOnly: false, + permissions: false, + + async execute(interaction: ChatInputCommandInteraction) { + const permissions = [PermissionFlagsBits.ManageChannels]; + const authorPerms = interaction.channel.permissionsFor(interaction.guild.members.cache.get(interaction.user.id)); + if (!authorPerms || !permissions.every((permission) => authorPerms.has(permission))) { + const permission: bigint[] = permissions; + return await interaction.error( + '権限不足', + 'このコマンドを実行するためには、あなたに`' + + translatePermission(permission).join(', ') + + '`の権限が必要です。', + true, + ); + } + const botPerms = interaction.channel.permissionsFor( + interaction.guild.members.cache.get(interaction.client.user.id), + ); + if (!botPerms || !permissions.every((permission) => botPerms.has(permission))) { + const permission: bigint[] = permissions; + return await interaction.error( + '権限不足', + 'このコマンドを実行するためには、Botに`' + translatePermission(permission).join(', ') + '`の権限が必要です。', + true, + ); + } + const { register } = interaction.client.botData.superGlobalChat; + const optionsChannel = interaction.options.getChannel('channel', true, [ChannelType.GuildText]); + + if (await register.get(optionsChannel.id)) { + await register.delete(optionsChannel.id); + await interaction.ok('退出しました。', '退出が完了しました。', false); + } else { + await register.set(optionsChannel.id, true); + await interaction.ok('参加しました。', '参加が完了しました。', false); + } + }, +}; diff --git a/src/command/chatinput/url_check.ts b/src/command/chatinput/url_check.ts new file mode 100644 index 0000000..35cf9ed --- /dev/null +++ b/src/command/chatinput/url_check.ts @@ -0,0 +1,71 @@ +import { ChatInputCommandInteraction, Colors, EmbedBuilder, SlashCommandBuilder } from 'discord.js'; +export default { + command: new SlashCommandBuilder() + .setName('url_check') + .setDescription('URLの安全性を確認します。') + .addStringOption((input) => input.setName('url').setDescription('確認したいurl').setRequired(true)), + ownersOnly: false, + modOnly: false, + permissions: false, + + async execute(interaction: ChatInputCommandInteraction) { + await interaction.deferReply(); + const url = interaction.options.getString('url'); + fetch(`https://safeweb.norton.com/report/show?url=${encodeURI(url)}&ulang=jpn`).then(async (value) => { + if (!value.ok) + return await interaction.editReply({ + embeds: [ + new EmbedBuilder() + .setTitle('❌ 確認失敗') + .setDescription('安全性の確認に失敗しました。') + .setColor(Colors.Red), + ], + }); + const data: string = await value.text(); + if (data.includes('安全性')) { + return await interaction.editReply({ + embeds: [ + new EmbedBuilder() + .setTitle('このサイトは安全です') + .setDescription(`ノートン セーフウェブが分析して安全性とセキュリティの問題を調べました。`) + .setColor(Colors.Green) + + .setFooter({ text: 'Powered by Norton Safeweb' }), + ], + }); + } else if (data.includes('[注意]')) { + return await interaction.editReply({ + embeds: [ + new EmbedBuilder() + .setTitle('このサイトは注意が必要です') + .setDescription( + `注意の評価を受けた Web サイトは少数の脅威または迷惑を伴いますが、赤色の警告に相当するほど危険とは見なされません。サイトにアクセスする場合には注意が必要です。`, + ) + .setColor(Colors.Yellow) + .setFooter({ text: 'Powered by Norton Safeweb' }), + ], + }); + } else if (data.includes('警告')) { + return await interaction.editReply({ + embeds: [ + new EmbedBuilder() + .setTitle('このサイトは危険です') + .setDescription(`これは既知の危険な Web ページです。このページを表示**しない**ことを推奨します。`) + .setColor(Colors.Red) + .setFooter({ text: 'Powered by Norton Safeweb' }), + ], + }); + } else { + return await interaction.editReply({ + embeds: [ + new EmbedBuilder() + .setTitle('このサイトは未評価です') + .setDescription(`このサイトはまだ評価されていません。`) + .setColor(Colors.Grey) + .setFooter({ text: 'Powered by Norton Safeweb' }), + ], + }); + } + }); + }, +}; diff --git a/src/command/chatinput/verify.ts b/src/command/chatinput/verify.ts new file mode 100644 index 0000000..fc49639 --- /dev/null +++ b/src/command/chatinput/verify.ts @@ -0,0 +1,157 @@ +import { + ButtonBuilder, + ButtonStyle, + EmbedBuilder, + ActionRowBuilder, + ChatInputCommandInteraction, + SlashCommandBuilder, + Colors, +} from 'discord.js'; +export default { + command: new SlashCommandBuilder() + .setName('verify') + .setDescription('認証パネルを生成します。') + .addStringOption((input) => + input + .setName('type') + .setDescription('認証の種類') + .addChoices( + { name: '足し算認証', value: '足し算認証' }, + { name: '引き算認証', value: '引き算認証' }, + { name: '掛け算認証', value: '掛け算認証' }, + { name: '割り算認証', value: '割り算認証' }, + { name: '1クリック認証', value: '1クリック認証' }, + { name: '乱数認証', value: '乱数認証' }, + ) + .setRequired(true), + ) + .addRoleOption((input) => + input.setName('role').setDescription('認証が完了した時に付与するロール').setRequired(true), + ) + .setGuildOnly(), + ownersOnly: false, + modOnly: false, + permissions: false, + + async execute(interaction: ChatInputCommandInteraction) { + switch (interaction.options.getString('type')) { + case '足し算認証': { + const role = interaction.options.getRole('role'); + const message = await interaction.reply({ + fetchReply: true, + embeds: [ + new EmbedBuilder() + .setTitle('足し算認証') + .setDescription(`下のボタンを押して、認証して下さい。\n付与されるロール: <@&${role.id}>`) + .setColor(Colors.Blue), + ], + components: [ + new ActionRowBuilder().addComponents( + new ButtonBuilder().setCustomId('verify_button_1').setStyle(ButtonStyle.Success).setLabel(`認証`), + ), + ], + }); + await interaction.client.botData.verifyPanel.set(message.id, role.id); + break; + } + case '引き算認証': { + const role = interaction.options.getRole('role'); + const message = await interaction.reply({ + fetchReply: true, + embeds: [ + new EmbedBuilder() + .setTitle('引き算認証') + .setDescription(`下のボタンを押して、認証して下さい。\n付与されるロール: <@&${role.id}>`) + .setColor(Colors.Blue), + ], + components: [ + new ActionRowBuilder().addComponents( + new ButtonBuilder().setCustomId('verify_button_2').setStyle(ButtonStyle.Success).setLabel(`認証`), + ), + ], + }); + await interaction.client.botData.verifyPanel.set(message.id, role.id); + break; + } + case '掛け算認証': { + const role = interaction.options.getRole('role'); + const message = await interaction.reply({ + fetchReply: true, + embeds: [ + new EmbedBuilder() + .setTitle('掛け算認証') + .setDescription(`下のボタンを押して、認証して下さい。\n付与されるロール: <@&${role.id}>`) + .setColor(Colors.Blue), + ], + components: [ + new ActionRowBuilder().addComponents( + new ButtonBuilder().setCustomId('verify_button_3').setStyle(ButtonStyle.Success).setLabel(`認証`), + ), + ], + }); + await interaction.client.botData.verifyPanel.set(message.id, role.id); + break; + } + case '割り算認証': { + const role = interaction.options.getRole('role'); + const message = await interaction.reply({ + fetchReply: true, + embeds: [ + new EmbedBuilder() + .setTitle('割り算認証') + .setDescription(`下のボタンを押して、認証して下さい。\n付与されるロール: <@&${role.id}>`) + .setColor(Colors.Blue), + ], + components: [ + new ActionRowBuilder().addComponents( + new ButtonBuilder().setCustomId('verify_button_4').setStyle(ButtonStyle.Success).setLabel(`認証`), + ), + ], + }); + await interaction.client.botData.verifyPanel.set(message.id, role.id); + break; + } + case '1クリック認証': { + const role = interaction.options.getRole('role'); + const message = await interaction.reply({ + fetchReply: true, + embeds: [ + new EmbedBuilder() + .setTitle('1クリック認証') + .setDescription(`下のボタンを押して、認証して下さい。\n付与されるロール: <@&${role.id}>`) + .setColor(Colors.Blue), + ], + components: [ + new ActionRowBuilder().addComponents( + new ButtonBuilder().setCustomId('verify_button_5').setStyle(ButtonStyle.Success).setLabel(`認証`), + ), + ], + }); + await interaction.client.botData.verifyPanel.set(message.id, role.id); + break; + } + case '乱数認証': { + const role = interaction.options.getRole('role'); + const message = await interaction.reply({ + fetchReply: true, + embeds: [ + new EmbedBuilder() + .setTitle('乱数認証') + .setDescription(`下のボタンを押して、認証して下さい。\n付与されるロール: <@&${role.id}>`) + .setColor(Colors.Blue), + ], + components: [ + new ActionRowBuilder().addComponents( + new ButtonBuilder().setCustomId('verify_button_6').setStyle(ButtonStyle.Success).setLabel(`認証`), + ), + ], + }); + await interaction.client.botData.verifyPanel.set(message.id, role.id); + break; + } + default: { + break; + } + } + }, +}; diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts index 8aa7374..f11ad04 100644 --- a/src/events/messageDelete.ts +++ b/src/events/messageDelete.ts @@ -1,30 +1,63 @@ /* eslint-disable unicorn/no-nested-ternary */ import { ChannelType, Events, Message, Webhook } from 'discord.js'; +import { MessageDeleteData } from '../utils/SuperGlobalChatType.js'; +async function gchat(message: Message) { + const user = message.author; + if (user.bot || user.system || user.discriminator === '0000') return; + if (message.channel.type !== ChannelType.GuildText) return; + if (!(await message.client.botData.globalChat.register.get(message.channelId))) return; + + const messages: undefined | { channelId: string; messageId: string }[] = + await message.client.botData.globalChat.messages.get(message.id); + for (const value of messages) { + const channel = message.client.channels.cache.get(value.channelId); + if (!channel) continue; + if (channel.type !== ChannelType.GuildText) continue; + const webhooks = await channel.fetchWebhooks(); + const webhook: Webhook = + !webhooks.some((value) => value.name === 'Aqued') || + webhooks.find((value) => value.name === 'Aqued').owner.id !== message.client.user.id + ? await channel.createWebhook({ name: 'Aqued' }) + : webhooks.find((value) => value.name === 'Aqued'); + + webhook.deleteMessage(value.messageId); + } +} +async function sgc(message: Message) { + const user = message.author; + + if (user.bot || user.system || user.discriminator === '0000') return; + if (message.channel.type !== ChannelType.GuildText) return; + if (!(await message.client.botData.superGlobalChat.register.get(message.channelId))) return; + + const messages: undefined | { channelId: string; messageId: string }[] = + await message.client.botData.superGlobalChat.messages.get(message.id); + for (const value of messages) { + const channel = message.client.channels.cache.get(value.channelId); + if (!channel) continue; + if (channel.type !== ChannelType.GuildText) continue; + const webhooks = await channel.fetchWebhooks(); + const webhook: Webhook = + !webhooks.some((value) => value.name === 'Aqued') || + webhooks.find((value) => value.name === 'Aqued').owner.id !== message.client.user.id + ? await channel.createWebhook({ name: 'Aqued' }) + : webhooks.find((value) => value.name === 'Aqued'); + + webhook.deleteMessage(value.messageId); + } + const channel = message.client.channels.cache.get(message.client.botData.sgcJsonChannelIdv2); + if (channel && channel.isTextBased()) { + if (message.channel.type !== ChannelType.GuildText) return; + const data: MessageDeleteData = { type: 'delete', messageId: message.id }; + channel.send(JSON.stringify(data)); + } +} export default { name: Events.MessageDelete, once: false, async execute(message: Message) { - const user = message.author; - - if (user.bot || user.system || user.discriminator === '0000') return; - if (message.channel.type !== ChannelType.GuildText) return; - if (!(await message.client.botData.globalChat.register.get(message.channelId))) return; - - const messages: undefined | { channelId: string; messageId: string }[] = - await message.client.botData.globalChat.messages.get(message.id); - for (const value of messages) { - const channel = message.client.channels.cache.get(value.channelId); - if (!channel) continue; - if (channel.type !== ChannelType.GuildText) continue; - const webhooks = await channel.fetchWebhooks(); - const webhook: Webhook = - !webhooks.some((value) => value.name === 'Aqued') || - webhooks.find((value) => value.name === 'Aqued').owner.id !== message.client.user.id - ? await channel.createWebhook({ name: 'Aqued' }) - : webhooks.find((value) => value.name === 'Aqued'); - - webhook.deleteMessage(value.messageId); - } + await gchat(message); + await sgc(message); }, }; diff --git a/src/events/messageUpdate.ts b/src/events/messageUpdate.ts index 1ad44ff..6ccea00 100644 --- a/src/events/messageUpdate.ts +++ b/src/events/messageUpdate.ts @@ -10,6 +10,7 @@ import { MessageType, StickerFormatType, } from 'discord.js'; +import { MessageEditData } from '../utils/SuperGlobalChatType.js'; async function dissoku(newMessage: Message) { if (!(await newMessage.client.botData.guildUpNotice.dissoku.get(newMessage.guildId))) return; if (newMessage.author.id !== '761562078095867916') return; @@ -114,11 +115,46 @@ async function globalChat(newMessage: Message) { }); } } +async function superGlobalChat(newMessage: Message) { + const user = newMessage.author; + + if (user.bot || user.system || user.discriminator === '0000') return; + if (newMessage.channel.type !== ChannelType.GuildText) return; + if (!(await newMessage.client.botData.superGlobalChat.register.get(newMessage.channelId))) return; + const msgs: undefined | { channelId: string; messageId: string }[] = + await newMessage.client.botData.superGlobalChat.messages.get(newMessage.id); + for (const value of msgs) { + const channel = newMessage.client.channels.cache.get(value.channelId); + if (!channel) continue; + if (channel.type !== ChannelType.GuildText) continue; + const webhooks = await channel.fetchWebhooks(); + const webhook: Webhook = + !webhooks.some((value) => value.name === 'Aqued') || + webhooks.find((value) => value.name === 'Aqued').owner.id !== newMessage.client.user.id + ? await channel.createWebhook({ name: 'Aqued' }) + : webhooks.find((value) => value.name === 'Aqued'); + + const content = + newMessage.content.slice(0, 1500) === newMessage.content + ? newMessage.content + : `${newMessage.content.slice(0, 1500)}...`; + webhook.editMessage(value.messageId, { + content: content, + }); + } + const channel = newMessage.client.channels.cache.get(newMessage.client.botData.sgcJsonChannelIdv2); + if (channel && channel.isTextBased()) { + if (newMessage.channel.type !== ChannelType.GuildText) return; + const data: MessageEditData = { type: 'edit', messageId: newMessage.id, content: newMessage.content }; + channel.send(JSON.stringify(data)); + } +} export default { name: Events.MessageUpdate, once: false, async execute(oldMessage: Message, newMessage: Message) { await dissoku(newMessage); await globalChat(newMessage); + await superGlobalChat(newMessage); }, }; diff --git a/src/index.ts b/src/index.ts index eaadc89..37b650f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -60,8 +60,17 @@ client.botData = { messages: newMongoDB('globalChatMessages'), blocks: newMongoDB('globalChatblocks'), }, + superGlobalChat: { + register: newMongoDB('superGlobalChatRegister'), + messages: newMongoDB('superGlobalChatMessages'), + replyMessages: newMongoDB('superGlobalReplyMessages'), + }, + sgcJsonChannelId: config.sgcJsonChannelId, + sgcJsonChannelIdv2: config.sgcJsonChannelIdv2, + afk: { afk: newMongoDB('afk'), mention: newMongoDB('afkMention') }, messageExpansion: newMongoDB('messageExpansion'), aquedAutoNews: newMongoDB('aquedAutoNews'), + verifyPanel: newMongoDB('verifyPanel'), artifacter: newMongoDB('artifacter'), errorChannelId: config.channelIds.error, botLogChannelId: config.channelIds.botLog, diff --git a/src/interactions/serverUpNoticeSetting.ts b/src/interactions/serverUpNoticeSetting.ts index 1b2cfc2..d95ff57 100644 --- a/src/interactions/serverUpNoticeSetting.ts +++ b/src/interactions/serverUpNoticeSetting.ts @@ -98,7 +98,7 @@ export default async function (interaction: BaseInteraction) { .addFields({ name: 'DISBOARD', value: `${ - (await interaction.client.botData.guildUpNotice.dissoku.get(interaction.guildId)) + (await interaction.client.botData.guildUpNotice.disboard.get(interaction.guildId)) ? '有効' : '無効' }`, diff --git a/src/interactions/verifyButton.ts b/src/interactions/verifyButton.ts new file mode 100644 index 0000000..e71257d --- /dev/null +++ b/src/interactions/verifyButton.ts @@ -0,0 +1,112 @@ +import { ActionRowBuilder, BaseInteraction, ModalBuilder, TextInputBuilder, TextInputStyle } from 'discord.js'; + +export default async function (interaction: BaseInteraction) { + if (!interaction.isButton()) return; + switch (interaction.customId) { + case 'verify_button_1': { + const number0 = Math.floor(Math.random() * 901), + number1 = Math.floor(Math.random() * 10); + await interaction.showModal( + new ModalBuilder() + .setCustomId(`verifyModal_${number0 + number1}`) + .setTitle('足し算認証') + .addComponents( + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setLabel(`${number0} + ${number1}の答え`) + .setStyle(TextInputStyle.Short) + .setPlaceholder('ここに入力して下さい。') + .setRequired(true) + .setCustomId('answer'), + ), + ), + ); + break; + } + case 'verify_button_2': { + const number0 = Math.floor(Math.random() * 901), + number1 = Math.floor(Math.random() * 10); + await interaction.showModal( + new ModalBuilder() + .setCustomId(`verifyModal_${number0 - number1}`) + .setTitle('引き算認証') + .addComponents( + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setLabel(`${number0} - ${number1}の答え`) + .setStyle(TextInputStyle.Short) + .setPlaceholder('ここに入力して下さい。') + .setRequired(true) + .setCustomId('answer'), + ), + ), + ); + break; + } + case 'verify_button_3': { + const number0 = Math.floor(Math.random() * 901), + number1 = Math.floor(Math.random() * 10); + await interaction.showModal( + new ModalBuilder() + .setCustomId(`verifyModal_${number0 * number1}`) + .setTitle('掛け算認証') + .addComponents( + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setLabel(`${number0} × ${number1}の答え(小数点以下削除)`) + .setStyle(TextInputStyle.Short) + .setPlaceholder('ここに入力して下さい。') + .setRequired(true) + .setCustomId('answer'), + ), + ), + ); + break; + } + case 'verify_button_4': { + const number0 = Math.floor(Math.random() * 901), + number1 = Math.floor(Math.random() * 10); + await interaction.showModal( + new ModalBuilder() + .setCustomId(`verifyModal_${Math.trunc(number0 / number1)}`) + .setTitle('割り算認証') + .addComponents( + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setLabel(`${number0} ÷ ${number1}の答え(小数点以下削除)`) + .setStyle(TextInputStyle.Short) + .setPlaceholder('ここに入力して下さい。') + .setRequired(true) + .setCustomId('answer'), + ), + ), + ); + break; + } + case 'verify_button_5': { + const role = await interaction.client.botData.verifyPanel.get(interaction.message.id); + await interaction.guild.members.resolve(interaction.user).roles.add(role); + await interaction.ok('認証に成功', '認証に成功しました!', true); + break; + } + case 'verify_button_6': { + const number0 = Math.floor(Math.random() * 901); + await interaction.showModal( + new ModalBuilder() + .setCustomId(`verifyModal_${number0}`) + .setTitle('割り算認証') + .addComponents( + new ActionRowBuilder().addComponents( + new TextInputBuilder() + .setLabel(`${number0}を入力してください。`) + .setStyle(TextInputStyle.Short) + .setPlaceholder('ここに入力して下さい。') + .setRequired(true) + .setCustomId('answer'), + ), + ), + ); + break; + } + } +} diff --git a/src/interactions/verifyModal.ts b/src/interactions/verifyModal.ts new file mode 100644 index 0000000..da4dfc1 --- /dev/null +++ b/src/interactions/verifyModal.ts @@ -0,0 +1,15 @@ +import { BaseInteraction } from 'discord.js'; + +export default async function (interaction: BaseInteraction) { + if (!interaction.isModalSubmit()) return; + if (!interaction.customId.startsWith('verifyModal_')) return; + const userAnswer = Number(interaction.fields.getTextInputValue('answer')); + const answer = Number(interaction.customId.replace('verifyModal_', '')); + const role = await interaction.client.botData.verifyPanel.get(interaction.message.id); + if (answer === userAnswer) { + await interaction.guild.members.resolve(interaction.user).roles.add(role); + await interaction.ok('認証に成功', '認証に成功しました!', true); + } else { + await interaction.error('認証に失敗', '答えが違います。', true); + } +} diff --git a/src/messages/afk.ts b/src/messages/afk.ts new file mode 100644 index 0000000..af57298 --- /dev/null +++ b/src/messages/afk.ts @@ -0,0 +1,28 @@ +import { Colors, EmbedBuilder, Message } from 'discord.js'; +export default async function (message: Message) { + const { afk, mention } = message.client.botData.afk; + if ((await afk.get(message.author.id)) && message.inGuild()) { + const mentions: string[] | undefined = await mention.get(message.author.id); + const embed = new EmbedBuilder().setTitle('afkを解除しました。').setColor(Colors.Blue); + if (mentions) embed.addFields({ name: 'メンション', value: mentions.join('\n') }); + await message.channel.send({ embeds: [embed] }); + await mention.delete(message.author.id); + await afk.delete(message.author.id); + } + if (message.mentions.users.size > 0 && message.inGuild()) { + for (const value of message.mentions.users.values()) { + const mentions: string[] | undefined = await mention.get(value.id); + const array = mentions ?? []; + if (!(await afk.get(value.id))) continue; + array.push( + `[${message.guild.name} > #${message.channel.name}](https://discord.com/channels/${message.guildId}/${message.channelId}/${message.id})`, + ); + const embed = new EmbedBuilder().setDescription(`<@!${value.id}>はafkです。`).setColor(Colors.Blue); + if ((await afk.get(message.author.id)) && (await afk.get(message.author.id)) !== true) { + embed.addFields({ name: '理由', value: await afk.get(message.author.id) }); + } + await message.channel.send({ embeds: [embed] }); + if (array.length > 0) await mention.set(value.id, array); + } + } +} diff --git a/src/messages/superGlobalChat.ts b/src/messages/superGlobalChat.ts new file mode 100644 index 0000000..7b024ff --- /dev/null +++ b/src/messages/superGlobalChat.ts @@ -0,0 +1,125 @@ +/* eslint-disable unicorn/no-nested-ternary */ +import { ChannelType, Colors, EmbedBuilder, Message, SnowflakeUtil, Webhook } from 'discord.js'; +import { MessageData } from '../utils/SuperGlobalChatType.js'; +import { calculateUserDefaultAvatarIndex } from '@discordjs/rest'; +import { inspect } from 'node:util'; + +export default async function (message: Message) { + try { + const channelDB = message.client.botData.superGlobalChat.register; + if (!(await channelDB.get(message.channelId))) return; + if (message.author.bot || message.author.system || message.author.discriminator === '0000') return; + if (message.channel.type !== ChannelType.GuildText) return; + const channels = await channelDB.keys(); + if (!channels) return; + const data: MessageData = { + type: 'message', + version: "2.1.7", + userId: message.author.id, + userName: message.author.username, + userDiscriminator: message.author.discriminator, + userAvatar: message.author.avatar, + isBot: message.author.bot, + guildId: message.guild.id, + guildName: message.guild.name, + guildIcon: message.guild.icon, + channelId: message.channel.id, + channelName: message.channel.name, + messageId: message.id, + content: message.content, + }; + if (message.attachments.size > 0) data['attachmentsUrl'] = message.attachments.map((value) => value.proxyURL); + let replymsg: string; + const content = + message.content.slice(0, 1500) === message.content ? message.content : `${message.content.slice(0, 1500)}...`; + + if (message.reference) { + const repliedMessage: { content: string; id: string } | undefined = + await message.client.botData.superGlobalChat.replyMessages.get(message.reference.messageId); + if (!repliedMessage) return; + data['reference'] = repliedMessage.id; + replymsg = repliedMessage.content; + if (repliedMessage.content.includes('\n')) { + replymsg = repliedMessage.content.slice(repliedMessage.content.indexOf('\n')); + } + } + + for (const channel of channels) { + const Sendchannel = message.client.channels.cache.get(channel); + if (!Sendchannel) continue; + if (Sendchannel.type !== ChannelType.GuildText) continue; + if (message.channelId === Sendchannel.id) continue; + const webhooks = await Sendchannel.fetchWebhooks(); + const webhook: Webhook = + !webhooks.some((value) => value.name === 'Aqued') || + webhooks.find((value) => value.name === 'Aqued').owner.id !== message.client.user.id + ? await Sendchannel.createWebhook({ name: 'Aqued' }) + : webhooks.find((value) => value.name === 'Aqued'); + await webhook + .send({ + content: data.reference + ? replymsg.replaceAll('\n', ' ').replaceAll('> ', '').slice(0, 15) === + replymsg.replaceAll('\n', ' ').replaceAll('> ', '') + ? `> ${replymsg.replaceAll('\n', ' ').replaceAll('> ', '')}\n${content}` + : `> ${replymsg.replaceAll('\n', ' ').replaceAll('> ', '').slice(0, 15)}...\n${content}` + : content, + files: data.attachmentsUrl || [], + avatarURL: message.author.avatar + ? message.client.rest.cdn.avatar(message.author.id, message.author.avatar, { extension: 'webp' }) + : message.client.rest.cdn.defaultAvatar( + message.author.discriminator === '0' + ? calculateUserDefaultAvatarIndex(message.author.id) + : Number(message.author.discriminator) % 5, + ), + username: `${message.author.username}${ + message.author.discriminator === '0' ? '' : `#${message.author.discriminator}` + }(id: ${message.author.id})`, + }) + .then(async (value) => { + const array: { channelId: string; messageId: string }[] = + (await message.client.botData.superGlobalChat.messages.get(message.id)) || []; + array.push({ + channelId: value.channelId, + messageId: value.id, + }); + await message.client.botData.superGlobalChat.messages.set(message.id, array); + if (message.reference) { + const repliedMessage: { content: string; id: string } | undefined = + await message.client.botData.superGlobalChat.replyMessages.get(message.reference.messageId); + if (!repliedMessage) return; + await message.client.botData.superGlobalChat.replyMessages.set(value.id, { + content: message.content, + id: repliedMessage.id, + }); + } + }); + } + await message.client.botData.superGlobalChat.replyMessages.set(message.id, { + content: message.content, + id: message.id, + }); + message.react('✅'); + const channel = message.client.channels.cache.get(message.client.botData.sgcJsonChannelId); + if (channel && channel.isTextBased()) { + if (message.channel.type !== ChannelType.GuildText) return; + channel.send(JSON.stringify(data)); + } + } catch (error) { + console.error(error); + const errorId = SnowflakeUtil.generate(); + + message.client.botData.errors.set(errorId.toString(), inspect(error).slice(0, 1800)); + + const Errorchannel = message.client.channels.cache.get(message.client.botData.errorChannelId); + if (Errorchannel.isTextBased()) + Errorchannel.send({ + embeds: [ + new EmbedBuilder() + .setTitle(':x: エラーが発生しました。') + .setDescription(`Id: ${errorId.toString()}`) + .setColor(Colors.Red), + ], + }); + message.react('❌'); + } +} diff --git a/src/messages/superGlobalChatDataGet.ts b/src/messages/superGlobalChatDataGet.ts new file mode 100644 index 0000000..6d4a308 --- /dev/null +++ b/src/messages/superGlobalChatDataGet.ts @@ -0,0 +1,145 @@ +/* eslint-disable unicorn/no-nested-ternary */ +import { Message, ChannelType, Webhook, Colors, EmbedBuilder, SnowflakeUtil } from 'discord.js'; +import { EmptyData, MessageData, MessageDeleteData, MessageEditData } from '../utils/SuperGlobalChatType.js'; +import { calculateUserDefaultAvatarIndex } from '@discordjs/rest'; +import { inspect } from 'node:util'; + +export default async function (message: Message) { + try { + const jsonChannelId = message.client.botData.sgcJsonChannelId; + const jsonChannelIdv2 = message.client.botData.sgcJsonChannelIdv2; + if (message.channelId !== jsonChannelId && message.channelId !== jsonChannelIdv2) return; + if (message.author.id === message.client.user.id) return; + const replyMessages = message.client.botData.superGlobalChat.replyMessages; + const registers = await message.client.botData.superGlobalChat.register.keys(); + const data: MessageData | MessageDeleteData | MessageEditData | EmptyData = JSON.parse(message.content); + switch (data.type) { + case 'message': { + await replyMessages.set(data.messageId, { content: data.content, id: message.id }); + + for (const value of registers) { + const channel = message.client.channels.cache.get(value); + if (!channel) return; + if (channel.id === message.channelId) return; + if (channel.type !== ChannelType.GuildText) return; + const webhooks = await channel.fetchWebhooks(); + const webhook: Webhook = + !webhooks.some((value) => value.name === 'Aqued') || + webhooks.find((value) => value.name === 'Aqued').owner.id !== message.client.user.id + ? await channel.createWebhook({ name: 'Aqued' }) + : webhooks.find((value) => value.name === 'Aqued'); + const files = data.attachmentsUrl ?? []; + let replymsg: string; + if (data.reference) { + const repliedMessage: { content: string; id: string } | undefined = + await message.client.botData.superGlobalChat.replyMessages.get(data.reference); + if (!repliedMessage) return; + replymsg = repliedMessage.content; + if (replymsg.includes('\n')) { + replymsg = replymsg.slice(replymsg.indexOf('\n')); + } + } + const content = + data.content.slice(0, 1500) === data.content ? data.content : `${data.content.slice(0, 1500)}...`; + webhook + .send({ + files, + username: `${data.userName}${data.userDiscriminator === '0' ? '' : `#${data.userDiscriminator}`}(id: ${ + data.userId + }) | ${message.author.username} 経由`, + content: data.reference + ? replymsg.replaceAll('\n', ' ').replaceAll('> ', '').slice(0, 15) === + replymsg.replaceAll('\n', ' ').replaceAll('> ', '') + ? `> ${replymsg.replaceAll('\n', ' ').replaceAll('> ', '')}\n${content}` + : `> ${replymsg.replaceAll('\n', ' ').replaceAll('> ', '').slice(0, 15)}...\n${content}` + : content, + avatarURL: data.userAvatar + ? `${message.client.rest.cdn.avatar(data.userId, data.userAvatar, { extension: 'webp' })}` + : `${this.client.rest.cdn.defaultAvatar( + this.discriminator === '0' + ? calculateUserDefaultAvatarIndex(message.author.id) + : Number(message.author.discriminator) % 5, + )}`, + }) + .then(async (value) => { + const array: { channelId: string; messageId: string }[] = + (await message.client.botData.superGlobalChat.messages.get(data.messageId)) || []; + array.push({ + channelId: value.channelId, + messageId: value.id, + }); + await message.client.botData.superGlobalChat.messages.set(data.messageId, array); + await message.client.botData.superGlobalChat.replyMessages.set(value.id, { + content: message.content, + id: data.messageId, + }); + }); + } + message.react('✅'); + + break; + } + case 'edit': { + const msgs: undefined | { channelId: string; messageId: string }[] = + await message.client.botData.superGlobalChat.messages.get(data.messageId); + for (const value of msgs) { + const channel = message.client.channels.cache.get(value.channelId); + if (!channel) continue; + if (channel.type !== ChannelType.GuildText) continue; + const webhooks = await channel.fetchWebhooks(); + const webhook: Webhook = + !webhooks.some((value) => value.name === 'Aqued') || + webhooks.find((value) => value.name === 'Aqued').owner.id !== message.client.user.id + ? await channel.createWebhook({ name: 'Aqued' }) + : webhooks.find((value) => value.name === 'Aqued'); + + const content = + data.content.slice(0, 1500) === data.content ? data.content : `${data.content.slice(0, 1500)}...`; + webhook.editMessage(value.messageId, { + content: content, + }); + } + message.react('✅'); + + break; + } + case 'delete': { + const msgs: undefined | { channelId: string; messageId: string }[] = + await message.client.botData.superGlobalChat.messages.get(data.messageId); + for (const value of msgs) { + const channel = message.client.channels.cache.get(value.channelId); + if (!channel) continue; + if (channel.type !== ChannelType.GuildText) continue; + const webhooks = await channel.fetchWebhooks(); + const webhook: Webhook = + !webhooks.some((value) => value.name === 'Aqued') || + webhooks.find((value) => value.name === 'Aqued').owner.id !== message.client.user.id + ? await channel.createWebhook({ name: 'Aqued' }) + : webhooks.find((value) => value.name === 'Aqued'); + + webhook.deleteMessage(value.messageId); + } + message.react('✅'); + break; + } + } + } catch (error) { + console.error(error); + const errorId = SnowflakeUtil.generate(); + + message.client.botData.errors.set(errorId.toString(), inspect(error).slice(0, 1800)); + + const Errorchannel = message.client.channels.cache.get(message.client.botData.errorChannelId); + if (Errorchannel.isTextBased()) + Errorchannel.send({ + embeds: [ + new EmbedBuilder() + .setTitle(':x: エラーが発生しました。') + .setDescription(`Id: ${errorId.toString()}`) + .setColor(Colors.Red), + ], + }); + message.react('❌'); + return; + } +} diff --git a/src/utils/SuperGlobalChatType.ts b/src/utils/SuperGlobalChatType.ts new file mode 100644 index 0000000..c367822 --- /dev/null +++ b/src/utils/SuperGlobalChatType.ts @@ -0,0 +1,30 @@ +export interface MessageData { + type: 'message'; + version: string; + userId: string; + userName: string; + userDiscriminator: string; + userAvatar: string; + isBot: boolean; + guildId: string; + guildName: string; + guildIcon: string; + channelId: string; + channelName: string; + messageId: string; + content: string; + reference?: string; + attachmentsUrl?: string[]; +} +export interface MessageDeleteData { + type: 'delete'; + messageId: string; +} +export interface MessageEditData { + type: 'edit'; + messageId: string; + content: string; +} +export interface EmptyData { + type: 'empty'; +} diff --git a/src/utils/extrans.ts b/src/utils/extrans.ts index 2c35f35..15eb36a 100644 --- a/src/utils/extrans.ts +++ b/src/utils/extrans.ts @@ -80,6 +80,12 @@ declare module 'discord.js' { owners: string[]; gbans: MongoDB; messageExpansion: MongoDB; + sgcJsonChannelId: string; + sgcJsonChannelIdv2: string; + afk: { + afk: MongoDB; + mention: MongoDB; + }; guildUpNotice: { dissoku: MongoDB; disboard: MongoDB }; mods: string[]; cooldowns?: Collection; @@ -90,7 +96,9 @@ declare module 'discord.js' { infos: MongoDB; errorChannelId: string; botLogChannelId: string; + verifyPanel: MongoDB; globalChat: { register: MongoDB; messages: MongoDB; blocks: MongoDB }; + superGlobalChat: { register: MongoDB; messages: MongoDB; replyMessages: MongoDB }; aquedAutoNews: MongoDB; commandLogChannelId: string; commandDatas: Array< diff --git a/yarn.lock b/yarn.lock index e9a4f19..d4bb68f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -315,9 +315,9 @@ __metadata: languageName: node linkType: hard -"@discordjs/rest@npm:^1.7.2-dev.1689034321-09b0382.0": - version: 1.7.2-dev.1689034321-09b0382.0 - resolution: "@discordjs/rest@npm:1.7.2-dev.1689034321-09b0382.0" +"@discordjs/rest@npm:^1.7.2-dev.1689249890-ceab07b.0": + version: 1.7.2-dev.1689249890-ceab07b.0 + resolution: "@discordjs/rest@npm:1.7.2-dev.1689249890-ceab07b.0" dependencies: "@discordjs/collection": ^1.5.1 "@discordjs/util": ^0.3.1 @@ -327,7 +327,7 @@ __metadata: file-type: ^18.4.0 tslib: ^2.5.2 undici: ^5.22.1 - checksum: 490d518139350cc3fd50b695942aa53b5a6909216b437f85f2fb48289c6357d3a79bbf73734b85ff1272ebd7b02728777439a29ead0968be5b0f4f2d975af8bd + checksum: 47914bf2294b415bbf951e3daea97f2fe6c3600815e455e2220818d0531ef38dd5fa25dd79cc861fd24c24022fd7eb8dd16a31f7cc937210a2f6e0f5a01a92ab languageName: node linkType: hard @@ -649,10 +649,10 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:20.4.1": - version: 20.4.1 - resolution: "@types/node@npm:20.4.1" - checksum: 22cbcc792f2eb636fe4188778ed0f32658ab872aa7fcb9847b3fa289a42b14b9f5e30c6faec50ef3c7adbc6c2a246926e5858136bb8b10c035a3fcaa6afbeed2 +"@types/node@npm:20.4.2": + version: 20.4.2 + resolution: "@types/node@npm:20.4.2" + checksum: 99e544ea7560d51f01f95627fc40394c24a13da8f041121a0da13e4ef0a2aa332932eaf9a5e8d0e30d1c07106e96a183be392cbba62e8cf0bf6a085d5c0f4149 languageName: node linkType: hard @@ -710,7 +710,7 @@ __metadata: languageName: node linkType: hard -"@types/ws@npm:^8.5.4": +"@types/ws@npm:^8.5.4, @types/ws@npm:^8.5.5": version: 8.5.5 resolution: "@types/ws@npm:8.5.5" dependencies: @@ -719,6 +719,15 @@ __metadata: languageName: node linkType: hard +"@types/xml2js@npm:^0.4.11": + version: 0.4.11 + resolution: "@types/xml2js@npm:0.4.11" + dependencies: + "@types/node": "*" + checksum: d0e7d2a8c7e0a53147c777a6756bdea0eb26a3de0d3c1f42c17e63332e4e2dc532f687c19ca26a0518336f5de60e1ec4345d7ef71e7ba0656fcf3390c9388eb5 + languageName: node + linkType: hard + "@typescript-eslint/eslint-plugin@npm:^6.0.0": version: 6.0.0 resolution: "@typescript-eslint/eslint-plugin@npm:6.0.0" @@ -1211,25 +1220,29 @@ __metadata: dependencies: "@commitlint/cli": ^17.6.6 "@commitlint/config-conventional": ^17.6.6 - "@discordjs/rest": ^1.7.2-dev.1689034321-09b0382.0 + "@discordjs/rest": ^1.7.2-dev.1689249890-ceab07b.0 "@types/json-bigint": ^1.0.1 - "@types/node": 20.4.1 + "@types/node": 20.4.2 + "@types/ws": ^8.5.5 + "@types/xml2js": ^0.4.11 "@typescript-eslint/eslint-plugin": ^6.0.0 "@typescript-eslint/parser": ^6.0.0 "@yarnpkg/pnpify": 3.1.6 "@yarnpkg/sdks": ^3.0.0-rc.48 - discord.js: ^14.11.1-dev.1689034320-09b0382.0 - enka-network-api: ^3.7.0 + discord.js: ^14.11.1-dev.1689249910-ceab07b.0 + enka-network-api: ^3.7.1 eslint: ^8.44.0 eslint-config-prettier: ^8.8.0 eslint-formatter-pretty: ^5.0.0 eslint-plugin-unicorn: ^47.0.0 husky: ^8.0.3 json-bigint: ^1.0.0 - mongoose: ^7.3.2 - prettier: ^3.0.0 + mongoose: ^7.3.4 + prettier: 2.8.8 rimraf: ^5.0.1 typescript: ^5.1.6 + ws: ^8.13.0 + xml2js: ^0.6.0 languageName: unknown linkType: soft @@ -1826,9 +1839,9 @@ __metadata: languageName: node linkType: hard -"discord.js@npm:^14.11.1-dev.1689034320-09b0382.0": - version: 14.11.1-dev.1689034320-09b0382.0 - resolution: "discord.js@npm:14.11.1-dev.1689034320-09b0382.0" +"discord.js@npm:^14.11.1-dev.1689249910-ceab07b.0": + version: 14.11.1-dev.1689249910-ceab07b.0 + resolution: "discord.js@npm:14.11.1-dev.1689249910-ceab07b.0" dependencies: "@discordjs/builders": ^1.6.3 "@discordjs/collection": ^1.5.1 @@ -1844,7 +1857,7 @@ __metadata: tslib: ^2.5.2 undici: ^5.22.1 ws: ^8.13.0 - checksum: 5f27bc981c9633dc0ec8ef670180e86a21952e3acf70fd8ed5b4bae96f2c8a9819a05e657259ba73e39f35551fd811ea9d7049930a9c63503baa76fa05312b19 + checksum: 638b864187213a3b8b68b3d09c60d6c372bfee3557de23f3358e543146b7cfc85d6e9c6b3368600d8e115c3be9d6d22c49a23b69df6e293574ba6f71590b078d languageName: node linkType: hard @@ -1912,14 +1925,14 @@ __metadata: languageName: node linkType: hard -"enka-network-api@npm:^3.7.0": - version: 3.7.0 - resolution: "enka-network-api@npm:3.7.0" +"enka-network-api@npm:^3.7.1": + version: 3.7.1 + resolution: "enka-network-api@npm:3.7.1" dependencies: axios: ^1.4.0 config_file.js: ^1.2.2 unzip-stream: ^0.3.1 - checksum: 34c154ab476c5c794052c030f4bba0043ceef20369039263292fa0409ae7a44e09b3026c2e130582ce39488b8043cc4272856f60b555a2c325517e39157f5e79 + checksum: fed8e9b52897f6738b7b3350476656e0a4c497ea7afe00068a2681a420cf4314d26dd74fff3d0795e394eef0ed8d9d336feee5b84bee68f8531abced20731637 languageName: node linkType: hard @@ -3360,9 +3373,9 @@ __metadata: languageName: node linkType: hard -"mongoose@npm:^7.3.2": - version: 7.3.2 - resolution: "mongoose@npm:7.3.2" +"mongoose@npm:^7.3.4": + version: 7.3.4 + resolution: "mongoose@npm:7.3.4" dependencies: bson: ^5.3.0 kareem: 2.5.1 @@ -3371,7 +3384,7 @@ __metadata: mquery: 5.0.0 ms: 2.1.3 sift: 16.0.1 - checksum: a8f4e35c50071c9d116c66293e1f9a0f558c7d1ce9773ce94adc8a2b5238c34d5351df58f4edf0aafc60429d4e34d3ee3a6c405ad931458f8224f2974895f683 + checksum: 1ffdb8449c7e151c1057679070b00072fb6f676ffcde5e33ff4e180c672a1ba4e7447c02bc0985e32ae25f795744a67974ded06df5a6124bd2dd0c2785974f5c languageName: node linkType: hard @@ -3689,12 +3702,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.0.0": - version: 3.0.0 - resolution: "prettier@npm:3.0.0" +"prettier@npm:2.8.8": + version: 2.8.8 + resolution: "prettier@npm:2.8.8" bin: - prettier: bin/prettier.cjs - checksum: 6a832876a1552dc58330d2467874e5a0b46b9ccbfc5d3531eb69d15684743e7f83dc9fbd202db6270446deba9c82b79d24383d09924c462b457136a759425e33 + prettier: bin-prettier.js + checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 languageName: node linkType: hard @@ -4021,6 +4034,13 @@ __metadata: languageName: node linkType: hard +"sax@npm:>=0.6.0": + version: 1.2.4 + resolution: "sax@npm:1.2.4" + checksum: d3df7d32b897a2c2f28e941f732c71ba90e27c24f62ee918bd4d9a8cfb3553f2f81e5493c7f0be94a11c1911b643a9108f231dd6f60df3fa9586b5d2e3e9e1fe + languageName: node + linkType: hard + "semver@npm:2 || 3 || 4 || 5": version: 5.7.2 resolution: "semver@npm:5.7.2" @@ -4709,6 +4729,23 @@ __metadata: languageName: node linkType: hard +"xml2js@npm:^0.6.0": + version: 0.6.0 + resolution: "xml2js@npm:0.6.0" + dependencies: + sax: ">=0.6.0" + xmlbuilder: ~11.0.0 + checksum: 437f353fd66d367bf158e9555a0625df9965d944e499728a5c6bc92a54a2763179b144f14b7e1c725040f56bbd22b0fa6cfcb09ec4faf39c45ce01efe631f40b + languageName: node + linkType: hard + +"xmlbuilder@npm:~11.0.0": + version: 11.0.1 + resolution: "xmlbuilder@npm:11.0.1" + checksum: 7152695e16f1a9976658215abab27e55d08b1b97bca901d58b048d2b6e106b5af31efccbdecf9b07af37c8377d8e7e821b494af10b3a68b0ff4ae60331b415b0 + languageName: node + linkType: hard + "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8"