-
Настройки бота
-
Интерактивное управление профилем — аналог команд BotFather
+
+ {onBack ? (
+
+ ) : null}
+
+
Настройки бота
+
+ {botHint ? `@${botHint.replace(/_bot$/i, '')}_bot · ` : ''}
+ Полное управление как в BotFather
+
+
+
{loading ? (
diff --git a/apps/frontend/app/mini-apps/bot-manage/page.tsx b/apps/frontend/app/mini-apps/bot-manage/page.tsx
index 36fa2dd..e4d09cc 100644
--- a/apps/frontend/app/mini-apps/bot-manage/page.tsx
+++ b/apps/frontend/app/mini-apps/bot-manage/page.tsx
@@ -1,20 +1,40 @@
-import { Suspense } from 'react';
-import { Loader2 } from 'lucide-react';
-import { BotManageMiniAppContent } from './content';
+'use client';
+
+import { useEffect } from 'react';
+import { useRouter, useSearchParams } from 'next/navigation';
+import { Loader2 } from 'lucide-react';
+import { Suspense } from 'react';
+
+function BotManageLegacyRedirectContent() {
+ const router = useRouter();
+ const searchParams = useSearchParams();
+ const botId = searchParams.get('botId');
+
+ useEffect(() => {
+ const target = botId
+ ? `/mini-apps/bot-father?botId=${encodeURIComponent(botId)}`
+ : '/mini-apps/bot-father';
+ router.replace(target);
+ }, [botId, router]);
-function BotManageFallback() {
return (
- Загрузка Mini App...
+ Перенаправление...
);
}
-export default function BotManageMiniAppPage() {
+export default function BotManageLegacyRedirectPage() {
return (
-
}>
-
+
+
+
+ }
+ >
+
);
}
diff --git a/apps/frontend/components/family/family-group-view.tsx b/apps/frontend/components/family/family-group-view.tsx
index ff726df..8e54d1c 100644
--- a/apps/frontend/components/family/family-group-view.tsx
+++ b/apps/frontend/components/family/family-group-view.tsx
@@ -365,10 +365,17 @@ export function FamilyGroupView({ groupId }: { groupId: string }) {
const loadMessages = useCallback(async (roomId: string) => {
if (!token || isPinLocked) return;
const room = rooms.find((item) => item.id === roomId);
- if (room?.type === 'BOT') return;
- const response = await fetchChatMessages(roomId, token);
- setMessages((response.messages ?? []).filter((message) => !message.isDeleted));
- }, [isPinLocked, rooms, token]);
+ if (!room || room.type === 'BOT') return;
+ try {
+ const response = await fetchChatMessages(roomId, token);
+ setMessages((response.messages ?? []).filter((message) => !message.isDeleted));
+ } catch (error) {
+ const message = getApiErrorMessage(error, 'Не удалось загрузить сообщения');
+ if (message && !message.includes('Bot API')) {
+ showToast(message);
+ }
+ }
+ }, [isPinLocked, rooms, showToast, token]);
const loadPresence = useCallback(async () => {
if (!token || isPinLocked) return;
@@ -406,10 +413,11 @@ export function FamilyGroupView({ groupId }: { groupId: string }) {
useEffect(() => {
if (!activeRoomId || activeRoomIsBot) return;
+ if (!rooms.some((room) => room.id === activeRoomId)) return;
void loadMessages(activeRoomId);
setEditingMessageId(null);
setDraft('');
- }, [activeRoomId, activeRoomIsBot, loadMessages]);
+ }, [activeRoomId, activeRoomIsBot, loadMessages, rooms]);
useEffect(() => {
if (!activeRoomId || !token || !messages.length) return;
diff --git a/apps/frontend/components/family/mini-family-chat.tsx b/apps/frontend/components/family/mini-family-chat.tsx
index 8fe8fd8..f1ec8a4 100644
--- a/apps/frontend/components/family/mini-family-chat.tsx
+++ b/apps/frontend/components/family/mini-family-chat.tsx
@@ -394,7 +394,10 @@ export function MiniFamilyChat() {
exitSelectionMode();
showToast(ids.length === 1 ? 'Сообщение удалено' : 'Сообщения удалены');
} catch (error) {
- if (activeRoom) {
+ if (view === 'bot' && activeBot) {
+ const response = await fetchBotChatMessages(activeBot.botRef, token);
+ setBotMessages(response.messages ?? []);
+ } else if (activeRoom && activeRoom.type !== 'BOT') {
const response = await fetchChatMessages(activeRoom.id, token);
setMessages((response.messages ?? []).filter((message) => !message.isDeleted));
}
diff --git a/apps/sso-core/src/domain/auth-grpc.controller.ts b/apps/sso-core/src/domain/auth-grpc.controller.ts
index b3afe4c..125a523 100644
--- a/apps/sso-core/src/domain/auth-grpc.controller.ts
+++ b/apps/sso-core/src/domain/auth-grpc.controller.ts
@@ -1160,7 +1160,13 @@ export class AuthGrpcController {
@GrpcMethod('BotService', 'ListAllBots')
listAllBots(command: { requesterId: string; isSuperAdmin?: boolean; search?: string; page?: number; limit?: number }) {
- return this.botFather.listAllBots(command.requesterId, Boolean(command.isSuperAdmin), command.search, command.page, command.limit);
+ return this.botFather.listAllBots(
+ command.requesterId,
+ Boolean(command.isSuperAdmin),
+ command.search,
+ Number(command.page) || 1,
+ Number(command.limit) || 20
+ );
}
@GrpcMethod('BotService', 'SetBotActive')
diff --git a/apps/sso-core/src/domain/bot/bot-father.constants.ts b/apps/sso-core/src/domain/bot/bot-father.constants.ts
index ff86b03..7ab9100 100644
--- a/apps/sso-core/src/domain/bot/bot-father.constants.ts
+++ b/apps/sso-core/src/domain/bot/bot-father.constants.ts
@@ -9,15 +9,19 @@ export function resolvePublicFrontendUrl() {
return (process.env.PUBLIC_FRONTEND_URL ?? 'http://localhost:3002').replace(/\/$/, '');
}
+export function buildBotFatherWebAppUrl() {
+ return `${resolvePublicFrontendUrl()}/mini-apps/bot-father`;
+}
+
export function buildBotManageWebAppUrl(botId: string) {
- return `${resolvePublicFrontendUrl()}/mini-apps/bot-manage?botId=${botId}`;
+ return `${resolvePublicFrontendUrl()}/mini-apps/bot-father?botId=${encodeURIComponent(botId)}`;
}
export function buildBotCreateWebAppUrl() {
- return `${resolvePublicFrontendUrl()}/mini-apps/bot-create`;
+ return `${buildBotFatherWebAppUrl()}?mode=create`;
}
export function isBotManageWebAppUrl(url: string | null | undefined) {
if (!url?.trim()) return false;
- return url.includes('/mini-apps/bot-manage');
+ return url.includes('/mini-apps/bot-manage') || url.includes('/mini-apps/bot-father');
}
diff --git a/apps/sso-core/src/domain/bot/bot-menu-button.util.ts b/apps/sso-core/src/domain/bot/bot-menu-button.util.ts
index e69a2d2..98d1df0 100644
--- a/apps/sso-core/src/domain/bot/bot-menu-button.util.ts
+++ b/apps/sso-core/src/domain/bot/bot-menu-button.util.ts
@@ -1,4 +1,4 @@
-import { BOTFATHER_BOT_USERNAME, buildBotCreateWebAppUrl, isBotManageWebAppUrl } from './bot-father.constants';
+import { BOTFATHER_BOT_USERNAME, buildBotFatherWebAppUrl, isBotManageWebAppUrl } from './bot-father.constants';
export type TelegramMenuButtonDefault = { type: 'default' };
export type TelegramMenuButtonCommands = { type: 'commands' };
@@ -141,11 +141,11 @@ export function resolveComposerMenuButton(options: {
}
if (options.bot.isSystemBot || options.bot.username === BOTFATHER_BOT_USERNAME) {
- const url = buildBotCreateWebAppUrl();
+ const url = buildBotFatherWebAppUrl();
return {
- menuButton: { type: 'web_app', text: 'Создать бота', web_app: { url } },
+ menuButton: { type: 'web_app', text: 'BotFather', web_app: { url } },
composerWebAppUrl: url,
- buttonText: 'Создать бота'
+ buttonText: 'BotFather'
};
}