Skip to content

Commit

Permalink
Merge pull request #311 from brendanrmoore/conversation-references-fixes
Browse files Browse the repository at this point in the history
Fixes for Microsoft Teams conversation references
  • Loading branch information
MichaelRyanWebber authored May 30, 2024
2 parents 5a6c79f + 3baebba commit b833ff1
Showing 1 changed file with 69 additions and 35 deletions.
104 changes: 69 additions & 35 deletions api-module-library/microsoft-teams/api/bot.js
Original file line number Diff line number Diff line change
@@ -1,75 +1,94 @@
const { BotFrameworkAdapter, StatusCodes, TeamsActivityHandler, CardFactory, MessageFactory, TeamsInfo, TurnContext
const {
BotFrameworkAdapter,
StatusCodes,
TeamsActivityHandler,
TeamsInfo,
TurnContext,
} = require('botbuilder');
const {OAuth2Requester} = require("@friggframework/module-plugin");
const {get} = require("@friggframework/assertions");


class botApi {
#conversationReferencesInternal = {};

set conversationReferences(newConversationReferences) {
this.#conversationReferencesInternal = newConversationReferences;
this.bot.conversationReferences = newConversationReferences;
}
get conversationReferences() {
return this.#conversationReferencesInternal;
}

constructor(params) {
// bot expects to listen on
this.adapter = new BotFrameworkAdapter({
appId: params.client_id,
appPassword: params.client_secret
appPassword: params.client_secret,
});
this.adapter.onTurnError = async (context, error) => {
await context.sendTraceActivity(
'OnTurnError Trace',
`${ error }`,
`${error}`,
'https://www.botframework.com/schemas/error',
'TurnError'
);
await context.sendActivity('The bot encountered an error.');
};
this.conversationReferences = {};
this.botId = params.client_id;
this.tenantId = params.tenant_id;
this.serviceUrl = params.service_url;
this.bot = new Bot(this.adapter, this.conversationReferences);
}
async receiveActivity(req, res){
await this.adapter.process(req, res, (context) => this.bot.run(context));
async receiveActivity(req, res) {
await this.adapter.process(req, res, (context) =>
this.bot.run(context)
);
}

// this circumvents the adapter middleware, only for testing
// this circumvents the adapter middleware
async run(activity) {
console.log('only for testing!')
await this.bot.run(activity);
}

async setConversationReferenceFromMembers(members){
async setConversationReferenceFromMembers(members) {
const ref = {
bot: {
id: this.botId
id: this.botId,
},
conversation: {
tenantId: this.tenantId
tenantId: this.tenantId,
},
serviceUrl: this.serviceUrl,
channelId: 'msteams'
}
channelId: 'msteams',
};

const refRequests = [];
members.map( (member) => {
members.map((member) => {
ref.user = member;
refRequests.push( this.adapter.createConversation(ref, async (context) => {
const ref = TurnContext.getConversationReference(context.activity);
this.conversationReferences[member.email] = ref;
}));
refRequests.push(
this.adapter.createConversation(ref, async (context) => {
const ref = TurnContext.getConversationReference(
context.activity
);
this.conversationReferences[member.email] = ref;
})
);
});
await Promise.all(refRequests);
return this.conversationReferences
return this.conversationReferences;
}

async sendProactive(userEmail, activity) {
const conversationReference = this.conversationReferences[userEmail];
if (conversationReference !== undefined) {
await this.adapter.continueConversation(conversationReference, async (context) => {
await context.sendActivity(activity);
});
await this.adapter.continueConversation(
conversationReference,
async (context) => {
await context.sendActivity(activity);
}
);
}
}

async createConversationReference(initialRef,member){
async createConversationReference(initialRef, member) {
initialRef.user = member;
await this.adapter.createConversation(initialRef, async (context) => {
const ref = TurnContext.getConversationReference(context.activity);
Expand All @@ -84,11 +103,11 @@ const invokeResponse = (card) => {
const cardRes = {
statusCode: StatusCodes.OK,
type: 'application/vnd.microsoft.card.adaptive',
value: card
value: card,
};
const res = {
status: StatusCodes.OK,
body: cardRes
body: cardRes,
};
return res;
};
Expand All @@ -100,9 +119,18 @@ class Bot extends TeamsActivityHandler {
this.adapter = adapter;
this.onMembersAdded(async (context, next) => {
const membersAdded = context.activity.membersAdded;
await Promise.all(membersAdded.map(async member => {
await this.setConversationReferenceForNewMember(context, member);
}));
await Promise.all(
membersAdded
.filter(
(member) => member.id !== context.activity.recipient.id
)
.map(async (member) => {
await this.setConversationReferenceForNewMember(
context,
member
);
})
);
await next();
});
}
Expand All @@ -115,21 +143,27 @@ class Bot extends TeamsActivityHandler {

async getUserConversationReference(context) {
const TeamMembers = await TeamsInfo.getPagedMembers(context);
TeamMembers.members.map(async member => {
TeamMembers.members.map(async (member) => {
await this.setConversationReferenceForNewMember(context, member);
});
}

async setConversationReferenceForNewMember(context, member){
const initialRef = TurnContext.getConversationReference(context.activity);
async setConversationReferenceForNewMember(context, member) {
const initialRef = TurnContext.getConversationReference(
context.activity
);
initialRef.user = member;
delete initialRef.conversation.id;
delete initialRef.activityId;
initialRef.bot = {id: undefined}
initialRef.bot = { id: undefined };
let memberInfo;
await this.adapter.createConversation(initialRef, async (context) => {
const ref = TurnContext.getConversationReference(context.activity);
memberInfo = await this.adapter.getConversationMembers(context);
ref.user = {
...memberInfo[0],
aadObjectId: memberInfo[0].objectId,
};
this.conversationReferences[memberInfo[0].email] = ref;
});
}
Expand Down

0 comments on commit b833ff1

Please sign in to comment.