基于Microsoft Bot Framework(C#)实现Telegram群聊共用列表的最简方法
问题:实现Telegram群聊共用列表的最简方法(Microsoft Bot Framework C#)
你想用Microsoft Bot Framework(C#)构建一个Telegram机器人,核心需求是在群聊里实现一个所有人可共同填写的共用列表,预期效果是:
user a: /add hello user b: /add world user a: /show bot: hello world user b: /show bot: hello world
但目前你的实现里,每个用户调用/show只能看到自己添加的内容:
user a: /add hello user b: /add world user a: /show bot: hello user b: /show bot: world
你的当前代码如下:
[Serializable] public class RootDialog : IDialog<object> { private List<string> list = new List<string>(); public Task StartAsync(IDialogContext context) { context.Wait(MessageReceivedAsync); return Task.CompletedTask; } private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result) { var activity = await result as Activity; switch (Parser.GetCommand(activity)) { case "/add": AddNewThingToList(activity); break; case "/show": ShowList(context); break; } context.Wait(MessageReceivedAsync); } private void AddNewThingToList(Activity activity) { list.Add(Parser.GetAfterCommandText(activity)); } private void ShowList(IDialogContext context) { var response = new StringBuilder(); for (var i = 0; i < list.Count; i++) { response.Append($"{i}. {list[i]}{Environment.NewLine}"); } context.PostAsync(response.ToString()); } }
最简解决方案
问题根源
你现在的list是每个RootDialog实例的私有字段——Bot Framework会给每个用户的会话创建独立的RootDialog实例,所以不同用户的列表完全隔离,自然看不到对方添加的内容。
最简实现:静态共享字典(区分群聊)
要实现群内共用,我们需要把列表改成全局共享的存储,而且要区分不同的群聊(不然所有群的内容会混在一起)。最简的方式就是用一个静态字典,以群聊ID为键,对应每个群的列表为值。
修改后的代码如下:
[Serializable] public class RootDialog : IDialog<object> { // 静态字典:key是群聊ID,value是对应群的共用列表 private static Dictionary<string, List<string>> _groupSharedLists = new Dictionary<string, List<string>>(); public Task StartAsync(IDialogContext context) { context.Wait(MessageReceivedAsync); return Task.CompletedTask; } private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result) { var activity = await result as Activity; // 获取当前群聊的唯一ID(Bot Framework中Conversation.Id对应Telegram的聊天ID) var groupId = activity.Conversation.Id; switch (Parser.GetCommand(activity)) { case "/add": AddNewThingToList(groupId, activity); break; case "/show": await ShowList(context, groupId); break; } context.Wait(MessageReceivedAsync); } private void AddNewThingToList(string groupId, Activity activity) { // 如果当前群还没有列表,先创建一个 if (!_groupSharedLists.ContainsKey(groupId)) { _groupSharedLists[groupId] = new List<string>(); } // 往对应群的列表里加内容 _groupSharedLists[groupId].Add(Parser.GetAfterCommandText(activity)); } private async Task ShowList(IDialogContext context, string groupId) { var response = new StringBuilder(); // 如果当前群没有列表,提示空;否则遍历输出 if (_groupSharedLists.TryGetValue(groupId, out var groupList) && groupList.Count > 0) { for (var i = 0; i < groupList.Count; i++) { response.Append($"{i + 1}. {groupList[i]}{Environment.NewLine}"); } } else { response.Append("当前列表为空~"); } await context.PostAsync(response.ToString()); } }
关键说明
- 静态字典
_groupSharedLists:这个字段是全局共享的,所有RootDialog实例都会访问同一个字典,实现了跨用户的数据共享。 - 群聊ID区分:用
activity.Conversation.Id作为群聊的唯一标识,确保不同群的列表完全独立,不会互相干扰。 - 空列表处理:新增了空列表的提示逻辑,体验更友好。
注意:这个方案是进程内存储,如果机器人重启,所有群的列表数据都会丢失。如果需要持久化数据,可以把字典换成数据库(比如SQLite、SQL Server)或者缓存(比如Redis),但这已经超出“最简”的范围啦。
内容的提问来源于stack exchange,提问作者Vladislav
相关产品推荐
相关产品推荐

