I am using Microsoft Bot Framework. My intent is to get the user email of customers when they are chatting with Microsoft Bot on Microsoft Teams.
On my application, I am using library "botbuilder" and NodeJs language.
I have an example code:
var builder = require('botbuilder');
let inMemoryStorage = new builder.MemoryBotStorage();
var botSetting = {appId: '4c8f3u2b-c56n-4117-bc16-ec31eeb5d25c', appPassword: '4CBNO8vBGtdcGh9PoiVYottY'};
var connector = new builder.ChatConnector(botSetting);
var bot = new builder.UniversalBot(connector).set('storage', inMemoryStorage);
bot.dialog("/Debug", [
function (session, args, next) {
session.endDialog("Hello");
}
]);
var address = {
"channelId" : "msteams",
"bot" : {
"id" : "28:1b435929-3da2-46ed-8ccc-29ecb50cf350",
"name" : "taskbot-prod",
"nickname" : "taskbot-prod"
},
"serviceUrl" : "https://smba.trafficmanager.net/amer-client-ss.msg/",
"user" : {
"id" : "29:1rf-2Bm6aD0BWc-yRNDFcgOBG1-uSaEjCWtJcoR-rcU-Humz3a_RddsCKifHqYpvNSUosrRpxUnYL907Qa1ZZuw",
"name" : "John Smith"
},
"channelData" : {
"tenant" : {
"id" : "adb94d72-6cf3-4244-86ae-aa69c9f2ad43"
}
}
};
bot.beginDialog(address, "/Debug", {});
In the example code above, I already have user id (29:1rf-2Bm6aD0BWc-yRNDFcgOBG1-uSaEjCWtJcoR-rcU-Humz3a_RddsCKifHqYpvNSUosrRpxUnYL907Qa1ZZuw), but I don't know how to get user email by this id.
So, what API should I use to get the user email by id? If not API, then what MS Bot Framework Library should I use to get user email by ID?
Related
(For reference I have admin_consent for the organization with a auth scope of offline_access User.ReadWrite.All Group.ReadWrite.All AppCatalog.ReadWrite.All for my token that I use to interact with the Teams instance.)
After installing the app via POST /teams/{id}/installedApps it sends an conversationUpdate event that I respond to and save the entire ConversationReference object. It has a lot of stuff I don't need but I'm not sure what is necessary. The immediate response goes to the General channel of the specified Team.
Now I want to use that ConversationReference to post proactive notification messages to a channel that the user has designated outside of Teams. So the user has not interacted with the bot in this channel, but I can list the channel and have its ID.
I can post the message into the General channel utilizing the entire ConversationReference I captured, or message the user directly in chat via ommiting the channel speicifc fields, but I can't seem to get the message sent to a specific channel if I specify it as the channelId
const msBotAdapter = new BotFrameworkAdapter({
appId: TEAMS_CLIENT_ID,
appPassword: TEAMS_CLIENT_SECRET,
});
//Paired down the saved reference to look like this
const conversationReference = {
"user" : {
"id" : "9:1rafmaopfopakdfafMzCYlCtg",
"aadObjectId" : "fffffff-ffff-ffff-ffff-ffffffff"
},
"bot" : {
"id" : "8:sdfsfsdf-dddd-ddddd-aaaaa-vvvvvvv",
"name" : "Bot Name"
},
"conversation" : {
"isGroup" : true,
"conversationType" : "channel",
"tenantId" : "ffffffff-ssssss-ssssss-ss-ssssss"
},
"channelId" : "msteams",
"serviceUrl" : "https://smba.trafficmanager.net/amer/"
}
const heroCard = CardFactory.heroCard(label, text, undefined, undefined, {
subtitle: fromUser?.name ? `From: ${fromUser.name}` : undefined,
});
const channelId = {...retrieve channel Id}
const activity = {
recipient: {
id: channelId,
name: 'Test channel 2',
},
type: ActivityTypes.Message,
timestamp: new Date(),
localTimezone: 'America/New_York',
callerId: TEAMS_CLIENT_ID,
serviceUrl: conversationReference.serviceUrl!,
channelId,
from: conversationReference.bot as { id: string; name: string },
valueType: 'text',
attachments: [heroCard],
};
await msBotAdapter.createConversation(
conversationReference,
async turnContext => {
await turnContext.sendActivity(activity);
}
);
SUCCESS! Turns out directing the message to another channel requires manipulating the ConversationReference not (as I thought) specifying it in the Activity being sent. I'm showing this by removing the Activity I created in the original question and just sending plain text via await turnContext.sendActivity('Test Message');
const channelId = //retrieve desitnation channelId I use the graph api `/teams/${teamId}/channels`
const msBotAdapter = new BotFrameworkAdapter({
appId: TEAMS_CLIENT_ID,
appPassword: TEAMS_CLIENT_SECRET,
});
//Paired down the initial conversation reference to bare necessities, the important part is setting the `conversationReference.conversation.id` to the `channelId` that you wish the message to go to.
const conversationReference = {
"bot" : {
"id" : "8:sdfsfsdf-dddd-ddddd-aaaaa-vvvvvvv",
},
"conversation" : {
//This is where you dictate where the message goes
id: channelId
},
"serviceUrl" : "https://smba.trafficmanager.net/amer/"
}
await msBotAdapter.createConversation(
conversationReference,
async turnContext => {
await turnContext.sendActivity('Test Message');
}
);
How would I add users to an IAuthRepository without allowing self-registration? Is there a way to require a certain role (e.g. admin) for the RegistrationFeature, or would it be easier to create a separate project with only the RegistrationFeature only running on localhost?
If you don't want users to be able to register themselves then maybe you don't want to enable the RegistrationFeature itself which is not registered by default.
You'll have more flexibility in just using the IAuthRepository itself in your own Service to create users.
ServiceStack's new Auth Templates shows examples of using the IAuthRepository to create Users on Startup, e.g:
if (authRepo.GetUserAuthByUserName("user#gmail.com") == null)
{
var testUser = authRepo.CreateUserAuth(new UserAuth
{
DisplayName = "Test User",
Email = "user#gmail.com",
FirstName = "Test",
LastName = "User",
}, "p#55wOrd");
}
if (authRepo.GetUserAuthByUserName("manager#gmail.com") == null)
{
var roleUser = authRepo.CreateUserAuth(new UserAuth
{
DisplayName = "Test Manager",
Email = "manager#gmail.com",
FirstName = "Test",
LastName = "Manager",
}, "p#55wOrd");
authRepo.AssignRoles(roleUser, roles:new[]{ "Manager" });
}
if (authRepo.GetUserAuthByUserName("admin#gmail.com") == null)
{
var roleUser = authRepo.CreateUserAuth(new UserAuth
{
DisplayName = "Admin User",
Email = "admin#gmail.com",
FirstName = "Admin",
LastName = "User",
}, "p#55wOrd");
authRepo.AssignRoles(roleUser, roles:new[]{ "Admin" });
}
I guess I've found out how:
typeof(RegisterService).AddAttributes(new RequiredRoleAttribute("Admin"));
More here: https://docs.servicestack.net/restricting-services
Please help me!
I'm working on to create a chat application using dialogflow API. I have done all setup with dialogflow. I'm using Nodejs for backend and MongoDb database to store all chat data with username but I'm stuck to integrate my MongoDB database with dialogflow and store all chats. I'm using MLab to store my all data.
My code is here.
exports.pizzabot = function(req, res) {
console.log("pizza bot details here");
if (req.body.result.action === "a_fetch_user_details") {
console.log("fetch user action fired");
if (req.body.result.parameters["username"] != "") {
return res.json({
speech : "Fetched user details",
displaytext : "welcome Bot!",
followupEvent : {
"data" : {
"pizzatype" : req.body.result.parameters["pizzatype"],
"pizzasize" : req.body.result.parameters["pizzasize"],
"username" : req.body.result.parameters["username"],
"address" : "New Delhi",
"phonenum" : "1234567891",
"email" : req.body.result.parameters["email"]
},
name : "e_fetch_user_details"
},
source : "from Dialogflow"
});
}
}
}
as sid8491 has said, you need to connect nodejs app with mongodb. You just need a function that connects to the database. Use mongoose if you need more functionality like validation and schema based approach. here is the code to connect to mongodb using mongoose.
const mongoose = require("mongoose");
const mongodb = require("../env");
mongoose.connect(mongodb.Mongo.url,{ useNewUrlParser: true }).then(() => {
console.log("MongoDB Connection successful");
}).catch((error) => {
console.log(error);
});
module.exports = mongoose;
I am trying to send simple push notifications using FCM services.
Every time my function is called, I want to receive one notification and I want my phone to ring and vibrate. I have 2 problems:
When I receive the notification, I get 5 of them instead of one.
The second problem is that if my phone's sound is activated when I receive the notifications, the phone doesn't vibrate or ring, but if it is on vibrations mode, it vibrates when I get the notifications.
Any ideas how to solve this? Thanks!
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Alerts/{email_encoded}/{alert_id}').onWrite(event => {
const email_encoded = event.params.email_encoded;
const alert_id = event.params.alert_id;
const deviceToken = admin.database().ref(`/Users/${email_encoded}/device_token`).once('value');
deviceToken.then(result => {
const token_id = result.val();
const payload = {
notification: {
title: "Alert",
body: "alert triggered",
icon: "default",
sound:"default",
vibrate:"true"
}
};
return admin.messaging().sendToDevice(token_id, payload);
});
});
And the firebase database json structure:
"Alerts" : {
"asdfgh#yahoo,com" : {
"-KtXc_c7RMxysWGEb98L" : {
"bid" : "1.30",
"email" : "asdfgh#yahoo.com",
"id" : "-KtXc_c7RMxysWGEb98L",
"parity" : "EURUSD",
"sign" : ">"
},
"-KtmCD7REa9AKK57xhXP" : {
"bid" : "1.33",
"email" : "asdfgh#yahoo.com",
"id" : "-KtmCD7REa9AKK57xhXP",
"parity" : "EURUSD",
"sign" : ">"
},
"-KtmCpypQM_N1ub471Ta" : {
"bid" : "1.333",
"email" : "asdfgh#yahoo.com",
"id" : "-KtmCpypQM_N1ub471Ta",
"parity" : "EURUSD",
"sign" : ">"
}
}
I tried sending a notification from the firebase dashboard. Even though at advanced settings I selected sound enabled, when I got the notification on my phone, it didn't vibrate or ring.
The problem was that on my phone my notification sound was off. I added a sound "mysound" in my android /res/raw and changed sound:"default"to sound:"mysound" and now I even get the sound I want when I receive the notification.
I have two mongoose models users and requests. One user can have multiple requests. To link these two data models, I am referencing the objectID of the user in the Request model. However when I am trying to fetch all the requests for a particular user ID, I don't get any result.
Users
var UserSchema = new Schema({
name: String,
username: String
});
module.exports = mongoose.model('User', UserSchema);
Requests
var RequestSchema = new Schema({
type: String,
user_id: { type : mongoose.Schema.Types.ObjectId, ref: 'User'}
});
module.exports = mongoose.model('Request', RequestSchema);
Below is the sample code which fetches the requests based on the User ID passed in the URL
exports.getRequests = function (req, res, next) {
var userId = req.params.id;
console.log('USER ID'+userId);
Request.findOne({'user_id': 'kenan'}, function (err, request) {
if (err) return next(err);
if (!requests){
console.log('NO REQUEST FOUND');
return res.send(401);
}
res.json(request);
});
};
I know I am using findOne which will return me a single resource. However this is failing and I am not getting any result. I have in my DB the data populated. Below is the URL for fetching the requests.
http://localhost:9000/api/V1/users/547ee1e82e47bb982e36e433/requests
Please help suggest as to what I am doing wrong over here.
Thanks
You need to populate the references to the users once you do a find().
Once you find all the requests, you need to resolve the references to
the users. Use populate to resolve the references.
After resolving, filter the requests based on the name that you
are searching for.
Updated Code:
Request
.find().populate({'path':'user_id',match:{'name':'kenan'}})
.exec(function (err, resp) {
var result = resp.filter(function(i){
return i.user_id != null;
});
console.log(result);
})
OK, the above answer is correct and thanks for your response. I incorrectly populated my Requests collection. This is just for every one's else knowledge. When you have a Object ID reference as one of the fields in the collection then make sure that you are inserting the ObjectID object instead of just the numerical value.
Wrong
{ "_id" : ObjectId("54803ae43b73bd8428269da3"), "user_id" : "547ee1e82e
47bb982e36e433", "name" : "Test", "service_type" : "test", "version" : "10"
, "environment" : "test", "status" : "OK", "__v" : 0 }
Correct
{ "_id" : ObjectId("54803ae43b73bd8428269da3"), "user_id" : ObjectId("547ee1e82e
47bb982e36e433"), "name" : "test", "service_type" : "test", "version" : "10"
, "environment" : "test", "status" : "OK", "__v" : 0 }