Music Quiz Discord bot - discord.js

So I am making a bot where it can play music and I wanted to have a Music Quiz command (Music getting play and you need to find the name and/or authors). I wrote the code but it get stuck at What is the number of songs you want the quiz to have?. I can't find the issue (Also I get no error).
Here is the code:
const { MessageEmbed } = require('discord.js');
const ytdl = require('ytdl-core');
const { PREFIX } = require('../../config')
const musictriviajson = require('../../JSON/musictrivia.json')
const db = require('quick.db');
module.exports = {
config: {
name: 'musictrivia',
category: 'music',
aliases: ['musicquiz', 'mt'],
description: "Music Trivia for You",
usage: "[amount of songs]",
accessableby: "everyone"
},
run: async (bot, message, args, ops) => {
let prefix;
let fetched = await db.fetch(`prefix_${message.guild.id}`);
if (fetched === null) {
prefix = PREFIX
} else {
prefix = fetched
}
const noperm = new MessageEmbed()
.setColor("GREEN")
.setDescription("**❌ You do not have permissions to add money!**")
if (!message.member.hasPermission("CONNECT", "SPEAK")) return message.channel.send(noperm)
const serverQueue = ops.queue.get(message.guild.id)
if (serverQueue) return message.channel.send("Cannot Play Music Trivia While Music is Playing!")
const triviaData = {
isTriviaRunning: false,
wasTriviaEndCalled: false,
triviaQueue: [],
triviaScore: new Map()
};
ops.queue2.set(message.guild.id, triviaData)
var { channel } = message.member.voice;
const channeljoin = new MessageEmbed()
.setColor("GREEN")
.setDescription("**Please Join A VC To Play Music Trivia!**")
if (!channel)
return message.channel.send(channeljoin);
if (serverQueue && serverQueue.playing)
return message.channel.send('**A quiz or a song is already running!**');
triviaData.isTriviaRunning = true;
if (!args[0]) return message.channel.send("**What is the number of songs you want the quiz to have?**")
if (args[0] >= 5 && args[0] <= 15) {
var videoDataArray = musictriviajson.songs;
const randomXVideoLinks = getRandom(videoDataArray, args[0]);
const infoEmbed = new MessageEmbed()
.setColor('GREEN')
.setTitle('Starting Music Quiz')
.setDescription(
`Get ready! There are ${args[0]} songs, you have 30 seconds to guess either the singer/band or the name of the song. Good luck!
You can end the trivia at any point by using the end-trivia command`
);
message.channel.send(infoEmbed);
for (let i = 0; i < randomXVideoLinks.length; i++) {
const song = {
url: randomXVideoLinks[i].url,
singer: randomXVideoLinks[i].singer,
title: randomXVideoLinks[i].title,
voiceChannel: channel
};
triviaData.triviaQueue.push(song);
}
const channelInfo = Array.from(
message.member.voice.channel.members.entries()
);
channelInfo.forEach(user => {
if (user[1].user.bot) return;
triviaData.triviaScore.set(user[1].user.username, 0);
});
} else {
return message.channel.send("**Please enter a number between 5 and 15**")
}
playQuizSong(triviaData.triviaQueue, message);
async function playQuizSong(queue, message) {
const queueConstruct = {
textChannel: message.channel,
voiceChannel: channel,
connection: null,
songs: [],
volume: 2,
playing: true,
loop: false
};
ops.queue3.set(message.guild.id, queueConstruct)
try {
const connection = await queue[0].voiceChannel.join();
queueConstruct.connection = connection
const dispatcher = connection
.play(
ytdl(queue[0].url, {
quality: 'highestaudio',
highWaterMark: 1 << 20
})
)
.on('start', function() {
dispatcher.setVolume(queueConstruct.volume);
let songNameFound = false;
let songSingerFound = false;
const filter = m =>
triviaData.triviaScore.has(m.author.username);
const collector = message.channel.createMessageCollector(filter, {
time: 30000
});
collector.on('collect', m => {
if (!triviaData.triviaScore.has(m.author.username))
return;
if (m.content.startsWith(prefix)) return;
if (m.content.toLowerCase() === queue[0].title.toLowerCase()) {
if (songNameFound) return;
songNameFound = true;
if (songNameFound && songSingerFound) {
triviaData.triviaScore.set(
m.author.username,
triviaData.triviaScore.get(m.author.username) +
1
);
m.react('✅');
return collector.stop();
}
triviaData.triviaScore.set(
m.author.username,
triviaData.triviaScore.get(m.author.username) + 1
);
m.react('✅');
}
else if (
m.content.toLowerCase() === queue[0].singer.toLowerCase()
) {
if (songSingerFound) return;
songSingerFound = true;
if (songNameFound && songSingerFound) {
triviaData.triviaScore.set(
m.author.username,
triviaData.triviaScore.get(m.author.username) +
1
);
m.react('✅');
return collector.stop();
}
triviaData.triviaScore.set(
m.author.username,
triviaData.triviaScore.get(m.author.username) + 1
);
m.react('✅');
} else if (
m.content.toLowerCase() ===
queue[0].singer.toLowerCase() +
' ' +
queue[0].title.toLowerCase() ||
m.content.toLowerCase() ===
queue[0].title.toLowerCase() +
' ' +
queue[0].singer.toLowerCase()
) {
if (
(songSingerFound && !songNameFound) ||
(songNameFound && !songSingerFound)
) {
triviaData.triviaScore.set(
m.author.username,
triviaData.triviaScore.get(m.author.username) +
1
);
m.react('✅');
return collector.stop();
}
triviaData.triviaScore.set(
m.author.username,
triviaData.triviaScore.get(m.author.username) + 2
);
m.react('✅');
return collector.stop();
} else {
return m.react('❌');
}
});
collector.on('end', function() {
if (triviaData.wasTriviaEndCalled) {
triviaData.wasTriviaEndCalled = false;
return;
}
const sortedScoreMap = new Map(
[...triviaData.triviaScore.entries()].sort(
(a, b) => b[1] - a[1]
)
);
const song = `${capitalize_Words(
queue[0].singer
)}: ${capitalize_Words(queue[0].title)}`;
const embed = new MessageEmbed()
.setColor('GREEN')
.setTitle(`**The song was - ${song}**`)
.setDescription(
getLeaderBoard(Array.from(sortedScoreMap.entries()))
);
message.channel.send(embed);
queue.shift();
dispatcher.end();
return;
});
})
.on('finish', function() {
if (queue.length >= 1) {
return playQuizSong(queue, message);
} else {
if (triviaData.wasTriviaEndCalled) {
queueConstruct.playing = false;
triviaData.isTriviaRunning = false;
queueConstruct.connection = null;
message.guild.me.voice.channel.leave();
return;
}
const sortedScoreMap = new Map(
[...triviaData.triviaScore.entries()].sort(
(a, b) => b[1] - a[1]
)
);
const embed = new MessageEmbed()
.setColor('GREEN')
.setTitle(`**Music Quiz Results\n\n**`)
.setDescription(
getLeaderBoard(Array.from(sortedScoreMap.entries()))
);
message.channel.send(embed);
queueConstruct.playing = false;
triviaData.isTriviaRunning = false;
triviaData.triviaScore.clear();
queueConstruct.connection = null;
message.guild.me.voice.channel.leave();
return;
}
});
} catch (e) {
console.error(e);
ops.queue.delete(message.guild.id)
await channel.leave();
return message.channel.send("**Something Went Wrong!**");
}
}
function getRandom(arr, n) {
var result = new Array(n),
len = arr.length,
taken = new Array(len);
if (n > len)
throw new RangeError('getRandom: more elements taken than available');
while (n--) {
var x = Math.floor(Math.random() * len);
result[n] = arr[x in taken ? taken[x] : x];
taken[x] = --len in taken ? taken[len] : len;
}
return result;
}
function getLeaderBoard(arr) {
if (!arr) return;
let leaderBoard = '';
leaderBoard = `👑 **${arr[0][0]}:** ${arr[0][1]} points`;
if (arr.length > 1) {
for (let i = 1; i < arr.length; i++) {
leaderBoard =
leaderBoard + `\n\n ${i + 1}: ${arr[i][0]}: ${arr[i][1]} points`;
}
}
return leaderBoard;
}
function capitalize_Words(str) {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
}
};
Thanks in advance!

Related

Memory leak warnings in electron

I'm getting memory leak warning in the console for my Electron app, i don't know what to do to increase limit. It's causing it everytime i run the app.
Does the error is linked to uiohook? Or did i miss something here?
How can i use emitter.setMaxListeners() in my case? I have no clue of how to fix it, and hwo to increase the memory leak.
[3452:1014/104426.056:ERROR:service_worker_storage.cc(1904)] Failed to delete the database: Database IO error
(node:21792) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 terminate-timer listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
(Use `electron --trace-warnings ...` to show where the warning was created)
(node:21792) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 set-activity listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
Electron
const electron = require('electron');
const BrowserWindow = electron.BrowserWindow;
const dialog = electron.dialog;
const desktopCapturer = electron.desktopCapturer;
const idle = electron.powerMonitor;
const remote = electron.remote;
const notification = electron.Notification;
const globalShortcut = electron.globalShortcut;
const screen = electron.screen;
const ipcMain = electron.ipcMain;
const app = electron.app;
const isDev = require('electron-is-dev');
const path = require('path');
const activeWindows = require('electron-active-window');
const activeWindowPage = require('active-win');
const BMParser = require('bookmark-parser');
const axios = require('axios');
const uiohook = require('uiohook-napi');
const { autoUpdater } = require("electron-updater");
const debug = require('debug')('Franz:ipcApi:autoUpdate');
const dns = require("dns");
const activity = { is_mouse: 0, is_keyboard: 0 };
const headers = {
'Content-Type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Origin": "*",
"Accept": "application/json"
}
const sessionUser = null;
let updateInterval = null;
app.disableHardwareAcceleration();
electron.powerSaveBlocker.start('prevent-app-suspension');
//electron.commandLine.appendSwitch ("disable-http-cache");
// Change App Name on Windows
if (process.platform === 'win32')
{
app.setAppUserModelId('Rubii');
}
let apiEndpoint = "http://creaz:81/xorix/api"; // Brian
let frameUrl = 'http://localhost:3000'; // Brian
//if (isDev) { // or if(process.env.NODE_ENV)
// apiEndpoint = "http://creaz:81/xorix/api";
// frameUrl = 'http://localhost:3000';
//}
var internetAvailable = require("internet-available");
let isConnected = false;
let counterInternet = 0;
let allowSendInternetNotification = 1;
async function liveInternetCheck() {
var userSessionCheck = await getSessionUser();
// Most easy way
internetAvailable({
domainName: "rubii.com",
// Provide maximum execution time for the verification
timeout: 10000,
// If it tries 10 times and it fails, then it will throw no internet
retries: 10
}).then(() => {
// Available Internet
isConnected = true;
counterInternet++;
if(counterInternet > 3 && allowSendInternetNotification == 0) {
allowSendInternetNotification = 1;
}
}).catch(() => {
// Not available internet
isConnected = false;
if(isConnected == false && userSessionCheck && allowSendInternetNotification == 1) {
var message = 'Your internet has been disconnected! Please login again';
new notification({ title: 'Ooops', body: message }).show();
// Logout the user in the other end
win.webContents.send("terminate-timer", "hello");
allowSendInternetNotification = 0;
counterInternet = 0;
}
});
}
autoUpdater.on("update-available", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Ok'],
title: 'Update Available',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version download started. The app will be restarted to install the update.'
};
dialog.showMessageBox(dialogOpts);
updateInterval = null;
});
autoUpdater.on("update-downloaded", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Restart'],
title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
};
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
});
});
function checkUpdate() {
updateInterval = setInterval(() => autoUpdater.checkForUpdates(), 600000);
}
let win;
ipcMain.on('close-me', (evt, arg) => {
new notification({ title: 'Ooops', body: 'We hope to see you again!' }).show();
app.quit()
});
function determineScreenShotSize() {
var screenSize = screen.getPrimaryDisplay().workAreaSize
return {
width: screenSize.width,
height: screenSize.height
}
}
async function takeScreenshot() {
var user = await getSessionUser();
var timer = await getSessionTimer();
if (user && timer) {
if (timer.timer == 1) {
//console.log('Gathering screens...');
//console.log(app.getPath('pictures'));
const thumbSize = determineScreenShotSize();
const workaroundTimestamp = Date.now();
const options = {
types: ['screen'],
thumbnailSize: { ...thumbSize, workaroundTimestamp }
};
desktopCapturer.getSources(options).then((sources) => {
console.log('Sources received:' + sources.length);
sources.forEach(function (source) {
const sourceName = source.name.toLowerCase();
//console.log(sourceName);
if (['entire screen', 'screen 1'].includes(sourceName)) {
var the_screenshot = source.thumbnail.toPNG();
var data = {
user_id: user.id,
company_id: timer.company_id,
image: the_screenshot.toString('base64')
}
axios.post(apiEndpoint + "/desktop/save_screenshots", data, {
headers: headers
})
.then((response) => {
// console.log(response);
})
.catch((error) => {
//console.log(error);
})
}
})
}).catch(console.error);
}
}
}
function saveSoftware() {
(async () => {
var options = [];
var software = await activeWindowPage();
var user = await getSessionUser();
var timer = await getSessionTimer();
if (user && timer) {
if (timer.timer == 1) {
software.user = user;
software.timer = timer;
axios.post(apiEndpoint + "/desktop/save_app", software, {
headers: headers
})
.then((response) => {
//console.log(response);
})
.catch((error) => {
//console.log(error);
})
}
}
})();
}
function getSessionUser() {
return win.webContents.executeJavaScript('sessionStorage.getItem("user");', true)
.then(result => {
if (result) {
return JSON.parse(result);
}
});
}
function getSessionTimer() {
return win.webContents.executeJavaScript('sessionStorage.getItem("timer");', true)
.then(result => {
if (result) {
return JSON.parse(result);
}
});
}
async function generateActivity() {
win.webContents.send("set-activity", activity);
// We reset after we send it
activity.is_mouse = activity.is_keyboard = 0;
}
function secondsToHms(d) {
d = Number(d);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
return hDisplay + mDisplay + sDisplay;
}
function createWindow() {
win = new BrowserWindow({
width: 1200,
height: 900,
frame: true,
webPreferences: {
webSecurity: false,
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
backgroundThrottling: false
}
});
//win.loadURL('https://desktop.rubii.com');
win.loadURL(frameUrl, { "extraHeaders": "pragma: no-cache\n" });
// http://localhost:3000
//win.webContents.openDevTools();
//win.removeMenu(); // Brian
// or set the Menu to null
//win.setMenu(null); // Brian
// Reload cache
win.webContents.reloadIgnoringCache();
// Keyboard activity
uiohook.uIOhook.on('keydown', (e) => {
//console.log('Keyboard!')
activity.is_keyboard = 1;
})
// Mouse activity
uiohook.uIOhook.on('mousemove', (e) => {
//console.log('mouse');
activity.is_mouse = 1;
})
// Start listener for keyboard and mouse
uiohook.uIOhook.start();
win.on('close', function () {
win = null;
})
}
app.whenReady().then(createWindow).then(checkUpdate);
app.on('window-all-closed', function () {
app.quit();
});
app.on('activate', function () {
if (win == null) {
createWindow();
}
})
setInterval(takeScreenshot, 10 * 60 * 1000); // 10 minutes
setInterval(saveSoftware, 5 * 1000); // 5 seconds
setInterval(generateActivity, 1 * 1000);
setInterval(function() { liveInternetCheck(); }, 10 * 1000); // 10 seconds
Render
ipcRenderer.on("terminate-timer", function (event, data) {
// Logout if there is no internet connection
handleLogout();
});
// Set activity if there were any keyboard, mouse
ipcRenderer.on("set-activity", function (event, data) {
// If the timer is on
if(timer) {
setActivity(data);
}
});

react-beautiful-dnd: Prevent flicker when drag and drop a lists with API call

I'm using this react-beautiful-dnd library to be able to reorder lists. However, even though I'm able to drag and drop and re-order, there is a flicker when I try to move a card from one list to another list I call API when a card is dragged to the destination list
const onDragEnd = (result: any) => {
if (!result.destination) {
return;
}
const listCopy: any = { ...elements };
const sourceList = listCopy[result.source.droppableId];
const [removedElement, newSourceList] = removeFromList(
sourceList,
result.source.index
);
listCopy[result.source.droppableId] = newSourceList;
const destinationList = listCopy[result.destination.droppableId];
listCopy[result.destination.droppableId] = addToList(
result.destination.droppableId,
destinationList || [],
result.destination.index,
removedElement,
result.source.droppableId
);
setElements(listCopy)};
and in addToList function I am calling API to update order on server
const addToList = (
changedList: string,
list: any[],
index: number,
element: any,
currentListId: string
) => {
let cardOrder;
const result = Array.from(list);
result.splice(index, 0, element);
const cardCurrentIndex = result.findIndex((item) => item.id === element.id);
if (list.length === 0) {
cardOrder = DEFAULT_PIPELINE_ORDER;
} else if (cardCurrentIndex === 0 && result.length !== 0) {
const nextCardOrder = result[1];
cardOrder = nextCardOrder.current_stage_order - STAGE_INCREMENT_AMOUNT;
} else if (cardCurrentIndex === result.length - 1) {
const nextCardOrder = result[result.length - 2];
cardOrder = nextCardOrder.current_stage_order + STAGE_INCREMENT_AMOUNT;
} else if (
Boolean(result[cardCurrentIndex - 1]) &&
Boolean(result[cardCurrentIndex + 1])
) {
cardOrder = Math.round(
(result[cardCurrentIndex - 1].current_stage_order +
result[cardCurrentIndex + 1].current_stage_order) /
2
);
}
let candidatesData: any = elements;
if (candidatesData) {
if (currentListId === changedList) {
candidatesData[changedList as any] = result as unknown as elementsType;
setElements([...candidatesData]);
} else {
candidatesData[currentListId as any] = candidatesData[
currentListId as any
]?.filter((item: any) => item.id !== element.id);
candidatesData[changedList as any] = result as unknown as elementsType;
setElements([...candidatesData]);
console.log("[...candidatesData]", [...candidatesData]);
}
}
const stageId = stagePipeLineLanes?.find(
(item) => item.id.toString() === changedList.toLowerCase()
)?.id;
if (
changedList === "applied" ||
changedList === "sourcing" ||
changedList === "interviewing"
) {
const changedDestination = changedList;
const destinationStages = positionDetails?.candidate_stages.filter(
(item) =>
item.pipeline.toLowerCase() === changedDestination.toLowerCase()
);
const stage = destinationStages.find((item) => item.is_default === true);
mutate(
{
candidateId: element.id.toString(),
data: compressObject({
stage: stage?.id.toString(),
}),
},
{
onSuccess: (response) => {
if (response) {
toast.success(
`Candidate moved to ${capitalizeFirstLetter(
changedDestination
)}`
);
}
},
}
);
} else {
mutate({
candidateId: element.id.toString(),
data: compressObject({
stage: stageId?.toString() || "",
current_stage_order: cardOrder?.toString() || "",
}),
});
}
return result;
};

Need helping know exactly what redux-toolkit is doing in the reducer method

I am currently creating a cart for a website that has multiple parts to it, this is what it looks like:
cart: {
dozenBoxes: [{dozen: 10.50, boxes:[[]]}, {dozen: 2.16, boxes:[[]]}],
dozenableDonuts: [{dozen: 10.50, donuts: []}, {dozen: 2.16, donuts: []}],
specialDonuts: []
}
The first route I took when creating this cart was redux-toolkit. I quickly realized that I didn't fully understand how redux worked because when trying to manipulate the nested parts of the cart. I was able to somewhat figure it out using the spread operator, but that only got me so far.
Here is what my cart reducer looked like:
const cartSlice2 = createSlice({
name: "cart2",
initialState,
reducers: {
addDonut(state, action) {
let { dozenableDonuts, specialDonuts, dozenBoxes } = state;
const { item, type } = action.payload;
console.log(current(dozenableDonuts));
if (type === "dozenable") {
let { dozenableDonutsNew, index } = addDonutToCart(
[...dozenableDonuts],
item
);
console.log(dozenableDonutsNew);
if (dozenableDonutsNew[index].amount >= 12) {
let { dozenBoxesNew, dozenableDonutsFinal } = createDozenBoxes(
[...dozenBoxes],
{ ...dozenableDonutsNew[index] }
);
state.dozenBoxes = dozenBoxesNew;
state.dozenableDonuts[index] = dozenableDonutsFinal;
} else {
state.dozenableDonuts = dozenableDonutsNew;
}
} else if (type === "special") {
specialDonuts = addSpecialToCart([...state.specialDonuts], item);
}
console.log(current(state));
},
},
});
I was able to get into the "createDozenBoxes" method but was not able to update the state correctly after, I also got the error: "TypeError: Cannot perform 'IsArray' on a proxy that has been revoked reduxtoolkit" where I dispatched the action.
I have tried to look up how to deal with nested state with redux, but I haven't found anything. How do you deal with nested state while using redux?
Methods:
export function addDonutToCart(dozenableDonuts, donut) {
const { name, extras, pricePer, amount, dozen } = donut;
const newDonut = {
name,
extras,
pricePer,
amount,
totalDonutPrice: getTotaldonutPrice(amount, pricePer),
dozen,
};
let index = 0;
//Checking if this donut's dozen group already exists
const dozenIndex = dozenableDonuts.findIndex(
(donutInfo) => donutInfo.dozen === dozen
);
if (dozenIndex !== -1) {
if (amount > 12) {
index = dozenableDonuts.length;
} else {
index = dozenIndex;
}
console.log(`Adding to $${dozen} Dozen Group!`);
let { donuts } = dozenableDonuts[dozenIndex];
const donutItemIndex = donuts.findIndex(
(donut) => donut.name === name && compareObjects(donut.extras, extras)
);
if (donutItemIndex === -1) {
console.log("Adding New donut!");
donuts.push(newDonut);
dozenableDonuts[dozenIndex].amount += amount;
} else {
console.log("Found donut, Adding to Amount!");
donuts[donutItemIndex].amount += newDonut.amount;
donuts[donutItemIndex].totalDonutPrice += newDonut.totalDonutPrice;
dozenableDonuts[dozenIndex].amount += amount;
}
//Update the given dozenableDonuts array to have the updated donuts
dozenableDonuts[dozenIndex].donuts = donuts;
} else {
console.log("Added NEW Dozen Group!");
dozenableDonuts.push({ dozen, donuts: [newDonut], amount });
}
// console.log(`Dozenable donuts`);
// console.log(dozenableDonuts);
return { dozenableDonutsNew: dozenableDonuts, index };
}
export function createDozenBoxes(dozenBoxes, dozenableDonuts) {
let { dozen, donuts, amount } = dozenableDonuts;
const numBoxes = Math.floor(amount / 12);
let newDozenBoxes;
const dozenIndex = dozenBoxes.findIndex((dozenGroup) => dozenGroup === dozen);
if (dozenIndex !== -1) {
console.log(`Found the $${dozen} Category!`);
newDozenBoxes = dozenBoxes[dozenIndex].boxes;
} else {
console.log("Created new Dozen Category!");
dozenBoxes.push({ dozen, boxes: [] });
newDozenBoxes = [[]];
}
let amountTillFull = 12;
let currBox = 0;
let newDonuts = donuts
.map((donut) => {
if (currBox < numBoxes) {
let { amount } = donut;
if (amountTillFull > amount) {
newDozenBoxes[currBox].push(donut);
amountTillFull -= amount;
donut.amount = 0;
} else if (amountTillFull === amount) {
newDozenBoxes[currBox].push(donut);
amountTillFull = 12;
currBox++;
donut.amount = 0;
} else if (amountTillFull < amount) {
console.log("AmountTillFull is less than amount!");
let remainingDonuts = amount - amountTillFull;
newDozenBoxes[currBox].push({ ...donut, amount: amountTillFull });
amountTillFull = 12;
currBox++;
const dozensToMake = Math.floor(remainingDonuts / 12);
if (currBox < numBoxes) {
if (dozensToMake === 0) {
newDozenBoxes[currBox].push({
...donut,
amount: remainingDonuts,
});
amountTillFull -= remainingDonuts;
donut.amount = 0;
} else {
let newDonut = { ...donut, amount: 12 };
for (let i = 0; i < dozensToMake; i++) {
newDozenBoxes.push(newDonut);
remainingDonuts - 12;
currBox++;
}
if (currBox < numBoxes) {
newDozenBoxes[currBox].push({
...donut,
amount: remainingDonuts,
});
amountTillFull -= remainingDonuts;
donut.amount = 0;
} else {
donut.amount = remainingDonuts;
}
}
}
}
}
return donut;
})
.filter((donut) => donut.amount !== 0);
dozenBoxes.boxes = newDozenBoxes;
return { dozenBoxesNew: dozenBoxes, dozenableDonutsFinal: newDonuts };
}

How to take multiple input one by one in - discord.js

How do I take input from user multiple times, store it, and then send an embed with the inputs?
User types command ?start
Bot replies "Hi type your name here"
User types a name, then it is stored in a variable
Bot asks again "Type your favourite game now"
User types games, it is again stored in a variable
Then the variables are taken and then made into an embed
const embed = new Discord.MessageEmbed()
.setTitle("Hobbies")
.setThumbnail(messsage.author.user.displayAvatarURL())
.addDescription("<name>")
.addDescription("<game>")
.setTimestamp();
message.channel.send(embed);
to solve that i created little "Scripts", just predefined Routines for each state of the command
script.js
class Script {
constructor (user, options, callback) {
if (!user.send) {
throw "Invalid Userhandle";
}
this.user = user;
this.options = options;
this.state = 0;
this.callback = callback;
this.responses = [];
if (!!this.options.greeting) {
this.user.send(this.options.greeting)
.then()
.catch(() => console.log(JSON.stringify(this.options.greeting)));
}
};
interpretMessage(message) {
if (!this.options.validator[this.state] || typeof this.options.validator[this.state] !== 'function') {
if (!!this.callback) {
this.callback(this.user, this.responses, false);
return;
} else {
throw "Invalid User Gatherer Object";
}
}
const [msg, steps] = this.options.validator[this.state](message, this.responses);
this.user.send(msg)
.then()
.catch(() => console.error(msg));
if (steps > 0 || steps < 0) {
if (!!this.responses && !!this.responses[this.state]) {
this.responses[this.state] = message;
} else {
this.responses.push(message);
}
this.state += steps;
}
if (this.state >= this.options.validator.length) {
this.callback(this.user, this.responses, false);
}
};
};
module.exports = Script;
I use this Method only in private Messages, that's the reason for my naming:
msg_script.js
const Script = require('./classes/script');
let privateInfoGatherer = {};
let privateInfoGathererCallback = {};
function deletePrivateInfoGatherer(usr, out) {
if (!usr || !usr.id) {
return;
}
privateInfoGathererCallback[usr.id](usr, out);
delete privateInfoGatherer[usr.id];
delete privateInfoGathererCallback[usr.id];
};
function PrivateInfoGatherer (usr, opts, callback) {
if (!usr || !usr.id || !opts || !callback) {
return;
}
privateInfoGatherer[usr.id] = new Script(usr, opts, deletePrivateInfoGatherer);
privateInfoGathererCallback[usr.id] = callback;
};
function checkPrivateMessage(msg, args) {
if (!msg || !msg.author || !privateInfoGatherer[msg.author.id] || msg.guild) {
return;
}
privateInfoGatherer[msg.author.id].interpretMessage(msg.content);
};
module.exports = {
provide: {
PrivateInfoGatherer: PrivateInfoGatherer,
},
events: {
message: checkPrivateMessage,
}
};
my final usage looked something like this:
const ressource = require('./classes/ressource');
function interpretAuth(msg, args, provider) {
const usr = msg.author;
const stage_1 = (msg) => {
let steps = msg.match("^([A-Za-z0-9_ ]{4,32})$") ? 1 : 0;
let ret;
if (msg === 'abort') {
steps = 100; // will result in ending the script
} else {
ret = steps === 1 ? 'And now your Password' : 'Gimme your username';
}
return [ret, steps];
};
const stage_2 = (msg) => {
let steps = msg.match("^([A-Za-z0-9\\!\\#\\#\\%\\&\\_\\(\\)\\*\\-\\$\\^\\[\\]]+)$") ? 1 : 0;
let ret;
if (msg === 'abort') {
steps = 100;
} else {
ret = steps === 1 ? 'I will check the Auth' : 'Your Password man...';
}
return [ret, steps];
};
const options = {
greeting: 'Ok for Authrole i need your login, so first your username pls',
validator: [
stage_1,
stage_2,
]
};
const callback = (usr, out) => {
const [username, password] = out;
// Now we have all, do what ever you want with it.
};
provider.PrivateInfoGatherer(usr, options, callback);
};

Message when collection ends

I'm trying to make a trivia command for my bot and I want to make it so that it sends a message after the amount of time for the collection it says "Times up".
This is what I have written so far:
const Discord = require("discord.js")
exports.run = async(client, message, args) => {
const collector = new Discord.MessageCollector(message.channel, m => m.author.id === message.author.id, {
time: 10000
});
number = 1;
var random = Math.floor(Math.random() * (number - 1 + 1)) + 1;
switch (random) {
case 1:
{
message.channel.send("Case 1");
collector.on('collect', message => {
if (message.content == "1") {
return message.channel.send("Correct!");
} else {
message.channel.send("wrong!");
}
});
collector.on('end', message => {
message.channel.send("times up!")
});
}
}
};
When I do this it says send of undefined for the end event.
I've also tried this below, but it does nothing:
const Discord = require("discord.js")
exports.run = async(client, message, args) => {
const collector = new Discord.MessageCollector(message.channel, m => m.author.id === message.author.id, {
time: 10000
});
number = 1;
var random = Math.floor(Math.random() * (number - 1 + 1)) + 1;
switch (random) {
case 1:
{
message.channel.send("Case 1");
collector.on('collect', message => {
if (message.content == "1") {
return message.channel.send("correct!");
} else {
message.channel.send("wrong!");
}
});
collector.stop('end', message => {
message.channel.send("times up!");
});
}
}
};
The last thing I tried was this, but I got .stop of undefined:
const Discord = require("discord.js")
exports.run = async(client, message, args) => {
const collector = new Discord.MessageCollector(message.channel, m => m.author.id === message.author.id, {
time: 10000
});
number = 1;
var random = Math.floor(Math.random() * (number - 1 + 1)) + 1;
switch (random) {
case 1:
{
message.channel.send("Case 1");
collector.on('collect', message => {
if (message.content == "1") {
return message.channel.send("correct!");
} else {
message.channel.send("wrong!");
}
}).stop(["times up"]);
}
}
};
Also, how could I make the collection stop after the "Correct!" spot?
Try using:
collector.on('end', (collected, reason) => {
message.channel.send("times up!")
});
Like in the docs: https://discord.js.org/#/docs/main/stable/class/MessageCollector?scrollTo=e-end

Resources