feat(accounts): improve waste judge and cleanup
This commit is contained in:
1 parent
f8befcb3d4
commit
923296bfeb
4 files changed
+155
-4
No files matched your search
@@ -10,9 +10,8 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
📦 <b><a href="docs/getting-started/installation.md">安装部署</a></b> |
|
||||
📚 <b><a href="https://moeacgx.github.io/Telegram-Panel/">文档站</a></b> |
|
||||
🏪 <b><a href="https://faka.boxmoe.eu.org/">API 账号购买</a></b> |
|
||||
🧯 <b><a href="docs/guides/anti-freeze.md">防冻结指南</a></b> |
|
||||
🖼️ <b><a href="screenshot/">截图</a></b> |
|
||||
💬 <b><a href="https://t.me/zhanzhangck">TG 频道</a></b> |
|
||||
👥 <b><a href="https://t.me/vpsbbq">站长交流群</a></b>
|
||||
|
||||
@@ -61,6 +61,21 @@ public static class TelegramAccountWasteJudge
|
||||
return true;
|
||||
}
|
||||
|
||||
// Session 冲突/撤销:实际使用中通常都需要重新登录生成新 session,否则无法稳定使用
|
||||
if (summary.Contains("Session 冲突", StringComparison.OrdinalIgnoreCase)
|
||||
|| summary.Contains("AUTH_KEY_DUPLICATED", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reason = "Session 冲突";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (summary.Contains("Session 已被撤销", StringComparison.OrdinalIgnoreCase)
|
||||
|| summary.Contains("SESSION_REVOKED", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
reason = "Session 已被撤销";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (summary.Contains("Session 无法读取", StringComparison.OrdinalIgnoreCase)
|
||||
|| summary.Contains("Can't read session block", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
||||
@@ -64,6 +64,10 @@ public class AccountRepository : Repository<Account>, IAccountRepository
|
||||
// Session 失效/损坏
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%Session 失效%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%AUTH_KEY_UNREGISTERED%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%Session 冲突%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%AUTH_KEY_DUPLICATED%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%Session 已被撤销%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%SESSION_REVOKED%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%Session 无法读取%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%Can't read session block%")
|
||||
|
||||
@@ -147,7 +151,7 @@ public class AccountRepository : Repository<Account>, IAccountRepository
|
||||
{
|
||||
return await _dbSet
|
||||
.Include(a => a.Category)
|
||||
.Where(a => a.IsActive)
|
||||
.Where(a => a.IsActive && (a.Category == null || !a.Category.ExcludeFromOperations))
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
@bind-Value="onlyWaste"
|
||||
@bind-Value:after="OnFiltersChanged"
|
||||
Dense="true"
|
||||
Disabled="@loading"
|
||||
Label="只看废号"
|
||||
Class="tp-input-full-xs"
|
||||
Style="min-width: 140px; flex: 0 1 160px;" />
|
||||
@@ -64,6 +63,13 @@
|
||||
Disabled="@(loading || selectedAccounts.Count == 0)" OnClick="CleanupSelectedWasteAccounts" Size="Size.Small">
|
||||
清理废号(已选)
|
||||
</MudButton>
|
||||
@if (onlyWaste)
|
||||
{
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Error" StartIcon="@Icons.Material.Filled.DeleteSweep"
|
||||
Disabled="@(loading || accounts.Count == 0)" OnClick="CleanupFilteredWasteAccounts" Size="Size.Small">
|
||||
清理废号(筛选)
|
||||
</MudButton>
|
||||
}
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Error" StartIcon="@Icons.Material.Filled.DeleteSweep"
|
||||
Disabled="@loading" OnClick="CleanupAllWasteAccounts" Size="Size.Small">
|
||||
清理所有废号
|
||||
@@ -1132,6 +1138,133 @@
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CleanupFilteredWasteAccounts()
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
||||
var categoryId = filterCategoryId <= 0 ? (int?)null : filterCategoryId;
|
||||
var targets = (await AccountManagement.QueryAccountsAsync(
|
||||
categoryId: categoryId,
|
||||
search: searchString,
|
||||
onlyWaste: true,
|
||||
cancellationToken: _pageCts.Token))
|
||||
.Where(a => a.Id > 0)
|
||||
.GroupBy(a => a.Id)
|
||||
.Select(g => g.First())
|
||||
.ToList();
|
||||
|
||||
if (targets.Count == 0)
|
||||
{
|
||||
Snackbar.Add("当前筛选条件下没有可清理的废号(需要先执行一次状态检测)", Severity.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
loading = true;
|
||||
try
|
||||
{
|
||||
bool? probeResult = await DialogService.ShowMessageBox(
|
||||
"清理筛选废号",
|
||||
$"将对筛选结果 {targets.Count} 个账号执行 Telegram 状态检测,并删除判定为废号的账号与 session 文件。\n\n是否进行深度探测(将对每个账号创建并删除一个测试频道,用于判断【创建频道接口是否被冻结】)?",
|
||||
yesText: "深度检测并清理",
|
||||
cancelText: "普通检测并清理");
|
||||
|
||||
var probe = probeResult == true;
|
||||
|
||||
// 批量风控检查:深度探测是敏感操作
|
||||
if (probe && targets.Count > 0)
|
||||
{
|
||||
var batchCheck = RiskService.CheckBatchAccounts(targets);
|
||||
if (batchCheck.HasRiskyAccounts)
|
||||
{
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
["Message"] = $"检测到 {batchCheck.RiskyCount} 个风险账号",
|
||||
["DetailedMessage"] = batchCheck.GetRiskySummary(),
|
||||
["ShowRecommendations"] = true,
|
||||
["ShowExcludeOption"] = true,
|
||||
["RiskyAccounts"] = batchCheck.RiskyAccounts.ToList()
|
||||
};
|
||||
var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Large };
|
||||
var dialog = DialogService.Show<RiskWarningDialog>("批量操作风控警告", parameters, options);
|
||||
var dialogResult = await dialog.Result;
|
||||
|
||||
if (dialogResult.Canceled)
|
||||
{
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dialogResult.Data is TelegramPanel.Core.Services.RiskWarningAction action
|
||||
&& action == TelegramPanel.Core.Services.RiskWarningAction.ExcludeRisky)
|
||||
{
|
||||
targets = batchCheck.SafeAccounts.ToList();
|
||||
if (targets.Count == 0)
|
||||
{
|
||||
Snackbar.Add("排除风险账号后无剩余账号", Severity.Info);
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var deleted = 0;
|
||||
var skipped = 0;
|
||||
var failures = new List<string>();
|
||||
|
||||
foreach (var a in targets)
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = await AccountTelegramTools.RefreshAccountStatusAsync(
|
||||
a.Id,
|
||||
probeCreateChannel: probe,
|
||||
cancellationToken: _pageCts.Token);
|
||||
telegramStatus[a.Id] = status;
|
||||
|
||||
if (!TelegramAccountWasteJudge.TryGetWasteReason(status, out _))
|
||||
{
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
await AccountManagement.PurgeAccountAsync(a.Id, _pageCts.Token);
|
||||
deleted++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
failures.Add($"{a.DisplayPhone}:{ex.Message}");
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
selectedAccounts.Clear();
|
||||
await ReloadTable();
|
||||
|
||||
var summary = $"清理完成:删除 {deleted},跳过 {skipped},失败 {failures.Count}(共 {targets.Count})";
|
||||
Snackbar.Add(summary, failures.Count == 0 ? Severity.Success : Severity.Warning);
|
||||
|
||||
if (failures.Count > 0)
|
||||
{
|
||||
var details = string.Join(Environment.NewLine, failures.Take(80));
|
||||
if (failures.Count > 80)
|
||||
details += Environment.NewLine + $"... 仅展示前 80 条(共 {failures.Count} 条)";
|
||||
|
||||
await DialogService.ShowMessageBox("失败明细(前 80 条)", details, "关闭");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"批量清理失败:{ex.Message}", Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CleanupAllWasteAccounts()
|
||||
{
|
||||
if (loading)
|
||||
|
||||
Reference in new issue
Block a user