some
This commit is contained in:
parent
6af9c974be
commit
ff66cd7bf0
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "telegram-invite-automation",
|
"name": "telegram-invite-automation",
|
||||||
"version": "1.4.0",
|
"version": "1.5.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Automated user parsing and invites for Telegram groups",
|
"description": "Automated user parsing and invites for Telegram groups",
|
||||||
"main": "src/main/index.js",
|
"main": "src/main/index.js",
|
||||||
|
|||||||
@ -1092,6 +1092,21 @@ const explainInviteError = (error) => {
|
|||||||
if (error === "CHAT_MEMBER_ADD_FAILED") {
|
if (error === "CHAT_MEMBER_ADD_FAILED") {
|
||||||
return "Telegram отказал в добавлении пользователя. Возможные причины: пользователь недоступен для инвайта, неверные данные, ограничения чата или лимиты аккаунта.";
|
return "Telegram отказал в добавлении пользователя. Возможные причины: пользователь недоступен для инвайта, неверные данные, ограничения чата или лимиты аккаунта.";
|
||||||
}
|
}
|
||||||
|
if (error === "INVITER_ENTITY_NOT_RESOLVED_BY_MASTER") {
|
||||||
|
return "Мастер-админ не смог получить сущность инвайтера в своей сессии. Обычно это кэш сущностей/доступность аккаунта.";
|
||||||
|
}
|
||||||
|
if (error === "MASTER_TARGET_RESOLVE_FAILED" || error === "TARGET_RESOLVE_FAILED") {
|
||||||
|
return "Не удалось корректно резолвить целевую группу для текущего аккаунта.";
|
||||||
|
}
|
||||||
|
if (error === "TARGET_CLIENT_NOT_SET") {
|
||||||
|
return "Внутренняя ошибка: не задан клиент для проверки цели.";
|
||||||
|
}
|
||||||
|
if (error === "INVITED_USER_NOT_RESOLVED_FOR_ADMIN") {
|
||||||
|
return "Не удалось резолвить приглашаемого пользователя в сессии админ-аккаунта.";
|
||||||
|
}
|
||||||
|
if (error === "INVITED_USER_NOT_RESOLVED_FOR_CONFIRM") {
|
||||||
|
return "Не удалось резолвить пользователя в сессии аккаунта, который проверяет участие.";
|
||||||
|
}
|
||||||
if (error === "SOURCE_ADMIN_SKIPPED") {
|
if (error === "SOURCE_ADMIN_SKIPPED") {
|
||||||
return "Пользователь является администратором в группе конкурента и пропущен по фильтру.";
|
return "Пользователь является администратором в группе конкурента и пропущен по фильтру.";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,48 @@ class TelegramManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _resolveAccountEntityForMaster(masterClient, targetEntity, account) {
|
||||||
|
if (!masterClient || !targetEntity || !account) return null;
|
||||||
|
const username = account.username ? String(account.username).trim() : "";
|
||||||
|
const userId = account.user_id ? String(account.user_id).trim() : "";
|
||||||
|
|
||||||
|
if (username) {
|
||||||
|
try {
|
||||||
|
const byUsername = await masterClient.getEntity(username.startsWith("@") ? username : `@${username}`);
|
||||||
|
if (byUsername && byUsername.className === "User") return byUsername;
|
||||||
|
} catch (error) {
|
||||||
|
// continue fallback chain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userId) {
|
||||||
|
try {
|
||||||
|
const byId = await masterClient.getEntity(BigInt(userId));
|
||||||
|
if (byId && byId.className === "User") return byId;
|
||||||
|
} catch (error) {
|
||||||
|
// continue fallback chain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const participants = await masterClient.getParticipants(targetEntity, {
|
||||||
|
limit: 400,
|
||||||
|
search: username || ""
|
||||||
|
});
|
||||||
|
const found = (participants || []).find((item) => {
|
||||||
|
if (!item || item.className !== "User") return false;
|
||||||
|
const sameId = userId && item.id != null && item.id.toString() === userId;
|
||||||
|
const sameUsername = username && item.username && item.username.toLowerCase() === username.toLowerCase();
|
||||||
|
return Boolean(sameId || sameUsername);
|
||||||
|
});
|
||||||
|
if (found) return found;
|
||||||
|
} catch (error) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
async _collectInviteDiagnostics(client, targetEntity) {
|
async _collectInviteDiagnostics(client, targetEntity) {
|
||||||
const lines = [];
|
const lines = [];
|
||||||
if (!targetEntity) return "Диагностика: цель не определена";
|
if (!targetEntity) return "Диагностика: цель не определена";
|
||||||
@ -90,13 +132,10 @@ class TelegramManager {
|
|||||||
|
|
||||||
async _grantTempInviteAdmin(masterClient, targetEntity, account, allowAnonymous = false) {
|
async _grantTempInviteAdmin(masterClient, targetEntity, account, allowAnonymous = false) {
|
||||||
const rights = this._buildInviteAdminRights(allowAnonymous);
|
const rights = this._buildInviteAdminRights(allowAnonymous);
|
||||||
const identifier = account.user_id
|
const user = await this._resolveAccountEntityForMaster(masterClient, targetEntity, account);
|
||||||
? BigInt(account.user_id)
|
if (!user) {
|
||||||
: (account.username ? `@${account.username}` : "");
|
throw new Error("INVITER_ENTITY_NOT_RESOLVED_BY_MASTER");
|
||||||
if (!identifier) {
|
|
||||||
throw new Error("NO_ACCOUNT_IDENTITY");
|
|
||||||
}
|
}
|
||||||
const user = await masterClient.getEntity(identifier);
|
|
||||||
await masterClient.invoke(new Api.channels.EditAdmin({
|
await masterClient.invoke(new Api.channels.EditAdmin({
|
||||||
channel: targetEntity,
|
channel: targetEntity,
|
||||||
userId: user,
|
userId: user,
|
||||||
@ -114,13 +153,8 @@ class TelegramManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _revokeTempInviteAdmin(masterClient, targetEntity, account) {
|
async _revokeTempInviteAdmin(masterClient, targetEntity, account) {
|
||||||
const identifier = account.user_id
|
const user = await this._resolveAccountEntityForMaster(masterClient, targetEntity, account);
|
||||||
? BigInt(account.user_id)
|
if (!user) return;
|
||||||
: (account.username ? `@${account.username}` : "");
|
|
||||||
if (!identifier) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const user = await masterClient.getEntity(identifier);
|
|
||||||
await masterClient.invoke(new Api.channels.EditAdmin({
|
await masterClient.invoke(new Api.channels.EditAdmin({
|
||||||
channel: targetEntity,
|
channel: targetEntity,
|
||||||
userId: user,
|
userId: user,
|
||||||
@ -565,6 +599,7 @@ class TelegramManager {
|
|||||||
let targetEntity = null;
|
let targetEntity = null;
|
||||||
let targetType = "";
|
let targetType = "";
|
||||||
let resolvedUser = null;
|
let resolvedUser = null;
|
||||||
|
const targetEntityCache = new Map();
|
||||||
const buildConfirmDetail = (code, message, sourceLabel) => {
|
const buildConfirmDetail = (code, message, sourceLabel) => {
|
||||||
if (!code) return message || "";
|
if (!code) return message || "";
|
||||||
const base = message ? `${code}: ${message}` : code;
|
const base = message ? `${code}: ${message}` : code;
|
||||||
@ -580,14 +615,100 @@ class TelegramManager {
|
|||||||
if (username) return `проверка аккаунтом ${username}`;
|
if (username) return `проверка аккаунтом ${username}`;
|
||||||
return "проверка аккаунтом";
|
return "проверка аккаунтом";
|
||||||
};
|
};
|
||||||
const confirmMembership = async (user, confirmClient = client, sourceLabel = "") => {
|
const resolveUserForClient = async (targetClient, preferredUser = null) => {
|
||||||
if (!targetEntity || targetEntity.className !== "Channel") {
|
if (!targetClient) return null;
|
||||||
|
const providedUsername = options.username || "";
|
||||||
|
const normalizedUsername = providedUsername
|
||||||
|
? (providedUsername.startsWith("@") ? providedUsername : `@${providedUsername}`)
|
||||||
|
: "";
|
||||||
|
if (normalizedUsername) {
|
||||||
|
try {
|
||||||
|
const byUsername = await targetClient.getEntity(normalizedUsername);
|
||||||
|
if (byUsername && byUsername.className === "User") return byUsername;
|
||||||
|
} catch (error) {
|
||||||
|
// continue fallback chain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (userId != null && userId !== "") {
|
||||||
|
try {
|
||||||
|
const byId = await targetClient.getEntity(BigInt(String(userId)));
|
||||||
|
if (byId && byId.className === "User") return byId;
|
||||||
|
} catch (error) {
|
||||||
|
// continue fallback chain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (preferredUser && preferredUser.className === "User") {
|
||||||
|
return preferredUser;
|
||||||
|
}
|
||||||
|
if (preferredUser && preferredUser.userId != null && preferredUser.accessHash != null) {
|
||||||
|
try {
|
||||||
|
return new Api.InputUser({
|
||||||
|
userId: BigInt(String(preferredUser.userId)),
|
||||||
|
accessHash: BigInt(String(preferredUser.accessHash))
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// ignore malformed input user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (preferredUser && preferredUser.id != null && preferredUser.accessHash != null) {
|
||||||
|
try {
|
||||||
|
return new Api.InputUser({
|
||||||
|
userId: BigInt(String(preferredUser.id)),
|
||||||
|
accessHash: BigInt(String(preferredUser.accessHash))
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// ignore malformed user entity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
const getTargetEntityForClient = async (clientForTarget, accountEntry = null) => {
|
||||||
|
if (!clientForTarget) {
|
||||||
|
return { ok: false, error: "TARGET_CLIENT_NOT_SET" };
|
||||||
|
}
|
||||||
|
if (targetEntityCache.has(clientForTarget)) {
|
||||||
|
return { ok: true, entity: targetEntityCache.get(clientForTarget) };
|
||||||
|
}
|
||||||
|
const accountForTarget = accountEntry && accountEntry.account
|
||||||
|
? accountEntry.account
|
||||||
|
: (accountEntry || account);
|
||||||
|
const resolvedTarget = await this._resolveGroupEntity(
|
||||||
|
clientForTarget,
|
||||||
|
task.our_group,
|
||||||
|
Boolean(task.auto_join_our_group),
|
||||||
|
accountForTarget || null
|
||||||
|
);
|
||||||
|
if (!resolvedTarget.ok) {
|
||||||
|
return { ok: false, error: resolvedTarget.error || "TARGET_RESOLVE_FAILED" };
|
||||||
|
}
|
||||||
|
targetEntityCache.set(clientForTarget, resolvedTarget.entity);
|
||||||
|
return { ok: true, entity: resolvedTarget.entity };
|
||||||
|
};
|
||||||
|
const confirmMembership = async (user, confirmClient = client, sourceLabel = "", confirmEntry = null) => {
|
||||||
|
const targetForClient = await getTargetEntityForClient(confirmClient, confirmEntry);
|
||||||
|
if (!targetForClient.ok) {
|
||||||
|
return {
|
||||||
|
confirmed: null,
|
||||||
|
error: targetForClient.error,
|
||||||
|
detail: buildConfirmDetail(targetForClient.error, "ошибка подтверждения участия", sourceLabel)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const confirmTargetEntity = targetForClient.entity;
|
||||||
|
if (!confirmTargetEntity || confirmTargetEntity.className !== "Channel") {
|
||||||
return { confirmed: true, error: "", detail: "" };
|
return { confirmed: true, error: "", detail: "" };
|
||||||
}
|
}
|
||||||
|
const participantForClient = await resolveUserForClient(confirmClient, user);
|
||||||
|
if (!participantForClient) {
|
||||||
|
return {
|
||||||
|
confirmed: null,
|
||||||
|
error: "INVITED_USER_NOT_RESOLVED_FOR_CONFIRM",
|
||||||
|
detail: buildConfirmDetail("INVITED_USER_NOT_RESOLVED_FOR_CONFIRM", "не удалось резолвить пользователя для проверки участия", sourceLabel)
|
||||||
|
};
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await confirmClient.invoke(new Api.channels.GetParticipant({
|
await confirmClient.invoke(new Api.channels.GetParticipant({
|
||||||
channel: targetEntity,
|
channel: confirmTargetEntity,
|
||||||
participant: user
|
participant: participantForClient
|
||||||
}));
|
}));
|
||||||
return { confirmed: true, error: "", detail: sourceLabel ? `OK (${sourceLabel})` : "OK" };
|
return { confirmed: true, error: "", detail: sourceLabel ? `OK (${sourceLabel})` : "OK" };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -617,7 +738,7 @@ class TelegramManager {
|
|||||||
const attempts = [];
|
const attempts = [];
|
||||||
const triedClients = new Set();
|
const triedClients = new Set();
|
||||||
const directLabel = formatAccountSource("", inviterEntry);
|
const directLabel = formatAccountSource("", inviterEntry);
|
||||||
const direct = await confirmMembership(user, client, directLabel || "проверка этим аккаунтом");
|
const direct = await confirmMembership(user, client, directLabel || "проверка этим аккаунтом", entry);
|
||||||
if (direct.detail) {
|
if (direct.detail) {
|
||||||
attempts.push({ strategy: "confirm", ok: direct.confirmed === true, detail: direct.detail });
|
attempts.push({ strategy: "confirm", ok: direct.confirmed === true, detail: direct.detail });
|
||||||
}
|
}
|
||||||
@ -633,7 +754,7 @@ class TelegramManager {
|
|||||||
if (!entry || !entry.client || triedClients.has(entry.client)) continue;
|
if (!entry || !entry.client || triedClients.has(entry.client)) continue;
|
||||||
triedClients.add(entry.client);
|
triedClients.add(entry.client);
|
||||||
const label = formatAccountSource("проверка подтверждающим аккаунтом", entry);
|
const label = formatAccountSource("проверка подтверждающим аккаунтом", entry);
|
||||||
const confirmResult = await confirmMembership(user, entry.client, label);
|
const confirmResult = await confirmMembership(user, entry.client, label, entry);
|
||||||
if (confirmResult.detail) {
|
if (confirmResult.detail) {
|
||||||
attempts.push({ strategy: "confirm_role", ok: confirmResult.confirmed === true, detail: confirmResult.detail });
|
attempts.push({ strategy: "confirm_role", ok: confirmResult.confirmed === true, detail: confirmResult.detail });
|
||||||
}
|
}
|
||||||
@ -647,7 +768,7 @@ class TelegramManager {
|
|||||||
const masterEntry = masterId ? this.clients.get(masterId) : null;
|
const masterEntry = masterId ? this.clients.get(masterId) : null;
|
||||||
if (masterEntry && masterEntry.client && !triedClients.has(masterEntry.client)) {
|
if (masterEntry && masterEntry.client && !triedClients.has(masterEntry.client)) {
|
||||||
const adminLabel = formatAccountSource("проверка админом", masterEntry);
|
const adminLabel = formatAccountSource("проверка админом", masterEntry);
|
||||||
const adminConfirm = await confirmMembership(user, masterEntry.client, adminLabel);
|
const adminConfirm = await confirmMembership(user, masterEntry.client, adminLabel, masterEntry);
|
||||||
if (adminConfirm.detail) {
|
if (adminConfirm.detail) {
|
||||||
attempts.push({ strategy: "confirm_admin", ok: adminConfirm.confirmed === true, detail: adminConfirm.detail });
|
attempts.push({ strategy: "confirm_admin", ok: adminConfirm.confirmed === true, detail: adminConfirm.detail });
|
||||||
}
|
}
|
||||||
@ -657,7 +778,7 @@ class TelegramManager {
|
|||||||
if (finalResult.confirmed === null && !finalResult.detail) {
|
if (finalResult.confirmed === null && !finalResult.detail) {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||||
const retryLabel = directLabel ? `${directLabel}, повтор через 10с` : "проверка этим аккаунтом, повтор через 10с";
|
const retryLabel = directLabel ? `${directLabel}, повтор через 10с` : "проверка этим аккаунтом, повтор через 10с";
|
||||||
const retry = await confirmMembership(user, client, retryLabel);
|
const retry = await confirmMembership(user, client, retryLabel, entry);
|
||||||
if (retry.detail) {
|
if (retry.detail) {
|
||||||
attempts.push({ strategy: "confirm_retry", ok: retry.confirmed === true, detail: retry.detail });
|
attempts.push({ strategy: "confirm_retry", ok: retry.confirmed === true, detail: retry.detail });
|
||||||
}
|
}
|
||||||
@ -670,20 +791,22 @@ class TelegramManager {
|
|||||||
return { ...finalResult, attempts };
|
return { ...finalResult, attempts };
|
||||||
};
|
};
|
||||||
const attemptInvite = async (user) => {
|
const attemptInvite = async (user) => {
|
||||||
if (!targetEntity) {
|
const targetForClient = await getTargetEntityForClient(client, entry);
|
||||||
throw new Error("Target group not resolved");
|
if (!targetForClient.ok || !targetForClient.entity) {
|
||||||
|
throw new Error(targetForClient.error || "Target group not resolved");
|
||||||
}
|
}
|
||||||
if (targetEntity.className === "Channel") {
|
const inviteTargetEntity = targetForClient.entity;
|
||||||
|
if (inviteTargetEntity.className === "Channel") {
|
||||||
await client.invoke(
|
await client.invoke(
|
||||||
new Api.channels.InviteToChannel({
|
new Api.channels.InviteToChannel({
|
||||||
channel: targetEntity,
|
channel: inviteTargetEntity,
|
||||||
users: [user]
|
users: [user]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else if (targetEntity.className === "Chat") {
|
} else if (inviteTargetEntity.className === "Chat") {
|
||||||
await client.invoke(
|
await client.invoke(
|
||||||
new Api.messages.AddChatUser({
|
new Api.messages.AddChatUser({
|
||||||
chatId: targetEntity.id,
|
chatId: inviteTargetEntity.id,
|
||||||
userId: user,
|
userId: user,
|
||||||
fwdLimit: 0
|
fwdLimit: 0
|
||||||
})
|
})
|
||||||
@ -736,23 +859,29 @@ class TelegramManager {
|
|||||||
}
|
}
|
||||||
return "Недостаточно прав для инвайта.";
|
return "Недостаточно прав для инвайта.";
|
||||||
};
|
};
|
||||||
const attemptAdminInvite = async (user, adminClient = client, allowAnonymous = false) => {
|
const attemptAdminInvite = async (user, adminClient = client, adminEntry = entry, allowAnonymous = false) => {
|
||||||
if (!targetEntity) {
|
const targetForAdmin = await getTargetEntityForClient(adminClient, adminEntry);
|
||||||
throw new Error("Target group not resolved");
|
if (!targetForAdmin.ok || !targetForAdmin.entity) {
|
||||||
|
throw new Error(targetForAdmin.error || "Target group not resolved");
|
||||||
}
|
}
|
||||||
if (targetEntity.className !== "Channel") {
|
const adminTargetEntity = targetForAdmin.entity;
|
||||||
|
if (adminTargetEntity.className !== "Channel") {
|
||||||
throw new Error("ADMIN_INVITE_UNSUPPORTED_TARGET");
|
throw new Error("ADMIN_INVITE_UNSUPPORTED_TARGET");
|
||||||
}
|
}
|
||||||
|
const userForAdminClient = await resolveUserForClient(adminClient, user);
|
||||||
|
if (!userForAdminClient) {
|
||||||
|
throw new Error("INVITED_USER_NOT_RESOLVED_FOR_ADMIN");
|
||||||
|
}
|
||||||
const rights = this._buildInviteAdminRights(allowAnonymous);
|
const rights = this._buildInviteAdminRights(allowAnonymous);
|
||||||
await adminClient.invoke(new Api.channels.EditAdmin({
|
await adminClient.invoke(new Api.channels.EditAdmin({
|
||||||
channel: targetEntity,
|
channel: adminTargetEntity,
|
||||||
userId: user,
|
userId: userForAdminClient,
|
||||||
adminRights: rights,
|
adminRights: rights,
|
||||||
rank: "invite"
|
rank: "invite"
|
||||||
}));
|
}));
|
||||||
await adminClient.invoke(new Api.channels.EditAdmin({
|
await adminClient.invoke(new Api.channels.EditAdmin({
|
||||||
channel: targetEntity,
|
channel: adminTargetEntity,
|
||||||
userId: user,
|
userId: userForAdminClient,
|
||||||
adminRights: new Api.ChatAdminRights({}),
|
adminRights: new Api.ChatAdminRights({}),
|
||||||
rank: ""
|
rank: ""
|
||||||
}));
|
}));
|
||||||
@ -904,8 +1033,14 @@ class TelegramManager {
|
|||||||
const masterId = Number(task.invite_admin_master_id || 0);
|
const masterId = Number(task.invite_admin_master_id || 0);
|
||||||
const masterEntry = masterId ? this.clients.get(masterId) : null;
|
const masterEntry = masterId ? this.clients.get(masterId) : null;
|
||||||
if (masterEntry && masterId !== account.id) {
|
if (masterEntry && masterId !== account.id) {
|
||||||
|
let masterTargetEntity = null;
|
||||||
try {
|
try {
|
||||||
await this._grantTempInviteAdmin(masterEntry.client, targetEntity, account, Boolean(task.invite_admin_anonymous));
|
const masterTarget = await getTargetEntityForClient(masterEntry.client, masterEntry);
|
||||||
|
if (!masterTarget.ok || !masterTarget.entity) {
|
||||||
|
throw new Error(masterTarget.error || "MASTER_TARGET_RESOLVE_FAILED");
|
||||||
|
}
|
||||||
|
masterTargetEntity = masterTarget.entity;
|
||||||
|
await this._grantTempInviteAdmin(masterEntry.client, masterTargetEntity, account, Boolean(task.invite_admin_anonymous));
|
||||||
lastAttempts.push({ strategy: "temp_admin", ok: true, detail: "granted" });
|
lastAttempts.push({ strategy: "temp_admin", ok: true, detail: "granted" });
|
||||||
await attemptInvite(user);
|
await attemptInvite(user);
|
||||||
const confirm = await confirmMembershipWithFallback(user, entry);
|
const confirm = await confirmMembershipWithFallback(user, entry);
|
||||||
@ -933,7 +1068,9 @@ class TelegramManager {
|
|||||||
lastAttempts.push({ strategy: "temp_admin_invite", ok: false, detail: adminText });
|
lastAttempts.push({ strategy: "temp_admin_invite", ok: false, detail: adminText });
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
await this._revokeTempInviteAdmin(masterEntry.client, targetEntity, account);
|
if (masterTargetEntity) {
|
||||||
|
await this._revokeTempInviteAdmin(masterEntry.client, masterTargetEntity, account);
|
||||||
|
}
|
||||||
} catch (revokeError) {
|
} catch (revokeError) {
|
||||||
// ignore revoke errors
|
// ignore revoke errors
|
||||||
}
|
}
|
||||||
@ -947,7 +1084,7 @@ class TelegramManager {
|
|||||||
const masterId = Number(task.invite_admin_master_id || 0);
|
const masterId = Number(task.invite_admin_master_id || 0);
|
||||||
const masterEntry = masterId ? this.clients.get(masterId) : null;
|
const masterEntry = masterId ? this.clients.get(masterId) : null;
|
||||||
const adminClient = masterEntry ? masterEntry.client : client;
|
const adminClient = masterEntry ? masterEntry.client : client;
|
||||||
await attemptAdminInvite(user, adminClient, Boolean(task.invite_admin_anonymous));
|
await attemptAdminInvite(user, adminClient, masterEntry || entry, Boolean(task.invite_admin_anonymous));
|
||||||
const confirm = await confirmMembershipWithFallback(user, entry);
|
const confirm = await confirmMembershipWithFallback(user, entry);
|
||||||
if (confirm.confirmed !== true && !confirm.detail) {
|
if (confirm.confirmed !== true && !confirm.detail) {
|
||||||
const label = formatAccountSource("", entry) || "проверка этим аккаунтом";
|
const label = formatAccountSource("", entry) || "проверка этим аккаунтом";
|
||||||
|
|||||||
@ -30,6 +30,21 @@ export const explainInviteError = (error) => {
|
|||||||
if (error === "CHAT_MEMBER_ADD_FAILED") {
|
if (error === "CHAT_MEMBER_ADD_FAILED") {
|
||||||
return "Telegram отклонил добавление. Обычно это антиспам-ограничение или недостаток прав.";
|
return "Telegram отклонил добавление. Обычно это антиспам-ограничение или недостаток прав.";
|
||||||
}
|
}
|
||||||
|
if (error === "INVITER_ENTITY_NOT_RESOLVED_BY_MASTER") {
|
||||||
|
return "Мастер-админ не смог получить сущность инвайтера в своей сессии. Обычно это кэш сущностей/доступность аккаунта.";
|
||||||
|
}
|
||||||
|
if (error === "MASTER_TARGET_RESOLVE_FAILED" || error === "TARGET_RESOLVE_FAILED") {
|
||||||
|
return "Не удалось корректно резолвить целевую группу для текущего аккаунта.";
|
||||||
|
}
|
||||||
|
if (error === "TARGET_CLIENT_NOT_SET") {
|
||||||
|
return "Внутренняя ошибка: не задан клиент для проверки цели.";
|
||||||
|
}
|
||||||
|
if (error === "INVITED_USER_NOT_RESOLVED_FOR_ADMIN") {
|
||||||
|
return "Не удалось резолвить приглашаемого пользователя в сессии админ-аккаунта.";
|
||||||
|
}
|
||||||
|
if (error === "INVITED_USER_NOT_RESOLVED_FOR_CONFIRM") {
|
||||||
|
return "Не удалось резолвить пользователя в сессии аккаунта, который проверяет участие.";
|
||||||
|
}
|
||||||
if (error === "SOURCE_ADMIN_SKIPPED") {
|
if (error === "SOURCE_ADMIN_SKIPPED") {
|
||||||
return "Пользователь является администратором в группе конкурента и пропущен по фильтру.";
|
return "Пользователь является администратором в группе конкурента и пропущен по фильтру.";
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user