Using client in other files than main file - javascript

I'm a very new discord.js coder. I have been trying to use this code in a different file, \modules\verifyForm.js, and it always comes up with client is not defined. I've had quite a large look around and it always comes up with something that is too outdated, something very advanced or something that just don't work.
I have a separate main file in \index.js in which this piece of code works. Client is defined in that file or course, but because you can't have two instances I can't re-define it. Am I just being dumb or is there a better way to do this. Would a collection or using exports help?
const { ActionRowBuilder, Events, InteractionType, ModalBuilder, TextInputBuilder, TextInputStyle, } = require('discord.js');
client.on(Events.InteractionCreate, async (interaction) => {
if (interaction.isButton()) {
if (interaction.customId === 'verification-button') {
const modal = new ModalBuilder()
.setCustomId('verification-modal')
.setTitle('Verify yourself')
.addComponents([
new ActionRowBuilder().addComponents(
new TextInputBuilder()
.setCustomId('verification-input')
.setLabel('Answer')
.setStyle(TextInputStyle.Short)
.setMinLength(0)
.setMaxLength(512)
.setPlaceholder('ABCDEF')
.setRequired(true),
),
]);
await interaction.showModal(modal);
}
}
if (interaction.type === InteractionType.ModalSubmit) {
if (interaction.customId === 'verification-modal') {
const response =
interaction.fields.getTextInputValue('verification-input');
interaction.channel(`Yay, your answer is submitted: "${response}"`);
}
}
});
I do have a separate embed with the button attached.
If you do have a way to get around using client or if you have a way to fix the error, thanks.

make the client a global variable so you can use it everywhere, basically global.client = new Client()

Related

Quick.db, SQLite database file wiping on Bot reboot. Discord.js

I'm trying to save a value of the server being "Down" or "Up", it seems to be working fine, however, when I clear the console, then run the bot again, it looks to have reset the database fully, is there a way to make the database, work like a normal database would? (Save after restart)
I'm having a check to see if the server is up, then don't allow it to run the command and say it's already online.
I wasn't like this before, and I haven't used quick.db for a while, so sorry if I missed anything.
Code:
// Main requirements
const { ROLE_SSUPIN, CHANNEL_SSU, CHANNEL_ROLESEL, BOT_PREFIX } = require('../../config.json')
const commandName = 'ssu'
// Optional Requirements
const { MessageEmbed } = require('discord.js')
const { QuickDB } = require('quick.db');
const db = new QuickDB();
// Main Code
module.exports = async client => {
client.on('messageCreate', async message => {
if (message.author.bot) return;
if (!message.content.toLowerCase().startsWith(BOT_PREFIX)) return;
const command = message.content.split(' ')
const args = message.content.substring(1).split(' ')
if (command.toString().toLowerCase().replace(BOT_PREFIX, '').startsWith(commandName)) {
const ssuStatus = await db.get("ssu.status")
await db.set("ssu.status", "down");
console.log(ssuStatus)
if (!message.member.roles.cache.get('998320362234323026')) return message.reply("Only staff with `SSU Permissions` can use this command!")//.then(m => {setTimeout( function() { m.delete(), message.delete() }, 10000)});
if (!message.channel.id == CHANNEL_SSU) return message.reply(`Please use this command in <#${CHANNEL_SSU}>.`)
if (ssuStatus == 'up') return message.reply(`Server Status is already set to Online. Say \`${BOT_PREFIX}Server Status Set Offline\` if you believe this is a mistake.`)
message.channel.send(`
Start up done.
`)
.then(await db.set("ssu.status", "up"))
}
})
}
I had "await db.set("ssu.status", "down");" in the start of each function, so it was reseting it back to "Down", I didn't mean for it do that, if you have the same issue, make sure that you don't have anything that sets the database value in the start, as it might be the reason it's getting reset and you think it's wiping.

How to add buttons to embed pages discord.js

I've been trying to add buttons to my slash command to make embed pages. All the info I've been able to find has either just been on buttons (not buttons + slash commands) or needs to be done within the index file and not done with a command handler. I've tried adding an await to the interaction.reply but it sends an error that it needs to be within an async function. I'm not entirely sure how async/await works so I couldn't work much more on that if that would be the proper way to solve my issue. How would I collect the button interaction within a command handled file to edit the embeds on button click? This is the guide I used to create the initial command handler.
Here's my current info.js file.
const { SlashCommandBuilder } = require("#discordjs/builders");
const Discord = require("discord.js");
const info = require("./info.json");
module.exports = {
data: new SlashCommandBuilder()
.setName("cinfo")
.setDescription("Shows AniGame card info")
.addStringOption(option =>
option
.setName("name")
.setDescription("Enter the name of a card")
.setRequired(false)
),
async execute(interaction) {
const msg = interaction.options.getString("name").toLowerCase();
function cinfo(
name,
info,
stats,
talent,
image,
sr1,
sr2,
sr3,
srt,
ur1,
ur2,
ur3,
urt
) {
const base = new Discord.MessageEmbed()
.setTitle(name)
.setColor(0xffd1dc)
.setDescription(info)
.addField("__Card Stats__", stats)
.addField("Talent", talent)
.setImage(image);
const sr = new Discord.MessageEmbed()
.setTitle(name + " | Level 50")
.setColor(0xffd1dc)
.addField("__SR Evo 1__", sr1, true)
.addField("__SR Evo 2__", sr2, true)
.addField("__SR Evo 3__", sr3, true)
.addField("Talent", srt)
.setImage(image);
const ur = new Discord.MessageEmbed()
.setTitle(name + " | Level 60")
.setColor(0xffd1dc)
.addField("__UR Evo 1__", ur1, true)
.addField("__UR Evo 2__", ur2, true)
.addField("__UR Evo 3__", ur3, true)
.addField("Talent", urt)
.setImage(image);
const row = new Discord.MessageActionRow().addComponents(
new Discord.MessageButton()
.setCustomId("backward")
.setStyle("PRIMARY")
.setEmoji("⬅️"),
new Discord.MessageButton()
.setCustomId("forward")
.setStyle("PRIMARY")
.setEmoji("➡️"),
new Discord.MessageButton()
.setCustomId("delete")
.setStyle("DANGER")
.setEmoji("🗑️")
);
const pages = [base, sr, ur];
interaction.reply({ embeds: [base], components: [row] });
// await interaction.editReply()
}
// location 1
if (
msg === "itaru hashida" ||
msg === "itaru" ||
msg === "hashida"
) {
cinfo(
info.Itaru_Hashida[0],
info.Itaru_Hashida[1],
info.Itaru_Hashida[2],
info.Itaru_Hashida[3],
info.Itaru_Hashida[4],
info.Itaru_Hashida[5],
info.Itaru_Hashida[6],
info.Itaru_Hashida[7],
info.Itaru_Hashida[8],
info.Itaru_Hashida[9],
info.Itaru_Hashida[10],
info.Itaru_Hashida[11],
info.Itaru_Hashida[12]
);
}
}
};
There is more than one way to do this.
You can use the interactionCreate event. Whenever the event is emitted, you can use <interaction>.isButton() to check if the interaction is from a button. If so, you can edit the <interaction>.message with the <interaction>.message.edit method.
You can also use an InteractionCollector (How to use | Example).
Here are some solutions I found for your question:
Solution 1: Package
I have created a package called discord.js-util that does various things like create embed pages. You could install it or just copy the source code here.
Solution 2: Create your own
As #Qreepex said you can create your own by using a interactionCollector and then using the customId to check if it should to back or forward.

Discord.js - Adding queue function to music system

Yes, I know there are a lot of threads on here regarding this topic. HOWEVER; I've found that in most cases, it is kind of dependant on what your music code looks like. Therefore, I decided to not mess too much around and potentially break my code and clutter it with stuff I won't need.
So here I go.
Below is the code I have in my play.js file. Most of it I got through a guide I found just to get me going then I tweaked it a bit to be more suitable for my use.
const discord = require('discord.js');
//Setting up constants
const ytdl = require("ytdl-core");
const ytSearch = require("yt-search");
const voiceChannel = msg.member.voice.channel;
// Check if user is in voiceChannel
if (!voiceChannel) return msg.channel.send(errorVoiceEmbed);
// Check if we have the correct permissions
const permissions = voiceChannel.permissionsFor(msg.client.user);
if (!permissions.has("CONNECT")) return msg.channel.send(permsEmbed);
if (!permissions.has("SPEAK")) return msg.channel.send(permsEmbed);
// Check if a second argument has been passed
if (!args.length) return msg.channel.send(playEmbed);
// Validating the passed URL
const validURL = (str) => {
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
if (!regex.test(str)){
return false;
} else {
return true;
}
}
// If we have a valid URL, load it and play the audio
if(validURL (args[0])){
const connection = await voiceChannel.join();
const stream = ytdl(args[0], {filter: 'audioonly'});
connection.play(stream, {seek: 0, volume: 1})
// Leave when done
.on('finish', () => {
voiceChannel.leave();
msg.channel.send(completedEmbed);
});
await msg.reply(playingEmbed);
return
}
const connection = await voiceChannel.join();
// If a user enters a search query instead of a link, Search YouTube and play a result.
const videoFinder = async (query) => {
const videoResult = await ytSearch(query);
return (videoResult.videos.length > 1) ? videoResult.videos[0] : null;
}
const video = await videoFinder(args.join(' '));
if (video) {
const stream = ytdl(video.url, {filter: 'audioonly'});
connection.play(stream, {seek: 0, volume: 1})
.on('finish', () => {
voiceChannel.leave();
msg.channel.send(completedEmbed);
});
await msg.reply (playingEmbed);
} else {
msg.channel.send(noResultsEmbed);
}
So - How would I go about adding a proper queue to this? I'm looking for a separate queue command that ties in perfectly with the play command. Therefore - I'm gonna be using two different files that would need to communicate through a songlist of some sort. How this would be done tho, I'm unsure. I looked into just using arrays for this but didn't manage to get that working.
And before you ask - Those embeds that are used in those msg.channel.send statements are embeds configured earlier up in the file. I didn't include these in here but they're there.
PLEASE NOTE:
I'm not looking for a complete solution. I just want some tips and hints as to how I can solve this in a simple and effective way without having to clutter up the code I already have.
That being said - Just on it's own, the code for the play command works perfectly . It plays either the requested song from the link provided or a song from the search query. But when a new song is requested, the old one just stops and the new one plays. You all know how this should go. If no song is playing, play it. If a song is played, add the requested song to the queue and play that once the previous song is done etc etc.

How to give an argument to command "explorer.newFile" in Visial Studio Code extension development

How to give an argument to command explorer.newFile in Visual Studio Code extension development?
I just want to add create a file with certain name in explorer view and then open it and insert a snippet, these operations will be realized in a function .Help ^_^
I could certainly be wrong but I am not sure explorer.newFile will take an argument.
Nevertheless, this function will do what you want: create a file, open it, and insert an existing snippet:
async function createFileOpen() {
const we = new vscode.WorkspaceEdit();
const thisWorkspace = await vscode.workspace.workspaceFolders[0].uri.toString();
// if you want it to be in some folder under the workspaceFolder: append a folder name
// const uriBase = `${thisWorkspace}/folderName`;
// let newUri1 = vscode.Uri.parse(`${uriBase}/index.js`);
// create a Uri for a file to be created
const newUri = await vscode.Uri.parse(`${ thisWorkspace }\\myTestIndex.js`);
// create an edit that will create a file
await we.createFile(newUri, { ignoreIfExists: false, overwrite: true });
await vscode.workspace.applyEdit(we); // actually apply the edit: in this case file creation
await vscode.workspace.openTextDocument(newUri).then(
async document => {
await vscode.window.showTextDocument(document);
// if you are using a predefined snippet
await vscode.commands.executeCommand('editor.action.insertSnippet', { 'name': 'My Custom Snippet Label Here'});
});
}

How do i optimise multiple require() call?

I'm making a bot for the mattermost server of my company (like a discord bot), and for my bot commands, I created one file per command.
The idea is that to send a command, the user must send a message like "!giveChannelPerms arg1 arg 2 ...". The bot will parse the message to identify the command (in this case !giveChannelPerms) and execute the code related to the command.
The problem is that for each command, I have to require() the file and make an if {} else if {} else if {} ... to find the command, as you can see with the code below.
const giveChannelPerms = require('../cmd/giveChannelPerms');
const removeChannelPerms = require('../cmd/removeChannelPerms');
[...]
if (cmd == "!giveChannelPerms") {
giveChannelPerms.giveChannelPerms(post, args, db, obj);
} else if (cmd == "!removeChannelPerms") {
removeChannelPerms.removeChannelPerms(post, args, db, obj);
}
This code is good if we only have 2 commands for our bot, but the more commands I create, the more require() and if {} else if {} will be big.
Isn't there a more "optimized" way to do what I'm trying to do? I had thought of doing something like C function pointers but I have no idea how to do it.
If you want less require and reduce if elses, I recommend you to create a file importing your commands and returning an associated map
const { giveChannelPerms } = require('../cmd/giveChannelPerms');
const { removeChannelPerms } = require('../cmd/removeChannelPerms');
const cmdMap = new Map();
cmdMap.set('!giveChannelPerms', giveChannelPerms)
cmdMap.set('!removeChannelPerms', removeChannelPerms)
export default cmdMap
Then you will be able to import it only once and use it without conditions in your file :
// Imported multiples functions in one require
const commands = require('../cmd/commands');
// Will execute function associated to cmd string without conditions
commands.get(cmd)(post, args, db, obj);
Borrowing from https://stackoverflow.com/a/38397640/932256 try:
const commandFiles = {
giveChannelPerms: require('../cmd/giveChannelPerms'),
removeChannelPerms: require('../cmd/removeChannelPerms')
};
const commandList = Object.keys(commandFiles);
if (cmd.match(new RegExp('^!(' + commandList.join('|') + ')$'))) {
let baseCommand = cmd.replace('!', '');
commandFiles[baseCommand][baseCommand](post, args, db, obj);
}
Now all you need to do is add your commands to the commandFiles object.
Maybe something like this would work
[...]
require('../cmd/giveChannelPerms').then(res => {
if (res) {
res.giveChannelPerms(post, args, db, obj);
} else {
require('../cmd/removeChannelPerms').then(rslt => {
if (rslt) rslt.removeChannelPerms(post, args, db, obj);
})
}
});
I think you are looking for below two solution, hope this helps
More elegant way to manage your imports -
For this you can create a index file (index.js) which will import all your commands from different file and export all commands from one place which is index.js
Simplify your if else condition - from your code snippet, it seems like you need to evaluate against each command as the code then executed is different for each command. As there is no escape from, switch-case will provide you better code readability than if-else
const Cmds = require('../cmd/index');
// or you use import as below
//const {giveChannelPerms, removeChannelPerms} = require('../cmd/index')
switch(cmd)
case: '!giveChannelPerms'
Cmds.giveChannelPerms.giveChannelPerms(post, args, db, obj);
case: '!removeChannelPerms'
Cmds.removeChannelPerms.removeChannelPerms(post, args, db, obj);
defualt:
// do-somthing
}

Categories