Connect Node.js BOT to MS Azure SQL database - node.js

I have a working MS Teams bot written in Node.js. The bot asks a series of questions and currently displays the responses at the end by accessing the session variables. All well and good.
Now I am attempting to store the session variables in a MS Azure SQL DB. The DB is correctly set up in Azure as I can access and write data to it in SSMS. But I believe I am probably connecting incorrectly to the DB in my bot code. The bot code I am using is pulled from:
connecting to SQL using Node.js
That code makes sense to me. But how do I use that code in my bot? Here is what I have attempted thus far...
Currently I am using the local memory MemoryBotStorage() and setting to that.
var inMemoryStorage = new builder.MemoryBotStorage();
.set('storage', inMemoryStorage)
In another Microsoft article dealing with the Azure Cosmos DB it states "4.Specify that you want to use your custom database instead of the in-memory storage." So from this I deduce that I hafta add my instantiated sql db to the .set('storage', DB Goes Here) but my attempts have failed and I am not sure if I am even correct?
So my question is how do I correctly access the Azure sql server DB form my bot code - and is the link I provided even the correct way?
Thank you
Note - This code sample worked for me - I was able to connect and query my Azure DB - but it is only DB code and does not take into consideration bot code.
EDIT - Code:
const builder = require('botbuilder');
const builderTeams = require('botbuilder-teams');
const restify = require('restify');
const connector = new builderTeams.TeamsChatConnector(
{
appId: "My app ID,
appPassword: "My App PW",
}
);
var inMemoryStorage = new builder.MemoryBotStorage();
const bot = new builder.UniversalBot(connector, [
function (session) {
session.send("Welcome.");
builder.Prompts.text(session, "Question1?");
},
function (session, results) {
session.dialogData.question1 = results.response;
builder.Prompts.text(session, "Question2?");
},
function (session, results) {
session.dialogData.Question2 = results.response;
builder.Prompts.text(session, "Question3?");
},
function (session, results) {
session.dialogData.Question3 = results.response;
// Begin DB
var Connection = require('tedious').Connection;
var config = {
userName: 'myusername',
password: 'mypw',
server: 'myserver.database.windows.net',
// If you are on Azure SQL Database, you need these next options.
options: { encrypt: true, database: 'mydb' }
};
var connection = new Connection(config);
connection.on('connect', function (err) {
// If no error, then good to proceed.
console.log("Connected");
executeStatement1();
});
var Request = require('tedious').Request
var TYPES = require('tedious').TYPES;
function executeStatement1() {
request = new Request("INSERT my (Username, Question1, Question2, Question3, StatusDate) VALUES (#Username, #Question1, #Question2, #Question3, CURRENT_TIMESTAMP);", function (err) {
if (err) {
console.log(err);
}
});
request.addParameter('Username', TYPES.NVarChar, session.userData.userName);
request.addParameter('Question1', TYPES.NVarChar, session.dialogData.Question1);
request.addParameter('Question2', TYPES.NVarChar, session.dialogData.Question2);
request.addParameter('Question3', TYPES.NVarChar, session.dialogData.Question3);
request.on('row', function (columns) {
columns.forEach(function (column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log("ID of inserted item is " + column.value);
}
});
});
connection.execSql(request);
// End DB
// Process request and display details
session.endDialog();
}
]).set('storage', inMemoryStorage)
const server = restify.createServer();
server.post('api/messages', connector.listen());
server.listen(portnumber)
Error when running with npm start:
npm start
> simplebot#1.0.0 start C:\Developer\dailyStatus
> node index.js
C:\Developer\dailyStatus\index.js:81
]).set('storage', inMemoryStorage)
^
SyntaxError: Unexpected token ]
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:616:28)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
at startup (bootstrap_node.js:188:16)
at bootstrap_node.js:609:3
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! simplebot#1.0.0 start: `node index.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the simplebot#1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely...
npm ERR! A complete log of this run can be found in:
npm ERR! C: etc.
FINAL
I was able to able to get this working with this tutorial. Thanks also to Marc LeFleur.

You have several typos. For example, you're missing the closing " on appId:
const connector = new builderTeams.TeamsChatConnector(
{
appId: "My app ID",
appPassword: "My App PW",
}
);
You also can't declare the function executeStatement1() {...} function within the your IDialogWaterfallStep function. This needs to live outside the constructor and called from the IDialogWaterfallStep.

Related

How to solve this Error: Cannot find module 'ibm-watson'

I have installed ibm-watson using "npm install ibm-watson" command
I can see the folder and its file in the node_modules folder, but still showing this error.
Node version - v10.15.3
const watson = require('ibm-watson');
const { IamAuthenticator } = require('ibm-watson/auth');
const { BasicAuthenticator } = require('ibm-watson/auth');
// to get an IAM Access Token
const authorization = new watson.AuthorizationV1({
authenticator: new IamAuthenticator({ apikey: 'fakekey-1234' }),
});
authorization.getToken(function (err, token) {
if (!token) {
console.log('error: ', err);
} else {
// Use your token here
}
});
Other modules are importing fine, Only this module not importing.
internal/modules/cjs/loader.js:584
throw err;
^
Error: Cannot find module 'ibm-watson'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)
at Function.Module._load (internal/modules/cjs/loader.js:508:25)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object.<anonymous>
I've just faced this issue. I did not install the correct version of the package. Please check the apidocs for Node to see the correct version of IBM Watson npm package that you need. for me I needed 5.6.0.
You can install it with the following command:
npm install ibm-watson#^5.6.0
As you are getting a token, I am going to guess that you are using Speech To Text. As the comments have suggested the failing line is const watson = require('ibm-watson'); because it isn't exported. Instead you would use, as per the API documentation - https://cloud.ibm.com/apidocs/speech-to-text/speech-to-text?code=node#authentication:
const SpeechToTextV1 = require('ibm-watson/speech-to-text/v1');
const { IamAuthenticator } = require('ibm-watson/auth');
const { IamTokenManager } = require('ibm-watson/auth');
If it's not STT that you are using then the other services work the same way when requiring ibm-watson. Links to the API Docs can be found here - https://cloud.ibm.com/apidocs
I faced the same problem. 
After reading the code, I understood.
There is only sdk.ts file, not index.ts file.
https://github.com/watson-developer-cloud/node-sdk
// const watson = require('ibm-watson');
const watson = require('ibm-watson/sdk');
But I still got the error.
Eventually it worked if I wrote the following
import AuthorizationV1 from 'ibm-watson/authorization/v1'
import { IamAuthenticator } from 'ibm-watson/auth'
const apikey = '********'
const authorization = new AuthorizationV1({
url: 'https://iam.cloud.ibm.com/identity/token',
authenticator: new IamAuthenticator({ apikey }),
})
authorization.getToken(function (err, token) {
if (!token) {
console.log('error: ', err);
} else {
// Use your token here
}
});
But there is a CORS problem. I don't know any more.
The answer was written here. I need to do it on the server side
https://github.com/watson-developer-cloud/node-sdk/issues/884#issuecomment-515050023

Connection to oracle database via nodeJS

I'm trying to establish an Oracle connection using NodeJS but while trying to connect i am receiving below error.
Error: Error: DPI-1047: Cannot locate a 64-bit Oracle Client library: "The specified module could not be found". See https://oracle.github.io/odpi/doc/installation.html#windows for help
Node-oracledb installation instructions: https://oracle.github.io/node-oracledb/INSTALL.html
You must have 64-bit Oracle client libraries in your PATH environment variable.
If you do not have Oracle Database on this computer, then install the Instant Client Basic or Basic Light package from
http://www.oracle.com/technetwork/topics/winx64soft-089540.html
A Microsoft Visual Studio Redistributable suitable for your Oracle client library version must be available.
at OracleDb.getConnection (C:\NodeCon\node_modules\oracledb\lib\oracledb.js:270:10)
at C:\NodeCon\node_modules\oracledb\lib\util.js:180:16
at new Promise (<anonymous>)
at OracleDb.getConnection (C:\NodeCon\node_modules\oracledb\lib\util.js:168:14)
at C:\NodeCon\server.js:41:32
at Object.<anonymous> (C:\NodeCon\server.js:58:3)
at Module._compile (internal/modules/cjs/loader.js:956:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
at Module.load (internal/modules/cjs/loader.js:812:32)
at Function.Module._load (internal/modules/cjs/loader.js:724:14) {
errorNum: 0,
offset: 0
I've downloaded and installed 64 bit Oracle Client Library but still below error appears.
Using Visual Studio Code v.1.36 as my editor.
NodeJS code i'm using is as below :
let connection;
var oracledb = require('oracledb');
(async function(){
try{
connection = await oracledb.getConnection({
user: 'Username',
password: 'Password',
connectString: 'hostname:portname/servicename'
});
console.log("Successfully connected");
} catch(err){
console.log("NOT connected");
}finally{
if(connection){
try{
await connection.close();
}catch(err){
console.log("Errror");
}
}
}
})()
Any help will be much appreciated. Thanks.
This got resolved by following code:
oracledb.getConnection({
user: 'username',
password: 'Password',
connectString: 'hostname:portname/servicename'
},
function(err, connection) {
if (err) throw err;
connection.execute(
//Your database query here.
//below code if you want to fetch data from database and show it on terminal
function(err,results){
var metaData = {};
var rows = {};
console.log("error")
if (err){
throw err
}
metaData.name1 = results.metaData[0].name;
metaData.name2 = results.metaData[1].name;
rows.row1 = results.rows[0][0];
rows.row2 = results.rows[0][1];
rows.row3 = results.rows[0][2];
console.log(metaData.name1+" : "+rows.row1)
console.log(metaData.name2+" : "+rows.row2)
console.log("Successfully connected");
);
}
And if you're connecting via VPN make sure to connect to the server first then run above.

Could not connect with MongoLab database URl using node.js and Heroku

I could not connect to MongoDB which is present in MongoLAB . I have one MEAN app and I have deployed in heroku. When I am trying to connect with database but could not. The logs are given below.
Disconnected from log stream. There may be events happening that you do not see here! Attempting to reconnect...
2017-07-31T11:46:48.243603+00:00 app[web.1]: at module.exports (/app/node_modules/mongodb/lib/url_parser.js:59:13)
2017-07-31T11:46:48.243605+00:00 app[web.1]: at Function.MongoClient.connect (/app/node_modules/mongodb/lib/mongo_client.js:113:3)
2017-07-31T11:46:48.243604+00:00 app[web.1]: at connect (/app/node_modules/mongodb/lib/mongo_client.js:289:16)
2017-07-31T11:46:48.243606+00:00 app[web.1]: at run (/app/node_modules/thunky/index.js:13:3)
2017-07-31T11:46:48.243606+00:00 app[web.1]: at /app/node_modules/mongojs/lib/database.js:29:15
2017-07-31T11:46:48.243607+00:00 app[web.1]: at Collection._getConnection (/app/node_modules/thunky/index.js:27:3)
2017-07-31T11:46:48.243608+00:00 app[web.1]: at Collection._getCollection (/app/node_modules/mongojs/lib/collection.js:17:10)
2017-07-31T11:46:48.243609+00:00 app[web.1]: at getCursor (/app/node_modules/mongojs/lib/collection.js:32:10)
2017-07-31T11:46:48.243610+00:00 app[web.1]: at run (/app/node_modules/thunky/index.js:13:3)
2017-07-31T11:46:48.243609+00:00 app[web.1]: at /app/node_modules/mongojs/lib/cursor.js:12:5
2017-07-31T11:46:48.244240+00:00 app[web.1]: [0mPOST /login [31m500 [0m30.134 ms - 22[0m
Disconnected from log stream. There may be events happening that you do not see here! Attempting to reconnect...
My code is below:
var mongoJs=require('mongojs');
var CryptoJS = require("crypto-js");
var database='FGDP';
var collections=['f_users'];
var MONGOLAB_URI="mongodb://username:password#ds127153.mlab.com:27153/fgdp";
var db=mongoJs(MONGOLAB_URI, collections);
var ses;
exports.userlogin=function(req,res){
var username=req.body.user_name;
var password=req.body.user_pass;
// console.log('pass'+typeof(password));
//var ciphertext = CryptoJS.AES.encrypt(password, 'lexelPass');
//var pass=ciphertext.toString();
db.f_users.findOne({'login_name':username},function(err,docs){
console.log('err',err);
if(!err){
if(docs){
var pass=docs.password;
var bytes = CryptoJS.AES.decrypt(pass.toString(), 'lexelPass');
var plaintext = bytes.toString(CryptoJS.enc.Utf8);
if(plaintext==password){
req.session.email=docs.email;
req.session.name=docs.name;
req.session.login_name=docs.login_name;
req.session.status=docs.status;
req.session.user_type=docs.user_type;
res.send(docs);
}else{
res.send("Login failed");
}
}
}
if(err){
res.send("Login failed");
}
})
}
That database and collection is present in mongoLAB. I need to connect it through mongojs. Actally I have a login App and I could not login.
You should do like
var db = mongoJs(MONGOLAB_URI);
db.on('connect', function () {
console.log('database connected')
});

Error from Azure IoT Hub library when sending a message

Im using the Node.JS libraries for Azure IoT Hub to send some telemetry data, and intermittently I get the following error thrown from the libraries.
Unhandled rejection TypeError: Cannot read property 'on' of undefined
at C:\Source\Messenger\app.js:156:17
at Amqp. (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:157:17)
at C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:54:19
at C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:84:17
at tryCatcher (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\util.js:11:23)
at Promise._settlePromiseFromHandler (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:489:31)
at Promise._settlePromise (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:546:18)
at Promise._settlePromise0 (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:591:10)
at Promise._settlePromises (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:670:18)
at Async._drainQueue (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:129:16)
at Async._drainQueues (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:139:10)
at Immediate.Async.drainQueues [as _onImmediate] (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:16:14)
At the moment im running my scripts through forever so it recovers when the error is generated.
Has anyone else had this issue and managed to resolve it ?
My code looks like as follows
azureClient = azureDevice.Client.fromConnectionString(connectionString, azureDevice.Amqp);
var message = new azureDevice.Message(JSON.stringify('TEST MESSAGE'));
azureClient.sendEvent(message, function (err) {
if (err != null) {
Configure();
}
});
For this issue, I recommend you can use the AMQPWS or HTTP transport to send and receive messages.
Please refer to my steps to achieve to send and receive the message:
Firstly, we should create a device and get the device id and SAS. After created the IOT hub on Azure new portal, I ran those command on node.js command line:
create IOT hub on new portal.
npm install -g iothub-explorer
iothub-explorer HostName=****.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=****/****= create mydevice --connection-string
I got the result as following:
Created device mydevice
-
deviceId: mydevice
generationId: 635881160181557968
etag: MA==
connectionState: Disconnected
status: enabled
statusReason: null
connectionStateUpdatedTime: 0001-01-01T00:00:00
statusUpdatedTime: 0001-01-01T00:00:00
lastActivityTime: 0001-01-01T00:00:00
cloudToDeviceMessageCount: 0
authentication:
SymmetricKey:
primaryKey: ****/****=
secondaryKey: ****/****=
-
connectionString: HostName=****.azure-devices.net;DeviceId=mydevice;SharedAccessKey=****/****=
Secondly, I installed the SDK on node.js project, the folder structure is same as this picture:
Thirdly, I run this code on my project:
var device = require('azure-iot-device');
var connectionString = 'HostName=****.azure-devices.net;DeviceId=mydevice;SharedAccessKey=****/****=';
var client = device.Client.fromConnectionString(connectionString,device.AmqpWS);
setInterval(function () {
var windSpeed = 10 + (Math.random() * 4); // range: [10, 14]
var data = JSON.stringify({ deviceId: 'mydevice', windSpeed: windSpeed });
var message = new device.Message(data);
message.properties.add('myproperty', 'myvalue');
console.log("Sending message: " + message.getData());
client.sendEvent(message, printResultFor('send'));
}, 1000);
client.getReceiver(function (err, receiver) {
receiver.on('message', function (msg) {
console.log('Id: ' + msg.properties.messageId + ' Body: ' + msg.body);
receiver.complete(msg, function () {
console.log('completed');
// receiver.reject(msg, function() {
// console.log('rejected');
// });
// receiver.abandon(msg, function() {
// console.log('abandoned');
// });
});
receiver.on('errorReceived', function (err) {
console.warn(err);
});
});
});
function printResultFor(op) {
return function printResult(err, res) {
if (err) console.log(op + ' error: ' + err.toString());
if (res) console.log(op + ' status: ' + res);
};
}
it works fine. Also if you used the "Http" transport, it also works fine.
You need use this code:
var client = device.Client.fromConnectionString(connectionString);
This is the reason why I recommend you use the AMQPWS, because of this code in "azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10-transport-ws":
if (this.uri.startsWith('wss')) {
var wsTransport = require('amqp10-transport-ws');
wsTransport.register(amqp10.TransportProvider);
}
If the URI is format with 'wss', it will be register the AMQP transport. But AMQP transport's format is like "amqp://". Hope this helps.
The Azure IoT Hub was by far a preview feature service on Azure. And the Azure IoT device SDK for Node.js is on the fast development.
I am trying to involve someone familiar with this topic to further look at this issue. There might be some time delay.
Appreciate your patience.

Redshift data access from node jdbc

I am getting below error when I try to data from redshift with the below mentioned code
var jdbc = new ( require('jdbc') );
var config = {
libpath: 'C:/Users/ABCD/Desktop/jar/RedshiftJDBC41-1.1.6.1006.jar',
//libs: [__dirname + 'path/to/other/jars.jar'],
drivername: 'com.amazon.redshift.jdbc41.Driver',
url: 'jdbc:redshift://examplecluster.abc123xyz789.us-west-2.redshift.amazonaws.com:5439/dev',
user: 'xxxx',
password: 'xxxxx'
};
jdbc.initialize(config, function(err, res) {
if (err) {
console.log(err);
}
});
var genericQueryHandler = function(err, results) {
if (err) {
console.log(err);
} else if (results) {
console.log(results);
}
jdbc.close(function(err) {
if(err) {
console.log(err);
} else {
console.log("Connection closed successfully!");
}
});
};
jdbc.open(function(err, conn) {
if (conn) {
// SELECT statements are called with executeQuery
jdbc.executeQuery("select * from information_schema.tables", genericQueryHandler);
}
});
Error:
C:\Users\ABCD> node redshift.js
C:\Users\ABCD\node_modules\jdbc\lib\jdbc.js:62>
if(this._props.getPropertySync('user') === undefined){>
^ TypeError: undefined is not a function
at JDBCConn.initialize
(C:\Users\ABCD\node_modules\jdbc\lib\jdbc.js:62:20)
at Object.<anonymous>
(C:\Users\ABCD\Desktop\AngularJS\redshift.js:15:6)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
Could you please let me know whether there is nay issue with the above mentioned node jdbc usage for redshift?
Please be aware that this answer applies to node-jdbc 0.0.15 and earlier only. It will not work for node-jdbc 0.1.1 or later, as the API has been completely reworked and is not backwards-compatible.
Try replacing the two lines in your configuration
user: 'xxxx',
password: 'xxxxx'
with
properties: [
['user', 'xxxx'],
['password', 'xxxxx']
]
I got the same error as you attempting to use Node to connect to a local Oracle XE database. After making the change above I was able to connect. I don't believe the error you are getting is specific to RedShift - I believe it affects all databases.
Note that the properties above have to be specified as an array of 2-element arrays. An object such as the following would seem the obvious way to specify the properties, but it doesn't work:
// Don't do this, it doesn't work.
properties: {
user: 'xxxx',
password: 'xxxxx'
}
To be honest, the fix I've proposed above is a workaround. I only found it by reading the source of the jdbc module. I can't say I'm terribly impressed with this module, what with the example code given in the documentation not working, and with a somewhat counter-intuitive and undocumented format for specifying custom properties.

Resources