When I execute the command in discord the bot reply's with a button that says "Subscribe!", once you click it, about 3 seconds later it just says "Interaction Failed" with no console error. I have been looking at this for an hour now and trying to figure it out myself, but I've gotten past that point and I need help.
sub-yt.js;
module.exports = {
data: {
name: "sub-yt",
},
async execute(interaction, client) {
await interaction.reply({
content: `https://youtube.com/duanetv`,
});
},
};
interactionCreate.js;
module.exports = {
name: "interactionCreate",
async execute(interaction, client) {
if (interaction.isChatInputCommand()) {
const { commands } = client;
const { commandName } = interaction;
const command = commands.get(commandName);
if (!command) return;
try {
await command.execute(interaction, client);
} catch (error) {
console.error(error);
await interaction.reply({
content: `interactionCreate has failed.`,
ephemeral: true,
});
}
} else if (interaction.isButton()) {
const { buttons } = client;
const { customId } = interaction;
const button = buttons.get(customId);
if (!button) return new Error("Button failed.");
try {
await button.execute(interaction, client);
} catch (err) {
console.error(err);
}
}
},
};
handleComponents.js;
const { readdirSync } = require("fs");
module.exports = (client) => {
client.handleComponent = async () => {
const componentFolders = readdirSync(`./src/components`);
for (const folder of componentFolders) {
const componentFiles = readdirSync(`./src/components/${folder}`).filter(
(file) => file.endsWith(".js")
);
const { buttons } = client;
switch (folder) {
case "buttons":
for (const file of componentFiles) {
const button = require(`../../components/${folder}/${file}`);
buttons.set(button.data.name, button);
}
break;
default:
break;
}
}
};
};
The thing I'm doing here is fetching anime characters from anilist graphql api. The reason I've added a loop is so I could fetch data from a certain character id to a limit. For example 1-100. But I want to respect their API rate limits and so I'd like a way to limit my requests to 1 per second. Hence, I've used setTimeout, but I still got rate-limited from the API and using setInterval only keeps on looping it every 5 seconds. Like the same data gets fetched every 5 seconds.
Is there any way I can make it as I've mentioned?
My code:
const fs = require("fs");
const number = 3;
const axios = require("axios");
async function fetchData() {
for (let i = 1; i <= number; i++) {
const query = axios
.post(
"https://graphql.anilist.co",
{
query: `query character(
$id: Int
$page: Int
$sort: [MediaSort]
$onList: Boolean
$withRoles: Boolean = false
) {
Character(id: $id) {
id
name {
first
middle
last
full
native
userPreferred
alternative
alternativeSpoiler
}
image {
large
}
favourites
isFavourite
isFavouriteBlocked
description
age
gender
bloodType
dateOfBirth {
year
month
day
}
media(page: $page, sort: $sort, onList: $onList) #include(if: $withRoles) {
pageInfo {
total
perPage
currentPage
lastPage
hasNextPage
}
edges {
id
characterRole
voiceActorRoles(sort: [RELEVANCE, ID]) {
roleNotes
voiceActor {
id
name {
userPreferred
}
image {
large
}
language: languageV2
}
}
node {
id
type
isAdult
bannerImage
title {
userPreferred
}
coverImage {
large
}
startDate {
year
}
mediaListEntry {
id
status
}
}
}
}
}
}`,
variables: {
id: i,
withRoles: false,
},
},
{
headers: {
"Content-Type": "application/json",
},
}
)
.then((response) => {
// console.log(response.data.data.Character)
const jsonContent =
JSON.stringify(response.data.data.Character, null, 4) + ", ";
fs.appendFile("./chars.json", jsonContent, function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
})
.catch((error) => console.log(`Code: ${error}`, error));
}
}
fetchData();
Something like that will work for you (Asuming all the rest was ok):
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function fetchData() {
for (let i = 1; i <= number; i++) {
// So in case your function is called in loop - request will be delayed
await delay(5000); // TODO: Change to whatever you need
const query = axios.post(
"https://graphql.anilist.co",
{
query: someQuery, // TODO: Set your query here
variables: { id: i, withRoles: false }
},
{
headers: { "Content-Type": "application/json" }
}
);
try {
const response = await query;
const jsonContent = JSON.stringify(response.data.data.Character, null, 4) + ", ";
fs.appendFile("./chars.json", jsonContent, function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
} catch (e) {
console.log(`Code: ${e}`, e);
}
}
}
When I make a request using postman to the server, I don't get the "Cannot set headers after they are sent to the client. But when I integrate with react.js, i keep getting the error. I would for someone to help look for the error. Thanks. Thanks in advance."
Cart.js (client)
import React, { Fragment, useEffect, useState } from 'react'
import { Redirect } from 'react-router-dom';
import Header from '../../components/Header/Header'
import './Cart.css'
import axios from 'axios'
import Loader from '../../components/Loader/Loader';
import {toast} from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
import CartProduct from '../../components/CartProduct/CartProduct';
import { Link } from 'react-router-dom';
import OrderDetails from '../../components/CartPricing/CartPricing';
import Empty from '../../components/Empty/Empty';
toast.configure();
function Cart({title, clientRootUrl, apiRootUrl, loggedInStatus, token, errorMessage, cartNum,decreaseCartNum, requireAuth}) {
document.title = `Cart - ${title}`;
/**
* To 2 d.p.
* Text: parseFloat("123.456").toFixed(2)
* Number: num.toFixed(2);
*/
const [isLoading, setIsLoading] = useState(true);
const [cartProducts, setCartProducts] = useState([]);
const [allowed, setAllowed] = useState(false);
const [subTotals, setSubTotals] = useState(0);
const [delivery, setDelivery] = useState(0); // use request to get details
const [total, setTotal] = useState(0);
const [all,setAll] = useState(false);
/** Pass the ffg data to App.js
* cart
* subtotal
* delivery
* total
*/
useEffect(() => {
// setIsLoading(true);
axios.post(`${apiRootUrl}miscellaneous/fee`,
{
subtotal: subTotals
},
{
headers: {
Authorization: `Bearer ${token}`
}
})
.then(({data})=>{
// setIsLoading(false);
setDelivery(data.cost);
})
.catch(err=>{
// setIsLoading(false);
console.log(err)
// toast.error(errorMessage, {
// position: toast.POSITION.BOTTOM_RIGHT
// })
})
}, [total])
useEffect(() => {
setTotal(subTotals + delivery);
}, [delivery])
useEffect(()=>{
axios.get(`${apiRootUrl}cart/`, {
headers: {
Authorization: `Bearer ${token}`
}
})
.then(({data})=>{
let cartItems = data;
// setCartProducts(data);
// console.log(cartItems)
if(cartItems.length < 1) {
setIsLoading(false);
} else {
cartItems.map(({id,productId,quantity})=>{
// cart: id, productId // product details
axios.get(`${apiRootUrl}product/${productId}`)
.then(({data})=>{
setIsLoading(false);
setAllowed(true); // show details
let product = data;
// no storing the previous one being asynchronous, so we have to use the previous in the argument
setCartProducts(prevCartProducts => [ ... prevCartProducts, {
cartId:id,
quantity:quantity,
id:product.id,
categoryId: product.categoryId,
name: product.name,
description: product.description,
image: product.image,
price: product.price
}]);
})
.catch(err=>{
setIsLoading(false);
console.log(err)
// toast.error(errorMessage, {
// position: toast.POSITION.BOTTOM_RIGHT
// })
})
})
}
})
.catch(err=>{
setIsLoading(false);
// toast.error(errorMessage, {
// position: toast.POSITION.BOTTOM_RIGHT
// })
console.log(err)
})
},[apiRootUrl])
function delCartItem(cartId) {
// delete from DB
setIsLoading(true);
axios.delete(`${apiRootUrl}cart/${cartId}`,{
headers: {
Authorization: `Bearer ${token}`
}
})
.then(({data})=>{
setIsLoading(false);
if(data.error === 0) {
toast.success(data.message, {
position: toast.POSITION.BOTTOM_RIGHT
})
setCartProducts([...cartProducts.filter(cartProduct=>cartProduct.cartId !== cartId)]);
// reduce cartNum by 1
decreaseCartNum();
} else {
toast.error(errorMessage, {
position: toast.POSITION.BOTTOM_RIGHT
})
}
if(cartProducts.length-1 < 1) {
setAllowed(false);
} else {
// as products are being deleted , RECALCULATE VALUES
// total prices will change authomatically
}
})
.catch(err=>{
setIsLoading(false);
// toast.error(errorMessage, {
// position: toast.POSITION.BOTTOM_RIGHT
// })
console.log(err)
})
}
function addSubTotals(subTotal) {
// setSubTotals(prevSubTotals=>prevSubTotals+subTotal);
}
useEffect(() => {
/** Get The Delivery Cost of The Products # The Good Time */
setTotal(subTotals+delivery);
}, [subTotals])
useEffect(() => {
let sum = 0;
cartProducts.map((p)=>{
let subtotal = Number(p.price) * Number(p.quantity);
sum+=subtotal;
})
setSubTotals(sum);
}, [cartProducts])
function calculateNewSubTotalAndTotal(newQuantity, cartId) {
// update quantity and update of the specific cartId
const elementsIndex = cartProducts.findIndex(item=>item.cartId === cartId)
let newCartProducts = [...cartProducts];
newCartProducts[elementsIndex] = {...newCartProducts[elementsIndex], quantity:newQuantity}
setCartProducts(newCartProducts);
}
// function payWithPaystack(e) {
// e.preventDefault();
// let handler = PaystackPop.setup({
// key: 'sk_test_f12711e9277e1a27aba8e58f3394b9717098efaf', // Replace with your public key
// email: "ekomboy012#gmail.com",
// amount: 1200 * 100,
// ref: ''+Math.floor((Math.random() * 1000000000) + 1), // generates a pseudo-unique reference. Please replace with a reference you generated. Or remove the line entirely so our API will generate one for you
// // label: "Optional string that replaces customer email"
// onClose: function(){
// alert('Window closed.');
// },
// callback: function(response){
// let message = 'Payment complete! Reference: ' + response.reference;
// alert(message);
// }
// });
// handler.openIframe();
// }
return (
<React.Fragment>
{requireAuth()}
{isLoading && <Loader />}
<Header title = {title} clientRootUrl = {clientRootUrl} loggedInStatus = {loggedInStatus} cartNum = {cartNum} token = {token} />
<br />
<br />
<div className = "small-container cart-page">
{
(cartProducts.length > 0) && (
<table>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Subtotal</th>
</tr>
{
cartProducts.map(({cartId,quantity,id,categoryId,name,description,image,price,out_of_stock})=><CartProduct key = {id} cartId = {cartId} quantity = {quantity} id = {id} categoryId = {categoryId} name = {name} description = {description} image = {image} price = {price} out_of_stock = {out_of_stock} apiRootUrl = {apiRootUrl} token = {token} errorMessage = {errorMessage} delCartItem = {delCartItem} addSubTotals = {addSubTotals} calculateNewSubTotalAndTotal = {calculateNewSubTotalAndTotal} />)
}
</table>
)
}
{
(cartProducts.length < 1) && (
<Fragment>
<Empty clientRootUrl = {clientRootUrl}>Ahh! Your cart seems empty.</Empty>
</Fragment>
)
}
{ (allowed) && (
<OrderDetails subTotals = {subTotals} delivery = {delivery} total = {total} >
<Link to = {`/checkout`} className = "btn">Proceed to Checkout</Link>
</OrderDetails>
)}
<br />
<br />
<br />
</div>
</React.Fragment>
)
}
export default Cart
app.js (server)
const express = require('express');
const app = express();
const morgan = require('morgan');
const bodyParser = require('body-parser');
const path = require('path');
const userRoutes = require('./api/routes/user');
const adminRoutes = require('./api/routes/admin');
const categoryRoutes = require('./api/routes/category');
const productRoutes = require('./api/routes/product');
const orderRoutes = require('./api/routes/order');
const marketRoutes = require('./api/routes/market');
const searchRoutes = require('./api/routes/search');
const cartRoutes = require('./api/routes/cart');
const miscellaneousRoutes = require('./api/routes/miscellaneous');
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.use((req,res,next) => {
res.header("Access-Control-Allow-Origin","*"); // change later
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
// res.header("Cache-Control", 'no-cache');
if(req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
res.status(200).json({});
}
next();
});
app.use('/user', userRoutes);
app.use('/admin', adminRoutes);
app.use('/category', categoryRoutes);
app.use('/product', productRoutes);
app.use('/order', orderRoutes);
app.use('/market', marketRoutes);
app.use('/search', searchRoutes);
app.use('/cart', cartRoutes);
app.use('/miscellaneous', miscellaneousRoutes);
// sample code to create static filepath
// app.use('/uploads', express.static('img'));
app.use('/uploads', express.static('uploads'));
app.use(express.static(path.join(__dirname,'public')));
app.use((req,res,next) => {
const error = new Error('Not found');
error.status = 404;
next(error);
});
app.use((error,req,res,next) => {
res.status(error.status || 500);
res.json({
error: {
message:error.message
}
});
});
module.exports = app;
cart.js (server(controller))
const pool = require('../../utils/pool');
exports.cart_get_all_for_user = (req,res,next) => {
const tokenUserId = req.userData.userId;
// const tokenEmail = req.userData.email;
// if(userId == tokenUserId || tokenEmail === process.env.adminEmail) {
pool.getConnection(function(err,conn){
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
conn.query(`select * from cartSchema where userId = ?`, [tokenUserId], function(err,result){
conn.release();
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
return res.status(200).json(result);
}
});
}
});
// res.end();
// } else {
// res.status(401).json({error:'No authorization!'});
// }
}
exports.add_to_cart = (req,res,next) => {
const { productId, quantity } = req.body;
const { userId } = req.userData;
pool.getConnection(function(err,conn){
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
pool.getConnection(function(err,conn){
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
conn.query(`select * from cartSchema where ( productId = ?) and ( userId = ? )`, [ productId,userId], function(err,cart_product){
// conn.release();
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
if(cart_product.length > 0) {
// update quantity in cart
conn.query(`update cartSchema set quantity = ? where ( productId = ?) and ( userId = ? )`, [quantity,productId,userId], function(err,result){
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
return res.status(200).json({error:455,message:'Product already exists in cart but the quantity has been updated'});
}
});
} else {
conn.query(`insert into cartSchema (userId, productId, quantity) values (?,?,?)`, [userId,productId, quantity], function(err,result){
conn.release();
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
return res.status(200).json({
error: 0,
message: 'Product has been added to cart',
id: result.insertId,
userId,
productId,
quantity
});
}
});
}
}
})
}
});
}
});
}
// update quantity
exports.update_cart_product_details = (req,res,next) => {
const {cartId} = req.params;
const {quantity} = req.body;
const {userId} = req.userData;
/**
* check if cartItem exists <i>
* check if the user is authorized to change <i>
* update cartItem
* give success message
*/
pool.getConnection((err, conn) => {
if (err) {
return res.status(500).json({ error: 'An error occured. Please try again!' });
} else {
conn.query(`select * from cartSchema where id = ? and userId = ?`, [cartId,userId], (err,cartItem) => {
if(err) {
return res.status(500).json({ error: 'An error occured. Please try again!' });
} else {
console.log(cartItem)
if(cartItem.length < 1) {
return res.status(500).json({ error: 'An error occured. Please try again!' }); // The CartItem you're trying to update does not exist
} else {
conn.query(`update cartSchema set quantity = ? where ( id = ? and userId = ? )`, [quantity,cartId,userId], (err,result)=>{
conn.release();
if(err) {
return res.status(500).json({ error: 'An error occured. Please try again!' });
} else {
return res.status(200).json({error:0,message:"Quantity updated successfully"});
}
})
}
}
});
}
})
}
exports.remove_from_cart = (req,res,next) => {
const { cartId } = req.params;
const {userId} = req.userData;
pool.getConnection(function(err,conn){
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
conn.query(`select * from cartSchema where id = ? and userId = ?`, [cartId,userId], (err,cartItem)=>{
if(err) {
return res.status(500).json({ error: 'An error occured. Please try again!' });
} else {
if(cartItem.length < 1) {
return res.status(500).json({ error: 'An error occured. Please try again!' }); // The CartItem you're trying to update does not exist
} else {
conn.query(`delete from cartSchema where id = ?`, [cartId], function(err,result){
conn.release();
if(err) {
return res.status(500).json({error:'An error occured. Please try again!'});
} else {
return res.status(200).json({error:0,message:'Product successfully removed from cart'});
}
});
}
}
})
}
});
}
miscellaneous.js
exports.city_cost = (req,res,next) => {
const {city} = req.params;
console.log(city)
return res.status(200).json({
fee:checkLocationFee(city)
})
}
exports.delivery_cost = (req,res,next) => {
const {userId} = req.userData;
/** Get the city of the user */
pool.getConnection((err,conn)=>{
if(err) {
logisticFees = logisticDefaultFee;
} else {
conn.query(`select * from userSchema where id = ?`, [userId], (err,user)=>{
if(err) {
logisticFees = logisticDefaultFee;
} else {
logisticFees = checkLocationFee(user[0].city);
}
});
}
});
console.log(logisticFees)
// const logisticFees = 1000; /** logistic fees varies based on LOCATION */
const { subtotal } = req.body;
/** FoodNet Logic */
let FoodNetFees;
if(subtotal < 1000) {
FoodNetFees = ((2.5/100)*subtotal) + 100; // 1.5 (down)
} else if(subtotal <= 5000) {
FoodNetFees = ((3/100)*subtotal) + 100;
} else if(subtotal > 5000 && subtotal <= 50000){
FoodNetFees = ((3.5/100)*subtotal) + 100;
} else { // above 50000
FoodNetFees = ((4/100)*subtotal) + 100;
}
/** ../end */
const paystackPaymentFee = ( subtotal + FoodNetFees + logisticFees ) * (1.5/100);
const paystackTransferFee = 10; // off transfer made to them
const totalCost = FoodNetFees + logisticFees + paystackPaymentFee + paystackTransferFee; // err to add subtotal
return res.status(200).json({
cost: totalCost
})
}
exports.verify_transaction = (req,res,next) => {
const {userId} = req.userData;
pool.getConnection((err,conn)=>{
if(err) {
logisticFees = logisticDefaultFee;
} else {
conn.query(`select * from userSchema where id = ?`, [userId], (err,user)=>{
if(err) {
logisticFees = logisticDefaultFee;
} else {
logisticFees = checkLocationFee(user[0].city);
}
});
}
});
const { reference } = req.params;
/** Verify Transaction (1) */
const promise = paystack.verifyTransaction({
reference
})
promise.then(function ({body}){
if(body.data.status === 'success') {
/** Create Transfer Recepient (2) */
const promise2 = paystack.createTransferRecipient({
type:"nuban",
name: logisticName,
account_number:logisticAccNumber,
bank_code:logisticBankCode,
currency:"NGN"
})
promise2.then(function({body}){
if(body.data.active === true) {
/** Make Transfer with Recipient(3) */
// store recipient_code
const recipient_code = body.data.recipient_code;
console.log(recipient_code)
/** JUST FOR DEVELOPMENT MODE ( REMOVE IN PRODUCTION MODE ) */
return res.status(200).json({error:0});
/** FOR PRODUCTION MODE BELOW */
// initiate transfer
const promise3 = paystack.initiateTransfer({
source:"balance",
reason: logisticReason,
amount: 900 * 100,
recipient: recipient_code,
reference: Math.floor((Math.random() * 1000000000) + 1)
})
promise3.then(function({body}){
if(body.data.status === "success") {
// will only work with real transactions
res.status(200).json({error:0})
} else {
/** Handle Error */
return res.status(500).json({error:'An error occured. Please try again!'})
}
}).catch(function(err){
/** Handle Error */
return res.status(500).json({error:'An error occured. Please try again!'})
});
/** FOR PRODUCTION MODE ABOVE */
} else {
/** Handle Error */
return res.status(500).json({error:'An error occured. Please try again!'})
}
})
} else {
/** Handle Error */
// console.log(2)
return res.status(500).json({error:'An error occured. Please try again!'})
}
}).catch(function(err){
/** Handle Error */
return res.status(500).json({error:'An error occured. Please try again!'})
})
// put return in all response
}
The problem got solved. I was making multiple requests to the server being asynchronous code. So i just nested my requests to the stay in the safe space and all worked perfectly.
How can I alert the user after nodejs validation?
router.post('/clocking', async (req,res) => {
const value = req.body.clock
const id = req.body.empId
try {
if( value == 'in' ){
const data = await Clocking.find({ employee: id }).populate('employee').lean()
const i = data.length
if(data[i-1].clockOut.getTime() == data[i-1].clockIn.getTime()) {
// ....alert the user.....
}else{
await Clocking.create({ employee:id });
res.redirect('/')
}
}
} catch (e) {}
})
How can I do such a thing in nodejs?
Respond with something.
e.g.
res.render("error-page", { /* data about the error */ });
How do you want to notify the user? If your want to simple send a message, you can do it like that:
router.post('/clocking', async (req, res) => {
const value = req.body.clock
const id = req.body.empId
try {
if (value === 'in') { // use `===`, not `==`
const data = await Clocking.find({ employee: id }).populate('employee').lean()
const i = data.length
if (data[i - 1].clockOut.getTime() === data[i - 1].clockIn.getTime()) { // use `===`, not `==`
res.send("The name is incorrect") // NEW
} else {
await Clocking.create({ employee: id });
res.redirect('/')
}
}
} catch (error) { // NEW
res.send("There was an error", error) // NEW
} // NEW
}
This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 4 years ago.
I am having an issue with using async/await using node v8.1. It appears my issue is that I am not returning a promise from my async functions. This is causing the flow of the program to run out of order. I thought by making a function async that the function automatically returns a promise, but that is not the case I am running into.
I expect the program below to output:
Validating xlsx file...
(text from validateParsedXlsx)
Adding users to cognito...
(text from addUsersToCognito)
Adding users to dynamodb...
(text from addUsersToDynamodb)
Instead, I get:
Validating xlsx file...
Adding users to cognito...
Adding users to dynamodb...
(text from validateParsedXlsx)
(text from addUsersToCognito)
(text from addUsersToDynamodb)
The issue seems to be pretty obvious, that validateParsedXlsx() addUsersToCognito() and addUsersToDynamodb() are not returning promises. Again, I thought that by using the async keyword, the function automatically took care of this.
Thanks for the help.
Here is my script:
const xlsx = require('xlsx');
const AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-2'});
const documentClient = new AWS.DynamoDB.DocumentClient({convertEmptyValues: true});
async function main(){
if (!process.argv[2]) {
console.log('\nAbsolute filepath missing. Pass the absolute filepath in as command line argument.\n')
process.exit(1);
}
const xlsxFilePath = process.argv[2];
let parsedXlsx = [];
try {
parsedXlsx = parseXlsx(xlsxFilePath);
} catch (error) {
if(error.code === 'ENOENT') {
console.log(`\nThe file path: ${process.argv[2]} cannot be resolved\n`)
} else {
console.log(error);
}
}
console.log('\n\nValidating xlsx file...\n');
await validateParsedXlsx(parsedXlsx);
console.log('\n\nAdding users to cognito...\n');
await addUsersToCognito(parsedXlsx);
console.log('\n\nAdding users to dynamodb...\n');
await addUsersToDynamodb(parsedXlsx);
}
function parseXlsx(filePath) {
const workbook = xlsx.readFile(filePath);
const sheetNameList = workbook.SheetNames;
const parsedXlsxSheets = sheetNameList.map(function (y) {
const worksheet = workbook.Sheets[y];
const headers = {};
const data = [];
for (z in worksheet) {
if(z[0] === '!') continue;
//parse out the column, row, and value
const col = z.substring(0,1);
const row = parseInt(z.substring(1));
const value = worksheet[z].v;
//store header names
if(row == 1) {
headers[col] = value;
continue;
}
if(!data[row]) data[row] = {};
data[row][headers[col]] = value;
}
//drop those first two rows which are empty
data.shift();
data.shift();
return data;
});
return parsedXlsxSheets[0]
}
async function validateParsedXlsx(users) {
let error = false;
users.forEach(async (user, index) => {
if (!user.email) {
console.log(`User at row ${index + 2} doesn't have 'email' entry in xlsx file.`);
error = true;
}
if (!user.displayName) {
console.log(`User at row ${index + 2} doesn't have 'displayName' entry in xlsx file.`);
error = true;
}
if (!user.serviceProviderId) {
console.log(`Userat row ${index + 2} doesn't have 'displayName' entry in xlsx file.`);
error = true;
} else {
const params = {
TableName: 'service-providers',
Key: {
serviceProviderId: user.serviceProviderId
}
}
const response = await documentClient.get(params).promise();
if (!response.Item) {
console.log(`User at row ${index +2} does not have a valid serviceProviderId.`);
error = true;
} else {
console.log(`User ${user.email} is valid, assigned to service provider: ${response.Item.displayName}`);
}
}
if (error) {
console.log(`Every user in xlsx file must have these attributes, spelled correctly: email, displayName, and serviceProviderId\n\nIn addition, make sure the serviceProviderId is correct by checking the service-providers dynanomdb table.`);
process.exit(1);
}
});
}
async function addUsersToCognito(users) {
const cognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider();
const results = await cognitoIdentityServiceProvider.listUserPools({MaxResults: 10}).promise();
let serviceProviderUserPoolId = '';
results.UserPools.forEach((userPool) => {
if(userPool.Name === 'service-provider-users') {
serviceProviderUserPoolId = userPool.Id;
}
});
users.forEach(async (user) => {
const params = {
UserPoolId: serviceProviderUserPoolId,
Username: user.email,
DesiredDeliveryMediums: ['EMAIL'],
TemporaryPassword: 'New_User1',
UserAttributes: [
{
Name: 'email',
Value: user.email
},
{
Name: 'custom:service_provider_id',
Value: user.serviceProviderId
}
]
}
try {
await cognitoIdentityServiceProvider.adminCreateUser(params).promise();
console.log(`Added user ${user.email} to cognito user pool`);
} catch (error) {
if (error.code === 'UsernameExistsException') {
console.log(`Username: ${user.email} already exists. No action taken.`);
}
else {
console.log(error);
}
}
});
}
async function addUsersToDynamodb(users) {
users.forEach(async (user) => {
const params = {
TableName: 'service-provider-users',
Item: {
serviceProviderId: user.serviceProviderId,
userId: user.email,
displayName: user.displayName,
isActive: false,
role: 'BASIC'
},
ConditionExpression: 'attribute_not_exists(userId)'
}
try {
await documentClient.put(params).promise();
console.log(`Added user ${user.email} to dynamodb user table`);
} catch (error) {
if (error.code === 'ConditionalCheckFailedException') {
console.log(`User ${user.email} already in the dynamodb table service-provider-users`);
} else {
console.log(error);
}
}
});
}
main();
users.forEach(async (user, index) => {
That starts a few promising actions but never awaits them. May do:
await Promise.all(users.map(async (user, index) => {
... to execute them in parallel or do this:
await users.reduce((chain, user, index) => async (user, index) => {
await chain;
//...
}, Promise.resolve());
To execute them one after another.
PS: Using process.exit should be the very last option to end your program