Teams安卓端Adaptive Card触发Action.Execute时出现短暂错误提示
版本信息
- 包:botbuilder@4.11.0
- Node.js:v16.19.0
- Teams安卓客户端:1416/1.0.0/2023012702/0115
我开发了一款通知类聊天机器人,会向用户发送Adaptive Card通知。用户可在卡片的Input.Text字段输入回复内容,点击触发Action.Execute的发送按钮后,Node.js机器人会处理该活动:向对应用户发送通知,并更新卡片内容。
该功能在Web端和桌面端运行完全正常,但在Teams安卓客户端中,卡片最终完成更新前,会短暂显示"Something Went Wrong"错误提示。
甚至无论我对卡片执行什么操作,即使仅返回InvokeResponse不做任何其他处理,该错误仍会出现。
发送的卡片代码
{ "type": "AdaptiveCard", "appId": process.env.MicrosoftBotAppId, "body": [ { "type": "TextBlock", "text": message, "wrap": true }, { "id": "history_title", "type": "TextBlock", "text": cardString.pastEvents, "wrap": true }, { "type": "Container", "spacing": "None", "items": [ { "id": "last_trail_name", "type": "TextBlock", "text": lastTrail ? cardString.action(lastTrail.userName, lastTrailAction) : "", "spacing": "None", // "size": "Small", "wrap": true }, { "id": "last_trail_comment", "type": "TextBlock", "text": lastTrail ? `${lastTrail.comment.replace(/<\/?[^>]+(>|$)/g, "")}` : "", "spacing": "None", // "size": "Small", "wrap": true }, { "id": "last_trail_date", "type": "TextBlock", "text": lastTrail ? `${lastTrailDateString}` : "", "spacing": "None", "isSubtle": true, "size": "Small", "wrap": true } ] }, { "type": "Container", "items": [ { "id": "second_last_trail_name", "type": "TextBlock", "text": secondLastTrail ? cardString.action(secondLastTrail.userName, secondLastTrailAction) : "", "spacing": "None", // "size": "Small", "wrap": true }, { "id": "second_last_trail_comment", "type": "TextBlock", "text": secondLastTrail ? `${secondLastTrail.comment.replace(/<\/?[^>]+(>|$)/g, "")}` : "", "spacing": "None", // "size": "Small", "wrap": true }, { "id": "second_last_trail_date", "type": "TextBlock", "text": secondLastTrail ? `${secondLastTrailDateString}` : "", "spacing": "None", "isSubtle": true, "size": "Small", "wrap": true } ] }, { "id": "comment", "isRequired": true, "type": "Input.Text", "placeholder": cardString.commentPlaceholder, "isMultiline": true }, { "id": "success-msg", "type": "TextBlock", "text": success ? cardString.commentSentAlert : "", "spacing": "None", "isSubtle": true, "size": "Small", "wrap": true, "color": "good" } ], "actions": [ { // "tooltip": isPremium ? cardString.send : cardString.premiumTooltip, // "isEnabled": isPremium, "type": "Action.Execute", "verb": "comment", "title": cardString.send, "data": data, }, { "type": "Action.OpenUrl", "title": cardString.goToTicketButton, "url": deeplink } ], "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "version": "1.4" }
处理动作的机器人代码
class Bot extends TeamsActivityHandler { constructor() { super(); this.onMembersAdded(async (turnContext: TurnContext, next: () => Promise<any>) => { const gettingStartedUrl: string = 'https://www.teamswork.app/gettingstarted'; const membersAdded = turnContext.activity.membersAdded; for (let cnt = 0; cnt < membersAdded.length; cnt++) { if (membersAdded[cnt].id !== turnContext.activity.recipient.id) { const welcomeMessage = "Welcome message" // add conv references if (await this.storeConversationReference(turnContext)) await turnContext.sendActivity(welcomeMessage); // Only send notification if conversation reference store (one time) } } // By calling next() you ensure that the next BotHandler is run. await next(); }); } // Listener for activity e.g. comment activity on notification card async onInvokeActivity(turnContext: TurnContext): Promise<InvokeResponse<any>> { // Listen for activity invocation and check if the comment action on adaptiveCard has been called const activity: Activity = turnContext.activity; // context.log('activity: ', activity); // turnContext.sendActivity("Hello World!"); let card: object; if (activity.name === "adaptiveCard/action") { // context.log("action activity"); const action = activity.value.action; // context.log("action : ", action); if (action.verb === "comment") { const userName: string = activity.from.name; const userId: string = activity.from.aadObjectId; const data: IActionData = action.data; // context.log('data: ', action.data); const date: Date = new Date(); const tenantId: string = activity.conversation.tenantId; const comment: string = data.comment; const lang: string = data.lang || "en"; // assignee Ticket == user commennt if ((data.ticket.assigneeId == userId) && (data.ticket.firstTimeResponse == "")) { this.updateTicket(data.ticket) } // Check for ticketId if (!!!data.ticket) { context.log("No ticketId found, aborting"); // throw ("No ticketId found, aborting") } // Construct new audit trail / comment let newComment: IAuditTrail = { userName: userName, userId: userId, ticketId: data.ticket.id, action: "commented", comment: comment, date: date, } // initialize parameters for card to be sent const cardContent: ICardContent = { userName: userName, type: "comment", action: "commented", comment: comment, isRequestor: false, } // Prepare response message const encodedDeeplink: string = constructDeeplink(data.ticket, data.ticketingAppUrl, data.channelId, data.entityId); const message: string = constructMessage(data.ticket, data.cardContent, encodedDeeplink, lang); const isPremium: boolean = await getPremium(tenantId); // const card = invokeSuccessResponse(encodedDeeplink, message, data); // Save audit trail const insertCommentEndpoint: string = process.env["InsertCommentEndpoint"]; try { await cosmosService.insertItem(insertCommentEndpoint + encodeQueryParams({ instanceId: data.ticket.instanceId }), { comment: newComment }); } catch (error) { context.log(error); } // Send request to SendCardNotification API try { // Notification recipient id array let recipientIds: string[] = []; if (data.ticket.requestorId) recipientIds.push(data.ticket.requestorId) if (data.ticket.assigneeId) recipientIds.push(data.ticket.assigneeId) // If ticket have custom fields get people from them if (data.ticket.customFields) { // Get instance so we can get customFieldSetting const instanceContainer: Container = ticketDatabase.container(process.env["InstanceContainer"]); const { resource: instance } = await instanceContainer.item(data.ticket.instanceId, tenantId).read<IInstance>(); // Create array for user who will receive the notification let activePersonaCustomFields: ICustomField[] = []; if (instance.customFieldsLeft) activePersonaCustomFields.push(...instance.customFieldsLeft); if (instance.customFieldsRight) activePersonaCustomFields.push(...instance.customFieldsRight); activePersonaCustomFields = activePersonaCustomFields.filter((value) => value.type.key === "6_peoplepicker"); activePersonaCustomFields = activePersonaCustomFields.filter((value) => value.isReceiveNotification); if (activePersonaCustomFields.length > 0) { for (const fields of activePersonaCustomFields) { if (data.ticket.customFields[fields.id]?.length > 0) { const personas: IPersonaProps[] = data.ticket.customFields[fields.id]; for (const element of personas) { recipientIds.push(element.id) } } } } } // Remove message sender from recipient list recipientIds = recipientIds.filter((id) => id !== userId); // Get unique notification recipient array const uniqueRecipientIds: string[] = [... new Set(recipientIds)]; context.log("Sending notifications"); for (const id of uniqueRecipientIds) { await this.sendNotification(cardContent, id, tenantId, data); } card = NotificationCard(encodedDeeplink, message, data, true, isPremium, lang); const cardAttachment: Attachment = CardFactory.adaptiveCard(card); const activityPayload = MessageFactory.attachment(cardAttachment); activityPayload.id = turnContext.activity.replyToId; context.log("Updating cards"); await turnContext.updateActivity(activityPayload); } catch (error) { context.log(error) } } } const cardRes = { statusCode: StatusCodes.OK, type: 'application/vnd.microsoft.card.adaptive', value: card }; const res = { status: StatusCodes.OK, body: cardRes }; return res; } }
预期行为
卡片更新时不显示任何错误提示。
截图

内容的提问来源于stack exchange,提问作者ingmar ramzan shidqi
相关产品推荐
相关产品推荐

