Forum Discussion
How to have app send message to channel without configuring connector
- Mar 20, 2020
You could send message in a team from your app by doing a POST API call to below endpoint.
https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-send-and-receive-messages?view=azure-bot-service-3.0
When bot is added into a group/team ConversationUpdate event is called in bot framework. You can cache the user details and serviceURL. And you can use these detail to post a message in teams or group.
You could send message in a team from your app by doing a POST API call to below endpoint.
https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-send-and-receive-messages?view=azure-bot-service-3.0
When bot is added into a group/team ConversationUpdate event is called in bot framework. You can cache the user details and serviceURL. And you can use these detail to post a message in teams or group.
subhasish-MSFT thank you, this is exactly what I was looking for. At first I dismissed this approach because I didn't realize a ConversationUpdate event was fired when the app was installed, I thought it needed direct user input.
That being said if I save the Conversation Reference from the initial app installation, can I use that indefinitely to post in other channels of the Team, or will it expire at some point like an Oauth Token?
- subhasish-MSFTMar 26, 2020Former Employee
adamhouck , You have to store the team Id, tenant Id, conversation Id(in case of personal scope). These are unique Ids and can be stored indefinite time.
- adamhouckMar 29, 2020Copper Contributor
subhasish-MSFT Thank you, I successfully implemented this based off the Microsoft example here https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs/16.proactive-messages
But I can't seem to authenticate correctly after restarting my server when using a saved conversation reference. I did put in a call to `MicrosoftAppCredentials.trustServiceURL()` as the example shows. Is there something else I am missing to authenticate after re-instantiating the `BotFrameworkAdapter` on server restart with a saved conversation reference?{ Error: Authorization has been denied for this request.
at new RestError (...../node_modules/@azure/ms-rest-js/lib/restError.ts:18:5)
at ..../node_modules/@azure/ms-rest-js/lib/policies/deserializationPolicy.ts:117:27
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
code: undefined,
statusCode: 401,
request:
WebResource {
streamResponseBody: false,
url: 'https://smba.trafficmanager.net/amer/v3/conversations/{convo ID}%40thread.skype/activities/{activiyID}',
method: 'POST',
headers: HttpHeaders { _headersMap: [Object] },
body: '{"type":"message","serviceUrl":"https://smba.trafficmanager.net/amer/","channelId":"msteams","from":{"id":"{ID}","name":"CrossLead Dev Local"},"conversation":{"isGroup":true,"conversationType":"channel","id":"{ID}","tenantId":"{ID}"},"recipient":{"id":"{ID}","aadObjectId":"{ID}"},"text":"The bot encountered an error or bug.","inputHint":"acceptingInput","replyToId":"{ID}"}',
query: undefined,
formData: undefined,
withCredentials: false,
abortSignal: undefined,
timeout: 0,
onUploadProgress: undefined,
onDownloadProgress: undefined,
operationSpec:
{ httpMethod: 'POST',
path: 'v3/conversations/{conversationId}/activities/{activityId}',
urlParameters: [Array],
requestBody: [Object],
responses: [Object],
serializer: [Object] } },
response:
{ body: '{"message":"Authorization has been denied for this request."}',
headers: HttpHeaders { _headersMap: [Object] },
status: 401 },
body: { message: 'Authorization has been denied for this request.' } }
const msBotAdapter = new BotFrameworkAdapter({
appId: {ID as string}
appPassword: {ID as string},
});
//Some people also said to do this, but never used it anywhere. It doesn't seem to help
const msCreditials = new MicrosoftAppCredentials(
{ID as string},
{ID as string}
);
//Save Conversation Reference from when the app was installed into teams
const conversationReference: {
[key: string]: Partial<ConversationReference>;
} = {
activityId: '{activity ID}',
//@ts-ignore
user: {
id:
'{ID}',
aadObjectId: '{ID}',
},
bot: {
id: '{Bot Id}',
name: '{Bot Name}',
},
//@ts-ignore
conversation: {
isGroup: true,
conversationType: 'channel',
tenantId: '{tenant ID}',
id: '19:{ID}@thread.skype',
},
channelId: 'msteams',
serviceUrl: 'https://smba.trafficmanager.net/amer/',
};
const postMessage = async () => {
MicrosoftAppCredentials.trustServiceUrl(conversationReference.serviceUrl);
await msBotAdapter.continueConversation(
conversationReference as any,
async turnContext => {
// If you encounter permission-related errors when sending this message, see
// https://aka.ms/BotTrustServiceUrl
await turnContext.sendActivity('test message);
}
);
}- adamhouckMar 31, 2020Copper Contributor
Turns out it was due to using an outdated dependency, `botbuilder` https://github.com/microsoft/botframework-sdk#readme though I was only on 4.7.2 and the latest was 4.8.0.
We will probably forgo these dependencies in favor of working with the REST API's directly like Stackoverflow. https://stackoverflow.blog/2019/11/04/a-technical-deep-dive-into-our-ms-teams-integration/Having our teams integration totally fail due to a slightly newer version of the botframework package coming out is not a longterm option.