fix(bot-channels): 自动选择执行账号按权限过滤
- 解析 Bot API 管理员权限(can_invite_users/can_promote_members) - 批量邀请/设管理员自动选择时跳过无权限账号并给出原因
This commit is contained in:
1 parent
f7873cd66b
commit
4cc3f92389
3 files changed
+66
-36
No files matched your search
@@ -393,6 +393,8 @@ public class BotTelegramService
|
||||
|
||||
var status = el.TryGetProperty("status", out var statusEl) ? (statusEl.GetString() ?? "") : "";
|
||||
var customTitle = el.TryGetProperty("custom_title", out var ctEl) ? ctEl.GetString() : null;
|
||||
var canInviteUsers = ReadBool(el, "can_invite_users");
|
||||
var canPromoteMembers = ReadBool(el, "can_promote_members");
|
||||
|
||||
if (!el.TryGetProperty("user", out var userEl) || userEl.ValueKind != JsonValueKind.Object)
|
||||
continue;
|
||||
@@ -410,7 +412,9 @@ public class BotTelegramService
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
Status: status,
|
||||
CustomTitle: string.IsNullOrWhiteSpace(customTitle) ? null : customTitle.Trim()
|
||||
CustomTitle: string.IsNullOrWhiteSpace(customTitle) ? null : customTitle.Trim(),
|
||||
CanInviteUsers: canInviteUsers,
|
||||
CanPromoteMembers: canPromoteMembers
|
||||
));
|
||||
}
|
||||
|
||||
@@ -646,7 +650,15 @@ public class BotTelegramService
|
||||
|
||||
public sealed record BotChatInfo(long TelegramId, string Type, string? Title, string? Username, string? Description, int? MemberCount);
|
||||
|
||||
public sealed record BotChatAdminInfo(long UserId, string? Username, string? FirstName, string? LastName, string Status, string? CustomTitle)
|
||||
public sealed record BotChatAdminInfo(
|
||||
long UserId,
|
||||
string? Username,
|
||||
string? FirstName,
|
||||
string? LastName,
|
||||
string Status,
|
||||
string? CustomTitle,
|
||||
bool CanInviteUsers,
|
||||
bool CanPromoteMembers)
|
||||
{
|
||||
public bool IsCreator => string.Equals(Status, "creator", StringComparison.OrdinalIgnoreCase);
|
||||
public string DisplayName
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
private readonly Random _rand = new();
|
||||
private readonly List<Account> eligibleAccounts = new();
|
||||
private readonly Dictionary<long, Account> accountsByUserId = new();
|
||||
private readonly Dictionary<long, HashSet<long>> channelAdminUserIds = new();
|
||||
private readonly Dictionary<long, List<BotTelegramService.BotChatAdminInfo>> channelAdmins = new();
|
||||
|
||||
private List<BotChannel> channels = new();
|
||||
private int selectedAccountId;
|
||||
@@ -228,7 +228,7 @@
|
||||
loadingAdmins = true;
|
||||
adminSummary = null;
|
||||
eligibleAccounts.Clear();
|
||||
channelAdminUserIds.Clear();
|
||||
channelAdmins.Clear();
|
||||
try
|
||||
{
|
||||
var eligibleUserIds = new HashSet<long>();
|
||||
@@ -236,13 +236,12 @@
|
||||
|
||||
foreach (var ch in channels)
|
||||
{
|
||||
var adminIds = new HashSet<long>();
|
||||
var admins = new List<BotTelegramService.BotChatAdminInfo>();
|
||||
try
|
||||
{
|
||||
var admins = await BotTelegram.GetChatAdminsAsync(BotId, ch.TelegramId, CancellationToken.None);
|
||||
admins = await BotTelegram.GetChatAdminsAsync(BotId, ch.TelegramId, CancellationToken.None);
|
||||
foreach (var a in admins)
|
||||
{
|
||||
adminIds.Add(a.UserId);
|
||||
if (accountsByUserId.ContainsKey(a.UserId))
|
||||
eligibleUserIds.Add(a.UserId);
|
||||
}
|
||||
@@ -255,7 +254,7 @@
|
||||
// ignore
|
||||
}
|
||||
|
||||
channelAdminUserIds[ch.TelegramId] = adminIds;
|
||||
channelAdmins[ch.TelegramId] = admins;
|
||||
}
|
||||
|
||||
foreach (var uid in eligibleUserIds)
|
||||
@@ -422,7 +421,7 @@
|
||||
|
||||
foreach (var ch in channels)
|
||||
{
|
||||
var executorId = ResolveExecutorAccountId(ch);
|
||||
var (executorId, reason) = ResolveExecutorAccountId(ch);
|
||||
if (executorId == null)
|
||||
{
|
||||
foreach (var _ in usernames)
|
||||
@@ -431,7 +430,7 @@
|
||||
failed++;
|
||||
}
|
||||
|
||||
failures.Add($"{ch.Title}:无可用执行账号(需要该频道管理员且存在于系统账号)");
|
||||
failures.Add($"{ch.Title}:{reason ?? "无可用执行账号"}");
|
||||
StateHasChanged();
|
||||
continue;
|
||||
}
|
||||
@@ -530,27 +529,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
private int? ResolveExecutorAccountId(BotChannel channel)
|
||||
private (int? ExecutorId, string? Reason) ResolveExecutorAccountId(BotChannel channel)
|
||||
{
|
||||
if (!channelAdminUserIds.TryGetValue(channel.TelegramId, out var adminIds) || adminIds.Count == 0)
|
||||
return null;
|
||||
if (!channelAdmins.TryGetValue(channel.TelegramId, out var admins) || admins.Count == 0)
|
||||
return (null, "无法获取频道管理员列表(请确认 Bot 已加入且为管理员)");
|
||||
|
||||
if (selectedAccountId > 0)
|
||||
{
|
||||
var selected = eligibleAccounts.FirstOrDefault(x => x.Id == selectedAccountId);
|
||||
if (selected == null || selected.UserId <= 0)
|
||||
return null;
|
||||
return (null, "所选执行账号无效");
|
||||
|
||||
return adminIds.Contains(selected.UserId) ? selected.Id : null;
|
||||
var admin = admins.FirstOrDefault(x => x.UserId == selected.UserId);
|
||||
if (admin == null)
|
||||
return (null, "所选执行账号不是该频道管理员");
|
||||
|
||||
if (!admin.IsCreator && !admin.CanPromoteMembers)
|
||||
return (null, "所选执行账号缺少“添加管理员”权限");
|
||||
|
||||
return (selected.Id, null);
|
||||
}
|
||||
|
||||
foreach (var uid in adminIds)
|
||||
foreach (var a in admins)
|
||||
{
|
||||
if (accountsByUserId.TryGetValue(uid, out var acc))
|
||||
return acc.Id;
|
||||
if (!a.IsCreator && !a.CanPromoteMembers)
|
||||
continue;
|
||||
|
||||
if (accountsByUserId.TryGetValue(a.UserId, out var acc))
|
||||
return (acc.Id, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
return (null, "无可用执行账号(需要该频道管理员且拥有“添加管理员”权限,并且在系统中存在)");
|
||||
}
|
||||
|
||||
private void CancelOrClose()
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
private readonly Random _rand = new();
|
||||
private readonly List<Account> eligibleAccounts = new();
|
||||
private readonly Dictionary<long, Account> accountsByUserId = new();
|
||||
private readonly Dictionary<long, HashSet<long>> channelAdminUserIds = new();
|
||||
private readonly Dictionary<long, List<BotTelegramService.BotChatAdminInfo>> channelAdmins = new();
|
||||
|
||||
private List<BotChannel> channels = new();
|
||||
private int selectedAccountId;
|
||||
@@ -179,7 +179,7 @@
|
||||
loadingAdmins = true;
|
||||
adminSummary = null;
|
||||
eligibleAccounts.Clear();
|
||||
channelAdminUserIds.Clear();
|
||||
channelAdmins.Clear();
|
||||
try
|
||||
{
|
||||
var eligibleUserIds = new HashSet<long>();
|
||||
@@ -187,13 +187,12 @@
|
||||
|
||||
foreach (var ch in channels)
|
||||
{
|
||||
var adminIds = new HashSet<long>();
|
||||
var admins = new List<BotTelegramService.BotChatAdminInfo>();
|
||||
try
|
||||
{
|
||||
var admins = await BotTelegram.GetChatAdminsAsync(BotId, ch.TelegramId, CancellationToken.None);
|
||||
admins = await BotTelegram.GetChatAdminsAsync(BotId, ch.TelegramId, CancellationToken.None);
|
||||
foreach (var a in admins)
|
||||
{
|
||||
adminIds.Add(a.UserId);
|
||||
if (accountsByUserId.ContainsKey(a.UserId))
|
||||
eligibleUserIds.Add(a.UserId);
|
||||
}
|
||||
@@ -206,7 +205,7 @@
|
||||
// ignore: 无权限/风控/频道已失效等,后续按“无可用执行账号”处理
|
||||
}
|
||||
|
||||
channelAdminUserIds[ch.TelegramId] = adminIds;
|
||||
channelAdmins[ch.TelegramId] = admins;
|
||||
}
|
||||
|
||||
foreach (var uid in eligibleUserIds)
|
||||
@@ -353,7 +352,7 @@
|
||||
|
||||
foreach (var ch in channels)
|
||||
{
|
||||
var executorId = ResolveExecutorAccountId(ch);
|
||||
var (executorId, reason) = ResolveExecutorAccountId(ch);
|
||||
if (executorId == null)
|
||||
{
|
||||
foreach (var _ in usernames)
|
||||
@@ -362,7 +361,7 @@
|
||||
failed++;
|
||||
}
|
||||
|
||||
failures.Add($"{ch.Title}:无可用执行账号(需要该频道管理员且存在于系统账号)");
|
||||
failures.Add($"{ch.Title}:{reason ?? "无可用执行账号"}");
|
||||
StateHasChanged();
|
||||
continue;
|
||||
}
|
||||
@@ -461,27 +460,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
private int? ResolveExecutorAccountId(BotChannel channel)
|
||||
private (int? ExecutorId, string? Reason) ResolveExecutorAccountId(BotChannel channel)
|
||||
{
|
||||
if (!channelAdminUserIds.TryGetValue(channel.TelegramId, out var adminIds) || adminIds.Count == 0)
|
||||
return null;
|
||||
if (!channelAdmins.TryGetValue(channel.TelegramId, out var admins) || admins.Count == 0)
|
||||
return (null, "无法获取频道管理员列表(请确认 Bot 已加入且为管理员)");
|
||||
|
||||
if (selectedAccountId > 0)
|
||||
{
|
||||
var selected = eligibleAccounts.FirstOrDefault(x => x.Id == selectedAccountId);
|
||||
if (selected == null || selected.UserId <= 0)
|
||||
return null;
|
||||
return (null, "所选执行账号无效");
|
||||
|
||||
return adminIds.Contains(selected.UserId) ? selected.Id : null;
|
||||
var admin = admins.FirstOrDefault(x => x.UserId == selected.UserId);
|
||||
if (admin == null)
|
||||
return (null, "所选执行账号不是该频道管理员");
|
||||
|
||||
if (!admin.IsCreator && !admin.CanInviteUsers)
|
||||
return (null, "所选执行账号缺少“邀请用户”权限");
|
||||
|
||||
return (selected.Id, null);
|
||||
}
|
||||
|
||||
foreach (var uid in adminIds)
|
||||
foreach (var a in admins)
|
||||
{
|
||||
if (accountsByUserId.TryGetValue(uid, out var acc))
|
||||
return acc.Id;
|
||||
if (!a.IsCreator && !a.CanInviteUsers)
|
||||
continue;
|
||||
|
||||
if (accountsByUserId.TryGetValue(a.UserId, out var acc))
|
||||
return (acc.Id, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
return (null, "无可用执行账号(需要该频道管理员且拥有“邀请用户”权限,并且在系统中存在)");
|
||||
}
|
||||
|
||||
private void CancelOrClose()
|
||||
|
||||
Reference in new issue
Block a user