@microsoft/agents-hosting-extensions-teams
Version:
Microsoft 365 Agents SDK for JavaScript. Teams extensions
1,141 lines (1,033 loc) • 41.1 kB
text/typescript
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import * as z from 'zod'
import { ActivityHandler, InvokeResponse, TurnContext } from '@microsoft/agents-hosting'
import { AppBasedLinkQuery, MessagingExtensionAction, MessagingExtensionActionResponse, MessagingExtensionQuery, MessagingExtensionResponse, parseValueMessagingExtensionQuery } from '../messageExtension'
import { TaskModuleRequest, TaskModuleResponse } from '../taskModule'
import { FileConsentCardResponse } from '../file'
import { ChannelInfo, parseTeamsChannelData, TeamInfo, TeamsChannelAccount } from '../activity-extensions'
import { MeetingEndEventDetails, MeetingParticipantsEventDetails, MeetingStartEventDetails, TeamsMeetingMember } from '../meeting'
import { ReadReceiptInfo } from './readReceipInfo'
const TeamsMeetingStartT = z
.object({
Id: z.string(),
JoinUrl: z.string(),
MeetingType: z.string(),
Title: z.string(),
StartTime: z.string()
})
const TeamsMeetingEndT = z
.object({
Id: z.string(),
JoinUrl: z.string(),
MeetingType: z.string(),
Title: z.string(),
EndTime: z.string()
})
/**
* A handler for processing Microsoft Teams-specific activities.
* Extends the ActivityHandler class to provide additional Teams-specific functionality.
* This class includes methods for handling various Teams events, such as message updates, channel events, and meeting events.
*/
export class TeamsActivityHandler extends ActivityHandler {
/**
* Handles invoke activities.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<InvokeResponse>} The invoke response.
*/
protected async onInvokeActivity (context: TurnContext): Promise<InvokeResponse> {
let runEvents = true
try {
if (!context.activity.name && context.activity.channelId === 'msteams') {
return await this.handleTeamsCardActionInvoke(context)
} else {
switch (context.activity.name) {
case 'config/fetch':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsConfigFetch(context, context.activity.value)
)
case 'config/submit':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsConfigSubmit(context, context.activity.value)
)
case 'fileConsent/invoke':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsFileConsent(context, context.activity.value as FileConsentCardResponse)
)
case 'actionableMessage/executeAction':
// TODO: Uncomment when O365ConnectorCardActionQuery is available
// await this.handleTeamsO365ConnectorCardAction(context, context.activity.value) // as O365ConnectorCardActionQuery
return ActivityHandler.createInvokeResponse()
case 'composeExtension/queryLink':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsAppBasedLinkQuery(context, context.activity.value as AppBasedLinkQuery)
)
case 'composeExtension/anonymousQueryLink':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsAnonymousAppBasedLinkQuery(context, context.activity.value as AppBasedLinkQuery)
)
case 'composeExtension/query':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsMessagingExtensionQuery(context, parseValueMessagingExtensionQuery(context.activity.value))
)
case 'composeExtension/selectItem':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsMessagingExtensionSelectItem(context, context.activity.value)
)
case 'composeExtension/submitAction':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsMessagingExtensionSubmitActionDispatch(
context,
context.activity.value as MessagingExtensionAction
)
)
case 'composeExtension/fetchTask':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsMessagingExtensionFetchTask(context, context.activity.value as MessagingExtensionAction)
)
case 'composeExtension/querySettingUrl':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsMessagingExtensionConfigurationQuerySettingUrl(
context,
context.activity.value as MessagingExtensionQuery
)
)
case 'composeExtension/setting':
await this.handleTeamsMessagingExtensionConfigurationSetting(context, context.activity.value)
return ActivityHandler.createInvokeResponse()
case 'composeExtension/onCardButtonClicked':
await this.handleTeamsMessagingExtensionCardButtonClicked(context, context.activity.value)
return ActivityHandler.createInvokeResponse()
case 'task/fetch':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsTaskModuleFetch(context, context.activity.value as TaskModuleRequest)
)
case 'task/submit':
return ActivityHandler.createInvokeResponse(
await this.handleTeamsTaskModuleSubmit(context, context.activity.value as TaskModuleRequest)
)
case 'tab/fetch':
return ActivityHandler.createInvokeResponse(
// TODO: Uncomment when TabRequest is available
// await this.handleTeamsTabFetch(context, context.activity.value) // as TabRequest
)
case 'tab/submit':
return ActivityHandler.createInvokeResponse(
// TODO: Uncomment when TabSubmit is available
// await this.handleTeamsTabSubmit(context, context.activity.value) // as TabSubmit
)
default:
runEvents = false
return await super.onInvokeActivity(context)
}
}
} catch (err: any) {
if (err.message === 'NotImplemented') {
return { status: 501 }
} else if (err.message === 'BadRequest') {
return { status: 400 }
}
throw err
} finally {
if (runEvents) {
this.defaultNextEvent(context)()
}
}
}
/**
* Handles card action invoke.
* @param {TurnContext} _context - The context object for the turn.
* @returns {Promise<InvokeResponse>} The invoke response.
*/
protected async handleTeamsCardActionInvoke (_context: TurnContext): Promise<InvokeResponse> {
throw new Error('NotImplemented')
}
/**
* Handles config fetch.
* @param {TurnContext} _context - The context object for the turn.
* @param {any} _configData - The config data.
* @returns {Promise<ConfigResponse>} The config response.
*/
protected async handleTeamsConfigFetch (_context: TurnContext, _configData: any): Promise<any> { // TODO ConfigResponse
throw new Error('NotImplemented')
}
/**
* Handles config submit.
* @param {TurnContext} _context - The context object for the turn.
* @param {any} _configData - The config data.
* @returns {Promise<ConfigResponse>} The config response.
*/
protected async handleTeamsConfigSubmit (_context: TurnContext, _configData: any): Promise<any> { // TODO ConfigResponse
throw new Error('NotImplemented')
}
/**
* Handles file consent.
* @param {TurnContext} context - The context object for the turn.
* @param {FileConsentCardResponse} fileConsentCardResponse - The file consent card response.
* @returns {Promise<void>}
*/
protected async handleTeamsFileConsent (
context: TurnContext,
fileConsentCardResponse: FileConsentCardResponse
): Promise<void> {
switch (fileConsentCardResponse.action) {
case 'accept':
return await this.handleTeamsFileConsentAccept(context, fileConsentCardResponse)
case 'decline':
return await this.handleTeamsFileConsentDecline(context, fileConsentCardResponse)
default:
throw new Error('BadRequest')
}
}
/**
* Handles file consent accept.
* @param {TurnContext} _context - The context object for the turn.
* @param {FileConsentCardResponse} _fileConsentCardResponse - The file consent card response.
* @returns {Promise<void>}
*/
protected async handleTeamsFileConsentAccept (
_context: TurnContext,
_fileConsentCardResponse: FileConsentCardResponse
): Promise<void> {
throw new Error('NotImplemented')
}
/**
* Handles file consent decline.
* @param {TurnContext} _context - The context object for the turn.
* @param {FileConsentCardResponse} _fileConsentCardResponse - The file consent card response.
* @returns {Promise<void>}
*/
protected async handleTeamsFileConsentDecline (
_context: TurnContext,
_fileConsentCardResponse: FileConsentCardResponse
): Promise<void> {
throw new Error('NotImplemented')
}
// TODO: Uncomment when O365ConnectorCardActionQuery is available
// /**
// * Handles O365 connector card action.
// * @param {TurnContext} _context - The context object for the turn.
// * @param {O365ConnectorCardActionQuery} _query - The O365 connector card action query.
// * @returns {Promise<void>}
// */
// protected async handleTeamsO365ConnectorCardAction (
// _context: TurnContext,
// _query: O365ConnectorCardActionQuery
// ): Promise<void> {
// throw new Error('NotImplemented')
// }
// TODO: Uncomment when SigninStateVerificationQuery is available
// /**
// * Handles sign-in verify state.
// * @param {TurnContext} _context - The context object for the turn.
// * @param {SigninStateVerificationQuery} _query - The sign-in state verification query.
// * @returns {Promise<void>}
// */
// protected async handleTeamsSigninVerifyState (
// _context: TurnContext,
// _query: SigninStateVerificationQuery
// ): Promise<void> {
// throw new Error('NotImplemented')
// }
// TODO: Uncomment when SigninStateVerificationQuery is available
// /**
// * Handles sign-in token exchange.
// * @param {TurnContext} _context - The context object for the turn.
// * @param {SigninStateVerificationQuery} _query - The sign-in state verification query.
// * @returns {Promise<void>}
// */
// protected async handleTeamsSigninTokenExchange (
// _context: TurnContext,
// _query: SigninStateVerificationQuery
// ): Promise<void> {
// throw new Error('NotImplemented')
// }
/**
* Handles messaging extension card button clicked.
* @param {TurnContext} _context - The context object for the turn.
* @param {any} _cardData - The card data.
* @returns {Promise<void>}
*/
protected async handleTeamsMessagingExtensionCardButtonClicked (
_context: TurnContext,
_cardData: any
): Promise<void> {
throw new Error('NotImplemented')
}
/**
* Handles task module fetch.
* @param {TurnContext} _context - The context object for the turn.
* @param {TaskModuleRequest} _taskModuleRequest - The task module request.
* @returns {Promise<TaskModuleResponse>} The task module response.
*/
protected async handleTeamsTaskModuleFetch (
_context: TurnContext,
_taskModuleRequest: TaskModuleRequest
): Promise<TaskModuleResponse> {
throw new Error('NotImplemented')
}
/**
* Handles task module submit.
* @param {TurnContext} _context - The context object for the turn.
* @param {TaskModuleRequest} _taskModuleRequest - The task module request.
* @returns {Promise<TaskModuleResponse>} The task module response.
*/
protected async handleTeamsTaskModuleSubmit (
_context: TurnContext,
_taskModuleRequest: TaskModuleRequest
): Promise<TaskModuleResponse> {
throw new Error('NotImplemented')
}
// TODO: Uncomment when TabRequest is available
// /**
// * Handles tab fetch.
// * @param {TurnContext} _context - The context object for the turn.
// * @param {TabRequest} _tabRequest - The tab request.
// * @returns {Promise<TabResponse>} The tab response.
// */
// protected async handleTeamsTabFetch (_context: TurnContext, _tabRequest: TabRequest): Promise<TabResponse> {
// throw new Error('NotImplemented')
// }
// TODO: Uncomment when TabSubmit is available
// /**
// * Handles tab submit.
// * @param {TurnContext} _context - The context object for the turn.
// * @param {TabSubmit} _tabSubmit - The tab submit.
// * @returns {Promise<TabResponse>} The tab response.
// */
// protected async handleTeamsTabSubmit (_context: TurnContext, _tabSubmit: TabSubmit): Promise<TabResponse> {
// throw new Error('NotImplemented')
// }
/**
* Handles app-based link query.
* @param {TurnContext} _context - The context object for the turn.
* @param {AppBasedLinkQuery} _query - The app-based link query.
* @returns {Promise<MessagingExtensionResponse>} The messaging extension response.
*/
protected async handleTeamsAppBasedLinkQuery (
_context: TurnContext,
_query: AppBasedLinkQuery
): Promise<MessagingExtensionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles anonymous app-based link query.
* @param {TurnContext} _context - The context object for the turn.
* @param {AppBasedLinkQuery} _query - The app-based link query.
* @returns {Promise<MessagingExtensionResponse>} The messaging extension response.
*/
protected async handleTeamsAnonymousAppBasedLinkQuery (
_context: TurnContext,
_query: AppBasedLinkQuery
): Promise<MessagingExtensionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles messaging extension query.
* @param {TurnContext} _context - The context object for the turn.
* @param {MessagingExtensionQuery} _query - The messaging extension query.
* @returns {Promise<MessagingExtensionResponse>} The messaging extension response.
*/
protected async handleTeamsMessagingExtensionQuery (
_context: TurnContext,
_query: MessagingExtensionQuery
): Promise<MessagingExtensionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles messaging extension select item.
* @param {TurnContext} _context - The context object for the turn.
* @param {any} _query - The query.
* @returns {Promise<MessagingExtensionResponse>} The messaging extension response.
*/
protected async handleTeamsMessagingExtensionSelectItem (
_context: TurnContext,
_query: any
): Promise<MessagingExtensionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles messaging extension submit action dispatch.
* @param {TurnContext} context - The context object for the turn.
* @param {MessagingExtensionAction} action - The messaging extension action.
* @returns {Promise<MessagingExtensionActionResponse>} The messaging extension action response.
*/
protected async handleTeamsMessagingExtensionSubmitActionDispatch (
context: TurnContext,
action: MessagingExtensionAction
): Promise<MessagingExtensionActionResponse> {
if (action.messagePreviewAction) {
switch (action.messagePreviewAction) {
case 'edit':
return await this.handleTeamsMessagingExtensionMessagePreviewEdit(context, action)
case 'send':
return await this.handleTeamsMessagingExtensionMessagePreviewSend(context, action)
default:
throw new Error('BadRequest')
}
} else {
return await this.handleTeamsMessagingExtensionSubmitAction(context, action)
}
}
/**
* Handles messaging extension submit action.
* @param {TurnContext} _context - The context object for the turn.
* @param {MessagingExtensionAction} _action - The messaging extension action.
* @returns {Promise<MessagingExtensionActionResponse>} The messaging extension action response.
*/
protected async handleTeamsMessagingExtensionSubmitAction (
_context: TurnContext,
_action: MessagingExtensionAction
): Promise<MessagingExtensionActionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles messaging extension message preview edit.
* @param {TurnContext} _context - The context object for the turn.
* @param {MessagingExtensionAction} _action - The messaging extension action.
* @returns {Promise<MessagingExtensionActionResponse>} The messaging extension action response.
*/
protected async handleTeamsMessagingExtensionMessagePreviewEdit (
_context: TurnContext,
_action: MessagingExtensionAction
): Promise<MessagingExtensionActionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles messaging extension message preview send.
* @param {TurnContext} _context - The context object for the turn.
* @param {MessagingExtensionAction} _action - The messaging extension action.
* @returns {Promise<MessagingExtensionActionResponse>} The messaging extension action response.
*/
protected async handleTeamsMessagingExtensionMessagePreviewSend (
_context: TurnContext,
_action: MessagingExtensionAction
): Promise<MessagingExtensionActionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles messaging extension fetch task.
* @param {TurnContext} _context - The context object for the turn.
* @param {MessagingExtensionAction} _action - The messaging extension action.
* @returns {Promise<MessagingExtensionActionResponse>} The messaging extension action response.
*/
protected async handleTeamsMessagingExtensionFetchTask (
_context: TurnContext,
_action: MessagingExtensionAction
): Promise<MessagingExtensionActionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles messaging extension configuration query setting URL.
* @param {TurnContext} _context - The context object for the turn.
* @param {MessagingExtensionQuery} _query - The messaging extension query.
* @returns {Promise<MessagingExtensionResponse>} The messaging extension response.
*/
protected async handleTeamsMessagingExtensionConfigurationQuerySettingUrl (
_context: TurnContext,
_query: MessagingExtensionQuery
): Promise<MessagingExtensionResponse> {
throw new Error('NotImplemented')
}
/**
* Handles messaging extension configuration setting.
* @param {TurnContext} _context - The context object for the turn.
* @param {any} _settings - The settings.
* @returns {Promise<void>}
*/
protected async handleTeamsMessagingExtensionConfigurationSetting (_context: TurnContext, _settings: any): Promise<void> {
throw new Error('NotImplemented')
}
/**
* Dispatches conversation update activity.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async dispatchConversationUpdateActivity (context: TurnContext): Promise<void> {
if (context.activity.channelId === 'msteams') {
const channelData = parseTeamsChannelData(context.activity.channelData)
if ((context.activity.membersAdded != null) && context.activity.membersAdded.length > 0) {
return await this.onTeamsMembersAdded(context)
}
if ((context.activity.membersRemoved != null) && context.activity.membersRemoved.length > 0) {
return await this.onTeamsMembersRemoved(context)
}
if (!channelData || !channelData.eventType) {
return await super.dispatchConversationUpdateActivity(context)
}
switch (channelData.eventType) {
case 'channelCreated':
return await this.onTeamsChannelCreated(context)
case 'channelDeleted':
return await this.onTeamsChannelDeleted(context)
case 'channelRenamed':
return await this.onTeamsChannelRenamed(context)
case 'teamArchived':
return await this.onTeamsTeamArchived(context)
case 'teamDeleted':
return await this.onTeamsTeamDeleted(context)
case 'teamHardDeleted':
return await this.onTeamsTeamHardDeleted(context)
case 'channelRestored':
return await this.onTeamsChannelRestored(context)
case 'teamRenamed':
return await this.onTeamsTeamRenamed(context)
case 'teamRestored':
return await this.onTeamsTeamRestored(context)
case 'teamUnarchived':
return await this.onTeamsTeamUnarchived(context)
default:
return await super.dispatchConversationUpdateActivity(context)
}
} else {
return await super.dispatchConversationUpdateActivity(context)
}
}
/**
* Dispatches message update activity.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async dispatchMessageUpdateActivity (context: TurnContext): Promise<void> {
if (context.activity.channelId === 'msteams') {
const channelData = parseTeamsChannelData(context.activity.channelData)
switch (channelData.eventType) {
case 'undeleteMessage':
return await this.onTeamsMessageUndelete(context)
case 'editMessage':
return await this.onTeamsMessageEdit(context)
default:
return await super.dispatchMessageUpdateActivity(context)
}
} else {
return await super.dispatchMessageUpdateActivity(context)
}
}
/**
* Dispatches message delete activity.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async dispatchMessageDeleteActivity (context: TurnContext): Promise<void> {
if (context.activity.channelId === 'msteams') {
const channelData = parseTeamsChannelData(context.activity.channelData)
switch (channelData.eventType) {
case 'softDeleteMessage':
return await this.onTeamsMessageSoftDelete(context)
default:
return await super.dispatchMessageDeleteActivity(context)
}
} else {
return await super.dispatchMessageDeleteActivity(context)
}
}
/**
* Handles Teams message undelete.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMessageUndelete (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsMessageUndelete', this.defaultNextEvent(context))
}
/**
* Handles Teams message edit.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMessageEdit (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsMessageEdit', this.defaultNextEvent(context))
}
/**
* Handles Teams message soft delete.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMessageSoftDelete (context: TurnContext): Promise<void> {
await this.handle(context, 'onTeamsMessageSoftDelete', this.defaultNextEvent(context))
}
/**
* Handles Teams members added.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMembersAdded (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsMembersAdded', this.defaultNextEvent(context))
}
/**
* Handles Teams members removed.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMembersRemoved (context: TurnContext): Promise<void> {
if ('TeamsMembersRemoved' in this.handlers && this.handlers.TeamsMembersRemoved.length > 0) {
await this.handle(context, 'TeamsMembersRemoved', this.defaultNextEvent(context))
} else {
await this.handle(context, 'MembersRemoved', this.defaultNextEvent(context))
}
}
/**
* Handles Teams channel created.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsChannelCreated (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsChannelCreated', this.defaultNextEvent(context))
}
/**
* Handles Teams channel deleted.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsChannelDeleted (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsChannelDeleted', this.defaultNextEvent(context))
}
/**
* Handles Teams channel renamed.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsChannelRenamed (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsChannelRenamed', this.defaultNextEvent(context))
}
/**
* Handles Teams team archived.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsTeamArchived (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsTeamArchived', this.defaultNextEvent(context))
}
/**
* Handles Teams team deleted.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsTeamDeleted (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsTeamDeleted', this.defaultNextEvent(context))
}
/**
* Handles Teams team hard deleted.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsTeamHardDeleted (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsTeamHardDeleted', this.defaultNextEvent(context))
}
/**
* Handles Teams channel restored.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsChannelRestored (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsChannelRestored', this.defaultNextEvent(context))
}
/**
* Handles Teams team renamed.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsTeamRenamed (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsTeamRenamed', this.defaultNextEvent(context))
}
/**
* Handles Teams team restored.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsTeamRestored (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsTeamRestored', this.defaultNextEvent(context))
}
/**
* Handles Teams team unarchived.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsTeamUnarchived (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsTeamUnarchived', this.defaultNextEvent(context))
}
/**
* Registers a handler for Teams message undelete event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMessageUndeleteEvent (handler: (context: TurnContext, next: () => Promise<void>) => Promise<void>): this {
return this.on('TeamsMessageUndelete', async (context, next) => {
await handler(context, next)
})
}
/**
* Registers a handler for Teams message edit event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMessageEditEvent (handler: (context: TurnContext, next: () => Promise<void>) => Promise<void>): this {
return this.on('TeamsMessageEdit', async (context, next) => {
await handler(context, next)
})
}
/**
* Registers a handler for Teams message soft delete event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMessageSoftDeleteEvent (handler: (context: TurnContext, next: () => Promise<void>) => Promise<void>): this {
return this.on('onTeamsMessageSoftDelete', async (context, next) => {
await handler(context, next)
})
}
/**
* Registers a handler for Teams members added event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMembersAddedEvent (
handler: (
membersAdded: TeamsChannelAccount[],
teamInfo: TeamInfo,
context: TurnContext,
next: () => Promise<void>
) => Promise<void>
): this {
return this.on('TeamsMembersAdded', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(context.activity.membersAdded || [], teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams members removed event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMembersRemovedEvent (
handler: (
membersRemoved: TeamsChannelAccount[],
teamInfo: TeamInfo,
context: TurnContext,
next: () => Promise<void>
) => Promise<void>
): this {
return this.on('TeamsMembersRemoved', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(context.activity.membersRemoved || [], teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams channel created event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsChannelCreatedEvent (
handler: (
channelInfo: ChannelInfo,
teamInfo: TeamInfo,
context: TurnContext,
next: () => Promise<void>
) => Promise<void>
): this {
return this.on('TeamsChannelCreated', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.channel as ChannelInfo, teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams channel deleted event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsChannelDeletedEvent (
handler: (
channelInfo: ChannelInfo,
teamInfo: TeamInfo,
context: TurnContext,
next: () => Promise<void>
) => Promise<void>
): this {
return this.on('TeamsChannelDeleted', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.channel as ChannelInfo, teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams channel renamed event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsChannelRenamedEvent (
handler: (
channelInfo: ChannelInfo,
teamInfo: TeamInfo,
context: TurnContext,
next: () => Promise<void>
) => Promise<void>
): this {
return this.on('TeamsChannelRenamed', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.channel as ChannelInfo, teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams team archived event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsTeamArchivedEvent (
handler: (teamInfo: TeamInfo, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsTeamArchived', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams team deleted event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsTeamDeletedEvent (
handler: (teamInfo: TeamInfo, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsTeamDeleted', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams team hard deleted event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsTeamHardDeletedEvent (
handler: (teamInfo: TeamInfo, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsTeamHardDeleted', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams channel restored event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsChannelRestoredEvent (
handler: (
channelInfo: ChannelInfo,
teamInfo: TeamInfo,
context: TurnContext,
next: () => Promise<void>
) => Promise<void>
): this {
return this.on('TeamsChannelRestored', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.channel as ChannelInfo, teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams team renamed event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsTeamRenamedEvent (
handler: (teamInfo: TeamInfo, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsTeamRenamed', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams team restored event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsTeamRestoredEvent (
handler: (teamInfo: TeamInfo, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsTeamRestored', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Registers a handler for Teams team unarchived event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsTeamUnarchivedEvent (
handler: (teamInfo: TeamInfo, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsTeamUnarchived', async (context, next) => {
const teamsChannelData = parseTeamsChannelData(context.activity.channelData)
await handler(teamsChannelData.team as TeamInfo, context, next)
})
}
/**
* Dispatches event activity.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async dispatchEventActivity (context: TurnContext): Promise<void> {
if (context.activity.channelId === 'msteams') {
switch (context.activity.name) {
case 'application/vnd.microsoft.readReceipt':
return await this.onTeamsReadReceipt(context)
case 'application/vnd.microsoft.meetingStart':
return await this.onTeamsMeetingStart(context)
case 'application/vnd.microsoft.meetingEnd':
return await this.onTeamsMeetingEnd(context)
case 'application/vnd.microsoft.meetingParticipantJoin':
return await this.onTeamsMeetingParticipantsJoin(context)
case 'application/vnd.microsoft.meetingParticipantLeave':
return await this.onTeamsMeetingParticipantsLeave(context)
}
}
return await super.dispatchEventActivity(context)
}
/**
* Handles Teams meeting start.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMeetingStart (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsMeetingStart', this.defaultNextEvent(context))
}
/**
* Handles Teams meeting end.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMeetingEnd (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsMeetingEnd', this.defaultNextEvent(context))
}
/**
* Handles Teams read receipt.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsReadReceipt (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsReadReceipt', this.defaultNextEvent(context))
}
/**
* Handles Teams meeting participants join.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMeetingParticipantsJoin (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsMeetingParticipantsJoin', this.defaultNextEvent(context))
}
/**
* Handles Teams meeting participants leave.
* @param {TurnContext} context - The context object for the turn.
* @returns {Promise<void>}
*/
protected async onTeamsMeetingParticipantsLeave (context: TurnContext): Promise<void> {
await this.handle(context, 'TeamsMeetingParticipantsLeave', this.defaultNextEvent(context))
}
/**
* Registers a handler for Teams meeting start event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMeetingStartEvent (
handler: (meeting: MeetingStartEventDetails, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsMeetingStart', async (context, next) => {
const meeting = TeamsMeetingStartT.parse(context.activity.value)
await handler(
{
id: meeting.Id,
joinUrl: meeting.JoinUrl,
meetingType: meeting.MeetingType,
startTime: new Date(meeting.StartTime),
title: meeting.Title
},
context,
next
)
})
}
/**
* Registers a handler for Teams meeting end event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMeetingEndEvent (
handler: (meeting: MeetingEndEventDetails, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsMeetingEnd', async (context, next) => {
const meeting = TeamsMeetingEndT.parse(context.activity.value)
await handler(
{
id: meeting.Id,
joinUrl: meeting.JoinUrl,
meetingType: meeting.MeetingType,
endTime: new Date(meeting.EndTime),
title: meeting.Title
},
context,
next
)
})
}
/**
* Registers a handler for Teams read receipt event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsReadReceiptEvent (
handler: (receiptInfo: ReadReceiptInfo, context: TurnContext, next: () => Promise<void>) => Promise<void>
): this {
return this.on('TeamsReadReceipt', async (context, next) => {
const receiptInfo = context.activity.value as { lastReadMessageId: string }
await handler(new ReadReceiptInfo(receiptInfo.lastReadMessageId), context, next)
})
}
/**
* Registers a handler for Teams meeting participants join event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMeetingParticipantsJoinEvent (
handler: (
meeting: MeetingParticipantsEventDetails,
context: TurnContext,
next: () => Promise<void>
) => Promise<void>
): this {
return this.on('TeamsMeetingParticipantsJoin', async (context, next) => {
const meeting = TeamsMeetingStartT.parse(context.activity.value)
await handler(
{
members: (meeting as unknown as { members: TeamsMeetingMember[] }).members
},
context,
next
)
})
}
/**
* Registers a handler for Teams meeting participants leave event.
* @param {function} handler - The handler function.
* @returns {this}
*/
onTeamsMeetingParticipantsLeaveEvent (
handler: (
meeting: MeetingParticipantsEventDetails,
context: TurnContext,
next: () => Promise<void>
) => Promise<void>
): this {
return this.on('TeamsMeetingParticipantsLeave', async (context, next) => {
const meeting = TeamsMeetingEndT.parse(context.activity.value)
await handler(
{
members: (meeting as unknown as { members: TeamsMeetingMember[] }).members
},
context,
next
)
})
}
}