I have a route that goes like this:
exports.downloadFile = app => {
app.get('/install/download', (request, result) => {
result.download(`${__dirname}../../../public/exec/install.exe`, error => {
if (error) console.log("[FAILURE][RESOURCE] Could not download installation file\r\n");
else console.log("[SUCCESS][RESOURCE] Installation file has been downloaded\r\n");
});
});
}
With this route, I am trying to make it that when I click on a button this file is downloaded. When I click the button I get a message indicating SUCCESS, but my browser makes no indication of any download and does not prompt me to do anything. Is there some additional component I need to add to make sure it works?
This is the code on my client side to do the fetching:
const downloadFile = () => {
const url = `${window.location.protocol}//${window.location.host}/install/download`;
fetch(url)
.catch(error => alertMessage(error.message));
}
I am assuming it might have to do with me having no .then to handle the fetch, but I am not sure what I should be adding there and I am under the impression from the documentation that the browser automatically handles this part?
You forget to pass one download name argument.
Please modify download function as below.
result.download(`${__dirname}../../../public/exec/install.exe`, 'install.exe', error => {
if (error) console.log("[FAILURE][RESOURCE] Could not download installation file\r\n");
else console.log("[SUCCESS][RESOURCE] Installation file has been downloaded\r\n");
});
Related
I want to create a delete command where when you right click on a message, it will show under apps "Delete Message" from my bot. For example, Atlas has a set reminder (which seems useless) function under apps [image.] I would like to create this as a guild command. Also, I would like to know how to use the interaction create with this right-click-context-menu function. Thanks!
To register these commands, you need to set the type of the ApplicationCommand to 1 (or ApplicationCommandType.ChatInput). See the docs.
Everything else should stay the same except the type. You can register these commands the usual way, which is documented in the guide here
Here's a snippet:
// token should be your bot's token
const rest = new REST({ version: '10' }).setToken(token);
(async () => {
try {
console.log(`Started refreshing ${commands.length} application (/) commands.`);
const data = await rest.put(
Routes.applicationGuildCommands(clientId, guildId),
// commands should be an array of ApplicationCommands
{ body: commands },
);
console.log(`Successfully reloaded ${data.length} application (/) commands.`);
} catch (error) {
console.error(error);
}
})();
I've been stuck on this problem for a day now and was wondering if there's a way I could go about this.
client side
Client side is going to be dynamic since it's an app type plugin.
The client side will open up a popup for oAuth purposes. Let's say its domain is www.google.com
I have the popup written like window.open('www.backend.com/api') in ReactJS.
The client button is something like this:
<button onClick={() => iveBeenClicked()}> sync up </button>
and then it runs this function
const iveBeenClicked = (e) => {
e.preventDefault()
const popupWindow = window.open('www.backend.com/api', "_blank")
}
oAuth and backend with ExpressJS
This is the backend which we'll say is www.backend.com/api
router.use("/api", (req, res) => {
if (req.query.code) {
res.send(res.query.code)
} else {
res.redirect(
`www.ApiRouteThatRedirectsWhenComplete.com`
);
}
});
Well I have the code I want, but how can I send that to the client from a different domain? If there's an alternative to window.open() where a user could press accept, please let me know.
So the big question is, how can client receive data from window.open's popup?
Thank you in advance!
#EDIT
So I finally got it thanks to #vishal-bartakke 's suggestion which I realized I implemented it wrong. I'm going to supply it here just in case it will help anyone that comes across this post.
for the ivebeenclicked() function in client side:
const iveBeenClicked = (e) => {
e.preventDefault()
const popupWindow = window.open('www.backend.com/api', "_blank")
//this is the part that was needed to receive the information of success
window.addEventListener('message', (e) => {
if (e.data) {
//do what you need to do with that key
}
})
}
in my expressjs's file:
router.use(['/api/', '/api/page?'], (req, res) => {
if (req.query.token) {
res.sendFile(path.join(__dirname +'/thatHTMLpage.html'))
} else {
res.redirect(`that route that does the oauth`)
}
})
In that html created upon success, I added this code to send in the data
window.onload = function () {
let urlParams = new URLSearchParams(window.location.search);
window.opener.postMessage(urlParams.get("code"), "*");
};
It is quite a messy setup but it works how I want it.
Thanks!
You can use postMessage (check here) to communicate between windows. In child window you can refer parent window as window.opener for posting message and in parent window you have popupWindow for posting
I am trying to read a music from my backend on chrome / firefox/a ionic projet.
I cant click the timeline to chose a time I want to go to when I'm listening on google chrome or ionic music player. The music just restart from 00:00 when I do so . I tried doing a request from postman and it could read the music correctly and set the time I wanted when I clicked the timeline , same on firefox (its working correctly). However it does not work on chrome, as I said the music just restart when you click the timeline. Here is my backend route :
EDIT1 : my only hint is when I use howler.js as my player, if I pass the HTML5= true its not gonna work and if I dont put it its working, even if its open on chrome... (https://www.npmjs.com/package/howler) or maybe a header is missing ?
getMusic(req, res) {
try {
var trackID = new ObjectID(req.params.trackID);
} catch (err) {
return res.status(400).json({ message: "Invalid trackID in URL parameter. Must be a single String of 12 bytes or a string of 24 hex characters" });
}
res.set('content-type', 'audio/mpeg');
res.set('accept-ranges', 'bytes');
let bucket = new mongodb.GridFSBucket(db, {
bucketName: 'tracks'
});
let downloadStream = bucket.openDownloadStream(trackID);
downloadStream.on('data', (chunk) => {
res.write(chunk);
});
downloadStream.on('error', () => {
res.sendStatus(404);
});
downloadStream.on('end', () => {
res.end();
});
},
The "Content-length" header was missing on this code and after trying it with a dummy it works. I just need to find how to get the music length now, so I close this post.
example res.set('content-length', '5000000');
I'm working on building a snippet manager app and through the interface you can create new snippets and edit them using a code editor but what I'm stuck at is how can I send the snippet code to my server using POST for it to create a new file for that snippet.
For ex. -
const getUser = async (name) => {
let response = await fetch(`https://api.github.com/users/${name}`);
let data = await response.json()
return data;
}
One solution that I can think of is to parse the code into JSON equivalent that'll contain all the tokens in JSON format but for that I'll have to add parsers for every language and select a parser based on what language the user selected. I'm trying to figure out a way to avoid having to add all the parsers unless there isnt any solution for this.
Another solution I can think of is to generate the file from the frontend and send that file through POST request.
My current stack is Node+React
Using the second solution is working for me right now. I've written the code below for it -
app.post("/create", isFileAttached, function(req, res) {
const { file } = req.files;
const saveLocation = `${saveTo}/${file.mimetype.split("/")[1]}`;
const savePath = `${saveLocation}/${file.name}`;
if (!fs.existsSync(saveLocation)) {
fs.mkdirSync(saveLocation, { recursive: true });
}
fs.writeFile(savePath, file.data.toString(), err => {
if (err) throw err;
res.status(200).send({ message: "The file has been saved!" });
});
});
With this solution I no longer have to add any parsers, since whatever's written in the files are no longer a concern anymore.
this particular Node issue has been driving me crazy for going on a week.
I have to create a layer of friction (a modal that asks the user if they're sure) in the process of a csv file upload. Essentially, the flow will be:
User Clicks 'UPLOAD SPREAD SHEET' > File uploads to s3 > S3 returns a reference key > Pass reference key into micro service web api to evaluate > if true => ask user 'if they're sure' > If user is sure continue uploading > pass reference key onward to another endpoint, same service, to finish the upload. false return would continue on to the upload with no modal.
its kind of a silly product-based functionality that makes a show of alerting the user to potential duplicate entries in their spreadsheet since we can't currently detect duplicate entries ourselves.
Problem is, I can't get a response to return from the evaluation to save my life. If I console.log the response, I can see it in Node's terminal window but nothing comes back in the network tab for the response. I'm not sure if it's because it's a file upload, if it's busyboy, if it's just not the right syntax for the response type but endless googling has brought me no answers and I'd love it if someone more experienced with Node and Express could take a look.
router.post('/import/csv',
// a bunch of aws s3 stuff to upload the file and return the key
s3.upload(uploadParams, (err, data) => {
if (err) {
res.status(500).send({
error_message: 'Unable to upload csv. Please try again.',
error_data: err
});
} else if (data) {
// creating the key object to pass in
const defaultImportCheck = {
body: data.Key
};
// endpoint that will evaluate the s3 reference key
SvcWebApiClient.guestGroup.defaultImportCheck(defaultImportCheck)
.then((response) => {
if (response.status === 'success') {
// where the response should be. this works but doesn't actually send anything.
res.send(response);
} else {
const errorJson = {
message: response.message,
category: response.category,
trigger: response.trigger,
errors: response.errors
};
res.status(500).send(errorJson);
}
})
.catch((error) => {
res.status(500).send({
error_message: 'Unable to upload csv. Please try again.',
error_data: error
});
});
}
});
});
req.pipe(busboy);
}
);
Got it, for anyone that ends up having my kind of problem. It's a two parter so buckle up.
1) the action function that handles the response on the react side didn't convert the response into json. Apparently, what would get returned is a "readable stream" which should have then converted to json. it didn't.
2) the response itself needed to be in json as well.
so from the action function:
export function csvUpload(file) {
do some stuff
return fetch(fetch some stuff) { with some parameters }
.then(some error stuff)
.then(response => response.response.json())
}
then from the post request:
if (response.status === "success") {
res.json({ valid: response.data, token: data.Key)};
}
this returns an object with what I need back to the client. hope this helps someone else.