基于Bot Framework v3(C#)实现Teams Bot线程5天无回复自动提醒
嘿,这个需求我之前在项目里实现过,用Bot Framework v3(C#)的话可以按这几个核心步骤来搞:
实现步骤
1. 追踪每个线程的最后活动时间
首先你得记录下每条消息线程的最后互动时间,这样才能判断是否超过5天未回复。建议用持久化存储(比如SQL Server、Azure Table Storage),内存存储的话Bot重启就丢数据了,不靠谱。
每次收到用户/团队的消息时,更新对应线程的最后活动时间:
public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result) { var incomingMessage = await result; var conversationId = incomingMessage.Conversation.Id; // 替换成你的存储操作,比如写入数据库 await ConversationStorage.UpdateLastActivityTime(conversationId, DateTime.UtcNow); // 处理你的业务逻辑... }
存储表的核心字段建议包含:
ConversationId(线程唯一标识,作为主键)LastActivityTime(最后互动时间)ServiceUrl(Teams的服务地址,发送消息必须用这个)TargetUserId/TeamId(要提醒的用户或团队ID,确定提醒对象)
2. 定时检查过期线程
接下来需要一个后台定时任务,定期扫描所有线程,找出超过5天未活动的。这里推荐用Hangfire(轻量级后台任务框架),或者如果是部署在Azure上,也可以用Azure Functions定时触发。
示例:用Hangfire设置每日检查
在Bot的Startup类里配置定时任务:
// 配置Hangfire(需要先安装Hangfire相关NuGet包) GlobalConfiguration.Configuration.UseSqlServerStorage("你的数据库连接字符串"); app.UseHangfireDashboard(); // 每天执行一次检查任务,也可以改成每小时执行 RecurringJob.AddOrUpdate( "check-inactive-threads", () => InactiveThreadReminderService.CheckAndSendRemindersAsync(), Cron.Daily);
然后编写检查和发送提醒的逻辑:
public class InactiveThreadReminderService { public async Task CheckAndSendRemindersAsync() { var cutoffTime = DateTime.UtcNow.AddDays(-5); // 从存储中获取所有超过5天未活动的线程 var inactiveConversations = await ConversationStorage.GetInactiveConversations(cutoffTime); foreach (var conv in inactiveConversations) { // 构造提醒消息 var reminderMessage = Activity.CreateMessageActivity(); reminderMessage.Conversation = new ConversationAccount { Id = conv.ConversationId }; reminderMessage.Recipient = new ChannelAccount { Id = conv.TargetUserId }; reminderMessage.Text = "提醒:这条线程已经5天没有新消息啦,记得跟进哦!"; reminderMessage.ServiceUrl = conv.ServiceUrl; // 这个字段必须存,否则发不出消息 // 如果需要@特定用户,加上提及信息 reminderMessage.Entities = new List<Entity> { new Mention { Text = $"<at>{conv.TargetUserName}</at>", Mentioned = new ChannelAccount { Id = conv.TargetUserId, Name = conv.TargetUserName } } }; // 使用ConnectorClient发送消息(不能用DialogContext,因为是后台任务) var connector = new ConnectorClient(new Uri(conv.ServiceUrl)); try { await connector.Conversations.SendToConversationAsync((Activity)reminderMessage); // 发送成功后可以更新最后提醒时间,避免重复发送 await ConversationStorage.UpdateLastReminderTime(conv.ConversationId, DateTime.UtcNow); } catch (Exception ex) { // 记录发送失败的日志,方便排查 Logger.LogError(ex, $"发送提醒失败,ConversationId: {conv.ConversationId}"); } } } }
3. 注意Teams的特殊细节
- ServiceUrl必须存储:Teams的ServiceUrl是每个对话/团队的专属地址,没有它Bot无法发送消息到对应线程。
- 权限问题:确保Bot在对应的团队/线程里有发送消息的权限,不然会发送失败。
- 避免重复提醒:建议在存储里加个
LastReminderTime字段,比如设置只在超过5天且上次提醒超过24小时才发送,防止频繁打扰用户。 - 线程识别:Teams里的线程ConversationId包含线程标识,直接用这个作为主键即可区分不同线程。
4. 替代方案:如果不用Hangfire
如果不想引入第三方框架,也可以自己写一个Timer后台任务,但要注意Web App的休眠问题(比如Azure Web App如果一段时间没请求会休眠,导致Timer停止)。这种情况下,Azure Functions定时触发会更可靠,直接在Function里写检查和发送逻辑就行,和上面的CheckAndSendRemindersAsync逻辑差不多。
内容的提问来源于stack exchange,提问作者Mayuresh Jaiswal
相关产品推荐
相关产品推荐

