I am unable to send proactive messages to a channel that I have not yet communicated with _(during this run)_.
REPRO:
const reference = JSON.parse('{"activityId":"1546604462703","user":{"id":"29:1....
await this._adapter.continueConversation(reference, async (proactiveTurnContext) => {
await proactiveTurnContext.sendActivity(Testing proactive message);
});
EXPECTED: to see the message in the Skype
ACTUAL: Exception
[onTurnError]: Error: Authorization has been denied for this request.
(node:20616) UnhandledPromiseRejectionWarning: Error: Authorization has been denied for this request.
warning.js:18
at new RestError (c:_Test\Test\TestWeb\Test2JSnode_modules\ms-rest-js\eslib\restError.js:7:28)
at c:_Test\Test\TestWeb\Test2JSnode_modules\ms-rest-js\eslibpolicies\deserializationPolicy.js:92:37
at
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
(node:20616) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)
warning.js:18
(node:20616) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
### NOW THE INTERESTING PART...
REPRO:
[bug]
I think I understand your problem. If so....
This is because the bot doesn't know that a user has joined the conversation until the user first sends a message. The bot sends ConversationUpdate when the conversation is created, but the user's ConversationUpdate isn't sent until they send a message.
This is by design to prevent spam. The only channel where proactive messages work without the user sending the message first is Email (and the Emulator).
You can, instead, try using contactRelationUpdate, but be aware that this is only sent when a user adds or removes the bot as a contact. It would look something like:
// Sample for Skype: in ContactRelationUpdate event
else if (activity.Type == ActivityTypes.ContactRelationUpdate && activity.ChannelId == "skype")
{
// Greeting
}
If you think your problem is different, can you provide:
Yes, this is a different problem.
After restarting, I can't send a proactive message to users that I've previously communicated with _(until there has been some activity on the channel)_.
REPRO:
More info -- it feels like something is happening or not happening with the bot framework connector magic which I haven't seen the source code to. It feels like this service never gets hooked up or started until some message comes from Skype, Facebook, Telegram, Kik, etc.
Maybe there's something that I need to do at start-up to say that I'm alive?
I'm still leaning towards it being a conversationUpdate issue, but if not, it's likely something state-related.
Can you share the following code snippets:
And for clarification, is this bot deployed or are you testing locally?
_Bot is in production and has been running for a year on 4 platforms -- ported recently to JS from C#._
index.js -- nothing special here that I can see
// Listen for incoming requests.
server.post('/api/messages', (req, res) => {
adapter.processActivity(req, res, async (context) => {
console.log(context.activity.type);
REPRO#3 - even with emulator
NOTE that there is no "conversationUpdate" until any new user interacts with the channel but our proactive messages are allowed *AFTER any message is received from the channel. *
Code related to memory/storage in index.ts Any code using state accessors in the rest of your bot Your createRefference() code
We do have our own storage which writes to SQL server and our own conversation state which uses this storage...
class MyConversationState extends BotState {
...but this doesn't seem to be involved in the flow.
Creating the reference could be but it's the same thing we get back from the botframework call...
Here is that code.
const reference = {
activityId: `${new Date().getTime()}`,
user: { id: data.RecipientCode, name: data.RecipientName },
bot: { id: data.ChannelCode, name: data.ChannelUsername },
conversation: { id: data.ConversationCode },
channelId: data.ChannelName,
serviceUrl: data.ChannelServiceUrl
};
await adapter.continueConversation(reference, async (proactiveTurnContext) => {
await proactiveTurnContext.sendActivity(`Testing proactive message`);
});
_I posted here because I believed that this is a bug in the backend but am open to all possibilities._
What about this article?
I have encountered this error before. Essentially, the channel that the message is coming from is "trusted". The workaround is to trust that channel access.
Try this (first parameter should be the service url):
MicrosoftAppCredentials.TrustServiceUrl(@"https://skype.botframework.com", DateTime.MaxValue);
Maybe it is a trust thing?
https://github.com/Microsoft/BotBuilder/issues/3329
How do you use this in JS?
I'll be working on your issue throughout the day. In the meantime, to answer your last question, the equivalent repo/library can be found here:
FIXED!
Thanks so much for your help. After getting onto the correct path it seems that LOTS of people were or are having the same problem -- might want to add this tip to the proactive sample.
Call this before starting and everything is good to go.
BotConnector.MicrosoftAppCredentials.trustServiceUrl('https://smba.trafficmanager.net/apis/', new Date(8640000000000000));
BotConnector.MicrosoftAppCredentials.trustServiceUrl('https://facebook.botframework.com/', new Date(8640000000000000));
BotConnector.MicrosoftAppCredentials.trustServiceUrl('https://telegram.botframework.com/', new Date(8640000000000000));
BotConnector.MicrosoftAppCredentials.trustServiceUrl('https://kik.botframework.com/', new Date(8640000000000000));
Glad you got it working! I'll work on getting it added to samples and documentation.
@qpongo I am having this issue now as well. What is the BotConnector variable that you're referring to in your fix?
I am using the BotFrameworkAdaptor and I notice that it is using MicrosoftAppCredentials but I can't directly interact with that class. Would you mind posting a more complete code sample?
@mdrichardson did you get a chance to add this to the samples and documentation? Can you link here if so? Thank you!
@alexbielen Nothing in the samples, but the docs have a section for it, now.
You should be able to use MicrosoftAppCredentials from the botframework-connector package.
Most helpful comment
FIXED!
Thanks so much for your help. After getting onto the correct path it seems that LOTS of people were or are having the same problem -- might want to add this tip to the proactive sample.
Call this before starting and everything is good to go.