Azure Bot Framework:用户10秒无活动时如何发送指定提醒消息?
Implementing 10-Second Inactivity Reminder in Azure Bot Framework
Got it, let's figure out how to make your Azure Bot send that inactivity reminder after 10 seconds of user silence. I'll walk you through the implementation with Bot Framework SDK v4, covering both C# and JavaScript since those are the most common stacks.
Core Approach
The idea is straightforward:
- Track the user's last activity timestamp using ConversationState (so we persist this data across conversation turns)
- Cancel any pending reminder tasks whenever the user sends a new activity
- Start a new 10-second delay task after each user interaction; if no new activity comes in by then, send the reminder
C# Implementation
First, define a state class to hold our tracking data:
public class UserActivityState { // Stores the last time the user interacted with the bot public DateTimeOffset LastActivityTime { get; set; } // Cancellation token to stop pending reminder tasks if user becomes active public CancellationTokenSource ReminderCts { get; set; } }
Next, set up your bot to use ConversationState and handle turns:
using Microsoft.Bot.Builder; using Microsoft.Bot.Schema; using System; using System.Threading; using System.Threading.Tasks; public class InactivityReminderBot : ActivityHandler { private readonly ConversationState _conversationState; private readonly IStatePropertyAccessor<UserActivityState> _userActivityStateAccessor; // Inject ConversationState via constructor (dependency injection) public InactivityReminderBot(ConversationState conversationState) { _conversationState = conversationState; _userActivityStateAccessor = _conversationState.CreateProperty<UserActivityState>("UserActivityState"); } public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default) { // Get or initialize the user's activity state var userActivityState = await _userActivityStateAccessor.GetAsync( turnContext, () => new UserActivityState(), cancellationToken ); // Cancel any existing reminder task if the user is active again if (userActivityState.ReminderCts != null) { userActivityState.ReminderCts.Cancel(); userActivityState.ReminderCts.Dispose(); } // Update the last activity timestamp (use UTC to avoid timezone issues) userActivityState.LastActivityTime = turnContext.Activity.Timestamp ?? DateTimeOffset.UtcNow; // Handle user messages (replace this with your bot's actual conversation logic) if (turnContext.Activity.Type == ActivityTypes.Message) { await turnContext.SendActivityAsync($"You said: {turnContext.Activity.Text}", cancellationToken: cancellationToken); } // Start a new reminder task userActivityState.ReminderCts = new CancellationTokenSource(); _ = SendReminderAfterInactivity(turnContext, userActivityState.ReminderCts.Token, cancellationToken); // Save the updated state to persist changes await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); } private async Task SendReminderAfterInactivity(ITurnContext turnContext, CancellationToken reminderToken, CancellationToken cancellationToken) { try { // Wait 10 seconds before sending the reminder await Task.Delay(TimeSpan.FromSeconds(10), reminderToken); // If the task wasn't canceled (user stayed inactive), send the reminder var reminderMessage = @"Looks like you aren't there for now. Bot Ping me again once you are back. Bye for now."; await turnContext.SendActivityAsync(reminderMessage, cancellationToken: cancellationToken); } catch (TaskCanceledException) { // User became active again, so we just ignore this exception } } }
JavaScript Implementation
First, set up your bot with ConversationState and tracking logic:
const { ActivityHandler, ConversationState, MemoryStorage } = require('botbuilder'); class InactivityReminderBot extends ActivityHandler { constructor(conversationState) { super(); this.conversationState = conversationState; // Create an accessor to manage our activity state this.userActivityStateAccessor = this.conversationState.createProperty('UserActivityState'); } async onTurn(context) { // Get or initialize the user's activity state let userActivityState = await this.userActivityStateAccessor.get(context, () => ({ lastActivityTime: null, reminderTimeout: null })); // Clear any pending reminder timeout if the user sends a new activity if (userActivityState.reminderTimeout) { clearTimeout(userActivityState.reminderTimeout); userActivityState.reminderTimeout = null; } // Update the last activity timestamp userActivityState.lastActivityTime = context.activity.timestamp || new Date(); // Handle user messages (replace with your bot's custom logic) if (context.activity.type === 'message') { await context.sendActivity(`You said: ${context.activity.text}`); } // Set a new 10-second timeout for the reminder userActivityState.reminderTimeout = setTimeout(async () => { const reminderMessage = `Looks like you aren't there for now. Bot Ping me again once you are back. Bye for now.`; await context.sendActivity(reminderMessage); // Clear the timeout reference after sending the reminder userActivityState.reminderTimeout = null; await this.conversationState.saveChanges(context); }, 10000); // 10,000ms = 10 seconds // Save the updated state to persist changes await this.conversationState.saveChanges(context); } } // Initialize storage and state (use Azure Blob/Cosmos DB in production) const memoryStorage = new MemoryStorage(); const conversationState = new ConversationState(memoryStorage); const bot = new InactivityReminderBot(conversationState);
Key Notes
- Production Storage: The examples use
MemoryStoragewhich works for testing, but in production, use Azure Blob Storage or Azure Cosmos DB to persist state across bot restarts. - Activity Types: This code tracks all user activities (not just messages) — if you want to limit it to only messages, adjust the logic to update the timestamp only when
ActivityTypes.Messageis received. - Time Zones: Always use UTC timestamps to avoid issues with different time zones across users.
- Task Cleanup: Make sure to cancel/dispose of pending tasks to prevent memory leaks and duplicate reminders.
内容的提问来源于stack exchange,提问作者Shwetanjali Dubey
相关产品推荐
相关产品推荐

