This commit is contained in:
Ivan Neplokhov 2026-02-03 16:47:43 +04:00
parent 37410dff97
commit e43eed7f9c
2 changed files with 39 additions and 7 deletions

View File

@ -87,7 +87,7 @@ export default function useTaskActions({
const chosen = pool.slice(0, required);
accountRolesMap = {};
chosen.forEach((accountId) => {
const existing = accountRolesMap[accountId] || {};
const existing = taskAccountRoles[accountId] || {};
accountRolesMap[accountId] = { monitor: true, invite: true, confirm: true, inviteLimit: existing.inviteLimit || 1 };
});
accountIds = chosen;
@ -98,7 +98,7 @@ export default function useTaskActions({
accountIds = accounts.map((account) => account.id);
accountRolesMap = {};
accountIds.forEach((accountId) => {
const existing = accountRolesMap[accountId] || {};
const existing = taskAccountRoles[accountId] || {};
accountRolesMap[accountId] = { monitor: true, invite: true, confirm: true, inviteLimit: existing.inviteLimit || 1 };
});
setTaskAccountRoles(accountRolesMap);

View File

@ -168,14 +168,36 @@ function LogsTab({
const buildUserReason = (invite) => {
const codeRaw = invite.error || invite.confirmError || invite.skippedReason || "";
const code = String(codeRaw).split(/[:(]/, 1)[0].trim();
const isInviteLinkTarget = String(invite.targetChat || "").includes("t.me/+");
if (invite.status === "success") return "Пользователь добавлен и участие подтверждено.";
if (invite.status === "unconfirmed") {
if (isInviteLinkTarget) {
return "Инвайт отправлен. Для цели по invite-ссылке вступление может подтверждаться с задержкой.";
}
if (code === "USER_NOT_PARTICIPANT") return "Инвайт отправлен, но пользователь еще не вступил в группу.";
return explainRawError(invite.confirmError) || "Инвайт отправлен, но участие пока не подтверждено.";
}
if (invite.status === "skipped") return explainRawError(invite.skippedReason) || "Попытка была пропущена.";
return explainRawError(invite.error) || "Telegram отклонил попытку приглашения.";
};
const buildDetailedExplanation = (invite) => {
if (!invite) return "Причина не определена";
if (invite.status === "unconfirmed") {
const isInviteLinkTarget = String(invite.targetChat || "").includes("t.me/+");
const confirmCode = String(invite.confirmError || "").split(/[:(]/, 1)[0].trim();
const hasRightForbidden = String(invite.strategyMeta || "").includes("RIGHT_FORBIDDEN");
if (confirmCode === "USER_NOT_PARTICIPANT") {
if (hasRightForbidden) {
return "У admin_invite не хватило прав (RIGHT_FORBIDDEN), а проверка показала, что пользователь пока не вступил в группу.";
}
return isInviteLinkTarget
? "Инвайт отправлен, но для цели по invite-ссылке пользователь может вступить позже (задержка подтверждения/ожидание одобрения)."
: "Инвайт отправлен, но пользователь ещё не вступил в группу на момент проверки.";
}
return explainRawError(invite.confirmError) || "Инвайт отправлен, но участие пока не подтверждено.";
}
return explainRawError(invite.error) || explainRawError(invite.confirmError) || "Причина не определена";
};
const buildInviteSummary = (invite) => {
const userLabel = invite.username
? `@${invite.username}${invite.userId ? ` (ID: ${invite.userId})` : ""}`
@ -193,8 +215,11 @@ function LogsTab({
if (invite.status === "success") {
reason = "Успешно добавлен в группу";
} else if (invite.status === "unconfirmed") {
const isInviteLinkTarget = String(invite.targetChat || "").includes("t.me/+");
if (invite.confirmError && invite.confirmError.includes("USER_NOT_PARTICIPANT")) {
reason = "Инвайт отправлен, но пользователь ещё не вступил (нужно согласие/вход по ссылке)";
reason = isInviteLinkTarget
? "Инвайт отправлен, ожидаем вступление (цель по invite-ссылке)"
: "Инвайт отправлен, но пользователь ещё не вступил (нужно согласие/вход по ссылке)";
} else {
reason = explainRawError(invite.confirmError) || "Участие не подтверждено";
}
@ -250,6 +275,13 @@ function LogsTab({
return "Ошибка";
}
};
const formatInviteStatusForRow = (invite) => {
if (!invite) return "—";
if (invite.status === "unconfirmed" && String(invite.targetChat || "").includes("t.me/+")) {
return "Ожидает вступления";
}
return formatInviteStatus(invite.status);
};
return (
<section className="card logs">
@ -527,7 +559,7 @@ function LogsTab({
<div className="log-time">
<div>{formatTimestamp(invite.invitedAt)}</div>
<div>
<span className={`log-status ${invite.status}`}>{formatInviteStatus(invite.status)}</span>
<span className={`log-status ${invite.status}`}>{formatInviteStatusForRow(invite)}</span>
</div>
</div>
<div className="log-details">
@ -543,7 +575,7 @@ function LogsTab({
</button>
{expandedInviteId === invite.id && (
<div className="invite-details">
<div><strong>Что случилось:</strong> {formatInviteStatus(invite.status)}</div>
<div><strong>Что случилось:</strong> {formatInviteStatusForRow(invite)}</div>
<div><strong>Почему:</strong> {buildUserReason(invite)}</div>
{suggestAction(invite) && (
<div><strong>Что сделать:</strong> {suggestAction(invite).replace(/^Совет:\s*/, "")}</div>
@ -607,7 +639,7 @@ function LogsTab({
<div>Цель: {invite.targetChat || "—"}</div>
<div>Тип цели: {formatTargetType(invite.targetType)}</div>
<div>Действие: {invite.action || "invite"}</div>
<div>Статус: {formatInviteStatus(invite.status)}</div>
<div>Статус: {formatInviteStatusForRow(invite)}</div>
<div>Результат: {formatErrorWithExplain(invite.skippedReason)}</div>
<div>Ошибка: {formatErrorWithExplain(invite.error)}</div>
{invite.confirmError && invite.confirmError.includes("(") && (
@ -617,7 +649,7 @@ function LogsTab({
&& selectedTask && selectedTask.randomAccounts && hasBothRoles(invite.watcherAccountId) && (
<div>Примечание: у наблюдателя стоят обе роли, но включен случайный выбор инвайт выполнен другим аккаунтом.</div>
)}
<div>Пояснение: {explainRawError(invite.error) || explainRawError(invite.confirmError) || "Причина не определена"}</div>
<div>Пояснение: {buildDetailedExplanation(invite)}</div>
<div>Стратегия: {invite.strategy || "—"}</div>
{invite.strategyMeta && !hasStrategySuccess(invite.strategyMeta) && (
<div>Результат: все стратегии не сработали</div>