I have to log the user-bot conversation in CosmosDB for audit/history purpose. In V3 using .Net, I was using table logger module, like the below code.
builder.RegisterModule(new TableLoggerModule(account, chatHistoryTableName));
Now we are upgrading/rewriting the bot to V4 in NodeJS. Please guide if there is a similar approach available for V4 in NodeJS to save the entire conversation?
This example hasn't been merged yet: https://github.com/Microsoft/BotBuilder-Samples/pull/1266
It uses AzureBlobTranscriptStore and TranscriptLoggerMiddleware
const { AzureBlobTranscriptStore } = require('botbuilder-azure');
const { TranscriptLoggerMiddleware } = require('botbuilder-core');
// Get blob service configuration as defined in .bot file
const blobStorageConfig = botConfig.findServiceByNameOrId(BLOB_CONFIGURATION);
// The transcript store has methods for saving and retrieving bot conversation transcripts.
let transcriptStore = new AzureBlobTranscriptStore({storageAccountOrConnectionString: blobStorageConfig.connectionString,
containerName: blobStorageConfig.container
});
// Create the middleware layer responsible for logging incoming and outgoing activities
// into the transcript store.
var transcriptMiddleware = new TranscriptLoggerMiddleware(transcriptStore);
adapter.use(transcriptMiddleware);
This should provide a good start.
https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-howto-v4-state?view=azure-bot-service-4.0&tabs=javascript
Related
I would like to post a message to personal chat instead of group chat while message post from group chat how to achieve this ?.
Is there is any methods available related to this issue ?.
As the others have noted in this thread, you need to use something called "Proactive Messaging". I see you're using node.js though, so here is a better sample than the C# or Java people have posted already: https://github.com/pnp/teams-dev-samples/tree/main/samples/bot-proactive-messaging . I put both a dotnet as well as a node.js version in the sample, and there are some links at the bottom of the page to read more about the topic. Here is also a link to a video session where I talk more about the concept: https://www.youtube.com/watch?v=mM7-fYdcJhw&t=1398s
It is important to know that proactive messaging will only work if you have a "context" with the user already, which basically means they have to have installed your app already. It is possible to pre-install it on their behalf though. You need to use Graph to do this, and you can read more about it here: https://learn.microsoft.com/en-us/graph/api/userteamwork-post-installedapps?view=graph-rest-1.0&tabs=http .
You can post a proactive personal message to a user:
Please find below sample code:
Also, before running this code, make sure that the user has installed the bot app in the personal scope or is a member of a Team which has the bot installed.
Reference docs:
https://learn.microsoft.com/en-us/java/api/com.microsoft.cognitiveservices.speech.transcription.conversation.createconversationasync?view=azure-java-stable
using Microsoft.Bot.Builder;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Bot.Schema;
using Microsoft.Bot.Schema.Teams;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Teams.Bot.Conversations
{
class Program
{
public static async Task Main(string[] args)
{
//Teams internal id
string teamInternalId = "19:96391bb270744e218c04dc8f571d3d8b#thread.skype";
//The Bot Service Url needs to be dynamically stored and fetched from the Team. Recommendation is to store the serviceUrl from the bot Payload and later re-use it to send proactive messages.
string serviceUrl = "https://smba.trafficmanager.net/emea/";
//the upn of the user who should recieve the personal message
string mentionUserPrincipalName = "user#tenant.onmicrosoft.com";
//Office 365/Azure AD tenant id for the
string tenantId = "<tenant-GUID>";
//From the Bot Channel Registration
string botClientID = "<client-id>";
string botClientSecret = "<client-secret>";
var connectorClient = new ConnectorClient(new Uri(serviceUrl), new MicrosoftAppCredentials(botClientID, botClientSecret));
var user = await ((Microsoft.Bot.Connector.Conversations)connectorClient.Conversations).GetConversationMemberAsync(mentionUserPrincipalName, teamInternalId, default);
var personalMessageActivity = MessageFactory.Text($"Personal message from the Bot!");
var conversationParameters = new ConversationParameters()
{
ChannelData = new TeamsChannelData
{
Tenant = new TenantInfo
{
Id = tenantId,
}
},
Members = new List<ChannelAccount>() { user }
};
var response = await connectorClient.Conversations.CreateConversationAsync(conversationParameters);
await connectorClient.Conversations.SendToConversationAsync(response.Id, personalMessageActivity);
}
}
}
I am using firebase cloud function in my firebase group chat app, Setup is already done but problem is when some one send message in any group then all user get notification for that message including non members of group.
I want to send notification to group specific users only, below is my code for firebase cloud function -
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const _ = require('lodash');
admin.initializeApp(functions.config().firebase);
exports.sendNewMessageNotification = functions.database.ref('/{pushId}').onWrite(event => {
const getValuePromise = admin.database()
.ref('messages')
.orderByKey()
.limitToLast(1)
.once('value');
return getValuePromise.then(snapshot => {
const { text, author } = _.values(snapshot.val())[0];
const payload = {
notification: {
title: text,
body: author,
icon: ''
}
};
return admin.messaging()
.sendToTopic('my-groupchat', payload);
});
});
This will be really help full, if anyway some one can suggest on this.
As per our conversation on the comments I believe that the issue is that you are using a topic that contains all the users, which is the my-groupchat topic. The solution would be to create a new topic with the users that are part of this subtopic.
As for how to create such topics, there are a couple of examples in this documentation, in there you can see that you could do it server side, or client side. In your case, you could follow the examples for the server side, since you would need to add them in bulk, but as new users are added it could be interesting to implement the client side approach.
Im working on a bot with Bot framework v4 in nodejs.
I want my Conversation reference for every user to be stored into an azure db.
Conversation reference is in a nested dictionary format. {'convid':{"a":'value","b":"value"}}
I want this dictionary to be stored in Azure DB (Which Db would be suitable?free version?Paid?) so that i could later retrieve this DB and send out a proactive messages to all users whose conv ref is stored.
I just want to know how to store dictionary into any azure DB with node js?
and retrieve it later? Any help would be appreciated.
Saving the conversation reference during a (private) conversation can be achieved using the following snippet.
conversationReference = TurnContext.getConversationReference(context.activity);
You can eventually save this JSON directly to CosmosDB using the Cosmos Javascript SDK.
const databaseDefinition = { id: "sample database" };
const collectionDefinition = { id: "sample collection" };
const { database } = await client.databases.create(databaseDefinition);
const { container } = await database.containers.create(collectionDefinition);
const { resource } = await container.items.create(conversationReference);
#Sree - You can pull all the conversation using Graph API's please check the documents. If you have requirement to store data in dictionary only, you can explore Cosmos db.
Please check Pricing.
I want change Default Answer in Q&A Maker Azure Framework Bot, but I cant find field that respond this value. I'm reading documentation (but it looks like it uses an older interface), and I'm trying to find this field but with result.
Here's my current configuration screen:
I'm assuming that you're referring to these docs: QnaMaker - Change Default Answer
They're a little confusing, but they key part is:
You can override this default response in the bot or application code
calling the endpoint.
Where the docs have this image:
What they actually mean is that in the QnAMaker Test Console, you can edit the default answer from your Application Settings. Be sure to Save, Train, and Publish your app or the setting may not show.
There's also kind of a way that you can use this setting for your default answer in a bot:
In Node/JS, your bot will not receive that DefaultAnswer at all. It receives nothing if there isn't a match, so you have to hard code it with something like:
const qnaResults = await this.qnaMaker.getAnswers(context);
// If an answer was received from QnA Maker, send the answer back to the user.
if (qnaResults[0]) {
await context.sendActivity(qnaResults[0].answer);
// If no answers were returned from QnA Maker, show this reply.
// Note: .getAnswers() does NOT return the default answer from the App Service's Application Settings
} else {
const defaultAnswer = 'No QnA Maker answers were found. This example uses a QnA Maker Knowledge Base that focuses on smart light bulbs. To see QnA Maker in action, ask the bot questions like "Why won\'t it turn on?" or "I need help."'
await context.sendActivity(defaultAnswer);
}
When creating an Azure Web Bot, one of the default Web Chat clients is a fork of microsoft's BotBuilder-Samples project, specifically 49 - QnAMaker All Features
The source code for Dialog/QnAMakerBaseDialog.cs defines the constant DefaultNoAnswer:
public const string DefaultNoAnswer = "No QnAMaker answers found.";
And then uses that value when returning a response from GetQnAResponseOptionsAsync:
protected async override Task<QnADialogResponseOptions> GetQnAResponseOptionsAsync(DialogContext dc)
{
var noAnswer = (Activity)Activity.CreateMessageActivity();
noAnswer.Text = DefaultNoAnswer; // <- used right here
var cardNoMatchResponse = (Activity)MessageFactory.Text(DefaultCardNoMatchResponse);
var responseOptions = new QnADialogResponseOptions
{
ActiveLearningCardTitle = DefaultCardTitle,
CardNoMatchText = DefaultCardNoMatchText,
NoAnswer = noAnswer,
CardNoMatchResponse = cardNoMatchResponse,
};
return responseOptions;
}
This particular sample repo doesn't appear to leverage the DefaultAnswer configuration key anywhere.
You can opt to include it when available by updating the noAnswer.Text like this:
- noAnswer.Text = DefaultNoAnswer;
+ noAnswer.Text = this._configuration["DefaultAnswer"] ?? DefaultNoAnswer;
You'll also have to pass in the configuration object through the dependency management system. See this commit for a full example.
Change the line in qamakerBaseDialog.js as below
var noAnswer = ActivityFactory.DefaultNoAnswer;
Remove ActivityFactory. and rebuild the code.
constructor(knowledgebaseId, authkey, host) {
//ActivityFactory.
var noAnswer = DefaultNoAnswer;
var filters = [];
super(knowledgebaseId, authkey, host, noAnswer, DefaultThreshold, DefaultCardTitle, DefaultCardNoMatchText,
DefaultTopN, ActivityFactory.cardNoMatchResponse, filters, QNAMAKER_BASE_DIALOG);
this.id = QNAMAKER_BASE_DIALOG;
}
I am able to send message to specific users with older botbuilder SDK 3.13.1 by saving message.address field in database.
var connector = new builder.ChatConnector({
appId: process.env.MicrosoftAppId,
appPassword: process.env.MicrosoftAppPassword,
openIdMetadata: process.env.BotOpenIdMetadata
});
var bot = new builder.UniversalBot(connector);
var builder = require('botbuilder');
var msg = new builder.Message().address(msgAddress);
msg.text('Hello, this is a notification');
bot.send(msg);
How can this be done with botbuilder SDK 4? I am aware of the Rest API but want to achieve this with the SDK itself because the SDK is the more preferred way of communication between the bot and user.
Thanks in advance.
Proactive Messages in the BotFramework v4 SDK enable you to continue conversations with individual users or send them notifications.
First, you need to import TurnContext from the botbuilder library so you can get the conversation reference.
const { TurnContext } = require('botbuilder');
Then, in the onTurn method, you can call the getConversationReference method from TurnContext and save the resulting reference in a database.
/**
* #param {TurnContext} turnContext A TurnContext object representing an incoming message to be handled by the bot.
*/
async onTurn(turnContext) {
...
const reference = TurnContext.getConversationReference(turnContext.activity);
//TODO: Save reference to your database
...
}
Finally, you can retrieve the reference from the database and call the continueConversation method from the adapter to send specific users a message or notification.
await this.adapter.continueConversation(reference, async (proactiveTurnContext) => {
await proactiveTurnContext.sendActivity('Hello, this is a notification')
});
For more information about proactive messages, take a look at the documentation or this example on GitHub. Hope this is helpful.