diff --git a/libraries/botbuilder/src/botFrameworkAdapter.ts b/libraries/botbuilder/src/botFrameworkAdapter.ts index ee726d5675..64a7e63ae3 100644 --- a/libraries/botbuilder/src/botFrameworkAdapter.ts +++ b/libraries/botbuilder/src/botFrameworkAdapter.ts @@ -852,7 +852,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide * @remarks * Override this in a derived class to create a mock connector client for unit testing. */ - protected createConnectorClient(serviceUrl: string): ConnectorClient { + public createConnectorClient(serviceUrl: string): ConnectorClient { const client: ConnectorClient = new ConnectorClient(this.credentials, { baseUri: serviceUrl, userAgent: USER_AGENT} ); return client; } diff --git a/libraries/botbuilder/src/index.ts b/libraries/botbuilder/src/index.ts index 6182b03286..47c06e06d9 100644 --- a/libraries/botbuilder/src/index.ts +++ b/libraries/botbuilder/src/index.ts @@ -11,5 +11,6 @@ export * from './fileTranscriptStore'; export * from './inspectionMiddleware'; export * from './teamsActivityHandler'; export * from './teamsActivityHelpers'; +export * from './teamsInfo'; export * from './teamsTurnContextHelpers'; export * from 'botbuilder-core'; diff --git a/libraries/botbuilder/src/teamsInfo.ts b/libraries/botbuilder/src/teamsInfo.ts new file mode 100644 index 0000000000..b6eb80b78b --- /dev/null +++ b/libraries/botbuilder/src/teamsInfo.ts @@ -0,0 +1,82 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { + ChannelInfo, + ConversationList, + TeamsChannelAccount, + TeamsChannelData, + TeamDetails, + TurnContext +} from 'botbuilder-core'; +import { ConnectorClient, TeamsConnectorClient } from 'botframework-connector'; + +import { BotFrameworkAdapter } from './botFrameworkAdapter'; + +export class TeamsInfo { + static async getTeamDetails(context: TurnContext): Promise { + const teamId = this.getTeamId(context); + if (!teamId) { + throw new Error('This method is only valid within the scope of a MS Teams Team.'); + } + return await this.getTeamsConnectorClient(context).teams.fetchTeamDetails(teamId); + } + + static async getChannels(context: TurnContext): Promise { + const teamId = this.getTeamId(context); + if (!teamId) { + throw new Error('This method is only valid within the scope of a MS Teams Team.'); + } + const channelList: ConversationList = await this.getTeamsConnectorClient(context).teams.fetchChannelList(teamId); + return channelList.conversations; + } + + static async getMembers(context: TurnContext): Promise { + const connectorClient = this.getConnectorClient(context); + const teamId = this.getTeamId(context); + if (teamId) { + return await this.getMembersInternal(connectorClient, teamId); + } else { + const conversation = context.activity.conversation; + const conversationId = conversation && conversation.id ? conversation.id : undefined; + return await this.getMembersInternal(connectorClient, conversationId); + } + } + + private static async getMembersInternal(connectorClient: ConnectorClient, conversationId: string): Promise { + if (!conversationId) { + throw new Error('The getMembers operation needs a valid conversationId.'); + } + + const teamMembers = await connectorClient.conversations.getConversationMembers(conversationId); + return teamMembers as TeamsChannelAccount[]; + } + + private static getTeamId(context: TurnContext): string { + if (!context) { + throw new Error('Missing context parameter'); + } + if (!context.activity) { + throw new Error('Missing activity on context'); + } + const channelData = context.activity.channelData as TeamsChannelData; + const team = channelData && channelData.team ? channelData.team : undefined; + const teamId = team && typeof(team.id) === 'string' ? team.id : undefined; + return teamId; + } + + private static getConnectorClient(context: TurnContext): ConnectorClient { + if (!context.adapter || !('createConnectorClient' in context.adapter)) { + throw new Error('This method requires a connector client.') + } + return (context.adapter as BotFrameworkAdapter).createConnectorClient(context.activity.serviceUrl); + } + + private static getTeamsConnectorClient(context: TurnContext): TeamsConnectorClient { + const connectorClient = this.getConnectorClient(context); + return new TeamsConnectorClient(connectorClient.credentials, { baseUri: context.activity.serviceUrl }); + } + +} \ No newline at end of file diff --git a/libraries/botbuilder/tests/teams/conversationUpdate/src/conversationUpdateBot.ts b/libraries/botbuilder/tests/teams/conversationUpdate/src/conversationUpdateBot.ts index 2b725c86a4..d176390446 100644 --- a/libraries/botbuilder/tests/teams/conversationUpdate/src/conversationUpdateBot.ts +++ b/libraries/botbuilder/tests/teams/conversationUpdate/src/conversationUpdateBot.ts @@ -1,17 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { - TeamsActivityHandler, -} from 'botbuilder'; import { CardFactory, ChannelAccount, ChannelInfo, MessageFactory, TeamInfo, + TeamsActivityHandler, TurnContext, -} from 'botbuilder-core'; +} from 'botbuilder'; + export class ConversationUpdateBot extends TeamsActivityHandler { constructor() { @@ -41,7 +40,7 @@ export class ConversationUpdateBot extends TeamsActivityHandler { await context.sendActivity(message); await next(); }); - this.onTeamsTeamRenamedEvent(async (channelInfo: ChannelInfo, teamInfo: TeamInfo, context: TurnContext, next: () => Promise): Promise => { + this.onTeamsTeamRenamedEvent(async (teamInfo: TeamInfo, context: TurnContext, next: () => Promise): Promise => { const card = CardFactory.heroCard('Team Renamed', `${teamInfo.name} is the new Team name`); const message = MessageFactory.attachment(card); await context.sendActivity(message);