質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

108閲覧

node.jsを使ってDiscord botを開発していますが、エラーによりチャンネルが作成できません。

saica94

総合スコア1

Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2024/05/05 02:08

実現したいこと

Discord botが表示しているボタンを押下した際にボタンを押下したユーザーと管理者のみが見れるプライベートチャンネルを作りたい

前提

node.jsでDiscord botを作成
チャンネル作成機能を実装中に以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

node:events:496 throw er; // Unhandled 'error' event ^ DiscordAPIError[50035]: Invalid Form Body name[BASE_TYPE_REQUIRED]: This field is required at handleErrors (D:\Programming\javascript\discord_bot\node_modules\@discordjs\rest\dist\index.js:730:13) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async SequentialHandler.runRequest (D:\Programming\javascript\discord_bot\node_modules\@discordjs\rest\dist\index.js:1133:23) at async SequentialHandler.queueRequest (D:\Programming\javascript\discord_bot\node_modules\@discordjs\rest\dist\index.js:963:14) at async _REST.request (D:\Programming\javascript\discord_bot\node_modules\@discordjs\rest\dist\index.js:1278:22) at async GuildChannelManager.create (D:\Programming\javascript\discord_bot\node_modules\discord.js\src\managers\GuildChannelManager.js:171:18) at async Client.<anonymous> (D:\Programming\javascript\discord_bot\server.js:87:9) Emitted 'error' event on Client instance at: at emitUnhandledRejectionOrErr (node:events:401:10) at process.processTicksAndRejections (node:internal/process/task_queues:84:21) { requestBody: { files: undefined, json: { name: undefined, topic: undefined, type: undefined, nsfw: undefined, bitrate: undefined, user_limit: undefined, parent_id: undefined, position: undefined, permission_overwrites: undefined, rate_limit_per_user: undefined, rtc_region: undefined, video_quality_mode: undefined, default_thread_rate_limit_per_user: undefined, available_tags: undefined, default_reaction_emoji: undefined, default_auto_archive_duration: undefined, default_sort_order: undefined, default_forum_layout: undefined } }, rawError: { message: 'Invalid Form Body', code: 50035, errors: { name: { _errors: [ { code: 'BASE_TYPE_REQUIRED', message: 'This field is required' } ] } } }, code: 50035, status: 400, method: 'POST', url: 'https://discord.com/api/v10/guilds/<hidden>/channels' }

該当のソースコード

javascript

1// server.js 2const fs = require('node:fs'); 3const path = require('node:path'); 4const { 5 Client, 6 Intents, 7 Collection, 8 Events, 9 GatewayIntentBits, 10 PermissionOverwrites, 11 MessageActionRow, 12 MessageButton 13} = require('discord.js'); 14const { token } = require('./config.json'); 15const client = new Client({ 16 intents: [GatewayIntentBits.Guilds, 17 GatewayIntentBits.GuildMessages 18 ] 19}); 20let ticketOwners= {}; 21 22// 各コマンドの読み込み 23client.commands = new Collection(); 24const commandsPath = path.join(__dirname, "commands"); 25const commandFiles = fs 26 .readdirSync(commandsPath) 27 .filter((file) => file.endsWith(".js")); 28 29for(const file of commandFiles) { 30 const filePath = path.join(commandsPath, file); 31 const command = require(filePath); 32 client.commands.set(command.data.name, command); 33} 34 35// BOTが稼働しているかの確認 36client.once(Events.ClientReady, () => { 37 console.log("ready"); 38}); 39 40// discordからコマンドを受け取り、それに応じた処理を行う 41client.on(Events.InteractionCreate, async(interaction) => { 42 if(!interaction.isChatInputCommand()) return; 43 44 const command = client.commands.get(interaction.commandName); 45 46 if(!command) return; 47 48 try { 49 await command.execute(interaction); 50 } catch (error) { 51 console.error(error); 52 await interaction.reply({ 53 content: "このコマンドの実行中にエラーが発生しました", 54 ephemral: true, 55 }); 56 } 57}); 58 59 60client.on(Events.InteractionCreate, async(interaction) => { 61 const customId = interaction.customId; 62 if(customId === "addteaminfoButton"){ 63 const server = interaction.guild; 64 65 66 if(ticketOwners[interaction.user.id]){ 67 await interaction.reply({content: "既にチケットが存在します", ephemral: true}); 68 return; 69 } 70 71 const overwrites = [ 72 { 73 id: server.roles.everyone, 74 deny: ["VIEW_CHANNEL"], 75 }, 76 { 77 id: server.me, 78 allow: ["VIEW_CHANNEL"], 79 }, 80 { 81 id: interaction.user.id, 82 allow: ["VIEW_CHANNEL"], 83 }, 84 ]; 85 86 const channelName = `チケット-${interaction.user.username}`; 87 console.log(channelName) 88 await interaction.guild.channels.create(channelName, { 89 type: "GUILD_TEXT", 90 parent: "<hidden>" 91 }); 92 93 ticketOwners[channel.id] = interaction.user.id; 94 95 await channel.send(`${interaction.user.toString()} チケットが作成されました`); 96 97 const ticketMessage = `チケットが作成されました\n${channel.toString()}`; 98 99 await interaction.reply({ content: ticketMessage, ephemeral: true}); 100 101 const view = new MessageActionRow() 102 .addComponents( 103 new MessageButton() 104 .setCustomId("delete_ticket") 105 .setLabel("チケットを削除") 106 .setStyle("DENGER") 107 ); 108 109 await channel.send({ content: "チケットを削除するには以下のボタンを押してください"}); 110 } 111}); 112 113// モーダルで受け取った値をDiscordに送信する 114client.on(Events.InteractionCreate, async(interaction) => { 115 if(!interaction.isModalSubmit()) return; 116 117 const teamname = interaction.fields.getTextInputValue("teamnameInput"); 118 const reading = interaction.fields.getTextInputValue("readingInput"); 119 const ingameId = interaction.fields.getTextInputValue("ingameIdInput"); 120 const favoriteRole = interaction.fields.getTextInputValue("favoriteRoleInput"); 121 const favoriteChara = interaction.fields.getTextInputValue("favoriteCharaInput"); 122 console.log({ nickname, reading, ingameId, favoriteRole, favoriteChara }); 123 await interaction.reply({ 124 content:"チーム名:" + teamname + "\n読み方:" + reading + "\nゲーム内ID:" + ingameId + "\n好きなロール:" + favoriteRole + "\n好きなキャラ:" + favoriteChara + "\n", 125 }); 126}); 127 128client.login(token);

javascript

1// buttons.js 2const { 3 Events, 4 ActionRowBuilder, 5 ButtonBuilder, 6 ButtonStyle, 7 SlashCommandBuilder, 8} = require('discord.js'); 9 10module.exports = { 11 // スラッシュコマンドの登録 12 data: new SlashCommandBuilder() 13 .setName("buttons") 14 .setDescription("ボタンを表示"), 15 // スラッシュコマンドを受け取ると以下が実行される 16 async execute(interaction) { 17 if(!interaction.isChatInputCommand()) return; 18 if(interaction.commandName === "buttons") { 19 const addteaminfoButton = new ButtonBuilder() 20 .setCustomId("addteaminfoButton") 21 .setLabel("チーム情報登録") 22 .setStyle(ButtonStyle.Primary); 23 const row = new ActionRowBuilder() 24 .addComponents(addteaminfoButton); 25 26 await interaction.reply({ 27 content:"", 28 components: [row], 29 }) 30 } 31 }, 32};

試したこと

google 検索

javascript

1await interaction.guild.channels.create(channelName, { 2 type: "GUILD_TEXT", 3 parent: "1120423753348825232" 4 });

の "interaction"を"server"などに変更

補足

server変数やchannelName変数などの中身を出力して期待通りの結果になることは確認できています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

server.jsを以下のように修正することで正常動作しました。

javascript

1const fs = require('node:fs'); 2const path = require('node:path'); 3const { 4 ButtonBuilder, 5 ButtonStyle, 6 Client, 7 Intents, 8 Collection, 9 ChannelType, 10 Events, 11 GatewayIntentBits, 12 PermissionFlagsBits, 13 PermissionOverwrites, 14 ActionRowBuilder, 15 MessageActionRowBuilder, 16 MessageButton, 17} = require('discord.js'); 18const { token } = require('./config.json'); 19const client = new Client({ 20 intents: [GatewayIntentBits.Guilds, 21 GatewayIntentBits.GuildMessages 22 ] 23}); 24let ticketOwners= {}; 25 26// 各コマンドの読み込み 27client.commands = new Collection(); 28const commandsPath = path.join(__dirname, "commands"); 29const commandFiles = fs 30 .readdirSync(commandsPath) 31 .filter((file) => file.endsWith(".js")); 32 33for(const file of commandFiles) { 34 const filePath = path.join(commandsPath, file); 35 const command = require(filePath); 36 client.commands.set(command.data.name, command); 37} 38 39// BOTが稼働しているかの確認 40client.once(Events.ClientReady, () => { 41 console.log("ready"); 42}); 43 44// discordからコマンドを受け取り、それに応じた処理を行う 45client.on(Events.InteractionCreate, async(interaction) => { 46 if(!interaction.isChatInputCommand()) return; 47 48 const command = client.commands.get(interaction.commandName); 49 50 if(!command) return; 51 52 try { 53 await command.execute(interaction); 54 } catch (error) { 55 console.error(error); 56 await interaction.reply({ 57 content: "このコマンドの実行中にエラーが発生しました", 58 ephemral: true, 59 }); 60 } 61}); 62 63 64client.on(Events.InteractionCreate, async(interaction) => { 65 const customId = interaction.customId; 66 if(customId === "addteaminfoButton"){ 67 const server = interaction.guild; 68 const myRole = server.roles.cache.find(role => role.name === 'nodejs_test'); 69 70 if(Object.values(ticketOwners).includes(interaction.user.id)){ 71 await interaction.reply({content: "既にチケットが存在します", ephemral: true}); 72 return; 73 } 74 75 const channelName = `チケット-${interaction.user.username}`; 76 const channel = await interaction.guild.channels.create({ 77 name: `ticket-${channelName}`, 78 topic: interaction.user.id, 79 type: ChannelType.GuildText, 80 permissionOverwrites: [ 81 { 82 id: interaction.guild.roles.everyone.id, 83 deny: [PermissionFlagsBits.ViewChannel], 84 }, 85 { 86 id: myRole.id, 87 allow: [PermissionFlagsBits.SendMessages,PermissionFlagsBits.ViewChannel], 88 }, 89 { 90 id: interaction.user.id, 91 allow: [PermissionFlagsBits.SendMessages,PermissionFlagsBits.ViewChannel], 92 }, 93 ], 94 }) 95 96 97 ticketOwners[channel.id] = interaction.user.id; 98 99 await channel.send(`${interaction.user.toString()} チケットが作成されました`); 100 101 const ticketMessage = `チケットが作成されました\n${channel.toString()}`; 102 103 await interaction.reply({ content: ticketMessage, ephemeral: true}); 104 105 const delete_ticketButton = new ButtonBuilder() 106 .setCustomId("delete_ticket") 107 .setLabel("チケットを削除") 108 .setStyle(ButtonStyle.Danger); 109 const view = new ActionRowBuilder() 110 .addComponents(delete_ticketButton); 111 112 await channel.send({ content: "チケットを削除するには以下のボタンを押してください", components: [view] }); 113 } 114 if(customId === 'delete_ticket'){ 115 const channel = interaction.channel 116 await channel.delete() 117 ticketOwners[channel.id] = "" 118 } 119}); 120 121// モーダルで受け取った値をDiscordに送信する 122client.on(Events.InteractionCreate, async(interaction) => { 123 if(!interaction.isModalSubmit()) return; 124 125 const teamname = interaction.fields.getTextInputValue("teamnameInput"); 126 const reading = interaction.fields.getTextInputValue("readingInput"); 127 const ingameId = interaction.fields.getTextInputValue("ingameIdInput"); 128 const favoriteRole = interaction.fields.getTextInputValue("favoriteRoleInput"); 129 const favoriteChara = interaction.fields.getTextInputValue("favoriteCharaInput"); 130 console.log({ teamname, reading, ingameId, favoriteRole, favoriteChara }); 131 await interaction.reply({ 132 content:"チーム名:" + teamname + "\n読み方:" + reading + "\nゲーム内ID:" + ingameId + "\n好きなロール:" + favoriteRole + "\n好きなキャラ:" + favoriteChara + "\n", 133 }); 134}); 135 136client.login(token);

投稿2024/05/05 17:05

saica94

総合スコア1

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問