global fix and update bot Api

This commit is contained in:
lendry
2026-06-26 13:01:52 +03:00
parent d3ea470d02
commit aa228d84eb
29 changed files with 980 additions and 221 deletions

View File

@@ -9,7 +9,14 @@ import { NotificationsService } from './notifications.service';
import { MinioService } from '../infra/minio.service';
import { BotFatherSeedService } from './bot/bot-father-seed.service';
import { BotFatherService } from './bot/bot-father.service';
import { BOTFATHER_BOT_USERNAME, BOTFATHER_DISPLAY_NAME, BOTFATHER_USER_USERNAME } from './bot/bot-father.constants';
import {
BOTFATHER_BOT_USERNAME,
BOTFATHER_DISPLAY_NAME,
BOTFATHER_USER_USERNAME,
GET_MY_ID_BOT_USERNAME,
GET_MY_ID_DISPLAY_NAME,
GET_MY_ID_USER_USERNAME
} from './bot/bot-father.constants';
import { normalizeBotUsername } from './bot/bot-token.util';
import { HUMAN_USER_WHERE, isProtectedSystemAccount } from './system-account.util';
@@ -386,49 +393,6 @@ export class FamilyService {
async addBotFatherToFamily(requesterId: string, groupId: string) {
const group = await this.getGroupWithMembers(groupId);
this.assertMember(group, requesterId);
const botFatherUserId = await this.botFatherSeed.getBotFatherUserId();
if (group.members.some((member) => member.userId === botFatherUserId)) {
throw new BadRequestException('BotFather уже добавлен в эту семью');
}
return this.addMember(groupId, botFatherUserId, 'bot');
}
async addBotToFamily(requesterId: string, groupId: string, botId: string) {
const group = await this.getGroupWithMembers(groupId);
this.assertMember(group, requesterId);
const bot = await this.prisma.bot.findUnique({
where: { id: botId },
select: { id: true, isActive: true, username: true, name: true }
});
if (!bot) {
throw new NotFoundException('Бот не найден');
}
if (!bot.isActive) {
throw new BadRequestException('Бот деактивирован и не может быть добавлен в семью');
}
const { userId: botSystemUserId } = await this.botFather.ensureBotSystemUser(bot.id);
if (group.members.some((member) => member.userId === botSystemUserId)) {
throw new BadRequestException('Этот бот уже добавлен в семью');
}
return this.addMember(groupId, botSystemUserId, 'bot');
}
async removeMember(requesterId: string, memberId: string) {
const member = await this.prisma.familyMember.findUnique({
@@ -483,7 +447,7 @@ export class FamilyService {
const invitee = options.inviteeUserId
? await this.prisma.user.findFirst({
where: { id: options.inviteeUserId, status: 'ACTIVE', deletedAt: null, ...HUMAN_USER_WHERE }
where: { id: options.inviteeUserId, status: 'ACTIVE', deletedAt: null }
})
: options.target
? await this.findUserByContact(options.target)
@@ -493,10 +457,6 @@ export class FamilyService {
throw new BadRequestException('Пользователь не найден. Выберите его из результатов поиска.');
}
if (isProtectedSystemAccount(invitee)) {
throw new BadRequestException('BotFather добавляется через отдельное действие «Добавить BotFather»');
}
if (invitee.id === requesterId) {
throw new BadRequestException('Нельзя пригласить самого себя');
}
@@ -513,6 +473,35 @@ export class FamilyService {
}
const inviter = await this.prisma.user.findUnique({ where: { id: requesterId } });
const isBotInvite = isProtectedSystemAccount(invitee);
if (isBotInvite) {
const invite = await this.prisma.familyInvite.create({
data: {
groupId,
inviterId: requesterId,
inviteeUserId: invitee.id,
targetEmail: invitee.email ?? undefined,
targetPhone: invitee.phone ?? undefined,
status: 'ACCEPTED',
expiresAt: new Date(Date.now() + INVITE_TTL_DAYS * 24 * 60 * 60 * 1000)
},
include: {
group: true,
inviter: true
}
});
await this.addMember(groupId, invitee.id, 'bot');
await this.notifications.create(
requesterId,
'family_bot_added',
'Бот добавлен в семью',
`${invitee.displayName} добавлен(а) в «${group.name}» по приглашению`,
{ groupId, inviteId: invite.id, botUserId: invitee.id },
{ skipPublish: true }
);
return this.toInvite(invite);
}
const invite = await this.prisma.familyInvite.create({
data: {
groupId,
@@ -555,10 +544,17 @@ export class FamilyService {
.filter((username): username is string => Boolean(username))
);
const botFatherUserId = await this.botFatherSeed.getBotFatherUserId();
const botFatherBotId = await this.botFatherSeed.getBotFatherBotId();
const getMyIdUserId = await this.botFatherSeed.getGetMyIdBotUserId();
const getMyIdBotId = await this.botFatherSeed.getGetMyIdBotId();
const botFatherMatches =
/bot\s*father|бот\s*father|botfather/i.test(trimmed) &&
!excludedIds.includes(botFatherUserId) &&
!excludedBotUsernames.has(BOTFATHER_BOT_USERNAME);
const getMyIdMatches =
/get\s*my\s*id|getmyid|мой\s*id|айди|chat[_\s-]*id/i.test(trimmed) &&
!excludedIds.includes(getMyIdUserId) &&
!excludedBotUsernames.has(GET_MY_ID_BOT_USERNAME);
const digits = trimmed.replace(/\D/g, '');
const normalizedBotQuery = normalizeBotUsername(trimmed.replace(/^@/, ''));
@@ -624,6 +620,8 @@ export class FamilyService {
for (const bot of matchedBots) {
if (excludedBotUsernames.has(bot.username)) continue;
if (botFatherMatches && bot.username === BOTFATHER_BOT_USERNAME) continue;
if (getMyIdMatches && bot.username === GET_MY_ID_BOT_USERNAME) continue;
const { userId } = bot.linkedSystemUser
? { userId: bot.linkedSystemUser.id }
: await this.botFather.ensureBotSystemUser(bot.id);
@@ -672,7 +670,25 @@ export class FamilyService {
verificationIcon: resolveVerificationIcon('bot'),
isBot: true,
botUsername: BOTFATHER_BOT_USERNAME,
botId: undefined,
botId: botFatherBotId,
ownerDisplayName: undefined
}
]
: []),
...(getMyIdMatches
? [
{
id: getMyIdUserId,
displayName: GET_MY_ID_DISPLAY_NAME,
email: undefined,
phone: undefined,
username: GET_MY_ID_USER_USERNAME,
hasAvatar: false,
isVerified: true,
verificationIcon: resolveVerificationIcon('bot'),
isBot: true,
botUsername: GET_MY_ID_BOT_USERNAME,
botId: getMyIdBotId,
ownerDisplayName: undefined
}
]
@@ -1004,6 +1020,10 @@ export class FamilyService {
botFatherAvailable: !group.members.some(
(member) => member.user?.linkedBot?.username === BOTFATHER_BOT_USERNAME
),
getMyIdBotAvailable: !group.members.some(
(member) => member.user?.linkedBot?.username === GET_MY_ID_BOT_USERNAME
)
};