chore(release): v1.2.5
This commit is contained in:
1 parent
422a4396e3
commit
b73f4141ae
7 files changed
+129
-56
No files matched your search
@@ -5,10 +5,10 @@
|
||||
<!-- 主版本: 重大变更/不兼容更新 -->
|
||||
<!-- 次版本: 新功能/兼容性更新 -->
|
||||
<!-- 修订号: Bug修复/小改进 -->
|
||||
<Version>1.2.4</Version>
|
||||
<AssemblyVersion>1.2.4.0</AssemblyVersion>
|
||||
<FileVersion>1.2.4.0</FileVersion>
|
||||
<InformationalVersion>1.2.4</InformationalVersion>
|
||||
<Version>1.2.5</Version>
|
||||
<AssemblyVersion>1.2.5.0</AssemblyVersion>
|
||||
<FileVersion>1.2.5.0</FileVersion>
|
||||
<InformationalVersion>1.2.5</InformationalVersion>
|
||||
|
||||
<!-- 项目元信息 -->
|
||||
<Authors>Telegram Panel Contributors</Authors>
|
||||
|
||||
@@ -63,9 +63,10 @@ public class AccountManagementService
|
||||
string? search,
|
||||
int pageIndex,
|
||||
int pageSize,
|
||||
bool onlyWaste = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var (items, total) = await _accountRepository.QueryPagedAsync(categoryId, search, pageIndex, pageSize, cancellationToken);
|
||||
var (items, total) = await _accountRepository.QueryPagedAsync(categoryId, search, pageIndex, pageSize, onlyWaste, cancellationToken);
|
||||
foreach (var a in items)
|
||||
FormatPhoneForDisplay(a);
|
||||
return (items, total);
|
||||
@@ -74,9 +75,10 @@ public class AccountManagementService
|
||||
public async Task<IReadOnlyList<Account>> QueryAccountsAsync(
|
||||
int? categoryId,
|
||||
string? search,
|
||||
bool onlyWaste = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var list = await _accountRepository.QueryAsync(categoryId, search, cancellationToken);
|
||||
var list = await _accountRepository.QueryAsync(categoryId, search, onlyWaste, cancellationToken);
|
||||
foreach (var a in list)
|
||||
FormatPhoneForDisplay(a);
|
||||
return list;
|
||||
|
||||
@@ -1047,6 +1047,22 @@ public class AccountTelegramToolsService
|
||||
{
|
||||
var msg = ex.Message ?? string.Empty;
|
||||
|
||||
if (msg.Contains("EMAIL_HASH_EXPIRED", StringComparison.OrdinalIgnoreCase))
|
||||
return (
|
||||
"邮箱验证码已过期(EMAIL_HASH_EXPIRED)",
|
||||
"请点击“重发验证码”,并使用最新邮件中的验证码。" + Environment.NewLine + msg);
|
||||
|
||||
if (msg.Contains("EMAIL_UNCONFIRMED", StringComparison.OrdinalIgnoreCase))
|
||||
return (
|
||||
"邮箱未确认(EMAIL_UNCONFIRMED)",
|
||||
"请在面板输入邮箱收到的验证码进行确认;如提示过期请重发并使用最新验证码。" + Environment.NewLine + msg);
|
||||
|
||||
if (msg.Contains("EMAIL_INVALID", StringComparison.OrdinalIgnoreCase))
|
||||
return ("邮箱无效(EMAIL_INVALID)", msg);
|
||||
|
||||
if (msg.Contains("EMAIL_NOT_ALLOWED", StringComparison.OrdinalIgnoreCase))
|
||||
return ("邮箱不允许使用(EMAIL_NOT_ALLOWED)", msg);
|
||||
|
||||
if (msg.Contains("FROZEN_METHOD_INVALID", StringComparison.OrdinalIgnoreCase))
|
||||
return ("账号被冻结(FROZEN_METHOD_INVALID)", "Telegram 提示该账号/ApiId 的某些接口被冻结(常见为创建频道接口)。" + Environment.NewLine + msg);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public class AccountRepository : Repository<Account>, IAccountRepository
|
||||
{
|
||||
}
|
||||
|
||||
private IQueryable<Account> BuildQuery(int? categoryId, string? search)
|
||||
private IQueryable<Account> BuildQuery(int? categoryId, string? search, bool onlyWaste)
|
||||
{
|
||||
var query = _dbSet
|
||||
.AsNoTracking()
|
||||
@@ -48,6 +48,44 @@ public class AccountRepository : Repository<Account>, IAccountRepository
|
||||
}
|
||||
}
|
||||
|
||||
if (onlyWaste)
|
||||
{
|
||||
// 仅废号:基于“上次 Telegram 状态检测摘要(Summary)”做筛选。
|
||||
// 注意:未检测的账号(Summary 为空)不会被包含。
|
||||
query = query.Where(a =>
|
||||
a.TelegramStatusSummary != null
|
||||
&& (
|
||||
// 账号封禁/停用
|
||||
EF.Functions.Like(a.TelegramStatusSummary, "%账号被封禁%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%被封禁/停用%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%USER_DEACTIVATED%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%PHONE_NUMBER_BANNED%")
|
||||
|
||||
// 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, "%Can't read session block%")
|
||||
|
||||
// 受限/冻结/未登录
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%账号受限%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%Restricted%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%账号被冻结%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%FROZEN_METHOD_INVALID%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%需要两步验证密码%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%SESSION_PASSWORD_NEEDED%")
|
||||
|
||||
// 注销/删除
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%账号已注销%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%已注销/被删除%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%被删除%")
|
||||
|
||||
// 连接/探测失败(按“废号”处理)
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%连接失败%")
|
||||
|| EF.Functions.Like(a.TelegramStatusSummary, "%创建频道探测失败%")
|
||||
));
|
||||
}
|
||||
|
||||
return query.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
@@ -118,13 +156,14 @@ public class AccountRepository : Repository<Account>, IAccountRepository
|
||||
string? search,
|
||||
int pageIndex,
|
||||
int pageSize,
|
||||
bool onlyWaste,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (pageIndex < 0) pageIndex = 0;
|
||||
if (pageSize <= 0) pageSize = 20;
|
||||
if (pageSize > 500) pageSize = 500;
|
||||
|
||||
var query = BuildQuery(categoryId, search);
|
||||
var query = BuildQuery(categoryId, search, onlyWaste);
|
||||
var total = await query.CountAsync(cancellationToken);
|
||||
var items = await query
|
||||
.Skip(pageIndex * pageSize)
|
||||
@@ -137,9 +176,10 @@ public class AccountRepository : Repository<Account>, IAccountRepository
|
||||
public async Task<IReadOnlyList<Account>> QueryAsync(
|
||||
int? categoryId,
|
||||
string? search,
|
||||
bool onlyWaste,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = BuildQuery(categoryId, search);
|
||||
var query = BuildQuery(categoryId, search, onlyWaste);
|
||||
return await query.ToListAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,12 @@ public interface IAccountRepository : IRepository<Account>
|
||||
string? search,
|
||||
int pageIndex,
|
||||
int pageSize,
|
||||
bool onlyWaste = false,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<IReadOnlyList<Account>> QueryAsync(
|
||||
int? categoryId,
|
||||
string? search,
|
||||
bool onlyWaste = false,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -43,18 +43,40 @@
|
||||
该账号未开启两步验证,无法绑定找回邮箱。请先设置二级密码。
|
||||
</MudAlert>
|
||||
}
|
||||
else if (step == Step.SetEmail)
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.subtitle2">发送验证码</MudText>
|
||||
|
||||
<MudTextField @bind-Value="currentPassword" Label="原二级密码" Variant="Variant.Outlined"
|
||||
InputType="InputType.Password" Required="true" />
|
||||
|
||||
<MudTextField @bind-Value="email" Label="新找回邮箱" Variant="Variant.Outlined"
|
||||
HelperText="将会向该邮箱发送验证码" Required="true" />
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<MudStack direction="Row" Spacing="2" AlignItems="AlignItems.Center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@running" OnClick="SendCode">
|
||||
@if (running)
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
|
||||
<span>发送中...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>发送验证码</span>
|
||||
}
|
||||
</MudButton>
|
||||
<MudText Typo="Typo.caption" Color="Color.Secondary">
|
||||
提示:即使“发送/重发”提示失败,但你实际收到了邮件验证码,也可以直接在下方输入验证码确认。
|
||||
</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudDivider Class="my-2" />
|
||||
|
||||
<MudText Typo="Typo.subtitle2">输入验证码确认</MudText>
|
||||
|
||||
<MudTextField @bind-Value="code" Label="邮箱验证码" Variant="Variant.Outlined"
|
||||
HelperText="请到邮箱中查看验证码(注意垃圾箱/延迟)" Required="true" />
|
||||
HelperText="请到邮箱中查看验证码(注意垃圾箱/延迟)。如提示过期,请先重发并使用最新验证码。"
|
||||
Required="true" />
|
||||
|
||||
<MudStack direction="Row" Spacing="2">
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Default" Disabled="@running" OnClick="Resend">
|
||||
@@ -63,6 +85,17 @@
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Default" Disabled="@running" OnClick="CancelVerification">
|
||||
取消验证
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@running" OnClick="Confirm">
|
||||
@if (running)
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
|
||||
<span>确认中...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>确认绑定</span>
|
||||
}
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
}
|
||||
}
|
||||
@@ -77,37 +110,7 @@
|
||||
去设置二级密码
|
||||
</MudButton>
|
||||
}
|
||||
else if (loaded && account != null && hasTwoFactorPassword)
|
||||
{
|
||||
@if (step == Step.SetEmail)
|
||||
{
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@running" OnClick="SendCode">
|
||||
@if (running)
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
|
||||
<span>发送中...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>发送验证码</span>
|
||||
}
|
||||
</MudButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Disabled="@running" OnClick="Confirm">
|
||||
@if (running)
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
|
||||
<span>确认中...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>确认绑定</span>
|
||||
}
|
||||
</MudButton>
|
||||
}
|
||||
}
|
||||
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@@ -124,7 +127,6 @@
|
||||
private bool hasRecoveryEmail;
|
||||
private string? unconfirmedEmailPattern;
|
||||
|
||||
private Step step = Step.SetEmail;
|
||||
|
||||
private string currentPassword = "";
|
||||
private string email = "";
|
||||
@@ -135,7 +137,7 @@
|
||||
await ReloadStatus();
|
||||
}
|
||||
|
||||
private async Task ReloadStatus()
|
||||
private async Task ReloadStatus(bool silent = false)
|
||||
{
|
||||
loaded = false;
|
||||
try
|
||||
@@ -146,7 +148,7 @@
|
||||
if (account != null)
|
||||
{
|
||||
var (ok, err, hasPwd, hasEmail, unconfirmed) = await AccountTelegramTools.GetTwoFactorRecoveryEmailStatusAsync(AccountId);
|
||||
if (!ok)
|
||||
if (!ok && !silent)
|
||||
{
|
||||
Snackbar.Add($"获取2FA邮箱状态失败:{err}", Severity.Warning);
|
||||
}
|
||||
@@ -154,7 +156,6 @@
|
||||
hasRecoveryEmail = hasEmail;
|
||||
unconfirmedEmailPattern = unconfirmed;
|
||||
|
||||
step = string.IsNullOrWhiteSpace(unconfirmedEmailPattern) ? Step.SetEmail : Step.Confirm;
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -203,11 +204,17 @@
|
||||
if (!ok)
|
||||
{
|
||||
Snackbar.Add($"发送失败:{err}", Severity.Error);
|
||||
await ReloadStatus(silent: true);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(unconfirmedEmailPattern))
|
||||
{
|
||||
Snackbar.Add("检测到账号存在待确认邮箱:你可以直接输入邮箱验证码完成确认。", Severity.Info);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
unconfirmedEmailPattern = pattern;
|
||||
step = Step.Confirm;
|
||||
unconfirmedEmailPattern = pattern ?? unconfirmedEmailPattern;
|
||||
code = "";
|
||||
Snackbar.Add("验证码已发送,请到邮箱中查看并输入验证码确认。", Severity.Success);
|
||||
}
|
||||
@@ -320,9 +327,4 @@
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private enum Step
|
||||
{
|
||||
SetEmail,
|
||||
Confirm
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,14 @@
|
||||
<MudSelectItem Value="@c.Id">@c.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudCheckBox T="bool"
|
||||
@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;" />
|
||||
<MudTextField @bind-Value="searchString" Placeholder="搜索账号..." Adornment="Adornment.Start"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0 tp-input-full-xs"
|
||||
Style="min-width: 200px; flex: 1; max-width: 400px;"
|
||||
@@ -190,6 +198,7 @@
|
||||
private bool loading = true;
|
||||
private string searchString = "";
|
||||
private int filterCategoryId = 0;
|
||||
private bool onlyWaste;
|
||||
private readonly Dictionary<int, TelegramAccountStatusResult> telegramStatus = new();
|
||||
private HashSet<Account> selectedAccounts = new();
|
||||
private readonly CancellationTokenSource _pageCts = new();
|
||||
@@ -222,6 +231,7 @@
|
||||
var (items, total) = await AccountManagement.QueryAccountsPagedAsync(
|
||||
categoryId: categoryId,
|
||||
search: searchString,
|
||||
onlyWaste: onlyWaste,
|
||||
pageIndex: state.Page,
|
||||
pageSize: state.PageSize,
|
||||
cancellationToken: cancellationToken);
|
||||
@@ -1097,6 +1107,7 @@
|
||||
var (_, total) = await AccountManagement.QueryAccountsPagedAsync(
|
||||
categoryId: null,
|
||||
search: null,
|
||||
onlyWaste: false,
|
||||
pageIndex: 0,
|
||||
pageSize: 1,
|
||||
cancellationToken: _pageCts.Token);
|
||||
|
||||
Reference in new issue
Block a user