how to extract data from spotify npm package? I keep getting undefine - node.js

===================This is my code below=========================
function spotifyThisSong() {
var spotify = new Spotify({
id: 'myid',
secret: 'mysecret'
});
var songName = process.argv[3];
if(!songName){
songName = "What's my age again";
}
var params = songName;
spotify.search({ type: 'track', query: params }, function(err, data) {
if ( err ) {
console.log('Error occurred: ' + err);
return; //from spotify npm docs
}
else{
console.log(data);
};
});
}
===================END OF CODE=========================
keeps giving me undefine. I need to extract the song name, year, album and its url. Thanks in advance.

//So this is what I found. This actually involves a few things.
//FIRST, capture user-input,
//SECOND, npm install spotify, and use the template as suggested in the DOCS.
//THIRD, parse through the JSON correctly as done below.
//HOPE this helps someone. (dont forget your keys from spotify)
var songName = process.argv[3]; //capture userInput and query it below
params = songName;
spotify.search({ type: 'track', query: params }, function(err, data) {
if ( err ) {
console.log('Error occurred: ' + err);
return;
}
else{
output = space + "================= DATA HERE ==================" +
space + "Song Name: " + "'" +songName.toUpperCase()+ "'" +
space + "Album Name: " + data.tracks.items[0].album.name +
space + "Artist Name: " + data.tracks.items[0].album.artists[0].name +
space + "URL: " + data.tracks.items[0].album.external_urls.spotify + "\n\n\n";
console.log(output);
};
});

Related

Canva publish extension API : Endpoint never get call

I try to make a Canva App with a publish extension.
I just follow the Quick start (https://docs.developer.canva.com/apps/extensions/publish-extensions/quick-start) with Glitch and it work well on it.
But when I try to put in on my own public host name, with a other port (like http://mydomaine.com:3000) Canva NEVER call my endpoint. I just write a log file of every action on my app post and I never get a update on it, and when I try the app on Canva.com it just show me a error message.
//Copy from the Quick Start
app.post('/publish/resources/upload', async (request, response) => {
try{
writeLog("Uploading file");
await fs.ensureDir(path.join(__dirname, 'export'));
// Get the first asset from the "assets" array
const [asset] = request.body.assets;
// Download the asset
const image = await jimp.read(asset.url);
const filePath = path.join(__dirname, 'export', asset.name);
await image.writeAsync(filePath);
// Respond with the URL of the published design
response.send({
type: 'SUCCESS',
url: url.format({
protocol: request.protocol,
host: request.get('host'),
pathname: asset.name,
}),
});
} catch (err) {
writeLog("ERROR (app.post('/publish/resources/upload'): " + err);
}
});
//Just log on the log file
function writeLog(log){
// fs.appendFile(path.join(__dirname, '/log/' + `${month}/${date}/${year}` +'log.txt'), dateDisplay + "|" + log + "\n", (err) => {
// if (err) throw err;
// });
var today = new Date();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
var dateTime = date + ' ' + time;
natifFS.appendFile('log.txt', dateTime + '| '+ log + "\n", (err) => {
if (err) throw err;
});
}
Last thing, when I try to call a post request on the same endpoint as Canva (/publish/resources/upload) with Postman, I get a update on my log.txt file
If anyone has idea, thank you.

nodejs POST request.post not working

I need to use request.post for sending a value to a server.
The url is: http://192.168.0.100/control/thermostat.cgi?param=thermostat_manualsetpoint
Value to send as plain text: 2000
Until now I've tried something like this, but it's not working:
a button in the app that should POST the temperature value:
HEAT17 : { states: [{ label:'Heat:17°', action:'', icon:'fa-fire',
serverExecute:function(node){
var targetNow=0, modeNow='';
var thejson = '2000';
var param = 'thermostat_manualsetpoint';
exports.tstatRequest(param, thejson, node._id);
},
}],
breakAfter:true,
},
The function exports.tstatRequest is:
exports.tstatRequest = function(param, thejson, nodeId) {
//console.log('tstatRequest:' + JSON.stringify(thejson));
db.findOne({ _id : nodeId }, function (err, dbNode) {
var thermostatIP = dbNode.settings && dbNode.settings.ip ? dbNode.settings.ip : (exports.motes[dbNode.type].settings.ip || settings.radiothermostat.ip.value);
//console.log('URL: ' + 'http://'+thermostatIP+'/control/thermostat.cgi?param=' + param);
request.post({ url: 'http://'+thermostatIP+'/control/thermostat.cgi?param=thermostat_manualsetpoint', body:'2000'},
function(error,response,body){
console.log('BODY: ' + JSON.stringify(response));
if (error) console.log('ERROR in tstatRequest(): ' + JSON.stringify(thejson) + ' nodeId:' + nodeId + ' - ' + error);
else exports.tstatPoll(nodeId); //now ask for a refresh of status from thermostat (HTTP GET)
}
);
});
}
I've tried in Advanced REST Client and the post query works like this:
Test query

Angular download file from byte array sent from node.js

I think I'm very close to what I want to do. I have the following api get method in node.js that is retrieving a file varbinary(MAX) from an SQL Server database. It was converted from a base64 encoded string before inserted so the Content Type information was stripped from the string.
node.js
router.get('/getFile', (req, res) => {
console.log("Calling getFile for file " + req.query.serialNumber + ".")
var serialNumber = req.query.serialNumber;
let request = new sql.Request(conn);
request.query('SELECT FileName + \'.\' + FileExtension AS \'File\', FileType, ContentType, SerialNumber, Chart ' +
'FROM dbo.ChangeFiles ' +
'WHERE SerialNumber = ' + serialNumber)
.then(function (recordset) {
log("Successfully retrieved file " + recordset[0].SerialNumber + " from database.");
log("Length of blob " + recordset[0].File + " is " + recordset[0].Chart.length)
res.status(200);
res.setHeader('Content-Type', recordset[0].ContentType);
res.setHeader('Content-Disposition', 'attachment;filename=' + recordset[0].File);
res.end(Buffer.from((recordset[0].Chart)));
}).catch(function (err) {
log(err);
res.status(500).send("Issue querying database!");
});
});
That works fine, but what to do in Angular to retrieve it and prompt for a download for the user has not been clear for me, nor has there been a lot as far as help/resources online. Here is what I have so far in my service class.
fileDownload.service.ts
downloadFile(serialNumber: string): Observable<any> {
return this.http.get(this.baseURL + '/getFile', { params: { serialNumber: serialNumber } })
.map(this.extractFile);
}
private extractFile(response: Response) {
const file = new Blob([response.blob]);
FileSaver.saveAs(file);
// const url = window.URL.createObjectURL(file);
// window.open(url);
return file;
}
As you can see I've tried a couple of approaches. The commented out portion of the extractFile method didn't work at all, and using the FileSaver.saveAs function produces a file download of an unknown type, so the headers sent from node.js didn't seem to affect the file itself.
Would someone be able to advise how to proceed in Angular with what is successfully being sent from node.js so that I can successfully download the file, regardless of type?
Thanks so much in advance.
I got it working afterall. I had to rework the api call so that it sent all of the file information separately so that the MIME type, and file name can be assigned to the file on the client side in the component class. For some reason when I tried to do so all in the api, it wouldn't work so that was my work around. So here is what works for me.
node.js api
router.get('/getFile', (req, res) => {
console.log("Calling getFile for file " + req.query.serialNumber + ".")
var serialNumber = req.query.serialNumber;
let request = new sql.Request(conn);
request.query('SELECT FileName + \'.\' + FileExtension AS \'File\', FileType, ContentType, SerialNumber, Chart ' +
'FROM dbo.ChangeFiles ' +
'WHERE SerialNumber = ' + serialNumber)
.then(function (recordset) {
log("Successfully retrieved file " + recordset[0].SerialNumber + " from database.");
log("Length of blob " + recordset[0].File + " is " + recordset[0].Chart.length)
res.send(recordset[0]);
}).catch(function (err) {
log(err);
res.status(500).send("Issue querying database!");
});
});
component class
downloadFile(serialNumber: string): void {
this.changeService.downloadFile(serialNumber).subscribe((res: any) => {
const ab = new ArrayBuffer(res.Chart.data.length);
const view = new Uint8Array(ab);
for (let i = 0; i < res.Chart.data.length; i++) {
view[i] = res.Chart.data[i];
}
const file = new Blob([ab], { type: res.ContentType });
FileSaver.saveAs(file, res.File);
console.log(res);
});
}
service class
downloadFile(serialNumber: string): Observable<any> {
return this.http.get(this.baseURL + '/getFile', { params: { serialNumber: serialNumber } })
.map(this.extractFile);
}
private extractFile(response: Response) {
// const file = new Blob([response.blob]);
// FileSaver.saveAs(file);
// const url = window.URL.createObjectURL(file);
// window.open(url);
const body = response.json();
return body || {};
}
Update your code to call subscribe instead of map

How to add ics file events in calendar using nodejs

There is a scenario where I need to send event meeting invites to end users. I am able to generate the ICS file and send it as attachment. But the ICS files are not readable or added in User Calander.
Code to generate and send email is as below:
var transport = require('nodemailer-smtp-transport'),
transporter = nodemailer.createTransport(transport(config.mailer)),
sendMail = function(mailOptions) {
transporter.sendMail(mailOptions, function(err, response) {
if (err) return err;
return response;
});
},
eventEmailToUser = function(user, events, createdBy, mailOptions) {
var ical = require('ical-generator');
var cal = ical();
var username = user.username ? user.username : ' ';
var eventName = events.title ? events.title : ' ';
var eventDate = moment.tz(events.date, 'Asia/Kolkata');
eventDate = eventDate.format('YYYY-MM-DD h:mm a');
cal.addEvent({
start: new Date(),
end: new Date(new Date().getTime() + 3600000),
summary: events.title,
uid: events._id, // Some unique identifier
sequence: 0,
description: events.description,
location: events.location,
organizer: {
name: createdBy.username,
email: createdBy.email
},
method: 'request'
});
var path = '/files/' + events._id + '.ics';
cal.save(path, function(err, file) {
if (err) return err;
});
mailOptions.alternatives = [{
contentType: "text/calendar",
contents: new Buffer(cal).toString()
}];
mailOptions.attachments = [{
filename: events.title + '.ics',
filePath: path
}];
mailOptions.html = [
'<div>',
'<div>Hi <b>' + username + '</b><br/<br/>',
' You have just confirmed to attend <b>' + eventName + '</b> on <b>' + eventDate + '</b>',
' <br/><br/>',
'Thanks',
' <br/>',
'</div>',
'<br/>',
'</div>'
].join('\n\n');
mailOptions.subject = 'Invitation for' + eventName;
return mailOptions;
};
exports.sendInvite = function(req, res) {
var userMailOptions = {
to: 'abc#gmail.com',
from: 'xyz#gmail.com',
};
userMailOptions = eventEmailToUser(user, events, eventCreator, userMailOptions);
var userEmailresult = sendMail(userMailOptions);
};
The first issue that strikes me is that you are missing an ATTENDEE property which is required in any iMIP REQUEST.
There might be other issues but we would need to see your full MIME message instead of your code to really spot those. As a starter, you might want to doublecheck Multipart email with text and calendar: Outlook doesn't recognize ics

NodeJS - Modularising SQLite3

I like to split out my code where possible - and having SQL in a route makes me cringe.
Node JS is new to me and I'm learning it at the moment, but I'm having a problem with the following (the page just hangs and doesn't serve anything).
It makes sense to me with my current level of knowledge - but I imagine there will be a better way of doing this.
Thank you for taking the time for reading this, and your help is greatly appreciated.
Route
var express = require('express');
var router = express.Router();
var db = require('../lib/db.js');
var model = require('../models/contacts.js');
/* GET contacts. */
router.get('/', function(req, res) {
// Get data from model - RETURN THE ROWSET HERE
model.get_names(db, function(rowset) {
res.render('contacts', {
title: 'Contacts | Rhubarb',
nav_active: "contacts",
}, function(err, output) {
res.status(200).send(rowset);
}); // res.render
}); // model.get_names
}); // router
module.exports = router;
Model
module.exports.get_names = function(db) {
var sql = " SELECT attr_name " +
" , attr_value " +
" FROM contacts a " +
" , contact_attributes b " +
" WHERE a.contact_id = b.contact_id " +
" AND (attr_name = 'forename' OR attr_name = 'surname')";
db.all(sql, function(err, rowset) {
if (err) throw err;
return rowset;
}); // db.all
} // get_names
Sorted it by adding an actual call back to the function... sigh...
module.exports.get_names = function(db, callback) {
var sql = " SELECT attr_name " +
" , attr_value " +
" FROM contacts a " +
" , contact_attributes b " +
" WHERE a.contact_id = b.contact_id " +
" AND (attr_name = 'forename' OR attr_name = 'surname')";
return db.all(sql, function(err, rowset) {
if (err) throw err;
return callback(rowset);
});
}

Resources