discord.js
менялась, и на данный момент (сейчас последняя версия — discord.js@14.13.0
) в файле, к которому вы обращаетесь (Constants.js
) не содержится объект DefaultOptions
.Discord.Constants.DefaultOptions
— undefined
.undefined
(в вашем случае свойство ws
, undefined.ws
), возникает ошибка Cannot read properties of undefined
.const {
DefaultWebSocketManagerOptions: {
identifyProperties
}
} = require("@discordjs/ws");
identifyProperties.browser = "Discord Android"; // или Discord iOS
обратите внимание: хоть этот способ и рабочий, официально он не задокументирован.browser
(которое изменяет код выше) должно быть название библиотеки:Discord iOS
или Discord Android
, мы можем получить статус «онлайн с телефона», несмотря на то, что этот подход не приветствуется ни Discord API
, ни discord.js
. message.reply()
и message.delete()
— это промисы.message.reply()
, тогда все будет работать, как задумано - сначала бот ответит на сообщение пользователя, потом это сообщение удалит.message.delete()
, бот вылетит с фатальной ошибкой REPLIES_UNKNOWN_MESSAGE
, т.к попытается опубликовать ответ на не существующее (уже удаленное) сообщение..then(),
либо синтаксис async/await
:message.reply("ответ на сообщение").then(() => { // после выполнения message.reply()...
message.delete(); // ...удалить сообщение
})
// или //
await message.reply("ответ на сообщение");
await message.delete();
/*
в этом примере выполнение кода не пойдет дальше, пока не выполнится message.reply().
после выполнения message.reply() компилятор будет так же ждать выполнения message.delete(), и пока оно не выполнится, весь код, написанный после message.delete() не будет приведен в действие.
*/
GatewayIntentBits.MessageContent
в код, а также в профиле бота в Discord Developer Portal включить Message Content Intent
:const { ChannelType } = require("discord.js")
// ... //
let channel = interaction.guild.channels.cache
.find(channel => channel.name === "название_категории" && channel.type === ChannelType.GuildCategory)
?.children.cache
.find(channel => channel.name === "название_канала")
.find()
вернёт undefined
, в связи с чем получится выражение undefined.children.cache.find()
, что приведёт к ошибке Cannot read properties of undefined (reading 'children').await interaction.reply({ components: [row], embeds: [embed] });
const message = await interaction.fetchReply(); // <===
const collector = message.createMessageComponentCollector({ componentType: ComponentType.Button, time: 15000, filter: i => i.user.id === interaction.member.id });
true
, коллектор "соберёт" нажатие; если false
— не соберёт).collector.on("collect", i => { // автор команды нажал на одну из кнопок
if (i.customId === "customId_одной_из_кнопок") { // проверяете, на какую кнопку нажал юзер
// *выдать роль пользователю* //
}
})
client.user.setActivity('название', { type: ActivityType.Watching });
const client = new Client({
intents: [/* интенты */],
presence: {
activities: [{
name: "название",
type: ActivityType.Watching
}]
}
});
DIRECT_MESSAGES
:const client = new Client({ intents: [GatewayIntentBits.DirectMessages, ...] });
const client = new Client({
intents: [GatewayIntentBits.DirectMessages, ...],
partials: [Partials.Channel]
});
client.on("interactionCreate" , async (Integration) =>{
if(Integration.isButton() && Integration.customId == "1"){
guildMember.roles.set(['880828678278352937'])
}
if(Integration.isButton() && Integration.customId == "2"){
var role = message.guild.roles.cache.find(role => role.id === "880828678278352937");
user.roles.add(role)
}
})
Integration
лучше было бы использовать название interaction
, т.к мы всё-таки работаем с взаимодействием, а не с интеграцией.if (Integration.isButton()) {
// проверки на .customId (можно использовать switch/case, если их много) //
}
1. guildMember.roles.set(['880828678278352937'])
guildMember
не определена, будет ошибка.Integration.member
, и в итоге будет Integration.member.roles.set(["880828678278352937"])
var role = message.guild.roles.cache.find(role => role.id === "880828678278352937");
message
не определена, тоже будет ошибка.interaction.guild.roles
.get()
..find()
используйте в случае, если нужно найти роль по её названию или другим параметрам.const defaultButtonGreen = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('defaultButtonGreen')
.setLabel('green')
.setStyle(ButtonStyle.Success),
),
defaultButtonRed = new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId('defaultButtonRed')
.setLabel('red')
.setStyle(ButtonStyle.Danger),
);
await interaction.reply({ content: "message", components: [defaultButtonGreen, defaultButtonRed] });
const message = await interaction.fetchReply();
const collector = message.createMessageComponentCollector({
componentType: ComponentType.Button,
time: 60000
});
collector.on('collect', async i => {
if (i.customId === "defaultButtonGreen") {
defaultButtonGreen.components[0].setStyle(
defaultButtonGreen.components[0].data.style === 3 ? ButtonStyle.Danger : ButtonStyle.Success
);
await i.update({ components: [defaultButtonGreen, defaultButtonRed] })
} else if (i.customId === "defaultButtonRed") {
defaultButtonRed.components[0].setStyle(
defaultButtonRed.components[0].data.style === 4 ? ButtonStyle.Success : ButtonStyle.Danger
);
await i.update({ components: [defaultButtonGreen, defaultButtonRed] })
}
});
`ticket-${int.member.displayName}`
await interaction.reply(...);
const message = await interaction.fetchReply();
const collector = message.createComponentCollector(...);
const {SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, Client, GatewayIntentBits, EmbedBuilder} = require('discord.js')
- const client = new Client({intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildPresences]});
module.exports = {
data: new SlashCommandBuilder()
.setName('add-animal')
.setNameLocalizations({"ru": "добавить-животное"})
.setDescription('Add animals to game "Guess the animal"!')
.setDescriptionLocalizations({"ru": 'Добавь животное в игру "Угадай животное"!'})
.addStringOption(option =>
option.setName('name')
.setNameLocalizations({"ru": 'имя'})
.setDescription("Animal name")
.setDescriptionLocalizations({"ru": "Имя животного"})
.setRequired(true)
)
.addAttachmentOption(option =>
option.setName('image')
.setNameLocalizations({"ru": "изображение"})
.setDescription("Animal image")
.setDescriptionLocalizations({"ru": "Изображение животного"})
.setRequired(true)
),
async execute(interaction) {
const name = interaction.options.getString('name')
const image = interaction.options.getAttachment('image')
const embed = new EmbedBuilder()
.setTitle(name)
.setDescription(`Прислал: ${interaction.user}`)
.setImage(image.url)
- client.channels.fetch('1007311557300068432')
- .then(channel => channel.send('ok'))
+ interaction.client.channels.fetch("1007311557300068432")
+ .then(channel => channel.send('ok'))
interaction.reply("ок")
}
}
Как уже говорилось ранее, у вас есть три секунды, чтобы ответить на Interaction, прежде чем его токен станет недействительным. Но что, если у вас есть команда, выполняющая задачу, которой требуется больше времени, чем три секунды?
В этом случае вы можете воспользоваться методомBaseInteraction#deferReply()
, который запускает<application> is thinking...
, а также действует как начальный ответ. Это позволит вам получить 15 минут на выполнение задач перед ответом.
axios.get()
иногда уходит более 3 секунд, из-за чего к моменту запуска .then()
токен Interaction уже является недействительным, что и вызывает ошибку.axios.get()
нужно поставить await interaction.deferReply()
, а после чего уже использовать await interaction.editReply(...)
вместо await interaction.reply(...)
.axios.get()
, юзер будет видеть надпись имя_бота думает...
(или имя_бота is thinking...
, в зависимости от языка).