'use client'; import { useCallback, useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { Ban, Bot, CheckCircle2, Loader2, MessageSquare, Search, Users } from 'lucide-react'; import { AdminShell } from '@/components/id/admin-shell'; import { useAuth } from '@/components/id/auth-provider'; import { useToast } from '@/components/id/toast-provider'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { AdminBotMetrics, AdminUser, ManagedBot, fetchAdminBotAccounts, fetchAdminBotMetrics, fetchAdminBots, setAdminBotActive } from '@/lib/api'; import { getAdminLandingPath } from '@/lib/admin-access'; export default function AdminBotsPage() { const router = useRouter(); const { token, user: currentUser } = useAuth(); const { showToast } = useToast(); const [bots, setBots] = useState([]); const [botAccounts, setBotAccounts] = useState([]); const [total, setTotal] = useState(0); const [metrics, setMetrics] = useState(null); const [search, setSearch] = useState(''); const [page, setPage] = useState(1); const [loading, setLoading] = useState(true); const [actionBotId, setActionBotId] = useState(null); const loadBots = useCallback(async () => { if (!token) return; setLoading(true); try { const [botsResponse, metricsResponse, accountsResponse] = await Promise.all([ fetchAdminBots({ search, page, limit: 20 }, token), fetchAdminBotMetrics(token), fetchAdminBotAccounts(search, token) ]); setBots(botsResponse.bots ?? []); setTotal(botsResponse.total ?? 0); setMetrics(metricsResponse); setBotAccounts(accountsResponse.users ?? []); } catch (error) { showToast(error instanceof Error ? error.message : 'Не удалось загрузить ботов'); } finally { setLoading(false); } }, [page, search, showToast, token]); useEffect(() => { if (!currentUser) return; if (!currentUser.canManageBots && !currentUser.isSuperAdmin) { router.replace(getAdminLandingPath(currentUser)); } }, [currentUser, router]); useEffect(() => { if (!currentUser?.canManageBots && !currentUser?.isSuperAdmin) return; void loadBots(); }, [currentUser?.canManageBots, currentUser?.isSuperAdmin, loadBots]); async function handleToggleActive(bot: ManagedBot) { if (!token) return; setActionBotId(bot.id); try { await setAdminBotActive(bot.id, !bot.isActive, token); showToast(bot.isActive ? 'Бот заблокирован' : 'Бот разблокирован'); await loadBots(); } catch (error) { showToast(error instanceof Error ? error.message : 'Не удалось изменить статус бота'); } finally { setActionBotId(null); } } const totalPages = Math.max(1, Math.ceil(total / 20)); return (

Telegram-боты

{ setSearch(event.target.value); setPage(1); }} />

Найдено: {total}

Бот Владелец Статус Действия {loading ? ( ) : bots.length ? ( bots.map((bot) => (

{bot.name}

@{bot.username}

{bot.isSystemBot ?

Системный

: null}

{bot.owner?.displayName ?? '—'}

{bot.owner?.username ?

@{bot.owner.username}

: null}
{bot.isActive ? 'Активен' : 'Заблокирован'} {!bot.isSystemBot ? ( ) : ( )}
)) ) : ( Боты не найдены )}
{totalPages > 1 ? (
{page} / {totalPages}
) : null}

Системные учётные записи ботов

Пользователи IdP, связанные с Telegram-ботами (BotFather и боты пользователей). Роль: «Бот».

Учётная запись Telegram-бот Роль Статус {loading ? ( ) : botAccounts.length ? ( botAccounts.map((account) => (

{account.displayName}

{account.username ? `@${account.username}` : account.id.slice(0, 8)}

{account.linkedBotUsername ? `@${account.linkedBotUsername}` : '—'} {account.isSystemBot ?

Системный

: null}
Бот {account.status === 'ACTIVE' ? 'Активен' : account.status}
)) ) : ( Системные учётные записи не найдены )}
); } function MetricCard({ label, value, icon: Icon, accent }: { label: string; value: number; icon: typeof Bot; accent?: string; }) { return (
{label}

{value.toLocaleString('ru-RU')}

); }