I am making a help command, but I want to disable it when the embed title is the same as the button label. Except this error pops out:
C:\Users\admin\OneDrive\Documents\VSCode\JS\Discord
Bots\Testing3.JS\node_modules\discord.js\src\rest\RequestHandler.js:350
throw new DiscordAPIError(data, res.status, request);
^
DiscordAPIError: Invalid Form Body components[0]: The specified
component type is invalid in this context components[1]: The specified
component type is invalid in this context
at RequestHandler.execute (C:\Users\admin\OneDrive\Documents\VSCode\JS\Discord
Bots\Testing3.JS\node_modules\discord.js\src\rest\RequestHandler.js:350:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async RequestHandler.push (C:\Users\admin\OneDrive\Documents\VSCode\JS\Discord
Bots\Testing3.JS\node_modules\discord.js\src\rest\RequestHandler.js:51:14)
at async MessageManager.edit (C:\Users\admin\OneDrive\Documents\VSCode\JS\Discord
Bots\Testing3.JS\node_modules\discord.js\src\managers\MessageManager.js:132:15)
{ method: 'patch', path:
'/channels/956427421073158194/messages/965228940685897748', code:
50035, httpStatus: 400, requestData: {
json: {
content: undefined,
tts: false,
nonce: undefined,
embeds: [
{
title: 'Economy',
type: 'rich',
description: null,
url: null,
timestamp: null,
color: null,
fields: [ [Object], [Object], [Object], [Object] ],
thumbnail: null,
image: null,
author: null,
footer: null
}
],
components: [
{
custom_id: 'econ',
disabled: true,
emoji: { animated: false, name: '💵', id: null },
label: 'Economy',
style: 1,
type: 2,
url: null
},
{
custom_id: 'info',
disabled: false,
emoji: { animated: false, name: '📃', id: null },
label: 'Info',
style: 2,
type: 2,
url: null
}
],
username: undefined,
avatar_url: undefined,
allowed_mentions: undefined,
flags: 0,
message_reference: undefined,
attachments: undefined,
sticker_ids: undefined
},
files: [] } }
Code:
if (cmd === "help") {
const econ = new Discord.MessageButton()
.setCustomId('econ')
.setEmoji('💵')
.setLabel('Economy')
.setStyle('PRIMARY')
const info = new Discord.MessageButton()
.setCustomId('info')
.setEmoji('📃')
.setLabel('Info')
.setStyle('SECONDARY')
const row = new Discord.MessageActionRow().addComponents([econ, info]);
let helpMsg = await message.channel.send({
embeds: [
{
title: "Economy",
fields: [
{
name: `\`${cPrefix}bal | balance [user]\``,
value: 'Displays your balance or a user\'s balance.'
},
{
name: `\`${cPrefix}dep | deposit <amount>\``,
value: 'Deposits a specified amount of cash to your bank.'
},
{
name: `\`${cPrefix}with | withdraw <amount>\``,
value: 'Withdraws a specified amount of cash to your wallet.'
},
{
name: `\`${cPrefix}addcoins <user> <amount>\``,
value: 'Adds a specified amount of cash to a user. (Administrator)'
}
]
}
],
components: [row]
});
const collector = helpMsg.createMessageComponentCollector({
componentType: 'BUTTON',
time: 60000
});
collector.on('collect', async (b) => {
if (b.user.id === message.author.id) {
if (b.customId === 'econ') {
helpMsg.edit({
embeds: [
{
title: "Economy",
fields: [
{
name: `\`${cPrefix}bal | balance [user]\``,
value: 'Displays your balance or a user\'s balance.'
},
{
name: `\`${cPrefix}dep | deposit <amount>\``,
value: 'Deposits a specified amount of cash to your bank.'
},
{
name: `\`${cPrefix}with | withdraw <amount>\``,
value: 'Withdraws a specified amount of cash to your wallet.'
},
{
name: `\`${cPrefix}addcoins <user> <amount>\``,
value: 'Adds a specified amount of cash to a user. (Administrator)'
}
]
},
],
components: [row.components[0].setDisabled(true), row.components[1].setDisabled(false)]
});
}
if (b.customId === 'info') {
helpMsg.edit({
embeds: [
{
title: "Info",
fields: [
{
name: `${cPrefix}info <user|server> <user: user>`,
value: 'Displays an info of the server or a user'
},
{
name: `${cPrefix}ping`,
value: 'Displays the current client ping and the database connection'
},
{
name: `${cPrefix}help`,
value: 'Umm... You used this command'
},
]
}
],
components: [row.components[0].setDisabled(false), row.components[1].setDisabled(true)]
})
}
} else {
b.reply({ content: 'These buttons are not for you.', ephemeral: true })
}
});
collector.on('end', async () => {
helpMsg.edit({ components: [row.components[0].setDisabled(true), row.components[1].setDisabled(true)] })
});
}
Is there anything wrong in this code?
You can create a new MessageActionRow and set everything to disabled. This code is from my bot's help command (discord.js v13.6.0):
let btnraw = new Discord.MessageActionRow().addComponents(
[
new Discord.MessageButton().setCustomId("home").setStyle("SUCCESS").setLabel("Home"),
new Discord.MessageButton().setCustomId("general").setStyle("PRIMARY").setLabel("General"),
new Discord.MessageButton().setCustomId("info").setStyle("PRIMARY").setLabel("Information"),
new Discord.MessageButton().setCustomId("mod").setStyle("PRIMARY").setLabel("Moderation"),
new Discord.MessageButton().setCustomId("fun").setStyle("PRIMARY").setLabel("Fun"),
]
);
let dbtnraw = new Discord.MessageActionRow().addComponents(
[
new Discord.MessageButton().setCustomId("d_home").setStyle("SUCCESS").setLabel("Home").setDisabled(true),
new Discord.MessageButton().setCustomId("d_general").setStyle("PRIMARY").setLabel("General").setDisabled(true),
new Discord.MessageButton().setCustomId("d_info").setStyle("PRIMARY").setLabel("Information").setDisabled(true),
new Discord.MessageButton().setCustomId("d_mod").setStyle("PRIMARY").setLabel("Moderation").setDisabled(true),
new Discord.MessageButton().setCustomId("d_fun").setStyle("PRIMARY").setLabel("Fun").setDisabled(true),
]
);
Then you can edit the message to replace the original row like this:
helpMsg.edit({components: [d_btnraw]});
Related
I have a javascript file on my NodeJS server that runs at 00:00:00 and updates some fields in the database, if that happens I want to send out a push notification to some users. I've set this up in my Javascript file:
https://dev.to/devsmranjan/web-push-notification-with-web-push-angular-node-js-36de
const subscription = {
endpoint: '',
expirationTime: null,
keys: {
auth: '',
p256dh: '',
},
};
const payload = {
notification: {
title: 'Title',
body: 'This is my body',
icon: 'assets/icons/icon-384x384.png',
actions: [
{action: 'bar', title: 'Focus last'},
{action: 'baz', title: 'Navigate last'},
],
data: {
onActionClick: {
default: {operation: 'openWindow'},
bar: {
operation: 'focusLastFocusedOrOpen',
url: '/signin',
},
baz: {
operation: 'navigateLastFocusedOrOpen',
url: '/signin',
},
},
},
},
};
const options = {
vapidDetails: {
subject: 'mailto:example_email#example.com',
publicKey: process.env.REACT_APP_PUBLIC_VAPID_KEY,
privateKey: process.env.REACT_APP_PRIVATE_VAPID_KEY,
},
TTL: 60,
};
webpush.sendNotification(subscription, JSON.stringify(payload), options)
.then((_) => {
console.log(subscription);
console.log('SENT!!!');
console.log(_);
})
.catch((_) => {
console.log(subscription);
console.log(_);
});
But when I run the file I get the message:
{ endpoint: '', expirationTime: null, keys: { auth: '', p256dh: '' } } Error: You must pass in a subscription with at least an endpoint.
Which makes sense since the server has no idea about service workers etc. Any suggestions on how to proceed?
When I run my Discord bot, which is made through the Discord.js and Node.js framework, I receive the following error.
node_modules\#discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:293
throw new DiscordAPIError.DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
^
DiscordAPIError[50035]: Invalid Form Body
options[0].type[NUMBER_TYPE_COERCE]: Value "string" is not int.
options[1].type[NUMBER_TYPE_COERCE]: Value "string" is not int.
at SequentialHandler.runRequest (D:\Programming\GitHub\void-bot\node_modules\#discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:293:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async SequentialHandler.queueRequest (D:\Programming\GitHub\void-bot\node_modules\#discordjs\rest\dist\lib\handlers\SequentialHandler.cjs:99:14)
at async REST.request (D:\Programming\GitHub\void-bot\node_modules\#discordjs\rest\dist\lib\REST.cjs:52:22)
at async GuildApplicationCommandManager.create (D:\Programming\GitHub\void-bot\node_modules\discord.js\src\managers\ApplicationCommandManager.js:144:18) {
rawError: {
code: 50035,
errors: {
options: {
'0': { type: { _errors: [Array] } },
'1': { type: { _errors: [Array] } }
}
},
message: 'Invalid Form Body'
},
code: 50035,
status: 400,
method: 'POST',
url: 'https://discord.com/api/v10/applications/1016623217399570512/guilds/915541815225118740/commands',
requestBody: {
files: undefined,
json: {
name: 'poll',
name_localizations: undefined,
description: 'Sets up a poll.',
description_localizations: undefined,
type: undefined,
options: [
{
type: 'string',
name: 'title',
name_localizations: undefined,
name_localized: undefined,
description: 'The title of the poll.',
description_localizations: undefined,
description_localized: undefined,
required: true,
autocomplete: undefined,
choices: undefined,
options: undefined,
channel_types: undefined,
min_value: undefined,
max_value: undefined,
min_length: undefined,
max_length: undefined
},
{
type: 'string',
name: 'content',
name_localizations: undefined,
name_localized: undefined,
description: 'The content of the poll.',
description_localizations: undefined,
description_localized: undefined,
required: true,
autocomplete: undefined,
choices: undefined,
options: undefined,
channel_types: undefined,
min_value: undefined,
max_value: undefined,
min_length: undefined,
max_length: undefined
}
],
default_member_permissions: undefined,
dm_permission: undefined
}
}
}
I am unsure why I am receiving this for the code below:
require("dotenv").config();
const { GatewayIntentBits } = require("discord.js");
const Discord = require("discord.js");
const PREFIX = "!";
const client = new Discord.Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildBans,
GatewayIntentBits.GuildEmojisAndStickers,
GatewayIntentBits.GuildIntegrations,
GatewayIntentBits.GuildWebhooks,
GatewayIntentBits.GuildInvites,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildPresences,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMessageReactions,
GatewayIntentBits.GuildMessageTyping,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.DirectMessageReactions,
GatewayIntentBits.DirectMessageTyping,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildScheduledEvents
]
});
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
const guildID = "915541815225118740";
const guild = client.guilds.cache.get(guildID);
let commands;
if (guild) {
commands = guild.commands;
} else {
commands = client.application?.commands;
}
commands?.create({
name: "poll",
description: "Sets up a poll.",
options: [
{
name: "title",
description: "The title of the poll.",
required: true,
type: "string"
},
{
name: "content",
description: "The content of the poll.",
required: true,
type: "string"
}
]
});
});
client.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) {
return;
}
const { commandName, options } = interaction;
if (commandName === "poll") {
const embed = new Discord.EmbedBuilder()
.setColor(0x0099FF)
.setTitle(options.get("title"))
.addFields(
{
value: options.get("content"),
inline: false
},
{
value: ":thumbsup: - Yes",
inline: true
},
{
value: ":thumbsdown: - No",
inline: true
}
)
}
interaction.reply(embed);
});
client.login(process.env.TOKEN);
I hope someone can help me out with this. It would be greatly appreciated as I have been stuck on this issue for a couple of days now.
Thanks,
nozzy
You've specified the option type using a string literal. It should be a value of the ApplicationCommandOptionType enum. So instead you should be using:
{
name: "...",
description: "...",
required: ...
type: ApplicationCommandOptionType.STRING
}
I need to assign the genre field to a new array but I am not sure how to only get that field, or how to call that field
var SpotifyWebApi = require('spotify-web-api-node');
var spotifyApi = new SpotifyWebApi();
spotifyApi.setAccessToken('-----');
spotifyApi.searchArtists('artist:queen')
.then(function(data) {
console.log('Search tracks by "queen" in the artist name', data.body.artists.items);
}, function(err) {
console.log('Something went wrong!', err);
});
This is the terminal when calling it.
I only want the first response.
PS C:\Users\g\Documents\js> node spotifyTest
Search tracks by "queen" in the artist name [ { external_urls:
{ spotify: 'https://open.spotify.com/artist/1dfeR4HaWDbWqFHLkxsg1d' },
followers: { href: null, total: 19579534 },
genres: [ 'glam rock', 'rock' ],
href: 'https://api.spotify.com/v1/artists/1dfeR4HaWDbWqFHLkxsg1d',
id: '1dfeR4HaWDbWqFHLkxsg1d',
images: [ [Object], [Object], [Object], [Object] ],
name: 'Queen',
popularity: 90,
type: 'artist',
uri: 'spotify:artist:1dfeR4HaWDbWqFHLkxsg1d' },
{ external_urls:
{ spotify: 'https://open.spotify.com/artist/3nViOFa3kZW8OMSNOzwr98' },
followers: { href: null, total: 1087117 },
genres: [ 'deep pop r&b', 'pop', 'r&b' ],
href: 'https://api.spotify.com/v1/artists/3nViOFa3kZW8OMSNOzwr98',
id: '3nViOFa3kZW8OMSNOzwr98',
images: [ [Object], [Object], [Object] ],
name: 'Queen Naija',
popularity: 68,
type: 'artist',
uri: 'spotify:artist:3nViOFa3kZW8OMSNOzwr98' } ]
You can access a field in a JSON object using the dot notation. Here's an example of replacing the genres of the first response with a new array.
let responseItems = [
{ external_urls: { spotify: 'https://open.spotify.com/artist/1dfeR4HaWDbWqFHLkxsg1d' },
followers: { href: null, total: 19579534 },
genres: [ 'glam rock', 'rock' ],
href: 'https://api.spotify.com/v1/artists/1dfeR4HaWDbWqFHLkxsg1d',
id: '1dfeR4HaWDbWqFHLkxsg1d',
images: [ [Object], [Object], [Object], [Object] ],
name: 'Queen',
popularity: 90,
type: 'artist',
uri: 'spotify:artist:1dfeR4HaWDbWqFHLkxsg1d'
},
{
external_urls: { spotify: 'https://open.spotify.com/artist/3nViOFa3kZW8OMSNOzwr98' },
followers: { href: null, total: 1087117 },
genres: [ 'deep pop r&b', 'pop', 'r&b' ],
href: 'https://api.spotify.com/v1/artists/3nViOFa3kZW8OMSNOzwr98',
id: '3nViOFa3kZW8OMSNOzwr98',
images: [ [Object], [Object], [Object] ],
name: 'Queen Naija',
popularity: 68,
type: 'artist',
uri: 'spotify:artist:3nViOFa3kZW8OMSNOzwr98'
}
];
let firstResponse = responseItems[0];
console.log(JSON.stringify(firstResponse.genres, null, 2));
let newGenres = [ 'rock', 'jazz' ];
firstResponse.genres = newGenres;
console.log(JSON.stringify(firstResponse.genres, null, 2));
This should show the following in the console:
[
"glam rock",
"rock"
]
[
"rock",
"jazz"
]
I try to call putMapping from elasticsearch javascript client, but always got an error with status code 400, illegal_argument_exception.
When I call getMapping for "documents" index I got:
{
"documents":{
"mappings": {
"properties":{
"category":{"type":"text","fields":{"keyword":
{"type":"keyword","ignore_above":256}}},
"createdAt":{"type":"text","fields":{"keyword":
{"type":"keyword","ignore_above":256}}},
"id":{"type":"text","fields":{"keyword":
{"type":"keyword","ignore_above":256}}},
"info":{"type":"text","fields":{"keyword":
{"type":"keyword","ignore_above":256}}},
"text":{"type":"text","fields":{"keyword":
{"type":"keyword","ignore_above":256}}},
"title":{"type":"text","fields":{"keyword":
{"type":"keyword","ignore_above":256}}},
"visibility":{"type":"boolean"}
}
}
}
}
I tried to call putMapping with same properties and add a new parameter 'index': 'not_analyzed' to category field:
esClient.indices.putMapping({
index: 'documents',
type: 'document',
body: {
document: {
properties: {
title: { type: 'text' },
info: { type: 'text' },
text: { type: 'text' },
category: { type: 'text', index:
'not_analyzed'
},
visibility: { type: 'boolean' },
createdAt: { type: 'text' },
},
},
},
}, (err, resp) => {
if (err) {
console.error(err);
}
else {
console.log('Successfully Created Index', resp);
}
});
I got this error:
ResponseError: illegal_argument_exception
at IncomingMessage.<anonymous> (/Users/user/reference_sys_cfu-back/node_modules/#elastic/elasticsearch/lib/Transport.js:287:25)
at IncomingMessage.emit (events.js:208:15)
at IncomingMessage.EventEmitter.emit (domain.js:476:20)
at endReadableNT (_stream_readable.js:1168:12)
at processTicksAndRejections (internal/process/task_queues.js:77:11) {
name: 'ResponseError',
meta: {
body: { error: [Object], status: 400 },
statusCode: 400,
headers: {
'content-type': 'application/json; charset=UTF-8',
'content-length': '345'
},
warnings: null,
meta: {
context: null,
request: [Object],
name: 'elasticsearch-js',
connection: [Object],
attempts: 0,
aborted: false
}
}
}
index: 'not_analyzed' - I do this for use "term" method for exact finding strings, but it (index: 'not_analyzed') deprecated in 2.x version of elasticsearch. Now I just use field.keyword: 'query string', to finding exact strings.
I try to have a response on my request GraphQL.
I tried many things but currently I have always the Sequence response, and no the Buckets response (belongs To relation).
I have 2 tables :
Sequence [id | is_active]
Bucket [id | fk_language_id | fk_sequence_id | is_active]
model/sequence.js
'use strict';
module.exports = (sequelize, DataTypes) => {
// define sequence
const Sequence = sequelize.define('sequence', {
is_active: {type: DataTypes.BOOLEAN}
});
Sequence.associate = function (models) {
models.Sequence.hasMany(models.Bucket, {
foreignKey: 'fk_sequence_id'
});
return Sequence;
};
model/bucket.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const Bucket = sequelize.define('bucket', {
code : {type: DataTypes.STRING},
is_active: {type: DataTypes.BOOLEAN}
});
Bucket.associate = function (models) {
models.Bucket.belongsTo(models.Language, {
foreignKey: 'fk_language_id',
});
models.Bucket.belongsTo(models.Sequence, {
foreignKey: 'fk_sequence_id',
});
};
return Bucket;
};
schema.js
# Sequence
type Sequence {
id: Int!,
code: String,
buckets: [Bucket],
is_active: Boolean
}
# Bucket
type Bucket {
id: Int!,
code: String
blocks: [Block]
is_active: Boolean
}
# SequenceInput
input SequenceInput {
buckets: [BucketInput],
is_active: Boolean
}
# BucketInput
input BucketInput {
code: String,
fk_language_id: Int,
fk_sequence_id: Int,
is_active: Boolean
}
type Query {
sequences: [Sequence]
sequence(id: Int): Sequence
buckets: [Bucket]
bucket(id: Int): Bucket
}
type Mutation {
createSequence(input: SequenceInput): Sequence,
}
Request GraphQL
mutation {
createSequence(input: {
is_active: false,
buckets: [
{fk_language_id: 2, code: "Test"}
]
}) {
is_active,
buckets {
id,
code
}
}
}
But I have this result, the Buckets doesn't load :
{
"data": {
"createSequence": {
"is_active": false,
"buckets": []
}
}
}
my mutation :
...
Sequence : {
buckets(sequence) {
return models.Bucket.findAll({
where: {id: sequence.id}
});
},
...
},
...
Mutation : {
createSequence(_, {input}) {
let sequenceId = 0;
// Create Sequence
return models.Sequence.create(input)
.then((sequence) => {
sequenceId = sequence.id;
console.log('sequence created');
// Create Bucket
// Foreach on buckets
return Promise.map(input.buckets, function (bucket) {
bucket.fk_sequence_id = sequenceId;
console.log('bucket created');
return models.Bucket.create(bucket);
})
})
.then(() => {
console.log('load created', sequenceId);
return models.Sequence.findOne({
where : {id: sequenceId},
include: [
{
model: models.Bucket,
where: { fk_sequence_id: sequenceId }
}
]
}).then((response) => {
console.log(response);
return response;
})
});
},
}
The final console.log show many informations...
sequence {
dataValues:
{ id: 416,
is_active: false,
created_at: 2019-03-29T20:33:56.196Z,
updated_at: 2019-03-29T20:33:56.196Z,
buckets: [ [Object] ] },
_previousDataValues:
{ id: 416,
is_active: false,
created_at: 2019-03-29T20:33:56.196Z,
updated_at: 2019-03-29T20:33:56.196Z,
buckets: [ [Object] ] },
_changed: {},
_modelOptions:
{ timestamps: true,
validate: {},
freezeTableName: true,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: { id: 416 },
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: { plural: 'sequences', singular: 'sequence' },
omitNull: false,
createdAt: 'created_at',
updatedAt: 'updated_at',
sequelize:
Sequelize {
options: [Object],
config: [Object],
dialect: [Object],
queryInterface: [Object],
models: [Object],
modelManager: [Object],
connectionManager: [Object],
importCache: [Object],
test: [Object] },
hooks: {} },
_options:
{ isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
include: [ [Object] ],
includeNames: [ 'buckets' ],
includeMap: { buckets: [Object] },
includeValidated: true,
attributes: [ 'id', 'is_active', 'created_at', 'updated_at' ],
raw: true },
isNewRecord: false,
buckets:
[ bucket {
dataValues: [Object],
_previousDataValues: [Object],
_changed: {},
_modelOptions: [Object],
_options: [Object],
isNewRecord: false } ] }
Your mutation resolver returns a Promise, which resolves into a Model instance. The promise in question is returned on this line:
return models.Sequence.create(input)
.
As such, the server will wait until that promise is resolved before passing the value forward. Other actions were also waiting on that promise, but they were not the promises returned, so they will not be waited for.
All you have to do is wait for all of your operations to finish before resolving your promise.
createSequence: async (parent, { input }) => {
const sequence = await models.Sequence.create({
is_active: input.is_active
})
if (!input.buckets) return sequence
// You may have to modify your Sequence.buckets resolver to avoid fetching buckets again.
sequence.buckets = await Promise.all(input.buckets.map(bucket => {
// You can avoid these if checks by implementing stricter input types.
// e.g. buckets: [BucketInput!]!
if (!bucket) return null
return models.Bucket.create({
...bucket,
fk_sequence_id: sequence.id
})
}))
return sequence
}
Also, make sure your Sequence.buckets resolver isn't overwriting buckets with faulty data. The resolver you've provided will try to match bucket primary keys with a sequence primary key instead of matching the correct foreign keys with a primary key.
Here's a resolver that will work:
buckets: (parent) => (
parent.buckets // This line may conflict with some of your code and cause problems.
|| models.Bucket.findAll({
where: {fk_sequence_id: parent.id}
})
)