Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add getMember and getPagedMember to teamsInfo #1833

Merged
merged 8 commits into from
Mar 3, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 80 additions & 2 deletions libraries/botbuilder/src/teamsInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import {
TeamsChannelAccount,
TeamsChannelData,
TeamDetails,
TurnContext
TurnContext,
PagedMembersResult,
TeamsPagedMembersResult
} from 'botbuilder-core';
import { ConnectorClient, TeamsConnectorClient } from 'botframework-connector';
import { ConnectorClient, TeamsConnectorClient, TeamsConnectorModels} from 'botframework-connector';

import { BotFrameworkAdapter } from './botFrameworkAdapter';

Expand Down Expand Up @@ -50,6 +52,32 @@ export class TeamsInfo {
}
}

public static async getPagedMembers(context: TurnContext, pageSize?: number, continuationToken?: string): Promise<TeamsPagedMembersResult> {
const teamId = this.getTeamId(context);
const options: TeamsConnectorModels.ConversationsGetConversationPagedMembersOptionalParams = {
"continuationToken" : continuationToken,
"pageSize": pageSize
}
if (teamId) {
return await this.getPagedTeamMembers(context, teamId, pageSize, continuationToken);
} else {
const conversation = context.activity.conversation;
const conversationId = conversation && conversation.id ? conversation.id : undefined;
return await this.getPagedMembersInternal(this.getConnectorClient(context), conversationId, options);
}
}

public static async getMember(context: TurnContext, userId: string): Promise<TeamsChannelAccount> {
const teamId = this.getTeamId(context);
if (teamId) {
return await this.getTeamMember(context, teamId, userId);
} else {
const conversation = context.activity.conversation;
const conversationId = conversation && conversation.id ? conversation.id : undefined;
return await this.getMemberInternal(this.getConnectorClient(context), conversationId, userId);
}
}

public static async getTeamMembers(context: TurnContext, teamId?: string): Promise<TeamsChannelAccount[]> {
const t = teamId || this.getTeamId(context);
if (!t) {
Expand All @@ -58,6 +86,27 @@ export class TeamsInfo {
return this.getMembersInternal(this.getConnectorClient(context), t);
}

public static async getPagedTeamMembers(context: TurnContext, teamId?: string, pageSize?: number, continuationToken?: string): Promise<TeamsPagedMembersResult> {
const t = teamId || this.getTeamId(context);
if (!t) {
throw new Error('This method is only valid within the scope of a MS Teams Team.');
}

const options: TeamsConnectorModels.ConversationsGetConversationPagedMembersOptionalParams = {
"continuationToken" : continuationToken,
"pageSize": pageSize
}
return this.getPagedMembersInternal(this.getConnectorClient(context), t, options);
}

public static async getTeamMember(context: TurnContext, teamId?: string, userId?: string): Promise<TeamsChannelAccount> {
const t = teamId || this.getTeamId(context);
if (!t) {
throw new Error('This method is only valid within the scope of a MS Teams Team.');
}
return this.getMemberInternal(this.getConnectorClient(context), t, userId);
}

private static async getMembersInternal(connectorClient: ConnectorClient, conversationId: string): Promise<TeamsChannelAccount[]> {
if (!conversationId) {
throw new Error('The getMembers operation needs a valid conversationId.');
Expand All @@ -71,6 +120,35 @@ export class TeamsInfo {
return teamMembers as TeamsChannelAccount[];
}

private static async getPagedMembersInternal(connectorClient: ConnectorClient, conversationId: string, options: TeamsConnectorModels.ConversationsGetConversationPagedMembersOptionalParams): Promise<TeamsPagedMembersResult> {
if (!conversationId) {
throw new Error('The getPagedMembers operation needs a valid conversationId.');
}

const pagedMembersResult: PagedMembersResult = await connectorClient.conversations.getConversationPagedMembers(conversationId, options)

const teamsPagedMembersResult: TeamsPagedMembersResult = {
"continuationToken": pagedMembersResult.continuationToken,
"members": pagedMembersResult.members as TeamsChannelAccount[]
}

return teamsPagedMembersResult;
}

private static async getMemberInternal(connectorClient: ConnectorClient, conversationId: string, userId: string): Promise<TeamsChannelAccount> {
if (!conversationId) {
throw new Error('The getMember operation needs a valid conversationId.');
}

if (!userId) {
throw new Error('The getMember operation needs a valid conversationId.');
}

const teamMember: ChannelAccount = await connectorClient.conversations.getConversationMember(conversationId, userId);

return teamMember as TeamsChannelAccount;
}

private static getTeamId(context: TurnContext): string {
if (!context) {
throw new Error('Missing context parameter');
Expand Down
18 changes: 14 additions & 4 deletions libraries/botbuilder/tests/teams/roster/src/rosterBot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export class RosterBot extends TeamsActivityHandler {
await this.showDetails(context);
break;

case "show member":
await this.showMember(context);
break;

default:
await context.sendActivity(
'Invalid command. Type "Show channels" to see a channel list. Type "Show members" to see a list of members in a team. ' +
Expand All @@ -59,23 +63,29 @@ export class RosterBot extends TeamsActivityHandler {
}

private async showMembers(context: TurnContext): Promise<void> {
let teamsChannelAccounts = await TeamsInfo.getMembers(context);
let options = {"continuationToken": null, "pageSize": 2};
let teamsChannelAccounts = await (await TeamsInfo.getPagedMembers(context, 5)).members;
await context.sendActivity(MessageFactory.text(`Total of ${teamsChannelAccounts.length} members are currently in team`));
let messages = teamsChannelAccounts.map(function(teamsChannelAccount) {
return `${teamsChannelAccount.aadObjectId} --> ${teamsChannelAccount.name} --> ${teamsChannelAccount.userPrincipalName}`;
});
await this.sendInBatches(context, messages);
}
private async showChannels(context: TurnContext): Promise<void> {

private async showChannels(context: TurnContext): Promise<void> {
let channels = await TeamsInfo.getTeamChannels(context);
await context.sendActivity(MessageFactory.text(`Total of ${channels.length} channels are currently in team`));
let messages = channels.map(function(channel) {
return `${channel.id} --> ${channel.name ? channel.name : 'General'}`;
});
await this.sendInBatches(context, messages);
}


private async showMember(context: TurnContext): Promise<void> {
let member = await TeamsInfo.getMember(context, context.activity.from.id);
await context.sendActivity(MessageFactory.text("You are: " + member.name));
}

private async showDetails(context: TurnContext): Promise<void> {
let teamDetails = await TeamsInfo.getTeamDetails(context);
await context.sendActivity(MessageFactory.text(`The team name is ${teamDetails.name}. The team ID is ${teamDetails.id}. The AAD GroupID is ${teamDetails.aadGroupId}.`));
Expand Down
20 changes: 20 additions & 0 deletions libraries/botframework-connector/src/connectorApi/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,26 @@ export type ConversationsGetConversationMembersResponse = Array<ChannelAccount>
};
};

/**
* Contains response data for the getConversationMember operation.
*/
export type ConversationsGetConversationMemberResponse = ChannelAccount & {
/**
* The underlying HTTP response.
*/
_response: msRest.HttpResponse & {
/**
* The response body as text (string format)
*/
bodyAsText: string;

/**
* The response body as parsed JSON or XML
*/
parsedBody: ChannelAccount;
};
};

/**
* Contains response data for the getConversationPagedMembers operation.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,23 @@ export class Conversations {
callback) as Promise<Models.ConversationsGetConversationMembersResponse>;
}

/**
* @param conversationId Conversation ID
* @param memberId MemberId for the user
* @param options The optional parameters
* @param callback The callback
*/
getConversationMember(conversationId: string, memberId: string, options?: msRest.RequestOptionsBase | msRest.ServiceCallback<Models.ChannelAccount[]>, callback?: msRest.ServiceCallback<Models.ChannelAccount[]>): Promise<Models.ConversationsGetConversationMemberResponse> {
return this.client.sendOperationRequest(
{
conversationId,
memberId,
options
},
getConversationMemberOperationSpec,
callback) as Promise<Models.ConversationsGetConversationMemberResponse>;
}

/**
* Enumerate the members of a conversation one page at a time.
*
Expand Down Expand Up @@ -696,13 +713,13 @@ const getConversationMembersOperationSpec: msRest.OperationSpec = {
bodyMapper: {
serializedName: "parsedResponse",
type: {
name: "Sequence",
element: {
type: {
name: "Composite",
className: "ChannelAccount"
name: "Sequence",
element: {
type: {
name: "Composite",
className: "ChannelAccount"
}
}
}
}
}
},
Expand All @@ -713,6 +730,24 @@ const getConversationMembersOperationSpec: msRest.OperationSpec = {
serializer
};

const getConversationMemberOperationSpec: msRest.OperationSpec = {
httpMethod: "GET",
path: "v3/conversations/{conversationId}/members/{memberId}",
urlParameters: [
Parameters.conversationId,
Parameters.memberId
],
responses: {
200: {
bodyMapper: Mappers.ChannelAccount,
},
default: {
bodyMapper: Mappers.ErrorResponse
}
},
serializer
};

const getConversationPagedMembersOperationSpec: msRest.OperationSpec = {
httpMethod: "GET",
path: "v3/conversations/{conversationId}/pagedmembers",
Expand Down
17 changes: 15 additions & 2 deletions libraries/botframework-connector/src/teams/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@


/*
* Code generated by Microsoft (R) AutoRest Code Generator.
* Changes may cause incorrect behavior and will be lost if the code is
Expand All @@ -6,7 +8,7 @@
// This code has been manually edited to reflect the integration of the Teams schemas into botframework-schema
// and the botframework-connector libraries.

import { HttpResponse, ServiceClientOptions } from '@azure/ms-rest-js';
import { HttpResponse, ServiceClientOptions, RequestOptionsBase } from '@azure/ms-rest-js';
import { ConversationList, TeamDetails } from 'botframework-schema';

/**
Expand Down Expand Up @@ -57,4 +59,15 @@ export type TeamsFetchTeamDetailsResponse = TeamDetails & {
*/
parsedBody: TeamDetails;
};
};
};

export interface ConversationsGetConversationPagedMembersOptionalParams extends RequestOptionsBase {
/**
* Suggested page size
*/
pageSize: number;
/**
* Continuation Token
*/
continuationToken: string;
}
11 changes: 11 additions & 0 deletions libraries/botframework-schema/src/teams/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ export interface TeamsChannelAccount extends ChannelAccount {
userPrincipalName?: string;
}

export interface TeamsPagedMembersResult {
/**
* Paging token
*/
continuationToken: string;
/**
* The Channel Accounts.
*/
members: TeamsChannelAccount[];
}

/**
* @interface
* An interface representing O365ConnectorCardFact.
Expand Down