const Discord = require('discord.js');
const client = new Discord.Client();
const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg');
const ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfmpegPath(ffmpegInstaller.path);
const fs = require('fs-extra')
const mergeStream = require('merge-stream');
const config = require('./config.json');
const { getAudioDurationInSeconds } = require('get-audio-duration');
const cp = require('child_process');
const path1 = require('path');
const Enmap = require('enmap');
const UserRecords = require("./models/userrecords.js")
const ServerRecords = require("./models/serverrecords.js")
let prefix = `$`
class Readable extends require('stream').Readable { _read() {} }
let recording = false;
let currently_recording = {};
let mp3Paths = [];
const silence_buffer = new Uint8Array(3840);
const express = require('express')
const app = express()
const port = 3000
const publicIP = require('public-ip')
const { program } = require('commander');
const { path } = require('@ffmpeg-installer/ffmpeg');
const version = '0.0.1'
program.version(version);
let debug = false
let runProd = false
let fqdn = "";
const mongoose = require("mongoose");
const MongoClient = require('mongodb').MongoClient;
require("dotenv").config()
function bufferToStream(buffer) {
let stream = new Readable();
stream.push(buffer);
return stream;
}
client.commands = new Enmap();
client.on('ready', async () => {
console.log(`Logged in as ${client.user.tag}`);
let host = "localhost"
let ip = await publicIP.v4();
let protocol = "http";
if (!runProd) {
host = "localhost"
} else {
host = ip;
}
fqdn = `${protocol}://${host}:${port}`
app.listen(port, host, () => {
console.log(`Listening on port ${port} for ${host} at fqdn ${fqdn}`)
})
});
let randomArr = []
let finalArrWithIds = []
let variable = 0
client.on('message', async message => {
if(message.content === `$record`){
finalArrWithIds = []
let membersToScrape = Array.from(message.member.voice.channel.members.values());
membersToScrape.forEach((member) => {
if(member.id === `740372581118640149`) {
console.log(`botid`);
}
else {
finalArrWithIds.push(member.id)
}
})
const randomNumber = Math.floor(Math.random() * 100)
randomArr = []
randomArr.push(randomNumber)
}
const generateSilentData = async (silentStream, memberID) => {
while(recording) {
if (!currently_recording[memberID]) {
silentStream.push(silence_buffer);
}
await new Promise(r => setTimeout(r, 20));
}
return "done";
}
function generateOutputFile(channelID, memberID) {
const dir = `./recordings/${channelID}/${memberID}`;
fs.ensureDirSync(dir);
const fileName = `${dir}/${randomArr[0]}.mp3`;
console.log(`${fileName} ---------------------------`);
return fs.createWriteStream(fileName);
}
if (!fs.existsSync("public")) {
fs.mkdirSync("public");
}
app.use("/public", express.static("./public"));
if (!message.guild) return;
if (message.content === config.prefix + config.record_command) {
mp3Paths = []
if (recording) {
message.reply("bot is already recording");
return
}
if (message.member.voice.channel) {
recording = true;
const connection = await message.member.voice.channel.join();
const dispatcher = connection.play('./audio.mp3');
connection.on('speaking', (user, speaking) => {
if (speaking.has('SPEAKING')) {
currently_recording[user.id] = true;
} else {
currently_recording[user.id] = false;
}
})
let members = Array.from(message.member.voice.channel.members.values());
members.forEach((member) => {
if (member.id != client.user.id) {
let memberStream = connection.receiver.createStream(member, {mode : 'pcm', end : 'manual'})
let outputFile = generateOutputFile(message.member.voice.channel.id, member.id);
console.log(outputFile, `outputfile here`);
console.log(outputFile.path, `outputfile path here`);
silence_stream = bufferToStream(new Uint8Array(0));
generateSilentData(silence_stream, member.id).then(data => console.log(data));
let combinedStream = mergeStream(silence_stream, memberStream);
ffmpeg(combinedStream)
.inputFormat('s32le')
.audioFrequency(48000)
.audioChannels(2)
.on('error', (error) => {console.log(error)})
.audioCodec('libmp3lame')
.format('mp3')
// .audioFilters('silenceremove=stop_periods=-1:stop_duration=1:stop_threshold=-90dB')
.pipe(outputFile)
}
})
} else {
message.reply('You need to join a voice channel first!');
}
}
if (message.content === config.prefix + config.stop_command) {
let date = new Date();
let dd = String(date.getDate()).padStart(2, '0');
let mm = String(date.getMonth() + 1).padStart(2, '0');
let yyyy = date.getFullYear();
date = mm + '/' + dd + '/' + yyyy;
let currentVoiceChannel = message.member.voice.channel;
if (currentVoiceChannel) {
recording = false;
await currentVoiceChannel.leave();
let mergedOutputFolder = './recordings/' + message.member.voice.channel.id + `/${randomArr[0]}/`;
fs.ensureDirSync(mergedOutputFolder);
let file_name = `${randomArr[0]}` + '.mp3';
let mergedOutputFile = mergedOutputFolder + file_name;
let download_path = message.member.voice.channel.id + `/${randomArr[0]}/` + file_name;
let mixedOutput = new ffmpeg();
mp3Paths.forEach((mp3Path) => {
mixedOutput.addInput(mp3Path);
})
//mixedOutput.complexFilter('amix=inputs=2:duration=longest');
mixedOutput.complexFilter('amix=inputs=' + mp3Paths.length + ':duration=longest');
function saveMp3(mixedData, outputMixed) {
console.log(`${mixedData} MIXED `)
return new Promise((resolve, reject) => {
mixedData.on('error', reject).on('progress',
(progress) => {
console.log('Processing: ' + progress.targetSize + ' KB converted');
}).on('end', () => {
console.log('Processing finished !');
resolve()
}).saveToFile(outputMixed);
console.log(`${outputMixed} IT IS HERE`);
})
}
// mixedOutput.saveToFile(mergedOutputFile);
await saveMp3(mixedOutput, mergedOutputFile);
console.log(`${mixedOutput} IN HEREEEEEEE`);
// We saved the recording, now copy the recording
if (!fs.existsSync(`./public`)) {
fs.mkdirSync(`./public`);
}
let sourceFile = `${__dirname}/recordings/${download_path}`
console.log(`DOWNLOAD PATH HERE ${download_path}`)
const guildName = message.guild.id;
const serveExist = `/public/${guildName}`
if (!fs.existsSync(`.${serveExist}`)) {
fs.mkdirSync(`.${serveExist}`)
}
let destionationFile = `${__dirname}${serveExist}/${file_name}`
let errorThrown = false
try {
fs.copySync(sourceFile, destionationFile);
} catch (err) {
errorThrown = true
await message.channel.send(`Error: ${err.message}`)
}
const usersWithTag = finalArrWithIds.map(user => `\n <@${user}>`);
let timeSpent = await getAudioDurationInSeconds(`public/${guildName}/${file_name}`)
let timesSpentRound = Math.floor(timeSpent)
let finalTimeSpent = timesSpentRound / 60
let finalTimeForReal = Math.floor(finalTimeSpent)
if(!errorThrown){
//--------------------- server recording save START
class GeneralRecords {
constructor(generalLink, date, voice, time) {
this.generalLink = generalLink;
this.date = date;
this.note = `no note`;
this.voice = voice;
this.time = time
}
}
let newGeneralRecordClassObject = new GeneralRecords(`${fqdn}/public/${guildName}/${file_name}`, date, usersWithTag, finalTimeForReal)
let checkingServerRecord = await ServerRecords.exists({userid: `server`})
if(checkingServerRecord === true){
existingServerRecord = await ServerRecords.findOne({userid: `server`})
existingServerRecord.content.push(newGeneralRecordClassObject)
await existingServerRecord.save()
}
if(checkingServerRecord === false){
let serverRecord = new ServerRecords()
serverRecord.userid = `server`
serverRecord.content.push(newGeneralRecordClassObject)
await serverRecord.save()
}
//--------------------- server recording save STOP
}
//--------------------- personal recording section START
for( member of finalArrWithIds) {
let personal_download_path = message.member.voice.channel.id + `/${member}/` + file_name;
let sourceFilePersonal = `${__dirname}/recordings/${personal_download_path}`
let destionationFilePersonal = `${__dirname}${serveExist}/${member}/${file_name}`
await fs.copySync(sourceFilePersonal, destionationFilePersonal);
const user = client.users.cache.get(member);
console.log(user, `user here`);
try {
ffmpeg.setFfmpegPath(`âȘC:/ffmpeg/bin/ffmpeg.exe`)
ffmpeg(`public/${guildName}/${member}/${file_name}`)
.audioFilters('silenceremove=stop_periods=-1:stop_duration=1:stop_threshold=-90dB')
.output(`public/${guildName}/${member}/personal-${file_name}`)
.on(`end`, function () {
console.log(`DONE`);
})
.on(`error`, function (error) {
console.log(`An error occured` + error.message)
})
.run();
}
catch (error) {
console.log(error)
}
// ----------------- SAVING PERSONAL RECORDING TO DATABASE START
class PersonalRecords {
constructor(generalLink, personalLink, date, time) {
this.generalLink = generalLink;
this.personalLink = personalLink;
this.date = date;
this.note = `no note`;
this.time = time;
}
}
let timeSpentPersonal = await getAudioDurationInSeconds(`public/${guildName}/${file_name}`)
let timesSpentRoundPersonal = Math.floor(timeSpentPersonal)
let finalTimeSpentPersonal = timesSpentRoundPersonal / 60
let finalTimeForRealPersonal = Math.floor(finalTimeSpentPersonal)
let newPersonalRecordClassObject = new PersonalRecords(`${fqdn}/public/${guildName}/${file_name}`, `${fqdn}/public/${guildName}/${member}/personal-${file_name}`, date, finalTimeForRealPersonal)
let checkingUserRecord = await UserRecords.exists({userid: member})
if(checkingUserRecord === true){
existingUserRecord = await UserRecords.findOne({userid: member})
existingUserRecord.content.push(newPersonalRecordClassObject)
await existingUserRecord.save()
}
if(checkingUserRecord === false){
let newRecord = new UserRecords()
newRecord.userid = member
newRecord.content.push(newPersonalRecordClassObject)
await newRecord.save()
}
// ----------------- SAVING PERSONAL RECORDING TO DATABASE END
const endPersonalEmbed = new Discord.MessageEmbed().setTitle(`Your performance was amazing ! Review it here :D`)
endPersonalEmbed.setColor('#9400D3')
endPersonalEmbed.setThumbnail(`https://media.discordapp.net/attachments/730811581046325348/745381641324724294/vinyl.png`)
endPersonalEmbed.addField(`đ Date`, `${date}`)
endPersonalEmbed.addField(`â° Time spent by you`, `${finalTimeForRealPersonal} minute(s)`)
endPersonalEmbed.addField(`đ» Download`, `${fqdn}/public/${guildName}/${member}/personal-${file_name}`)
endPersonalEmbed.setFooter(`Use \`$myrecordings\` to get a list of all your recordings !`)
user.send(endPersonalEmbed)
}
// ----------------- personal recording section OVER
const endEmbed = new Discord.MessageEmbed().setTitle(`I will be honest, that recording session was sick !`)
endEmbed.setColor('#9400D3')
endEmbed.addField(`đïž Voices`, usersWithTag)
endEmbed.addField(`â° Time spent`, `${finalTimeForReal} minute(s)`)
endEmbed.addField(`đ» Download`, `${fqdn}/public/${guildName}/${file_name}`)
endEmbed.setThumbnail(`https://media.discordapp.net/attachments/730811581046325348/745370416352067704/microphone.png`)
endEmbed.setFooter(`Check your DMs for a recording of your personal voice during this session.`)
message.channel.send(endEmbed)
} else {
message.reply('You need to join a voice channel first!');
}
}
if (message.content.indexOf(prefix) !== 0) return;
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
const cmd = client.commands.get(command);
if (!cmd) return;
cmd.run(client, message, args);
});
fs.readdir('./commands/', async (err, files) => {
if (err) return console.error;
files.forEach(file => {
if (!file.endsWith('.js')) return;
let props = require(`./commands/${file}`);
let cmdName = file.split('.')[0];
console.log(`Loaded command '${cmdName}'`);
// Register extra Listeners
client.commands.set(cmdName, props);
});
});
async function main() {
program.option('-debug')
program.option('-prod')
program.parse(process.argv)
console.log(program.opts())
if (program.Debug != undefined) {
debug = !debug
}
if (program.Prod != undefined) {
runProd = !runProd
}
if (runProd) {
client.login(process.env.DISCORD_TOKEN_PROD).catch(e => {
console.log("ERROR")
console.log(e)
})
} else {
client.login(process.env.DISCORD_TOKEN_TEST).catch(e => {
console.log("ERROR")
console.log(e)
})
}
}
main()
(note: if the problem only happens with some inputs, include a link to such an input file)
Expected results
This my code to record voice chat in discord.js
This was working completely fine but then suddenly I started getting this error and now it never works normally
Observed results
(node:15136) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'isStream' of undefined
at runFfprobe (C:\Users\user\Desktop\swami1\botf1\node_modules\fluent-ffmpeg\lib\processor.js:25:40)
at FfmpegCommand.proto._prepare (C:\Users\user\Desktop\swami1\botf1\node_modules\fluent-ffmpeg\lib\processor.js:373:9)
at FfmpegCommand.proto.exec.proto.execute.proto.run (C:\Users\user\Desktop\swami1\botf1\node_modules\fluent-ffmpeg\lib\processor.js:431:10)
at FfmpegCommand.proto.saveToFile.proto.save (C:\Users\user\Desktop\swami1\botf1\node_modules\fluent-ffmpeg\lib\recipes.js:28:25)
at C:\Users\user\Desktop\swami1\botf1\index.js:216:20
at new Promise ()
at saveMp3 (C:\Users\user\Desktop\swami1\botf1\index.js:209:20)
at Client. (C:\Users\user\Desktop\swami1\botf1\index.js:221:15)
at runMicrotasks ()
@ayezinzu Too much code! No one will be able to help you if you don't reduce the problem to the minimum needed to reproduce the problem. If you need some space, share a link to a gist or a repository.
Version information
Code to reproduce
(note: if the problem only happens with some inputs, include a link to such an input file)
Expected results
This my code to record voice chat in discord.js This was working completely fine but then suddenly I started getting this error and now it never works normally
Observed results
(node:15136) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'isStream' of undefined at runFfprobe (C:\Users\user\Desktop\swami1\botf1\node_modules\fluent-ffmpeg\lib\processor.js:25:40) at FfmpegCommand.proto._prepare (C:\Users\user\Desktop\swami1\botf1\node_modules\fluent-ffmpeg\lib\processor.js:373:9) at FfmpegCommand.proto.exec.proto.execute.proto.run (C:\Users\user\Desktop\swami1\botf1\node_modules\fluent-ffmpeg\lib\processor.js:431:10) at FfmpegCommand.proto.saveToFile.proto.save (C:\Users\user\Desktop\swami1\botf1\node_modules\fluent-ffmpeg\lib\recipes.js:28:25) at C:\Users\user\Desktop\swami1\botf1\index.js:216:20 at new Promise ()
at saveMp3 (C:\Users\user\Desktop\swami1\botf1\index.js:209:20)
at Client. (C:\Users\user\Desktop\swami1\botf1\index.js:221:15)
at runMicrotasks ()