Access SharePoint list from Node.js - node.js

I am trying to get SharePoint list items from Node.js app but I am still getting following error:
No XML to parse!
at new XmlDocument (C:\Users\xx\Desktop\AppTest2\node_modules\xmldoc\lib\xmldoc.js:247:11)
at C:\Users\xx\Desktop\AppTest2\node_modules\node-sp-auth\lib\src\utils\AdfsHelper.js:28:25
at processTicksAndRejections (node:internal/process/task_queues:96:5)
As you may see, I tried it with 'node-sp-auth' and 'sp-request' but result is the same.
Could it be some security or network related issue or do I miss something?
I tried the same http request via power automate and it was working.
Thanks for your help in advance.
var express = require('express');
var app = express();
const port = process.env.PORT || 3000;
//sharepoint auth libs
var spauth = require('node-sp-auth');
var request = require('request-promise');
var $REST = require("gd-sprest");
var url = "https://inoffice.sharepoint.com/sites/";
const credentialOptions =
{
username: "xx",
password: "oxxVMQOz",
online: true
};
const credentialOptions2 =
{
username: "yy",
password: "xxx",
online: true
};
var sprequest = require('sp-request');
let spr = sprequest.create(credentialOptions);
spr.get('https://inoffice.sharepoint.com/sites/DEV/_api/web/lists/GetByTitle(\'Users\')')
.then(response => {
console.log('List Id: ' + response.body.d.Id);
})
.catch(err =>{
console.log(err);
});
/*
spauth.getAuth(
url,
{
username: "WW_DEV_AAPeople_Mgmt#emea.adecco.net",
password: "oq&a#Dl59XVMQOz",
online: true
}
).then(options => {
// Log
console.log("Connected to SPO");
// Code Continues in 'Generate the Request'
});
*/

Related

WA business api nodejs

I have a problem with my nodejs code and the connection to the official whatsapp business api.
The bot connects the webhook correctly, the messages arrive to the server correctly but the code I have implemented to make it respond is not being effective, I checked the code from top to bottom but I can't find the fault.
I leave you the codes so you have more context:
whatsappController.js:
const fs = require("fs");
const myConsole = new console.Console(fs.createWriteStream("./logs.txt"));
const whatsappService = require("../services/whatsappService")
const VerifyToken = (req, res) => {
try {
var accessToken = "456E7GR****************************";
var token = req.query["hub.verify_token"];
var challenge = req.query["hub.challenge"];
if(challenge != null && token != null && token == accessToken){
res.send(challenge);
}
else{
res.status(400).send();
}
} catch(e) {
res.status(400).send();
}
}
const ReceivedMessage = (req, res) => {
try {
var entry = (req.body["entry"])[0];
var changes = (entry["changes"])[0];
var value = changes["value"];
var messageObject = value["messages"];
if(typeof messageObject != "undefined"){
var messages = messageObject[0];
var text = GetTextUser(messages);
var number = messages["from"];
myConsole.log("Message: " + text + " from: " + number);
whatsappService.SendMessageWhatsApp("The user say: " + text, number);
myConsole.log(messages);
myConsole.log(messageObject);
}
res.send("EVENT_RECEIVED");
}catch(e) {
myConsole.log(e);
res.send("EVENT_RECEIVED");
}
}
function GetTextUser(messages){
var text = "";
var typeMessage = messages["type"];
if(typeMessage == "text"){
text = (messages["text"])["body"];
}
else if(typeMessage == "interactive"){
var interactiveObject = messages["interactive"];
var typeInteractive = interactiveObject["type"];
if(typeInteractive == "button_reply"){
text = (interactiveObject["button_reply"])["title"];
}
else if(typeInteractive == "list_reply"){
text = (interactiveObject["list_reply"])["title"];
}else{
myConsole.log("sin mensaje");
}
}else{
myConsole.log("sin mensaje");
}
return text;
}
module.exports = {
VerifyToken,
ReceivedMessage
}
The second file is whatsappService which I make the connection with the api using the token and I also send the format of the message I want to send when I receive a hello for example...
const https = require("https");
function SendMessageWhatsApp(textResponse, number){
const data = JSON.stringify({
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": number,
"type": "text",
"text": {
"preview_url": false,
"body": textResponse
}
});
const options = {
host:"graph.facebook.com",
path:"/v15.0/1119744*************/messages",
method:"POST",
body:data,
headers: {
"Content-Type":"application/json",
Authorization:"Bearer EAAWNbICfuWEBAK5ObPbD******************************************************"
}
};
const req = https.request(options, res => {
res.on("data", d=> {
process.stdout.write(d);
});
});
req.on("error", error => {
console.error(error);
});
req.write(data);
req.end();
}
module.exports = {
SendMessageWhatsApp
};
Then I declare the routes for the get (to check token) and post (to receive and reply to messages) methods:
const expres = require("express");
const router = expres.Router();
const whatsappController = require("../controllers/whatsappControllers");
router
.get("/", whatsappController.VerifyToken)
.post("/", whatsappController.ReceivedMessage)
module.exports = router;
Last but not least the index file for the code to run correctly:
const express = require("express");
const apiRoute = require("./routes/routes");
const app = express();
const PORT = process.env.PORT || 3000
app.use(express.json());
app.use("/whatsapp", apiRoute);
app.listen(PORT, () => (console.log("El puerto es: " + PORT)));
I should clarify that I did the tests with Postman and they were all successful, it responds and receives messages correctly, finally I did the tests by uploading the bot to the Azure service and it works without problem until it has to answer/replicate the user's message.
The bot is not responding to the user when he talks to it but everything arrives correctly to the server and it processes it with a 200 response. I attach the evidence that there is no problem in the reception.
Finally I must say that in the meta platform I have everything configured as specified by the same platform, I have already configured the api to answer the messages through the webhooks and everything is correct, I just can't get the bot to answer correctly.
The bot is hosted in the Azure service.
Solved: some numbers have a problema with the api of WAB in my country (Argentina) the phone numbers start in +54 9 11. The problem is the 9 in the phone number, and this have a conflict in the servers of meta, Solution quit number 9 to numbers of this country and the message will send to user.

Getting Express error via localhost, Error Cannot GET / or GET /sms

I'm a huge sneaker head and getting my feet wet in node and express and I'm trying to create an app using Twilio to text me when a certain shoe decreases in price and the shoe is triggered by replying "Track (SKU)" to add it to the database. I have it completely written and when I input "node index.js", it connects to my localhost just fine, but when I input http://localhost:3000/sms, I get Cannot GET /sms. I've been trying to look for a fix by trying to find some videos or if someone has done a similar project to model off of, but no luck. Is anyone familiar with creating Twilio apps with express servers able to help me out? My current index.js is below.
const SneaksAPI = require('sneaks-api');
const sneaks = new SneaksAPI();
const express = require('express');
const app = express();
app.use(express.urlencoded({ extended: false }));
const MessagingResponse = require('twilio').twiml.MessagingResponse;
const Subscribers = [
{
"number": 2025550121,
"styleID": "FY2903",
"lastResellPrice": 475
},
{
"number": 1234567890,
"styleID": "DD0587-600",
"lastResellPrice": 285
}
];
app.post('/sms', function (req, res) {
const twiml = new MessagingResponse();
const SMS = twiml.message();
const recievedSMS = req.body.Body.toLowerCase().trim();
const firstWord = recievedSMS.split(" ")[0];
if (firstWord == 'track'){
const styleID = recievedSMS.split(" ")[1] || null;
if(styleID){
const sneaker = sneaksApiFunctionWrapper(styleID);
if(!sneaker){
SMS.body("Sneaker could not be found");
} else {
const sub = {
"number": req.body.From,
"styleID": sneaker.styleID,
"lastResellPrice": sneaker.price
};
Subscribers.push(sub);
SMS.media(sneaker.image);
SMS.body(`Current lowest price for ${sneaker.name} is $${String(sneaker.price)} at ${sneaker.site}: ${sneaker.url}\nYou will be notified when the price drops. Reply STOP to opt-out of alerts.`);
}
}
} else {
SMS.body('To start tracking a sneaker, text \"track\" followed by the sneaker ID.');
}
res.writeHead(200, {'Content-Type': 'text/xml'});
res.end(twiml.toString());
});
function sneaksApiFunctionWrapper(styleID) {
return new Promise((resolve, reject) => {
sneaks.getProductPrices(styleID, function(err, product){
const lowestResellSite = Object.keys(product.lowestResellPrice).reduce((a, b) => product.lowestResellPrice[a] > product.lowestResellPrice[b] ? a : b);
const sneaker = {
name: product.shoeName,
image: product.thumbnail,
site: lowestResellSite,
price: product.lowestResellPrice[lowestResellSite],
url: product.resellLinks[lowestResellSite],
styleID: product.styleID
};
resolve(sneaker);
}, (errorResponse) => {
reject(errorResponse);
});
});
}
app.listen(3000, () => {
console.log('Express server listening on port 3000');
});```
You are using a POST request via app.post(), which is different from a GET request. You'll need to submit data via a form or apps like Postman to properly access the POST request.
When should I use GET or POST method? What's the difference between them? This gives a solid response.

node-media-server: session.reject() not working

I am trying to create an RTMP-server with the npm package: http://github.com/illuspas/Node-Media-Server. So the server works fine but I need to implement authentication in it. I am trying to check the authentication on "prePublish" event. I am querying the database and retrieving the user if the user was found then I want to let the user stream otherwise rejected. But the problem is, it doesn't leave it instead disconnects and then the stream automatically reconnected to it then it disconnects again and the loop goes on. How do I fix this problem?
Here is the code for the event:
const NodeMediaServer = require('node-media-server');
const config = require('./config').rtmp_server;
const db = require('./db');
const nms = new NodeMediaServer(config);
const getStreamKeyFromStreamPath = (path) => {
const parts = path.split('/');
return parts[parts.length - 1];
};
nms.on('prePublish', async (id, StreamPath, args) => {
const session = nms.getSession(id);
try {
const streamKey = getStreamKeyFromStreamPath(StreamPath);
const validStream = (
await db.query('SELECT * FROM public."People" WHERE stream_key = $1', [streamKey])
).rows[0];
console.log(validStream);
if (validStream) {
// do stuff
} else {
session.reject((reason) => {
console.log(reason);
});
}
console.log(
'[NodeEvent on prePublish]',
`id=${id} StreamPath=${StreamPath} args=${JSON.stringify(args)}`
);
} catch (err) {
session.reject();
}
});
module.exports = nms;
Here is the code of the entry point of the server:
require("dotenv").config();
const db = require("./db");
const nms = require("./nms");
// database connection
db.connect()
.then(() => {
console.log("Connected to database");
// start the rtmp server
nms.run();
})
.catch((err) => console.log(err.message));
Here is the db file:
const { Pool } = require('pg');
const connectionString = process.env.PG_CONNECTION_STRING;
const poolOptions = {
host: process.env.PG_HOST,
user: process.env.PG_USER,
port: process.env.PG_PORT,
password: process.env.PG_PASSWORD,
database: process.env.PG_DATABASE,
};
const pool = new Pool(process.env.NODE_ENV === 'production' ? connectionString : poolOptions);
module.exports = pool;
My procedures to solve that problem:
Instead of the async function, I tried to handle the database query using a callback but it didn't work.
Before I was calling session.reject() now I am passing a callback there but the behavior is still the same
If you have any solution for that, please let me know.
Thanks in advance

Duplicate Log Messages in Azure App Service

I have an Azure App Service as a backend that is written using Node currently with verbose logging enabled. Within the application logs, I seem to always get duplicate log messages for various requests.
2018-02-28T16:26:33 PID[22384] Verbose Received request: GET https://appname.azurewebsites.net/tables/TableOne?$filter=(email%20eq%20'stevejohns%40gmail.com')
2018-02-28T16:26:33 PID[22384] Verbose Received request: GET https://appname.azurewebsites.net/tables/TableOne?$filter=(email%20eq%20'stevejohns%40gmail.com')
I have confirmed this issue isn't in my mobile application as the result is the same if I send a request from Postman. This leads me to believe I somehow have a second instance of something running in the service. I've looked through Kudu as much as possible but haven't come across any indication that would cause this logging issue.
Please see below for my current app.js and TableOne.js files.
Any tips are much appreciated!
app.js
var express = require('express'), azureMobileApps = require('azure-mobile-apps');
var app = express();
var mobile = azureMobileApps({
homePage: true
});
mobile.tables.import('./tables');
mobile.api.import('./api');
mobile.tables.initialize()
.then(function () {
app.use(mobile);
app.listen(process.env.PORT || 3000);
});
TableOne.js
var azureMobileApps = require('azure-mobile-apps');
var table = azureMobileApps.table();
table.access = 'authenticated';
table.name = 'TableOne';
table.maxTop = 1000;
table.softDelete = false;
table.dynamicSchema = false;
table.columns = {
firstname: 'string',
lastname: 'string',
email: 'string',
profilepictureurl: 'string',
phonenumber: 'string'
};
table.insert(function (context) {
return context.execute();
});
table.read(function (context) {
return context.execute();
});
table.update(function (context) {
return context.execute();
});
table.delete(function (context) {
return context.execute();
});
module.exports = table;

UCWA Lync authentication - 500 web ticket is invalid

I'm trying to create a simple client for Lync using Nodejs.
Base on http://ucwa.lync.com/documentation/KeyTasks-CreateApplication I've made someting like this.
It works until last step #9 when I should register my app with UCWA. Server responds with code 500 and silly explanation
There is a problem with the resource you are looking for, and it cannot be displayed
And headers
x-ms-diagnostics': '28032;source="mysource";reason="The web ticket is invalid."'
var http = require('request-promise');
var lync = {};
lync.setup = function(email, password){
var self = this;
var hostname = email.split('#');
this.username = email;
//discover urls
return http.get('http://lyncdiscover.'+hostname[1])
.then(function(d) {
var parsed = JSON.parse(d);
self.urls = {
self: parsed._links.self.href,
user: parsed._links.user.href,
xframe: parsed._links.xframe.href
};
return http.get(self.urls.user);
}).catch(function(err){
if(err.statusCode == 401){
var toParse = err.response.headers['www-authenticate'];
var Oauth = toParse.match(/https:\/\/[\d\w\./_-]*/i)[0];
var loginPost = {
grant_type: 'password',
username: email,
password: password
};
return http.post(Oauth, {form:loginPost});
}
return false
}).then(function(data){
var parsed = JSON.parse(data);
//setup authorization
http = http.defaults({
headers: {Authorization: parsed.token_type + ' ' + parsed.access_token}
});
//console.log(self.urls.user);
//console.log('Authorization:'+ parsed.token_type + ' ' + parsed.access_token);
return http.get(self.urls.user);
}).then(function(data){
var parsed = JSON.parse(data);
self.urls.applications = parsed._links.applications.href;
var registerApp = {
culture : "en-us",
endpointId : "2d9dc28d-4673-4035-825c-feb64be28e4e",
userAgent : "Test"
};
var r = "{'userAgent': 'NodeJs', 'endpointId' : '2d9dc28d-4673-4035-825c-feb64be28e4e', 'culture': 'en-US'}";
return http.post(self.urls.applications, {body: registerApp, json:true});
})
.then(function(data){
console.log(data);
})
.catch(function(err){
console.log(err);
return false;
});
};
//run app
lync.setup('login#domain.com', 'password').then(function(ret){
});
One key point here. It's not my server. I just have an account over there and I can login with official Lync client or Pidgin plugin.
Are there some extra steps to "allow" my app to work with UCWA?
#ShelbyZ
I can easily authorize using Oauth. I'm receiving authorization token so I'm logged in.
I'm receiving json similar to
"_links":{
"self":{"href":"link"},
"applications":{"href":"i need this"},
"xframe":{"href":"link"}
} }
Now. I need to "register my application" doing POST.
In this last step I get 500 code response.
I hope It's not related with that #Matthew Proctor said..
becouse I cannot simple administrate the server
Thank you #ShelbyZ
You were right, it was split-domain scenario. Now authorization works, and I can register my app. Also example for future generations
var http = require('request-promise');
var lync = {};
lync._authorize = function(){
var self = this;
var orgDomain = self.urls.user.match(/https:\/\/([\w\d\.]+)/i)[0];
//console.log(orgDomain);
http.get(self.urls.user).catch(function(err){
if(err.statusCode == 401){
var toParse = err.response.headers['www-authenticate'];
var Oauth = toParse.match(/https:\/\/[\d\w\./_-]+/i)[0];
var loginPost = {
grant_type: 'password',
username: self.username,
password: self.password
};
return http.post(Oauth, {form:loginPost});
}
}).then(function(data){
if(data) {
var parsed = JSON.parse(data);
//setup authorization
http = http.defaults({
headers: {Authorization: parsed.token_type + ' ' + parsed.access_token}
});
return http.get(self.urls.user);
}
}).then(function(data){
//check for split-domain scenario
var parsed = JSON.parse(data);
var domain = parsed._links.self.href.match(/https:\/\/([\w\d\.]+)/i)[0];
console.log('[1] '+orgDomain);
console.log('[2] '+domain);
if(domain!== orgDomain){
//split domain scenario
self.urls.user = self.urls.user.replace(orgDomain, domain);
http = http.defaults({
headers: {Authorization: null}
});
self._authorize();
} else { //create app
var parsed = JSON.parse(data);
self.urls.applications = parsed._links.applications.href;
var registerApp = {
culture : "en-us",
endpointId : "2d9dc28d-4673-4035-825c-feb64be28e4e",
userAgent : "NodeJs client"
};
return http.post(self.urls.applications, {body: registerApp, json:true});
}
}).then(function(app){
console.log(app);
});
};
lync.setup = function(email, password){
var self = this;
var hostname = email.split('#');
this.username = email;
this.password = password;
//discover urls
return http.get('http://lyncdiscover.'+hostname[1])
.then(function(d) {
var parsed = JSON.parse(d);
self.urls = {
self: parsed._links.self.href,
user: parsed._links.user.href,
xframe: parsed._links.xframe.href
};
return self._authorize();
});
};
//run app
lync.setup('username#domain.com', 'password');
I was getting the same error before I added my test domain to the list of Allowed Domains.
This can be updated via PowerShell, full details below:
Enabling UCWA and Configuring Allowed Domains
I've had clients see similar errors when running my code from http://localhost/, their fix was to test their code on a FQDN (ie http://testmyucwacode.mydomain.com/).

Resources