Hello, this example obviously shows "proactivity" in terms of running fake background jobs and replying asynchronously almost "right away".
This unfortunately does not show how to trigger the bot remotely and have it say something to the user.
Example use cases :
⚠Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
This scenario requires an additional app or service. The serverice generates the event activity, which it sends to the bot's api/messages endpoint, and the bot then sends the notice (proactive message) to the user. The event activity that the service generatates needs to contain the following information:
The first item is the event activity's name property.
Include the remaining information in the event activity's value property.
The code to have the bot generate a proactive message when it receives a message activity is only for demonstration and testing purposes.
Let me know if that helps or if you're still blocked.
One other note about this. The bot will send the proactive message right after it receives the event activity from the service, so the service should send the event at an appropriate time.
@myselfhimself , I'll close this for now. If you have more questions, feel free to reopen this or open a new issue.
Is there a way to create a bot adapter from code and use that to send the message?
When you have a conversation reference, how can you send a message without having a turncontext/botadapter?
EDIT: it seems simply resolving form IServiceProvider does the trick.
That's how I worked it out:
The outer side (that triggers the proactive dialog) should know your bot's id and client secret to begin conversation with your bot. As written in the Authentication part of wiki, you need to generate the token by sending the POST request to https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token with difference that the scope parameter should be {your_bot_app_id}/.default
Then you need to send the POST request to api/messages route of your bot, with Authorization: Bearer {your_token} header. You can look the JSON structure of the message within Bot Framework Emulator or in documentation.
The rest you can know out by placing the breakpoint in OnTurnAsync method and looking inside context.Activity object of your bot while sending him messages first from the messenger (Skype/Telegram/Facebook), then from your own application. The key parameters are replyToId and serviceUrl. They should be the same as in the message where user started the dialog.
Tim, thank you very much for your kind and thoroughful reply.
The proactive chatbot feature has been put on hold for now for our project.
I am sure that your very insightful comment brings more material for even
more developers reading the Internet.
Best,
On Mon, Nov 19, 2018 at 7:08 PM timkernighan notifications@github.com
wrote:
That's how I worked it out:
-
The outer side (that triggers the proactive dialog) should know your
bot's id and client secret to begin conversation with your bot. As written
in the Authentication part of wiki
https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-authentication?view=azure-bot-service-4.0,
you need to generate the token by sending the POST request to
https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
with difference that the scope parameter should be
{your_bot_app_id}/.default
-Then you need to send the POST request to api/messages route of your
bot, with Authorization: Bearer {your_token} header. The JSON structure of
the message you can look within Bot Framework Emulator or in documentation.
-The rest you can know out by placing the breakpoint in OnTurnAsync
method and looking inside context.Activity object of your bot while sending
him messages first from the messenger (Skype/Telegram/Facebook), then from
your own application. The key parameters are replyToId and serviceUrl. They
should be the same as in the message where user started the dialog.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/MicrosoftDocs/bot-docs/issues/401#issuecomment-439988130,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABNOws4K2AgPeBAZ6CfLd1KVqoa1gcgyks5uwvOIgaJpZM4XeJAe
.
Does anyone have any example code for 'real proactivity'? thanks
@jorn1
If I had that message some months ago, it would save me about three days of my working hours ;)
private BotMetadata CreateBotMetadataFromDialogContext(WaterfallStepContext context)
{
var activity = context.Context.Activity;
var botData = new BotMetadata
{
Channel = EnumHelpers.GetChannelById(activity.ChannelId),
ChannelId = activity.ChannelId,
ConversationId = activity.Conversation.Id,
IsGroup = activity.Conversation.IsGroup == true,
FromId = activity.From.Id,
FromName = activity.From.Name,
RecipientId = activity.Recipient.Id,
RecipientName = activity.Recipient.Name,
ServiceUrl = activity.ServiceUrl,
DialogId = context.ActiveDialog.Id,
};
return botData;
}
You decide to trigger the dialog from external service.
Form the urlencoded string: grant_type=client_credentials&client_id={your_client_id}&client_secret={your_client_secret}&scope={your_client_id}/.default
Send it within your body of https POST request to login.microsoftonline.com/oauth2/v2.0/token
Get the value from access_token field from JSON-response. You can use that token for about an hour or so (the expires_in field)
Headers:
Content-Type: application/json
Authorization: Bearer {token_from_step2}
Body:
{
"channelId": "{BotMetadata.ChannelId from step 1.}",
"conversation": { "id": "{BotMetadata.ConversationId}" },
"from": {
"id": "{BotMetadata.FromId}",
"name": "{BotMetadata.FromName} ?? {String.Empty}",
"role": "MyExternalClientOrWhatever"
},
"id": "{BotMetadata.DialogId}",
"replyToId": "{BotMetadata.FromId}",
"inputHint": "acceptingInput",
"recipient": {
"id": "{BotMetadata.RecipientId}",
"name": "{BotMetadata.RecipientName}"
},
"serviceUrl": "{BotMetadata.ServiceUrl}",
"text": "{Your message to the bot or whatever}",
"timestamp": "{Current timestamp in XML rfc3339 2002-10-02T10:00:00-05:00}",
"type": "message",
}
Send it to {your_bot_address}/api/messages
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken token = default(CancellationToken))
{
var dialogCtx = await this.dialogSet.CreateContextAsync(turnContext, token);
if (turnContext.Activity.Type == ActivityTypes.Message)
{
if (turnContext.Activity.From.Role == "MyExternalClientOrWhatever")
{
await HandleMessageFromExternalClientOrWhatever(dialogCtx, token);
}
else
{
await HandleMessageFromMessenger(dialogCtx, token);
}
}
}
{your_client_id}&client_secret={your_client_secret}&scope={your_client_id}/.default - what is scope param? Where can I get it?
@DmitryBLR {your_client_id}/.default where your_client_id is your client id. I don't now how to explain it any other way.
Most helpful comment
@jorn1
If I had that message some months ago, it would save me about three days of my working hours ;)
1. User had started the dialog, you gathered all the required information. Collect it, send it to the external service.
You decide to trigger the dialog from external service.
2. You need to gather the token for your bot to recognize you. (On external side)
Form the urlencoded string:
grant_type=client_credentials&client_id={your_client_id}&client_secret={your_client_secret}&scope={your_client_id}/.defaultSend it within your body of https POST request to login.microsoftonline.com/oauth2/v2.0/token
Get the value from access_token field from JSON-response. You can use that token for about an hour or so (the
expires_infield)3. Form the POST request for your bot and send it.
Headers:
Body:
Send it to
{your_bot_address}/api/messages4. Profit