Why isn't my slash command working? discord.js - discord

I was trying to create a bot that with a slash command can create a azure ad account and message it to the user. However when I run the code it doesn't create a slash command. How would I fix this.
Code:
// import dependencies
const Discord = require('discord.js');
const axios = require('axios');
// create a new Discord client
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
],
});
// listen for the ready event
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
// listen for the interactionCreate event
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
if (interaction.commandName === 'create-account') {
// retrieve user input from slash command
const displayName = interaction.options.getString('displayname');
const password = interaction.options.getString('password');
// retrieve sensitive information from Replit secrets
const tenantId = process.env.AZURE_TENANT_ID;
const clientId = process.env.AZURE_CLIENT_ID;
const clientSecret = process.env.AZURE_CLIENT_SECRET;
try {
// create Azure AD account using Microsoft Graph API
const response = await axios.post(`https://graph.microsoft.com/v1.0/${tenantId}/users`, {
displayName: displayName,
passwordProfile: {
password: password
},
accountEnabled: true
}, {
headers: {
'Authorization': `Bearer ${await getAccessToken(clientId, clientSecret, tenantId)}`
}
});
// send success message to Discord
await interaction.reply(`Account with display name "${displayName}" created on Azure AD.`);
// log created account to Discord webhook
const webhook = new Discord.WebhookClient({
id: process.env.DISCORD_WEBHOOK_ID,
token: process.env.DISCORD_WEBHOOK_TOKEN
});
await webhook.send(`Account created on Azure AD:\nDisplay name: ${displayName}\nObject ID: ${response.data.id}`);
} catch (error) {
console.error(error);
// send error message to Discord
await interaction.reply('An error occurred while creating the account. Please try again later.');
}
}
});
// start the Discord client
client.login(process.env.DISCORD_TOKEN);
// helper function to get access token for Microsoft Graph API
async function getAccessToken(clientId, clientSecret, tenantId) {
const response = await axios.post(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, {
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
scope: 'https://graph.microsoft.com/.default'
});
return response.data.access_token;
}
I want it to create a slash command which I can run that'll let me create an azure ad account but the slash command does not show up when I try using it.

Related

TypeError when trying to create a discord bot

I'm trying to build a discord bot that sends data to an airtable. This one sends user info when they join my server. I have the following code, but every time I try to run it, I get the following error:
TypeError: Cannot read properties of undefined (reading 'GUILDS')at Object.
This is the code:
const { Intents } = require('discord.js');
const Discord = require('discord.js');
const Airtable = require('airtable');
const client = new Discord.Client({
token: 'TOKEN_ID',
intents: [Intents.GUILDS, Intents.GUILD_MEMBERS]
});
Airtable.configure({ apiKey: 'API_KEY' });
const base = Airtable.base('BASE_ID');
client.on('guildMemberAdd', member => {
base('New Members').create({
'Username': member.user.username,
'Time Joined': new Date().toISOString()
}, function(err, record) {
if (err) {
console.error(err);
return;
}
console.log(`Added new record with ID ${record.getId()}`);
});
});
client.login();
Using Discord.js v14, the way to declare intents is as follows:
import { Client, GatewayIntentBits } from "discord.js";
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers
]
});
and your token should be put in client.login
client.login("your-bot-token");

DiscordJS 403 Error Missing Access Error when trying to add Slash Commands

I am following the docs at DiscrodJS step by step and have been able to invite my bot just fine to my test server. My problem comes in when I try to add the slash commands.
Here is my index.js file.
const { Client, GatewayIntentBits } = require('discord.js')
require('dotenv').config()
const client = new Client({
intents: [
GatewayIntentBits.GuildMessages,
],
})
client.once('ready', () => {
console.log('Ready!')
})
client.on('interactionCreate', async interaction => {
if (!interaction.isChatInputCommand()) return
const { commandName } = interaction
const command = interaction.client.commands.get(commandName)
if (!command) {
console.error(`No command matching ${commandName} was found.`)
return
}
try {
await command.execute(interaction)
}
catch (error) {
console.error(error)
await interaction.reply({ ontent: 'There was an error while executing this command', ephemeral: true })
}
})
client.login(process.env.DISCORD_PRIVATE_TOKEN)
Here is my deploy-commands.js file.
const fs = require('node:fs')
const { Routes } = require('discord.js')
const { REST } = require('#discordjs/rest')
require('dotenv').config()
const {
DISCORD_PRIVATE_TOKEN,
DISCORD_CLIENT_ID,
DISCORD_GUILD_ID,
} = process.env
const commands = []
// Grab all the command files from the commands directory you created earlier
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'))
// Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment
for (const file of commandFiles) {
const command = require(`./commands/${file}`)
commands.push(command.data.toJSON())
}
// Construct and prepare an instance of the REST module
const rest = new REST({ version: '10' }).setToken(DISCORD_PRIVATE_TOKEN)
// and deploy your commands!
const deployCommand = async () => {
try {
console.log(`Started refreshing ${commands.length} application (/) commands.`)
// The put method is used to fully refresh all commands in the guild with the current set
const data = await rest.put(
Routes.applicationGuildCommands(DISCORD_CLIENT_ID, DISCORD_GUILD_ID),
{ body: commands },
)
console.log(`Successfully reloaded ${data.length} application (/) commands.`)
}
catch (error) {
// And of course, make sure you catch and log any errors!
console.error(error)
}
}
deployCommand()
There error that I get back from this is the following:
requestBody: { files: undefined, json: [ [Object] ] },
rawError: { message: 'Missing Access', code: 50001 },
code: 50001,
status: 403,
method: 'PUT',
url: 'https://discord.com/api/v10/applications/[client_id]/guilds/[guild_id]/commands'
}
In the bot settings
I've set auth method to In-app Authorization.
I've set the scope to bot and applications.commands then included Use Slash Commands (also tried this with ALL including Administrator bot permissions.
I've also done this through the URL Generator path.
In my discord server
I've put my Discord server into Developer mode to test my bot.
I've invited my bot to my test server.
In my code
I've ran the one time script for deploy-commands.js.

My discord bot isn't working after 13.0.0

I am trying out discord.js version 13.1.0 and I am following discord's guide on how to setup a bot. I have followed all the steps. When I have the bot running, and I send a message or a command into the server, nothing gets printed to the console. Any ideas?
My code:
const { Client, Intents } = require("discord.js");
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
client.once("ready", () => {
console.log("Ready!");
});
client.on("interactionCreate", (interaction) => {
console.log(interaction);
});
client.login(process.env.TOKEN);
From the Discord Developer Portal:
An Interaction is the message that your application receives when a user uses an application command or a message component.
By an application command is meant a special type of command, that you have to register against the Discord API. To learn more about application commands, read this.
From the discord.js docs main page, how to register an application (slash) command:
const { REST } = require('#discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const commands = [{
name: 'ping',
description: 'Replies with Pong!'
}];
const rest = new REST({ version: '9' }).setToken('token');
(async () => {
try {
console.log('Started refreshing application (/) commands.');
await rest.put(
Routes.applicationGuildCommands(CLIENT_ID, GUILD_ID),
{ body: commands },
);
console.log('Successfully reloaded application (/) commands.');
} catch (error) {
console.error(error);
}
})();
However if you are looking for a way to reply to (or just capture) a normal message sent in a TextChannel, you are probably looking for the messageCreate event.
client.on("messageCreate", (message) => {
console.log(message);
});
Also note that to receive messageCreate event, you need GUILD_MESSAGES intent.
const client = new Discord.Client({ intents: ["GUILDS", "GUILD_MESSAGES"] });

Microsoft Graph API - Create user in Azure AD B2C with local account identity gives Request_ResourceNotFound error

My goal is to create a local account, like michele#gmail.com, in Azure Active Directory B2C.
I want to use my own UI, so I started to look at how to implement the API. After some research, it looks like the best way to do it should be via Microsoft Graph.
I started by following Manage Azure AD B2C user accounts with Microsoft Graph, and I properly created an app (not sure if I need to choose the third options, but looks like the broader one):
with the following permissions (updated following also #Tony Ju screenshot):
Then I created the client secret and coded my own auth provider
const { AuthenticationContext } = require('adal-node');
class AuthProvider {
async getAccessToken() {
return new Promise((resolve, reject) => {
const tenant = 'tenant';
const authority = `https://login.microsoftonline.com/${tenant}`;
const authenticationContext = new AuthenticationContext(authority);
const resource = 'https://graph.microsoft.com';
const clientId = 'clientId';
const clientSecret = 'clientSecret';
authenticationContext.acquireTokenWithClientCredentials(
resource,
clientId,
clientSecret,
(err, tokenResponse) => {
if (err) {
console.error('error!', err);
return reject(err);
}
return resolve(tokenResponse.accessToken);
},
);
});
}
}
and initialized the client
require('isomorphic-fetch'); //needed for server side request with the client
const { Client } = require('#microsoft/microsoft-graph-client');
const options = {
authProvider: new AuthProvider(),
};
const client = Client.initWithMiddleware(options);
Following the official documentation, I create a local account
const user = {
displayName: 'John Smith',
identities: [
{
signInType: 'emailAddress',
issuer: 'MY_ISSUER.onmicrosoft.com',
issuerAssignedId: 'jsmith#yahoo.com',
},
],
passwordProfile: {
password: 'df42bfe2-8060-411f-b277-06b819874573',
},
passwordPolicies: 'DisablePasswordExpiration',
};
client
.api('/users')
.post(user)
.then(data => console.log(data))
.catch(e => console.error(e))
And I get back this "Request_ResourceNotFound" error
GraphError {
statusCode: 404,
code: 'Request_ResourceNotFound',
message:
'Resource \'User_30140fa1-ae7e-40b7-ad5a-ef4d0b4cd4dc\' does not exist or one of its queried reference-property objects are not present.',
requestId: 'fbf4c987-0383-472a-bc22-c94f98710344',
date: 2020-05-18T13:19:14.000Z,
body:
'{"code":"Request_ResourceNotFound","message":"Resource \'User_30140fa1-ae7e-40b7-ad5a-ef4d0b4cd4dc\' does not exist or one of its queried reference-property objects are not present.","innerError":{"request-id":"fbf4c987-0383-472a-bc22-c94f98710344","date":"2020-05-18T15:19:14"}}' }
The error does not help and I don't know how to continue. The basic configuration looks correct, because I'm able to get all the users and also create a user in the same tenant.
What am I missing? Feels so weird having this type of error by following the official docs. I'm starting to think that I need to use the invitation API, but I just want to create a user and don't go into the full email verification flow. Plus, what I exactly need is in the official docs and I would expect it to work. So maybe there is just something wrong on my side.
Your code works perfectly. I only updated tenant,clientId,clientSecret and MY_ISSUER in your code. Here is the whole code I ran.
const { AuthenticationContext } = require('adal-node');
class AuthProvider {
async getAccessToken() {
return new Promise((resolve, reject) => {
const tenant = '6b72a356-867d-4c35-bde6-959d99388ca8';
const authority = `https://login.microsoftonline.com/${tenant}`;
const authenticationContext = new AuthenticationContext(authority);
const resource = 'https://graph.microsoft.com';
const clientId = '270408b5-85a6-4e99-861e-7634853a5827';
const clientSecret = 'VYD_F_Rr~eHYqLtTXqa1~1KRS_932yNw35';
authenticationContext.acquireTokenWithClientCredentials(
resource,
clientId,
clientSecret,
(err, tokenResponse) => {
if (err) {
console.error('error!', err);
return reject(err);
}
return resolve(tokenResponse.accessToken);
},
);
});
}
}
require('isomorphic-fetch'); //needed for server side request with the client
const { Client } = require('#microsoft/microsoft-graph-client');
const options = {
authProvider: new AuthProvider(),
};
const client = Client.initWithMiddleware(options);
const user = {
displayName: 'John Smith',
identities: [
{
signInType: 'emailAddress',
issuer: 'tonyb2ctest.onmicrosoft.com',
issuerAssignedId: 'jsmith4#yahoo.com',
},
],
passwordProfile: {
password: 'df42bfe2-8060-411f-b277-06b819874573',
},
passwordPolicies: 'DisablePasswordExpiration',
};
client
.api('/users')
.post(user)
.then(data => console.log(data))
.catch(e => console.error(e))
The result:
I registered an application under Azure Active Directory and granted Directory.ReadWrite.All permission.

Async Post with "await axios"

in my React-App, I want to send an email with axios and nodemailer to the user after registration. So, when the button "Register" is pushed, it will use the api "/api/form" for sending the data to the server.
My problem is that the data will not be sent to the server in normal using. If I use the developertools with breackpoints for debugging this function, it works! So it can not be a problem with the server side, I think the problem is at the front end, but I donĀ“t see why.
Is it the way I call axios.post?
Here is the code for the submit function (front end):
async onSubmit(e) {
e.preventDefault
var token = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
const { firstName, email, authToken } = this.state;
const form = await axios.post('/api/form', {
firstName,
email,
authToken: token
}, console.log("form"),this.props.history.push(`/login`));
return form;
}
This is the code in index.js (server):
/*Double-Opt-In*/
app.use(express.static('public'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
/*Double-Opt-In*/
app.post('/api/form', (req, res) => {
console.log(req.body);
nodemailer.createTestAccount((err, account) => {
token= req.body.authToken;
link="http://localhost:3000/verify"+"?token="+token;
console.log("createTestAccount");
const htmlEmail = `
<h3>WebFit Registrierung</h3>
`
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: 'email',
pass: 'password'
}
})
let mailOptions = {
from: 'WebFit', // sender address
to: req.body.email, // list of receivers
replyTo: 'app#webfit.app',
subject: 'Welcome to Webfit <3', // Subject line
text: req.body.message, // plain text body
html: htmlEmail // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
// Preview only available when sending through an Ethereal account
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321#example.com>
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});
});
});
const PORT = process.env.PORT || 3001
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
})
/*End Double-Opt-In*/
axios runs fine with async/await, so catch the throw/reject and check if axios or other. Depending on your api you can extract further info like shown:
async function login(token) {
/* post token and return jwt */
try {
const d = await api.post("/login", token);
return res.data["jwt"];
} catch (e) {
if(e.name == 'AxiosError'){
// map axios error to an app-friendly display message
// your api error handling dictates what you pull out,
// expressjs: return res.status(401).send("expired.");
// results in: '401 expired.'
return new Error(`${e.response.status} ${e.response.data}`);
} else {
return new Error(`${e.name} ${e.message}`);
}
}
}
If your tired of handling on every api call, use interceptors which can do the api error 2 local app error mapping service.js wide.

Resources