You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:54:16