Problems with calling functions in other file (Firebase Functions) - node.js

I'm making an API using express in Firebas Functions. So Im having the following problem:
error:Error>>TypeError: firebase_util.updateWalletData is not a function
Basically I have a index.js, and two files (firebase and axies.js)
The problem comes in a function in axies.js:
async function firstUpdate(wallet) {
const baseUrl = 'https://game-api.skymavis.com/game-api/clients/'
const path = '/items/1'
try {
let newAdd = wallet.replace('ronin:', '0x');
let requestURL = baseUrl+newAdd + path;
console.log('wallet>>' + newAdd);
let response = await axios.get(requestURL, {raxConfig: {statusCodesToRetry: [[100, 199], [400, 429], [500, 599]]}});
if(response.status === 200) {
let requestData = response['data'];
console.log('data>>' + util.inspect(requestData, true, null, true));
console.log('request>>' + requestURL);
let total_slp = requestData.total;
let last_claim_amount = 0;
let claim_timestamp = 0;
if (requestData.blockchain_related.signature) {
last_claim_amount = requestData.blockchain_related.signature.amount;
claim_timestamp = requestData.blockchain_related.signature.timestamp;
} else {
claim_timestamp = requestData.item.created_at;
}
let next_claim_timestamp = claim_timestamp + 1296000;
let ronin_slp = requestData.blockchain_related.balance;
console.log('ron>>' + ronin_slp);
if (ronin_slp === null) {
ronin_slp = 0;
console.log('ronin value changed to>>' + ronin_slp);
}
let ingame_slp = total_slp - ronin_slp;
let lastupdate = Math.floor(+new Date() / 1000);
let walletInfo = {total_slp, last_claim_amount, claim_timestamp, next_claim_timestamp, ronin_slp, ingame_slp, lastupdate};
console.log('util>>' + util.inspect(walletInfo, true, null, true));
firebase_util.updateWalletData(wallet, walletInfo);
}
} catch(error) {
console.log('Error>>' + error);
}
}
I have a cronjob that once an hour update the information in all wallets, but this function is called when a new wallet is added, so it force an update to get the data for the first time.
In the firebase.js Im doing all the job from writing/reading all the data in firebase realtime database.
firebase.js:
async function updateWalletData(walletID, walletData) {
database.ref('ScolarsToCheck/' + walletID + '/walletData/').update(walletData);
return {'message': 'updated', 'status': 200};
}
module.exports = {setCalendar, createEmptyCalendar, checkCalendar, getAllScolars, addScolar, deleteScolar, addExpenses, deleteExpenses, addClaim, deleteClaim, getScolars, updateWalletData};
All the other stuff works great, but the calls to firebase_util.updateWalletData() just stopped working. I have a lot of functions and endpoints in index.js calling to those functions and all works smothly, except for that single call.

Related

TypeError: Cannot read property ' ' error with discord.js

So I have figured out how to set up a simple database with discord.js in a users.json file and my !start cmnd works to create the users database, but when me and my cousin tried the !daily cmnds, the cmnd seems to be fine but I get this error: TypeError: Cannot read property 'a number' of undefined. I believe the number refers to my user number or database number (a number means an actual long number, not "a number").
Also here is the code that goes along with this that is in my index.js file:
var UserJSON = JSON.parse(Fs.readFileSync('./DB/users.json'));
UserJSON[message.author.id] = {
bal: 0,
lastclaim: 0,
}
Fs.writeFileSync('./DB/users.json', JSON.stringify(UserJSON));
let SuccessEmbed = new Discord.MessageEmbed();
SuccessEmbed.setTitle("**SUCCESS**");
SuccessEmbed.setDescription("You have joined the economy! type !help to get started");
message.channel.send(SuccessEmbed);
return;
}
if (args[0] == "daily") {
let userJSON = JSON.parse(Fs.readFileSync('./DB/users.json'));
if (Math.floor(new Date().getTime() - UserJSON[message.author.id].lastclaim) / (1000 * 60 * 60 * 24) < 1) {
let WarningEmbed = new Discord.MessageEmbed()
WarningEmbed.setTitle("**ERROR**");
WarningEmbed.setDescription("You have claimed today already");
message.channel.send(WarningEmbed);
return;
}
UserJSON[message.author.id].bal += 500;
UserJSON[message.author.id].lastclaim = new Date().getTime();
Fs.writeFileSync('./DB/users.json', JSON.stringify(UserJSON));
let SuccessEmbed = new Discord.MessageEmbed();
SuccessEmbed.setTitle("**SUCCESS**");
SuccessEmbed.setDescription("You have claimed a daily reward of 500 coins!");
message.channel.send(SuccessEmbed);
}
}
})
Also to specify, the ./DB/users.json refers to the folder DB for database and users.json is the file that stores the databases.
Here is what the user.json file looks like:
{"*my database number*":{"bal":0,"lastclaim":0},"*my cousin's database number*":{"bal":0,"lastclaim":0}}
Is there any code I need to add into my index.js file to stop this from happening. If possible, answer as soon as possible so I can get this error worked out. Thank You!
Edit: I somehow figured this out by re-doing it and this is the finished product if anyone wants to start an economy bot:
const Discord = require("discord.js");
const client = new Discord.Client();
const Fs = require("fs");
const prefix = "!";
client.on("ready", () => {
console.log("Ready!");
});
client.on("message", async (message) => {
if(message.content.startsWith(prefix)) {
var args = message.content.substr(prefix.length)
.toLowerCase()
.split(" ");
if (args[0] == "start") {
let UserJSON = JSON.parse(Fs.readFileSync("./DB/users.json"));
UserJSON[message.author.id] = {
bal: 0,
lastclaim: 0,
}
Fs.writeFileSync("./DB/users.json", JSON.stringify(UserJSON));
let SuccessEmbed = new Discord.MessageEmbed();
SuccessEmbed.setTitle("**SUCCESS**");
SuccessEmbed.setDescription("You have joined the economy! type !help to get started");
message.channel.send(SuccessEmbed);
return;
}
if (args[0] == "daily") {
let UserJSON = JSON.parse(Fs.readFileSync("./DB/users.json"));
if (Math.floor(new Date().getTime() - UserJSON[message.author.id].lastclaim) / (1000 * 60 * 60 * 24) < 1) {
let WarningEmbed = new Discord.MessageEmbed()
WarningEmbed.setTitle("**ERROR**");
WarningEmbed.setDescription("You have claimed today already");
message.channel.send(WarningEmbed);
return;
}
UserJSON[message.author.id].bal += 500;
UserJSON[message.author.id].lastclaim = new Date().getTime();
Fs.writeFileSync("./DB/users.json", JSON.stringify(UserJSON));
let SuccessEmbed = new Discord.MessageEmbed();
SuccessEmbed.setTitle("**SUCCESS**");
SuccessEmbed.setDescription("You have claimed a daily reward of 500 discord coins!");
message.channel.send(SuccessEmbed);
}
}
})
client.login('your token');
also remember to make a DB folder with an users.json file
I realized that the problem with the code is that instead of vars, it needed to be let before the UserJSON, so the line of code should read:
let UserJSON = JSON.parse(Fs.readFileSync("./DB/users.json"));
UserJSON[message.author.id] = {
bal: 0,
lastclaim: 0,
}

Async communicating with serialport gives mixed data

I'm trying to communicating with an arduino that has sensors.
So i have an object called motherboard who has sensors and each sensor has metric which may have threshold and/or polling which has a methode called getValue that sends data to the arduino and returns data with a promise. The problem is that if i async the sensors to get their values all sensors get the same value.
I don't know why this is happening. I only have programmed with javascript for 1 year and with angular for 5 months. I checked the post async/await using serialport in node.js but i checked my code and i did the something that was suggested in the post.
The communicate method is inside a service.
Can anyone help?
tl;dr :
send data to arduino get data back in a promise.
Metric A and B get the same promise.
The component polling also gets the promise of threshold. (metric has threshold and polling)
Me
communication.service.ts
communicate(cmd: string, serialPort: SerialPort, expectedResponse: string, notExpectedResponse){
const parser = serialPort.pipe(new Delimiter({delimiter: '\n'}));
return new Promise((resolve, reject) => {
serialPort.write(cmd, () => {
console.log('message written');
parser.on('data', data => {
const dataString = data.toString();
if (dataString != null && dataString.includes(expectedResponse)) {
let responseRemoved = dataString.replace(expectedResponse + ' ', '');
resolve(responseRemoved);
} else {
let response;
if (dataString != null && dataString.includes(notExpectedResponse)) {
response = dataString.replace(notExpectedResponse + ' ', '');
}
reject(response);
}
});
setTimeout(() => {
reject('');
}, this.timeOutTime);
});
});
}
threshold.component.ts
private getValuesThreshold(): void{
console.log(this.metricId);
this.motherboardInUse.getValues(this.metricId, GlobalVariableCMD.GET_THRESHOLD_VALUES,
GlobalVariableResponse.GET_THRESHOLD_VALUES, GlobalVariableResponse.GET_THRESHOLD_VALUES).then(data => {
let dataString = data.toString();
if(dataString){
console.log(dataString);
let responseSplit = dataString.toString().split(' ');
let minimumValue = parseInt(responseSplit[1]);
let maximumValue = parseInt(responseSplit[2]);
minimumValue < this.floor ? this.minimumThreshold = this.floor : this.minimumThreshold = minimumValue;
maximumValue > this.ceil ? this.maximumThreshold = this.ceil : this.maximumThreshold = 90;
this.enabled = responseSplit[0].includes('1');
console.log(this.minimumThreshold);
console.log(this.maximumThreshold);
console.log(this.enabled);
}
}).catch(err => {
let errString = err.toString();
if(errString){
console.log(errString);
}
});
}
motherboard.component.ts
getValuesThreshold(metricId: string, ATcmd: string, expectedResponse: string, notExpectedResponse: string) {
let command = this.communicateBuilder.BuildCommandGetMetricValue(ATcmd, this.usedSensorId, metricId);
console.log('motherboard get values' + command);
let responseOk = this.commandBuilderService.respondsSuccess(expectedResponse);
let responseNotOk = this.commandBuilderService.respondsFail(notExpectedResponse);
return this.communicateService.communicate(command, this.motherboard.serialPort, responseOk, responseNotOk);
}
Maybe you can try this
async getValuesThreshold(metricId: string, ATcmd: string, expectedResponse: string, notExpectedResponse: string) {
let command = this.communicateBuilder.BuildCommandGetMetricValue(ATcmd, this.usedSensorId, metricId);
console.log('motherboard get values' + command);
let responseOk = this.commandBuilderService.respondsSuccess(expectedResponse);
let responseNotOk = this.commandBuilderService.respondsFail(notExpectedResponse);
return await this.communicateService.communicate(command, this.motherboard.serialPort, responseOk, responseNotOk);
}
The problem was sending async data with serialport.
Serialport node had no way of knowing what response was linked to what data that was send.
So it acted on the first response it got and returned that.
Only way to solve this was to ask them sync.

Random number generator does not produce an expected answer Node JS

In a Node JS script, a formula is being used to generate a random number between two values. Here is the function randomIntInc:
function randomIntInc(low, high) {
return Math.floor(Math.random() * (high - low + 1) + low);
}
The function is called with two values as low and high:
let randomNumber = randomIntInc(requestedStart, requestedEnd);
console.log(requestedStart) before executing the above line produces 542 (expected)
console.log(requestedEnd) before executing the above line produces 592 (expected)
Now, running the above line and logging the output produces any value, generally within 6 and 50.
What is happening? Logging before executing the random number shows the correct ranges, but the outputted number just does not fall within the given range.
Here's the full code (related code at 113) (please ignore bad practice code that's unrelated / memes or easter eggs):
// Copyright (C) 2018, Julian Lachniet, Jacob Wysko
// Dependencies
var Discord = require('discord.io'),
logger = require('winston'),
auth = require('../auth.json'),
rn = require('random-number'),
http = require('http'),
request = require('request');
// Authorize connection
var bot = new Discord.Client({
token: auth.token,
autorun: true
});
// GOOGLE SHEETS API
const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly'];
const TOKEN_PATH = 'credentials.json';
// If bot disconnects, try to reconnect
bot.on('disconnect', function(msg, code) {
if (code === 0) return console.error(msg);
bot.connect();
});
// Returns the current timestamp
function timeStamp() {
return "[" + new Date().toString().split(" G")[0] + "]";
}
// Returns a random integer
function randomIntInc(low, high) {
return Math.floor(Math.random() * (high - low + 1) + low);
}
// When a message is recieved
bot.on('message', function(user, userID, channelID, message, evt) {
let valid = false;
// Log what the user sent (verifies it wasn't sent by the bot)
if (user !== 'teacher-quotes-bot') {
console.log(timeStamp() + " " + user + ": " + message);
}
// Sends a message with text "message", logs it
function sendMessage(message) {
bot.sendMessage({
to: channelID,
message: message
});
console.log(timeStamp() + " Bot: " + message);
valid = true;
}
// Sends a message based on a list of commands
function infoMessage(commands, response) {
if (commands.includes(input)) {
sendMessage(response);
}
validCommands.push(commands);
}
// If the message began with a '!' (e.g., !cmd)
if (message.substring(0, 1) === '!') {
var args = message.substring(1).split(' ');
var input = args[0];
var validCommands = [];
// Commands
infoMessage(['accuracy', 'disclaimer', 'terms'], '<#440534402171404289>');
infoMessage(['android', 'app'], 'https://play.google.com/store/apps/details?id=com.jacobwysko.teacherquotes');
infoMessage(['format', 'formats', 'formatting'], '"Quote text." - Teacher, MM/DD/YYYY');
infoMessage(['code', 'git', 'github', 'roadmap', 'trello', 'source', 'sourcecode'], 'https://github.com/wyskoj/TeacherQuotesVersion3\nhttps://github.com/jlachniet/TeacherQuotesBot');
infoMessage(['faq', 'help', '?'], "You've been <#440504422028804107>ed.");
infoMessage(['ping', 'pong'], 'Pong!');
infoMessage(['rule', 'rules'], "You've been <#440500062011916298>ed");
infoMessage(['apple', 'ios', 'web', 'website'], 'http://jacobwysko.com/teacherquotes');
infoMessage(['cmd', 'cmds', 'command', 'commands'], 'Valid Commands:\n - accuracy\n - app\n - format\n - github\n - help\n - ping\n - rules\n - website');
// Easter eggs
infoMessage(['ivefallenandicantgetup'], 'Stay right there, ' + user + "! Don't worry, help is on the way!");
infoMessage(['goddammitimpregnant'], '...for the fifteenth damn time!');
infoMessage(['yeah'], 'boiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii');
infoMessage(['ohhi'], 'mark');
infoMessage(['poopity'], 'scoop');
switch (input) {
case 'fact':
case 'randomfact':
// Sends a random fact
request('https://spreadsheets.google.com/feeds/list/1ggvma51cj7ryPqfxGv47ZPLuP72keZmFbGE-KBHqbuU/4/public/values?alt=json', function(error, response, body) {
let boi = body;
let output = JSON.parse(boi);
let options = {
min: 0,
max: 11,
integer: true
};
let randomNumber = rn(options);
sendMessage(output["feed"]["entry"][randomNumber]["gsx$randomfact"]["$t"]);
});
break;
case 'randomquote':
// Sends a random quote
if (args.length !== 2) {
request('https://spreadsheets.google.com/feeds/list/1ggvma51cj7ryPqfxGv47ZPLuP72keZmFbGE-KBHqbuU/1/public/values?alt=json', function(error, response, body) {
let output = JSON.parse(body);
let options = {
min: 0,
max: output["feed"]["entry"].length,
integer: true
};
let randomNumber = rn(options);
sendMessage(('"' + output["feed"]["entry"][randomNumber]["gsx$quote"]["$t"] + '" - ' + output["feed"]["entry"][randomNumber]["gsx$teacherquoted"]["$t"] + ", " + output["feed"]["entry"][randomNumber]["gsx$date"]["$t"]))
});
} else {
console.log("SPECIFICS TEACHER");
let requestedTeacher = args[1];
request('https://spreadsheets.google.com/feeds/list/1ggvma51cj7ryPqfxGv47ZPLuP72keZmFbGE-KBHqbuU/1/public/values?alt=json', function (error, response, body) {
let quotes = JSON.parse(body);
console.log(quotes);
request('https://spreadsheets.google.com/feeds/list/1ggvma51cj7ryPqfxGv47ZPLuP72keZmFbGE-KBHqbuU/2/public/values?alt=json', function (error, response, body){
let ranges = JSON.parse(body);
console.log(ranges);
let teachers = [];
for (i = 0; i < ranges["feed"]["entry"].length; i++){
teachers.push(ranges["feed"]["entry"][i]["gsx$teacher"]["$t"]);
}
let teacherStart = [];
for (i = 0; i < ranges["feed"]["entry"].length; i++){
teacherStart.push(ranges["feed"]["entry"][i]["gsx$rangestart"]["$t"]);
}
let teacherEnd = [];
for (i = 0; i < ranges["feed"]["entry"].length; i++){
teacherEnd.push(ranges["feed"]["entry"][i]["gsx$rangeend"]["$t"]);
}
let requestedTeacherId = teachers.indexOf(requestedTeacher);
let requestedStart = teacherStart[requestedTeacherId];
let requestedEnd = teacherEnd[requestedTeacherId];
console.log(requestedStart);
console.log(requestedEnd);
let randomNumber = randomIntInc(requestedStart, requestedEnd);
console.log(requestedTeacher);
console.log(randomNumber);
});
});
}
break;
}
if (!valid && !['fact', 'randomfact', 'randomquote'].includes(input)) {
sendMessage('Invalid command. Type "!command" for a list of commands.');
}
} else
if (user !== 'teacher-quotes-bot' && channelID === '465330717782441986') {
let validQuoteRegex = /".+"\s-\s\w+,\s\d{2}\/\d{2}\/\d{4}/;
if (validQuoteRegex.test(message)) { // If the message sent was a valid quote
let justMessage = message.split('"')[1];
let justTeacher = message.split('"')[2].substring(3, message.split('"')[2].length - 12);
let justDate = message.substring(message.length - 10, message.length);
if (justTeacher.indexOf("(") > -1) {
justTeacher = justTeacher.substring(0, justTeacher.indexOf("("));
}
sendMessage("Message: " + justMessage + "\nTeacher: " + justTeacher + "\nDate: " + justDate);
} else {
sendMessage("Invalid Quote");
}
}
});
It appears the returned JSON is storing the values assigned to requestedStart and requestedEnd as strings rather than numbers. If that is the case, you will need to convert them to numbers before performing the arithmetic for the random number range.
function randomIntInc(low, high) {
console.log({
low,
high,
'(high - low) + 1': (high - low) + 1,
'(high - low + 1) + low': (high - low + 1) + low
});
return Math.floor(Math.random() * (high - low + 1) + low);
}
console.log({
strings: randomIntInc('10', '20'),
numbers: randomIntInc(10, 20)
});
Stepping through the string invocation, '10' and '20', results in the following operations:
('20' - '10' + 1): the order of operations will cause the subtraction operations to be done first which will automatically convert both strings to numbers and result in 10. The final addition will simply add the two number and produce 11.
The key part is the last addition which attempts to add a number with a string. This will cause the number, '11', to be converted to a string and then concatenated with the string, '10', which results in '1110'. This can be confusing unless you remember that the addition symbol is also used for string concatenation.
Finally the multiplication uses the random number times a string value of '1110' which results in a value of 0 - 11.1.

copy data from one node1 child to another node2 child with using firebase cloud functions

Below is my code of cloud functions I am trying to copy the data from users node to challenge node
exports.copyChallengeDate = functions.database.ref(`Users/{pushId}/DateChallengeAccept`).onCreate((snapshot, context)=>{
var DateChallengeAccept = snapshot.val();
console.log('Challenge', context.params.pushId, DateChallengeAccept);
var challenge = DateChallengeAccept;
return admin.database().ref('Challenge/' + context.params.pushId).child('DateChallengeAccept').set(challenge);
});
But the thing is when I am trying to copy the date from user table to challenge node it's only occur in QS5h99YxS0ZGpT42fpUFvzOdpTi1
D uid same as of Users node. I want to copy it in both uid's(QS5h99YxS0ZGpT42fpUFvzOdpTi1, 7aH9Ag8414VzM0n7P6ur4LvcepI2)
D present in challenge node. I was stuck in it from last two days please help me out
Update following you remark that DateChallengeAccept is not initialized when you create the record. You should use another method, like onUpdate() (or onWrite()) and not onCreate(), as you do in your question. Do as follows:
exports.copyChallengeDate = functions.database.ref(`Users/{pushId}`).onUpdate((change, context) =>
const DateChallengeAccept = change.after.val().DateChallengeAccept;
if ( DateChallengeAccept === undefined) {
return false;
}
const referredBy = change.after.val().referredBy;
console.log('Challenge', context.params.pushId, DateChallengeAccept);
const dateChallengeAcceptObj = {
"DateChallengeAccept": DateChallengeAccept
};
let updates = {};
updates['Challenge/' + context.params.pushId + '/DateChallengeAccept'] = dateChallengeAcceptObj;
updates['Challenge/' + referredBy + '/DateChallengeAccept'] = dateChallengeAcceptObj;
return admin.database().ref().update(updates);
});
You need to get the referredId value in your Function, because it is this data item that holds the ID of the other user (i.e. 7aH9Ag8414VzM0n7P6ur4LvcepI2). So you have to trigger the event on the parent node, not at the DateChallengeAccept node.
Then you have to use the update() method to write simultaneously to two nodes, see the doc here: https://firebase.google.com/docs/database/web/read-and-write#update_specific_fields
So you should do as follows:
exports.copyChallengeDate = functions.database.ref(`Users/{pushId}`).onCreate((snapshot, context)=>{
const DateChallengeAccept = snapshot.val().DateChallengeAccept;
if ( DateChallengeAccept === undefined) {
return false;
}
const referredBy = snapshot.val().referredBy;
console.log('Challenge', context.params.pushId, DateChallengeAccept);
const dateChallengeAcceptObj = {
"DateChallengeAccept": DateChallengeAccept
};
let updates = {};
updates['Challenge/' + context.params.pushId + '/DateChallengeAccept'] = dateChallengeAcceptObj;
updates['Challenge/' + referredBy + '/DateChallengeAccept'] = dateChallengeAcceptObj;
return admin.database().ref().update(updates);
});

How to pipe large file into mongodb using gridfsbucket, when receiving file in chunks?

I am using nodejs, mongodb, and gridfsbucket.
I am receiving a file into my server in 255 byte chunks, the files can be extremely large so creating a variable to store the chunks and then piping that into mongo using gridfsbucket is not a viable option.
Currently I have a working method of temporarily storing the file on disk and then piping that into mongo. This actually works pretty well, the only problem is I don't want to temporarily store the data before streaming into mongo using gridfsbucket.
Does anyone know how to take those chunks as they are coming into my server and immediately stream them into mongo using gridfsbucket? I am thinking that I would need to open the pipe and then constantly stream the chunks into the pipe, but I am not sure how to accomplish this.
This is my current code for storing to the disk:
fs.appendFileSync(this.tempFileName, Buffer.from(this.currfile.currdatachunk));
this.currfile.filename = this.currfile.filename.replace(")", Date.now() + ")");
var fileName = decodeURI(this.currfile.filename.replace("$(", "").replace(")", ""));
fileName = encodeURI(fileName);
var self = this;
var gb = new GridFSBucket(mongoCacheDb, { bucketName: this.cacheCollection });
var uploadStream = gb.openUploadStream(fileName);
uploadStream.options.metadata = {
'url': "/getFile/" + fileName,
'id': uploadStream.id
}
uploadStream.once("finish", function uploadStream_onceFinish() {
if (this.length > 0) {
var ms = new Message();
ms.data = self.cacheCollection + "/" + self.currfile.filename;
ms.datatype = "URL";
ms.hasdata = "yes";
ms.haserrors = "no";
ms.type = "APPXLOADURL";
sendMessage(ws, ms);
/*Send response to server indicating file receipt*/
var nameAB = Buffer.from(self.currfile.filename);
self.clientsocket.write(Buffer.from(hton32(nameAB.length)));
self.clientsocket.write(Buffer.from(nameAB));
self.clientsocket.write(Buffer.from([3, 1]));
console.log("Finished: " + Date.now());
} else {
var nameAB = Buffer.from(self.currfile.filename);
self.clientsocket.write(Buffer.from(hton32(nameAB.length)));
self.clientsocket.write(Buffer.from(nameAB));
self.clientsocket.write(Buffer.from([0, 0]));
}
fs.unlinkSync(self.tempFileName);
});
fs.createReadStream(this.tempFileName).pipe(uploadStream);
I guess I should have waited another day. Finally wrapped my head around it and stopped overthinking it. I created the pipe on the first run and then just pushed the buffered chunks into the pipe as they were received. Code is below:
if (this.chunksReceived == 0) {
this.rStream = new Readable({ read(size) { } });
this.currfile.filename = this.currfile.filename.replace(")", Date.now() + ")");
var fileName = decodeURI(this.currfile.filename.replace("$(", "").replace(")", ""));
fileName = encodeURI(fileName);
var self = this;
var gb = new GridFSBucket(mongoCacheDb, { bucketName: this.cacheCollection });
this.uploadStream = gb.openUploadStream(fileName);
this.uploadStream.options.metadata = {
'url': "/getFile/" + fileName,
'id': this.uploadStream.id
}
this.uploadStream.once("finish", function uploadStream_onceFinish() {
if (this.length > 0) {
var ms = new Message();
ms.data = self.cacheCollection + "/" + self.currfile.filename;
ms.datatype = "URL";
ms.hasdata = "yes";
ms.haserrors = "no";
ms.type = "APPXLOADURL";
sendMessage(ws, ms);
/*Send response to server indicating file receipt*/
var nameAB = Buffer.from(self.currfile.filename);
self.clientsocket.write(Buffer.from(hton32(nameAB.length)));
self.clientsocket.write(Buffer.from(nameAB));
self.clientsocket.write(Buffer.from([3, 1]));
console.log("Finished: " + Date.now());
} else {
var nameAB = Buffer.from(self.currfile.filename);
self.clientsocket.write(Buffer.from(hton32(nameAB.length)));
self.clientsocket.write(Buffer.from(nameAB));
self.clientsocket.write(Buffer.from([0, 0]));
}
});
this.rStream.pipe(this.uploadStream);
}
this.rStream.push(Buffer.from(this.currfile.currdatachunk));
this.chunksReceived++;

Resources