UNPKG

@microsoft/teams.api

Version:

<p> <a href="https://www.npmjs.com/package/@microsoft/teams.api" target="_blank"> <img src="https://img.shields.io/npm/v/@microsoft/teams.api/latest" /> </a> <a href="https://www.npmjs.com/package/@microsoft/teams.api?activeTab=code" t

581 lines (580 loc) • 16.7 kB
class ActivityInput { /** * Activity type discriminator. */ type; /** * Optional activity ID used when updating an existing sent activity. */ id; /** * Optional recipient account. */ recipient; /** * ID of the activity this outbound activity replies to. */ replyToId; /** * Entities attached to the outbound activity. */ entities; /** * Channel-specific metadata for the outbound activity. */ channelData; /** * Create an outbound activity input. * @param type - Activity type discriminator. * @param value - Initial outbound activity fields. */ constructor(type, value = {}) { Object.assign(this, value); this.type = type; } /** * Set the activity ID for update scenarios. * @param value - Activity ID. */ withId(value) { this.id = value; return this; } /** * Set the activity recipient. * @param value - Recipient account. * @param isTargeted - Whether the activity is targeted only to this recipient. */ withRecipient(value, isTargeted = false) { this.recipient = { ...value, isTargeted: isTargeted ? true : void 0 }; return this; } /** * Merge channel-specific metadata into the outbound activity. * @param value - Channel metadata to merge. */ withChannelData(value) { const merged = { ...this.channelData, ...value }; if (merged.feedbackLoop !== void 0) { merged.feedbackLoopEnabled = void 0; } else if (merged.feedbackLoopEnabled === true) { merged.feedbackLoop = { type: "default" }; merged.feedbackLoopEnabled = void 0; } this.channelData = merged; return this; } /** * Add an entity to the outbound activity. * @param value - Entity to add. */ addEntity(value) { if (this.isRootLevelMessageEntity(value)) { this.mergeRootLevelMessageEntity(this.ensureSingleRootLevelMessageEntity(), value); return this; } if (!this.entities) { this.entities = []; } this.entities.push(value); return this; } /** * Add multiple entities to the outbound activity. * @param value - Entities to add. */ addEntities(...value) { for (const entity of value) { this.addEntity(entity); } return this; } /** * Add the `Generated By AI` label. */ addAiGenerated() { const messageEntity = this.ensureSingleRootLevelMessageEntity(); if (messageEntity.additionalType?.includes("AIGeneratedContent")) { return this; } if (!messageEntity.additionalType) { messageEntity.additionalType = []; } messageEntity.additionalType.push("AIGeneratedContent"); return this; } /** * Add a Microsoft Purview sensitivity label to the message. * Replaces any label previously added. * @param label - The sensitivity label, identified by its Purview label ID. */ addSensitivityLabel(label) { const messageEntity = this.ensureSingleRootLevelMessageEntity(); messageEntity.usageInfo = { ...label, "@type": label["@type"] ?? "CreativeWork" }; return this; } /** * Enable message feedback. * @param mode - `'default'` shows Teams' built-in thumbs up/down UI. * `'custom'` triggers a `message/fetchTask` invoke so the bot can return its own task module dialog. */ addFeedback(mode = "default") { if (!this.channelData) { this.channelData = {}; } this.channelData.feedbackLoop = { type: mode }; this.channelData.feedbackLoopEnabled = void 0; return this; } /** * Add citations * @param position - Citation position in the message text. * @param appearance - Citation appearance metadata. */ addCitation(position, appearance) { const messageEntity = this.ensureSingleRootLevelMessageEntity(); if (!messageEntity.citation) { messageEntity.citation = []; } messageEntity.citation.push({ "@type": "Claim", position, appearance: { "@type": "DigitalDocument", abstract: appearance.abstract, name: appearance.name, encodingFormat: appearance.text ? "application/vnd.microsoft.card.adaptive" : void 0, image: appearance.icon ? { "@type": "ImageObject", name: appearance.icon } : void 0, keywords: appearance.keywords, text: appearance.text, url: appearance.url, usageInfo: appearance.usageInfo ? { ...appearance.usageInfo, "@type": appearance.usageInfo["@type"] ?? "CreativeWork" } : void 0 } }); return this; } /** * Add a targeted message info entity for prompt preview. * Skips if already present. * * @param messageId the message ID of the targeted message */ addTargetedMessageInfo(messageId) { if (this.entities) { this.entities = this.entities.filter((e) => e.type !== "quotedReply"); } if (this.type === "message") { const msg = this; if (msg.text) { msg.text = msg.text.replace(`<quoted messageId="${messageId}"/>`, "").trim(); } } if (this.entities?.some((e) => e.type === "targetedMessageInfo")) { return this; } return this.addEntity({ type: "targetedMessageInfo", messageId }); } /** * Determine whether the activity contains stream metadata. */ isStreaming() { return this.entities?.some((e) => e.type === "streaminfo") || false; } /** * Get or create the base message entity. * There should only be one root level message entity. */ ensureSingleRootLevelMessageEntity() { let messageEntity = this.entities?.find( (e) => this.isRootLevelMessageEntity(e) ); if (!messageEntity) { messageEntity = { type: "https://schema.org/Message", "@type": "Message", "@context": "https://schema.org", "@id": "" }; if (!this.entities) { this.entities = []; } this.entities.push(messageEntity); } return messageEntity; } isRootLevelMessageEntity(entity) { return entity.type === "https://schema.org/Message" && entity["@type"] === "Message"; } mergeRootLevelMessageEntity(target, source) { const merged = { ...target, ...source }; if (target.additionalType || source.additionalType) { merged.additionalType = [ .../* @__PURE__ */ new Set([...target.additionalType || [], ...source.additionalType || []]) ]; } if (target.citation || source.citation) { const dedupedCitations = /* @__PURE__ */ new Map(); for (const citation of [...target.citation || [], ...source.citation || []]) { dedupedCitations.set(citation.position, citation); } merged.citation = Array.from(dedupedCitations.values()); } Object.assign(target, merged); return target; } } class Activity { /** * Contains the type of the activity. */ type; /** * Contains an ID that uniquely identifies the activity on the channel. */ id; /** * Contains the URL that specifies the channel's service endpoint. Set by the channel. */ serviceUrl; /** * Contains the date and time that the message was sent, in UTC, expressed in ISO-8601 format. */ timestamp; /** * A locale name for the contents of the text field. * The locale name is a combination of an ISO 639 two- or three-letter culture code associated * with a language * and an ISO 3166 two-letter subculture code associated with a country or region. * The locale name can also correspond to a valid BCP-47 language tag. */ locale; /** * Contains the local date and time of the message, expressed in ISO-8601 format. * * For example, 2016-09-23T13:07:49.4714686-07:00. */ localTimestamp; /** * Contains an ID that uniquely identifies the channel. Set by the channel. */ channelId; /** * Identifies the sender of the message. */ from; /** * Identifies the conversation to which the activity belongs. */ conversation; /** * A reference to another conversation or activity. * @deprecated This will be removed by end of summer 2026. */ relatesTo; /** * Identifies the recipient of the message. */ recipient; /** * Contains the ID of the message to which this message is a reply. */ replyToId; /** * Represents the entities that were mentioned in the message. */ entities; /** * Contains channel-specific content. */ channelData; /** * Information about the tenant in which the message was sent. */ get tenant() { return this.channelData?.tenant; } /** * Information about the channel in which the message was sent. */ get channel() { return this.channelData?.channel; } /** * Information about the team in which the message was sent. */ get team() { return this.channelData?.team; } /** * Information about the tenant in which the message was sent. */ get meeting() { return this.channelData?.meeting; } /** * Notification settings for the message. */ get notification() { return this.channelData?.notification; } constructor(value) { Object.assign(this, { channelId: "msteams", ...value }); } static from(activity) { return new Activity(activity); } toInterface() { return Object.assign({}, this); } clone(options = {}) { return new Activity({ ...this.toInterface(), ...options }); } withId(value) { this.id = value; return this; } withChannelId(value) { this.channelId = value; return this; } withFrom(value) { this.from = value; return this; } withConversation(value) { this.conversation = value; return this; } /** * @deprecated This will be removed by end of summer 2026. */ withRelatesTo(value) { this.relatesTo = value; return this; } /** * Set the recipient of this activity, optionally marking it as a targeted message. * Targeted messages are ephemeral to the specified recipient in a shared conversation. * @param value - The recipient account * @param isTargeted - If true, marks this as a targeted message visible only to the recipient (default: false) * @returns this instance for chaining * * @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities. */ withRecipient(value, isTargeted = false) { this.recipient = { ...value, isTargeted: isTargeted ? true : void 0 }; return this; } withServiceUrl(value) { this.serviceUrl = value; return this; } withTimestamp(value) { this.timestamp = value; return this; } withLocale(value) { this.locale = value; return this; } withLocalTimestamp(value) { this.localTimestamp = value; return this; } /** * @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities. */ withChannelData(value) { const merged = { ...this.channelData, ...value }; if (merged.feedbackLoop !== void 0) { merged.feedbackLoopEnabled = void 0; } else if (merged.feedbackLoopEnabled === true) { merged.feedbackLoop = { type: "default" }; merged.feedbackLoopEnabled = void 0; } this.channelData = merged; return this; } /** * Add an entity. */ addEntity(value) { if (this.isRootLevelMessageEntity(value)) { this.mergeRootLevelMessageEntity(this.ensureSingleRootLevelMessageEntity(), value); return this; } if (!this.entities) { this.entities = []; } this.entities.push(value); return this; } /** * Add multiple entities */ addEntities(...value) { for (const entity of value) { this.addEntity(entity); } return this; } /** * Add the `Generated By AI` label. * * @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities. */ addAiGenerated() { const messageEntity = this.ensureSingleRootLevelMessageEntity(); if (messageEntity.additionalType?.includes("AIGeneratedContent")) { return this; } if (!messageEntity.additionalType) { messageEntity.additionalType = []; } messageEntity.additionalType.push("AIGeneratedContent"); return this; } /** * Enable message feedback. * @param mode - `'default'` shows Teams' built-in thumbs up/down UI. * `'custom'` triggers a `message/fetchTask` invoke so the bot can return its own task module dialog. * * @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities. */ addFeedback(mode = "default") { if (!this.channelData) { this.channelData = {}; } this.channelData.feedbackLoop = { type: mode }; this.channelData.feedbackLoopEnabled = void 0; return this; } /** * Add citations * * @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities. */ addCitation(position, appearance) { const messageEntity = this.ensureSingleRootLevelMessageEntity(); if (!messageEntity.citation) { messageEntity.citation = []; } messageEntity.citation.push({ "@type": "Claim", position, appearance: { "@type": "DigitalDocument", abstract: appearance.abstract, name: appearance.name, encodingFormat: appearance.text ? "application/vnd.microsoft.card.adaptive" : void 0, image: appearance.icon ? { "@type": "ImageObject", name: appearance.icon } : void 0, keywords: appearance.keywords, text: appearance.text, url: appearance.url, usageInfo: appearance.usageInfo ? { ...appearance.usageInfo, "@type": appearance.usageInfo["@type"] ?? "CreativeWork" } : void 0 } }); return this; } /** * Add a targeted message info entity for prompt preview. * Skips if already present. In reactive flows, `ctx.send()` and `ctx.reply()` * populate this automatically — use this helper for proactive or deferred sends. * An invalid or expired messageId causes the Teams service to silently drop the preview * while still delivering the message. * * @param messageId the message ID of the targeted message (from the incoming activity's `id`) * * @deprecated Use ActivityInput/MessageActivityInput/TypingActivityInput when constructing outbound activities. */ addTargetedMessageInfo(messageId) { if (this.entities) { this.entities = this.entities.filter((e) => e.type !== "quotedReply"); } if (this.type === "message") { const msg = this; if (msg.text) { msg.text = msg.text.replace(`<quoted messageId="${messageId}"/>`, "").trim(); } } if (this.entities?.some((e) => e.type === "targetedMessageInfo")) { return this; } return this.addEntity({ type: "targetedMessageInfo", messageId }); } /** * is this a streaming activity */ isStreaming() { return this.entities?.some((e) => e.type === "streaminfo") || false; } /** * Get or create the base message entity. * There should only be one root level message entity. */ ensureSingleRootLevelMessageEntity() { let messageEntity = this.entities?.find( (e) => this.isRootLevelMessageEntity(e) ); if (!messageEntity) { messageEntity = { type: "https://schema.org/Message", "@type": "Message", "@context": "https://schema.org", "@id": "" }; if (!this.entities) { this.entities = []; } this.entities.push(messageEntity); } return messageEntity; } isRootLevelMessageEntity(entity) { return entity.type === "https://schema.org/Message" && entity["@type"] === "Message"; } mergeRootLevelMessageEntity(target, source) { const merged = { ...target, ...source }; if (target.additionalType || source.additionalType) { merged.additionalType = [ .../* @__PURE__ */ new Set([...target.additionalType || [], ...source.additionalType || []]) ]; } if (target.citation || source.citation) { const dedupedCitations = /* @__PURE__ */ new Map(); for (const citation of [...target.citation || [], ...source.citation || []]) { dedupedCitations.set(citation.position, citation); } merged.citation = Array.from(dedupedCitations.values()); } Object.assign(target, merged); return target; } } export { Activity, ActivityInput }; //# sourceMappingURL=activity.mjs.map //# sourceMappingURL=activity.mjs.map