So,
I searched far and wide, read everything I could find on the topic and I am still failing at this. I have managed to send proactive message to user, reply to a topic in team, etc. but I am unable to send a proactive message (create new post) in a team channel.
Is there an available example (I was unable to find any)? MS Docs for NodeJS seem to show an example of messaging each user in the team, but not the channel itself.
I explored the source code, and channelData is hardcoded to null inside botFrameworkAdapter.js, which only adds to the confusion.
So, basic code is:
const builder = require('botbuilder');
const adapter = new builder.BotFrameworkAdapter({
appId: 'XXX',
appPassword: 'YYY'
});
const conversation = {
channelData: {
//I have all this (saved from event when bot joined the Team)
},
...
// WHAT THIS OBJECT NEEDS TO BE TO SEND A SIMPLE "HELLO" TO A CHANNEL?
// I have all the d
};
adapter.createConversation(conversation, async (turnContext) => {
turnContext.sendActivity('HELLO'); //This may or may not be needed?
});
Has anyone done this with Node ? If so, can anyone show me a working example (with properly constructed conversation object)?
* EDIT *
As Hilton suggested in the answer below, I tried using ConnectorClient directly, but it returns resource unavailable (/v3/conversations)
Here is the code that I am using (it's literally only that, just trying to send demo message):
const path = require('path');
const { ConnectorClient, MicrosoftAppCredentials } = require('botframework-connector');
const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });
const serviceUrl = 'https://smba.trafficmanager.net/emea/';
async function sendToChannel() {
MicrosoftAppCredentials.trustServiceUrl(serviceUrl);
var credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
var client = new ConnectorClient(credentials, { baseUri: serviceUrl });
var conversationResponse = await client.conversations.createConversation({
bot: {
id: process.env.MicrosoftAppId,
name: process.env.BotName
},
isGroup: true,
conversationType: "channel",
id: "19:XXX#thread.tacv2"
});
var acivityResponse = await client.conversations.sendToConversation(conversationResponse.id, {
type: 'message',
from: { id: process.env.MicrosoftAppId },
text: 'This a message from Bot Connector Client (NodeJS)'
});
}
sendToChannel();
What am I doing wrong?
Okay, so, this is how I made it work. I am posting it here for future reference.
DISCLAIMER: I still have no idea how to use it with botbuilder as was asked in my initial question, and this answer is going to use ConnectorClient, which is acceptable (for me, at least). Based on Hilton's directions and a GitHub issue that I saw earlier ( https://github.com/OfficeDev/BotBuilder-MicrosoftTeams/issues/162#issuecomment-434978847 ), I made it work finally. MS Documentation is not that helpful, since they always use context variable which is available when your Bot is responding to a message or activity, and they keep a record of these contexts internally while the Bot is running. However, if your Bot is restarted for some reason or you want to store your data in your database to be used later, this is the way to go.
So, the code (NodeJS):
const path = require('path');
const { ConnectorClient, MicrosoftAppCredentials } = require('botframework-connector');
const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });
const serviceUrl = 'https://smba.trafficmanager.net/emea/';
async function sendToChannel() {
MicrosoftAppCredentials.trustServiceUrl(serviceUrl);
var credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
var client = new ConnectorClient(credentials, { baseUri: serviceUrl });
var conversationResponse = await client.conversations.createConversation({
bot: {
id: process.env.MicrosoftAppId,
name: process.env.BotName
},
isGroup: true,
conversationType: "channel",
channelData: {
channel: { id: "19:XXX#thread.tacv2" }
},
activity: {
type: 'message',
text: 'This a message from Bot Connector Client (NodeJS)'
}
});
}
sendToChannel();
NOTE: As Hilton pointed out, serviceUrl also needs to be loaded from your database, along with the channel id. It is available inside the activity which you receive initially when your Bot is added to team / channel / group along with channelId which you will also need, and you need to store those for future reference (do not hardcode them like in the example).
So, there is no separate createConversation and sendActivity, it's all in one call.
Thanks Hilton for your time, and a blurred image of my hand to MS Docs :)
Hope this helps someone else
(I'm replacing my previous answer as I think this fits the situation much better).
I've looked more into this and done a Fiddler trace to get you a more complete answer. I'm not a Node guy, so I'm not sure this will translate 100%, but let's see.
Basically, you're wanting to send to the following endpoint:
https://smba.trafficmanager.net/emea/v3/conversations/19:[RestOfYourChannelId]/activities
and you'll be posting a message like the following:
{
"type": "message",
"from": {
"id": "28:[rest of bot user id]",
"name": "[bot name]"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:[RestOfYourChannelId]"
},
"text": "Test Message"
}
However, to post to that endpoint, you need to authenticate to it properly. It's possible to do that, and communicate with the endpoint directly, but it's actually easier to just use the built-in mechanisms. This means getting and storing the conversationreference when the bot is first installed to the channel. This file shows how to do that (see how it gets and stores the conversationReference in the this.onConversationUpdate function). In that same sample, in a different file, it shows how to use that conversation reference to actually send the pro-active message - see here, where it uses adapter.continueConversation.
One of the Microsoft bot team members also shows this in similar detail over here. He also adds MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl); which can be necessary under certain circumstances (if you're having security issues, give that a try).
That -should- cover what you need, so give it a go, and let me know if you're still having difficulties.
I am trying to create an ECS instance using the Node SDK, but failing. I am not sure if I have done the right thing.
I am able to create the ECS with same configuration using Portal as well as ROS.
//using the SDK for ECS
var ECSClient = require('#alicloud/ecs-2014-05-26');
// crearting the client
var client = new ECSClient({
accessKeyId: 'myaccesskeyid',
accessKeySecret: 'myaccesskeysecret',
endpoint: 'https://ecs.aliyuncs.com'
});
// image id and instance type procured using the OpenApi explorer
var params = {
ImageId: 'winsvr_64_dtcC_1809_en-us_40G_alibase_20190528.vhd',
InstanceType: 'ecs.t1.xsmall',
RegionId: 'ap-south-1'
}
// options
var opts = {
'x-acs-region-id': "ap-south-1"
}
// calling the sdk method to create ecs instance
client.createInstance(params, opts).then((res) => {
console.log(res)
}, (err) => {
console.log('ERROR!!')
console.log(JSON.stringify(err))
});
Not a solution but a suggestion. Create a support ticket in Portal. They replied pretty fast and solved my ECS problems.
This is my firebase data
users
-L2yfvAU0cihwcJHqIv9
City: "wah cantt"
Email: "sharjeel2014#namal.edu.pk"
Firstname: "sharjeel"
Lastname: "malik"
Latitude: "74.27559833333333"
Longtitude: "31.509099999999997"
Phone: "03035602137"
Username: "sharjeel089"
This is my current cloud function
exports.retreivefromdatabase = functions.https.onRequest((req,res) => {
var db = admin.database();
var ref = db.ref();
ref.on("value", function(snapshot){
res.send(snapshot.val());
});
});
This function retrieves all data from firebase database. I just want to retrieve user data in the form of key value pairs like this on the basis of username.
{"City": "wah
cantt","Email":"sharjeel2014#namal.edu.pk","Firstname":"sharjeel"........}
How to do that?
This is one of the many ways to do this:
exports.retreivefromdatabase = functions.https.onRequest((req,res) => {
var db = admin.database();
var ref = db.ref();
var username = req.params.username;
ref.orderByChild("Username").equalTo(username).once("child_added", function(snapshot){
res.send(snapshot.val());
});
});
As I commented, Cloud Functions is not the easiest nor best way to learn how to interact with the Firebase Database from JavaScript. I'd recommend taking the codelab I mentioned or one of the many other tutorials out there. These allow you to simply run your code in a web page, which is a way faster way to work this out. Then once you've gotten the basics, deploying similar functionality on Cloud Functions is a much simpler step.
I've been trying to retrieve the Resource with the path "/" (the root) from AWS Api Gateway using the Nodejs AWS SDK. I know the naïve solution would be to do it this way:
var AWS = require('aws-sdk');
var __ = require('lodash');
var Promise = require('bluebird');
var resources = [];
var apiGateway = Promise.promisifyAll(new AWS.APIGateway({apiVersion: '2015-07-09', region: 'us-west-2'}));
var _finishRetrievingResources = function (resources) {
var orderedResources = __.sortBy(resources, function (res) {
return res.path.split('/').length;
});
var firstResource = orderedResources[0];
};
var _retrieveNextPage = function (resp) {
resources = resources.concat(resp.data.items);
if (resp.hasNextPage()) {
resp.nextPage().on('success', _retrieveNextPage).send();
} else {
_finishRetrievingResources(resources);
}
};
var foo = apiGateway.getResources({restApiId: 'mah_rest_api_id'}).on('success', _retrieveNextPage).send();
However, does anybody know of an alternate method? I'd prefer to know that I'll alway have to do at most one call than having to do multiple.
PS: I know there are several optimizations that could be made (e.g. check for root path on every response), I really want to know if there's a single SDK Call that could fix this.
There is not a single call, though it can be if you have less than 500 resources. As a consolation prize, this is the best-practice, using position to prevent accidental misses if there are over 500 resources. If there are less than 500 resources, this will work with one call:
https://github.com/andrew-templeton/cfn-api-gateway-restapi/blob/bd964408bcb4bc6fc8ec91b5e1f0387c8f11691a/index.js#L77-L102
while writing application using nodejs/azure and table services, how can we set what type of authorization should be used.
Shared Key Lite (or) Shared Key.
How can we set that?
It depends how you're accessing Table Services. If you use the SDK you can do it like this:
Shared Key
var sharedKey = = new SharedKeyTable(storageAccount, storageAccessKey, usePathStyleUri);
var tableService = azure.createTableService(null, null, null, sharedKey);
Shared Key Lite
var sharedKeyLite = = new SharedKeyLiteTable(storageAccount, storageAccessKey, usePathStyleUri);
var tableService = azure.createTableService(null, null, null, sharedKeyLite);
Take a look at the code and you'll see that Shared Key will be used if you omit the authentication provider.
If you use http.request you need to specify the type in the authorization header:
Authorization="[SharedKey|SharedKeyLite] <AccountName>:<Signature>"
So your code will be something like this:
var http = require('http');
function doSomethingWithTables() {
var settings = {
host: ...,
port: 80,
path: ...,
headers: {},
method: 'GET'
};
settings.headers['Authorization'] = 'SharedKeyLite myaccount:xxiofojpfzaopfiaz';
var req = http.request(settings);
req.write(...);
req.on('response', function(res){
...
});
}