write to a JSON folder from the following element - javascript

I want to know how to read/write from/to json files.
const Discord = require ('discord.js');
const client = new Discord.Client();
const {prefix, token,} = require('./config.json');
const fs = require ('fs');
client.login(token)
client.on('message', message => {
if(message.content.startsWith(prefix + "TC")) { //TC = team create
var args = message.content.split(' ').join(' ').slice(4);
if(!args) return message.channel.send("No")
var TeamCreate = `{"NameTeam": "${args}", "ManagerTeam": ${message.author.id}}`
fs.writeFile("./team.json", TeamCreate, (x) => {
if (x) console.error(x)
})}});
The json file will display :
{"NameTeam": "teste","ManagerTeam": 481117441955463169}
And I would like that each time we place the order, it gets added to the json file.
Example:
1 first order = {"NameTeam": "teste","ManagerTeam": 481117441955463169}
2 second order = {"NameTeam": "teste","ManagerTeam": 481117441955463169}, {"NameTeam": "teste2","ManagerTeam": 1234567890}

From what I understand, you want to make a json file that contains a list of teams.
The easy way to do that is to read and parse the json, make changes to it, and then stringify the jsonand update the file. Also, making json with strings is really messy and can lead to syntax errors, while in javascript turning js objects into json is as simple as doing JSON.stringify(javascriptObject)
Try something like this:
const Discord = require('discord.js');
const client = new Discord.Client();
const { prefix, token, } = require('./config.json');
const fs = require('fs');
client.login(token)
client.on('message', message => {
if (message.content.startsWith(prefix + "TC")) { //TC = team create
var args = message.content.split(' ').join(' ').slice(4);
if (!args) return message.channel.send("No")
var team = {
NameTeam: args,
ManagerTeam: message.author.id
}
fs.readFile("./team.json", (err, data) => {
if (!err && data) {
var parsedJson;
try {
parsedJson = JSON.parse(data);
//Make sure the parsedJson is an array
if (!(parsedJson instanceof Array)) {
parsedJson = [];
}
}
catch (e) {
console.log("Couldn't parse json.");
parsedJson = [];
}
finally {
//Add the newly created team to parsedJson
parsedJson.push(team);
//Write file, stringifying the json.
fs.writeFile("./team.json", JSON.stringify(parsedJson), (err) => {
if (!err) {
console.log("Successfully created team.");
}
else {
console.log("Error writing to file.")
}
});
}
}
else {
console.log("Error reading json");
}
});
}
});
Hope this helps and good luck.

Related

Why does my program crash when managing this JSON file?

Whenever somebody sends !setmainchannel, my program crashes. I am using Node.js with the package discord.js. This is the only problem I have. I don't and can't understand what's wrong, and I would extremely appreciate it if someone could help me out.
bot.js:
let Discord = require("discord.js");
let client = new Discord.Client();
let fs = require('fs');
let help = require("./helpembed.json");
var jsonRead = function(filePath){
fs.readFile(filePath, 'utf-8', (err, returnJson) => {
if(err){
console.log(err);
}
else{
let ret = JSON.parse(returnJson);
return ret;
}
})
}
var jsonWrite = function(filePath, objIn){
fs.writeFile(filePath, JSON.stringify(objIn), err => {
if(err){
console.log(err);
}
})
}
client.on("message", msg => {
let time = new Date();
let cstTimeStamp = `${time.getMonth() + 1}/${time.getDate()}/${time.getFullYear()} ${time.getHours() + 1}:${time.getMinutes()}:${time.getSeconds()}`
if(msg.content == "!setmainchannel"){
let mainChannel = msg.mentions.channels.first();
if(!mainChannel){
console.log(`${cstTimeStamp} #${msg.author.tag} requested to set a main channel but didn't provide a channel\n`);
msg.channel.send("There's no channel to set the main to");
}
else{
let currentSettings = jsonRead("./main-channel.json");
currentSettings.channel = mainChannel;
jsonWrite("./main-channel.json", currentSettings);
console.log(`${cstTimeStamp} #${msg.author.tag} set the main channel as ${currentSettings.channel}\n`);
msg.channel.send(`Set the main channel as ${currentSettings.channel}`);
}
}
})
client.once('ready', () => {
console.log('Bot is online\n');
});
client.login('Token hidden for safety reasons');
main-channel.json:
{
"channel":null
}
First, your bot does nothing because it only reacts if (msg.content == "!setmainchannel"). If you provide an argument, like a channel (!setmainchannel #ch-name), it won't run as the message's content is not exactly the prefix and the command.
You'll need to fix that first. By removing the prefix and chopping off the arguments, you can get the command itself and check if this exact command is used. (Again, you should not check the whole message.content)
Second, you don't wait for the callback inside readFile to run. It means, when you try to update currentSettings.channel, your jsonRead() function has just started to read the file and the currentSettings is undefined. You won't be able to update its channel property.
I've updated both your jsonWrite and jsonRead functions to return promises and make it easier to use. Check the working code below:
const Discord = require("discord.js");
const fs = require('fs');
const path = require('path');
const client = new Discord.Client();
const prefix = '!';
client.on('message', async (msg) => {
// create an args variable that slices off the prefix and splits it into an array
const args = msg.content.slice(prefix.length).split(/ +/);
// create a command variable by taking the first element in the array
// and removing it from args
const command = args.shift().toLowerCase();
const cstTimeStamp = new Date().toLocaleString();
if (command === 'setmainchannel') {
const mainChannel = msg.mentions.channels.first();
const filePath = path.resolve(__dirname, './main-channel.json');
if (!mainChannel) {
console.log(`${cstTimeStamp} ${msg.author.tag} requested to set a main channel but didn't provide a channel\n`);
return msg.channel.send("There's no channel to set the main to");
}
try {
const currentSettings = await jsonRead(filePath);
currentSettings.channel = mainChannel;
jsonWrite(filePath, currentSettings);
console.log(`${cstTimeStamp} ${msg.author.tag} set the main channel as ${currentSettings.channel}\n`);
msg.channel.send(`Set the main channel as ${currentSettings.channel}`);
} catch (err) {
console.log(err);
}
}
});
client.once('ready', () => {
console.log('Bot is online\n');
});
client.login('Token hidden for safety reasons');
function jsonRead(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf-8', (err, content) => {
if (err) {
reject(err);
} else {
try {
const parsedContent = JSON.parse(content);
resolve(parsedContent);
} catch (err) {
reject(err);
}
}
});
});
}
function jsonWrite(filePath, data) {
return new Promise((resolve, reject) => {
fs.writeFile(filePath, JSON.stringify(data), (err) => {
if (err) {
reject(err);
}
resolve(true);
});
});
}
Alright, I see what's going on here. I made the logic react to ONLY !setmainchannel, whereas I should've done if(msg.content.startsWith("!setmainchannel")!

How to read/write to a JSON file in node.js

I am fairly new to node.js and i am wondering how to (or even if) i can read and write to a JSON file. I am trying to create an accessible punishment history.
Ideally i would want to be able to create something along the lines of this:
{
"punishments": {
"users": {
"<example user who has a punishment history>": {
"punishment-1567346": {
"punishment-id": "1567346",
"punishment-type": "mute",
"punishment-reason": "<reason>"
},
"punishment-1567347": {
"punishment-id": "1567347",
"punishment-type": "ban",
"punishment-reason": "<reason>"
}
}
}
}
}
Then i would have a way to access the formatted punishment history. I genuinely have no clue where to start.
You can use a NodeJS built-in library called fs to do read/write operations.
Step #1 - Import fs
const fs = require('fs');
Step #2 - Read the file
let rawdata = fs.readFileSync('punishmenthistory.json');
let punishments= JSON.parse(rawdata);
console.log(punishments);
Now you can use the punishments variable to check the data inside the JSON File. Also, you can change the data but it only resides inside the variable for now.
Step #3 - Write to the File
let data = JSON.stringify(punishments);
fs.writeFileSync('punishmenthistory.json', data);
Full code:
const fs = require('fs');
let rawdata = fs.readFileSync('punishmenthistory.json');
let punishments= JSON.parse(rawdata);
console.log(punishments);
let data = JSON.stringify(punishments);
fs.writeFileSync('punishmenthistory.json', data);
References:
https://stackabuse.com/reading-and-writing-json-files-with-node-js/
Use NodeJS File System https://nodejs.org/dist/latest-v14.x/docs/api/fs.html.
Here I have used writeFileSync API to write to file and readFileSync to read from file. Also, when writing don't forget to JSON.stringify(data) because you are writing the data to a JSON file.
const fs = require("fs");
const path = require("path");
// Write Data
const data = {
"punishments": {
"users": {
"<example user who has a punishment history>": {
"punishment-1567346": {
"punishment-id": "1567346",
"punishment-type": "mute",
"punishment-reason": "<reason>"
},
"punishment-1567347": {
"punishment-id": "1567347",
"punishment-type": "ban",
"punishment-reason": "<reason>"
}
}
}
}
};
fs.writeFileSync(path.join(__dirname, "outputfilepath", "outputfile.json"), JSON.stringify(data), "utf8");
// Read data
const rData = fs.readFileSync(path.join(__dirname, "outputfilepath", "outputfile.json"), "utf8");
const jsonData = JSON.parse(rData);
Here is the working example,
https://repl.it/repls/OutrageousInbornBruteforceprogramming#index.js
you can do something like this for reading:
const fs = require('fs')
function jsonReader(filePath, cb) {
fs.readFile(filePath, (err, fileData) => {
if (err) {
return cb && cb(err)
}
try {
const object = JSON.parse(fileData)
return cb && cb(null, object)
} catch(err) {
return cb && cb(err)
}
})
}
jsonReader('./customer.json', (err, customer) => {
if (err) {
console.log(err)
return
}
console.log(customer.address) // => "Infinity Loop Drive"
})
and like this for writing:
const fs = require('fs')
const customer = {
name: "Newbie Co.",
order_count: 0,
address: "Po Box City",
}
const jsonString = JSON.stringify(customer)
fs.writeFile('./newCustomer.json', jsonString, err => {
if (err) {
console.log('Error writing file', err)
} else {
console.log('Successfully wrote file')
}
})

Making a Server User ID function | Discord.js

I am trying to get all user's ID and name from a server which I done so by using this:
const list = client.guilds.cache.get("GUILD_ID");
list.members.cache.forEach(member => console.log('Name: ' + member.user.username + ' ID: ' + member.user.id));
But i want to input those member ID's and names into a .json file and I tried doing this via a function:
const Discord = require('discord.js');
const client = new Discord.Client();
const token = 'TOKEN';
const prefix = 'a';
const getuser = require('./GetUserId/getID.json');
const fs = require('fs');
const { readdirSync } = require("fs");
const { join } = require("path");
client.commands = new Discord.Collection();
const commandFiles = readdirSync(join(__dirname, "GetUserId")).filter(file => file.endsWith(".js"));
for (const file of commandFiles) {
const command = require(join(__dirname, "GetUserId", `${file}`));
client.commands.set(command.name, command);
}
client.on('message', message => {
if (message.content === 'getID'){
getuser(message);
function getuser (message) {
const list = client.guilds.cache.get("749337851174322288");
if(!getuser[message.author.id]){
getuser[message.author.id] = {
ID: `${list.members.cache.forEach(member => member.user.id)}`,
Name: `${list.members.cache.forEach(member => member.user.username)}`
}
}
fs.writeFile('./GetUserId/getID.json', JSON.stringify(getuser, null, 2), (err) => {
if (err) console.log(err)
})
}
message.delete()
message.channel.send(`*Done.*`)
}
})
client.login(token);
So I tried this code and this came on the .json file:
{
"709827684888215582": {
"ID": "undefined",
"Name": "undefined"
}
}
How would I make the "ID" display user ID's and display all members username in "Name:" in a server/guild in that .json file?
You're looking for Array.prototype.map(), not Array.prototype.forEach()
forEach() simply executes a function on all elements of an array (or a Collection, in this case). map() creates a new array populated with the results of the function.

Execute block of code only after loop with requests from axios is finished

I have a script that reads an excel file and gets data from a specific column to perform a search on the Google Maps API where I use axios. For each request made, I need to save it in the newFileList variable. After completing all the requests, I must save the contents of this variable in a file. However, whenever I run my code, the file is being saved without the content of the newFileList variable. How do I wait for all requests to finish before being able to save the content in the file?
Note: the reading, writing and requesting data are working. I just need the rescue to happen only after all the loop requests are finished. I tried to solve by placing the loop inside a promisse and at the end of the execution of this loop I used resolve.
const xlsx = require("node-xlsx");
const fs = require("fs");
const coordinate = require("./coordinate");
const resourcePath = `${__dirname}/resources`;
const contentFile = xlsx.parse(`${resourcePath}/file-2.xlsx`)[0].data;
const newFile = [[...contentFile, ...["Latitude", "Longitude"]]];
for (let i = 1; i < contentFile.length; i++) {
const data = contentFile[i];
const address = data[2];
coordinate
.loadCoordinates(address)
.then((response) => {
const { lat, lng } = response.data.results[0].geometry.location;
newFile.push([...data, ...[lat.toString(), lng.toString()]]);
})
.catch((err) => {
console.log(err);
});
}
console.log(newFile);
//The code below should only be executed when the previous loop ends completely
var buffer = xlsx.build([{ name: "mySheetName", data: newFile }]); // Returns a buffer
fs.writeFile(`${resourcePath}/file-3.xlsx`, buffer, function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
The coordinate file:
const axios = require("axios");
module.exports = {
loadCoordinates(address) {
const key = "abc";
return axios
.get(`https://maps.googleapis.com/maps/api/geocode/json`, {
params: {
address,
key,
},
})
},
};
Will using an async IIFE help?
const xlsx = require("node-xlsx");
const fs = require("fs");
const coordinate = require("./coordinate");
const resourcePath = `${__dirname}/resources`;
const contentFile = xlsx.parse(`${resourcePath}/file-2.xlsx`)[0].data;
const newFile = [[...contentFile, ...["Latitude", "Longitude"]]];
(async() => {
try{
for (let i = 1; i < contentFile.length; i++) {
const data = contentFile[i];
const address = data[2];
await coordinate
.loadCoordinates(address)
.then((response) => {
const { lat, lng } = response.data.results[0].geometry.location;
newFile.push([...data, ...[lat.toString(), lng.toString()]]);
})
.catch((err) => {
console.log(err);
});
}
console.log(newFile);
//The code below should only be executed when the previous loop ends completely
var buffer = xlsx.build([{ name: "mySheetName", data: newFile }]); // Returns a buffer
fs.writeFile(`${resourcePath}/file-3.xlsx`, buffer, function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
} catch(e) {
console.log(e)
}
})();
Do note that I added await before coordinate.loadCoordinates, in order to make sure the first axios request is finished before we proceed to the next one.
You need to use Promise.all() to wait until all the promises are resolved. After that execute the writeToFile part. For more info on Promise.all(), you can refer https://www.javascripttutorial.net/es6/javascript-promise-all/
const requestPromiseArray = [];
for (let i = 1; i < contentFile.length; i++) {
const data = contentFile[i];
const address = data[2];
requestPromiseArray.push(coordinate
.loadCoordinates(address))
}
Promise.all(requestPromiseaArray).then(results=>{
// Handle "results" which contains the resolved values.
// Implement logic to write them onto a file
var buffer = xlsx.build([{ name: "mySheetName", data: results }]);
fs.writeFile(`${resourcePath}/file-3.xlsx`, buffer, function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
})

Sending list of images as response using Javascript

I am making an API that gets a list of image names, then it has to download them one by one from S3 bucket and then send them all as a response.
The issue is that my images are being uploaded but it seems that when I put them in a list as base64 and then try to send the list then the list just comes up empty.
const getImagesById = async (req, res) => {
const { id } = req.params;
const imagesSet = new Map();
try {
const documentFromDB = await document.findOne({ id });
documentFromDB.devices.forEach((device) => {
const images = new Set();
device.images.forEach(item => images.add(downloadFromS3(item)))
imagesSet.set(device.name, JSON.stringify(mapToObj(images))) // tried adding just images also but neither works
});
res.status(200).json(JSON.stringify(mapToObj(imagesSet)));
} catch (e) {
console.log(`An error occurred : ${e.message}`);
res.status(500)
.send(e.message);
}
};
function mapToObj(inputMap) {
let obj = {};
inputMap.forEach(function(value, key){
obj[key] = value
});
return obj;
}
And this is how I get images from S3:
const downloadFromS3 = async (imageName) => {
try {
const image = await S3Utils.downloadFile(BUCKET_NAME, imageName);
if (image.stack) {
return null;
}
const imageBase64 = image.Body.toString('base64');
return imageBase64;
} catch (e) {
console.log(`An error occurred while downloading : ${e.message}`);
throw e;
}
};
This is the response I am getting at the moment:
"{\"{ name: 'Martin'}\":\"{\\\"[object Promise]\\\":{}}\"}"
What I am trying to do is get a lits of device names, map them in a Map as key with value as the base64 list of images and then send it all in a response to the UI to show the images with the names.
What am I doing wrong here?
You just need to add await before call the downloadFromS3 function, consequently changing all the above functions.
const getImagesById = async (req, res) => {
const { id } = req.params;
const imagesSet = new Map();
try {
const documentFromDB = await document.findOne({ id });
await Promise.all(documentFromDB.devices.map(async (device) => {
const images = new Set();
await Promise.all(device.images.map(async item => images.add(await downloadFromS3(item))))
imagesSet.set(device.name, JSON.stringify(mapToObj(images))) // tried adding just images also but neither works
}));
res.status(200).json(JSON.stringify(mapToObj(imagesSet)));
} catch (e) {
console.log(`An error occurred : ${e.message}`);
res.status(500)
.send(e.message);
}
};
function mapToObj(inputMap) {
let obj = {};
inputMap.forEach(function(value, key){
obj[key] = value
});
return obj;
}

Categories

Resources