"use client"; import { useEffect, useState, useRef } from "react"; import { useRouter } from "next/navigation"; import { motion, AnimatePresence } from "framer-motion"; import { Shield, ShieldAlert, ShieldCheck, Loader2, Terminal, } from "lucide-react"; import { CyberButton } from "@/components/ui/cyber-button"; import { Dictionary } from "@/lib/IDict"; declare global { interface Window { onTelegramAuth: (user: any) => void; } } interface AuthClientProps { dict: Dictionary["auth"]; lang: string; } export function AuthClient({ dict, lang }: AuthClientProps) { const router = useRouter(); const [status, setStatus] = useState< "processing" | "granted" | "denied" | "awaiting" >("processing"); const [logs, setLogs] = useState([]); const tgContainerRef = useRef(null); const initialized = useRef(false); const widgetInjected = useRef(false); useEffect(() => { if (initialized.current) return; initialized.current = true; const authenticate = async () => { setLogs((prev) => [...prev, `> ${dict.processing}`]); // Эмулируем задержку для "хакерского" эффекта консоли await new Promise((resolve) => setTimeout(resolve, 800)); const hash = window.location.hash; let token = localStorage.getItem("nrxp_token"); // Логика получения токена из query parameters или хеша const searchParams = new URLSearchParams(window.location.search); const queryToken = searchParams.get("token"); if (queryToken) { token = queryToken; searchParams.delete("token"); const newSearch = searchParams.toString(); const newUrl = window.location.pathname + (newSearch ? `?${newSearch}` : "") + window.location.hash; window.history.replaceState(null, "", newUrl); } else if (hash.includes("token=")) { const params = new URLSearchParams(hash.replace("#", "?")); const urlToken = params.get("token"); if (urlToken) { token = urlToken; // Безопасно очищаем URL от токена, сохраняя search params window.history.replaceState(null, "", window.location.pathname + window.location.search); } } if (!token) { setLogs((prev) => [ ...prev, "> [WAITING] INITIALIZE TELEGRAM SECURE LOGIN...", ]); setStatus("awaiting"); return; } if (status !== "processing") setStatus("processing"); setLogs((prev) => [...prev, `> ${dict.verifying}`]); try { const API_BASE = process.env.NEXT_PUBLIC_API_URL || "/api"; const res = await fetch(`${API_BASE}/me`, { headers: { Authorization: `Bearer ${token}` }, }); if (res.ok) { localStorage.setItem("nrxp_token", token); setLogs((prev) => [...prev, "> [OK] SIGNATURE VALID"]); setStatus("granted"); setLogs((prev) => [...prev, `> ${dict.redirecting}`]); setTimeout(() => router.push(`/${lang}/profile`), 1500); } else { localStorage.removeItem("nrxp_token"); setLogs((prev) => [...prev, "> [FAIL] API REJECTED TOKEN"]); setStatus("awaiting"); } } catch (err) { setLogs((prev) => [...prev, "> [FAIL] CORE OFFLINE"]); setStatus("denied"); } }; authenticate(); }, [dict, lang, router]); // Этот эффект запустится 1 раз при маунте useEffect(() => { window.onTelegramAuth = async (user: any) => { setStatus("processing"); setLogs((prev) => [ ...prev, "> [AUTH] RECEIVED TELEGRAM PAYLOAD", "> VERIFYING HMAC-SHA256 SIGNATURE...", ]); try { const API_BASE = process.env.NEXT_PUBLIC_API_URL || "/api"; const res = await fetch(`${API_BASE}/auth/telegram`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(user), }); if (res.ok) { const data = await res.json(); localStorage.setItem("nrxp_token", data.token); setLogs((prev) => [ ...prev, "> [OK] SIGNATURE VALID", `> ${dict.redirecting}`, ]); setStatus("granted"); setTimeout(() => router.push(`/${lang}/profile`), 1500); } else { setLogs((prev) => [...prev, "> [FAIL] INVALID SIGNATURE OR EXPIRED"]); setStatus("denied"); } } catch (e) { setLogs((prev) => [...prev, "> [FAIL] NETWORK ERROR"]); setStatus("denied"); } }; }, [dict, lang, router]); useEffect(() => { if ( status === "awaiting" && tgContainerRef.current && !widgetInjected.current ) { widgetInjected.current = true; const script = document.createElement("script"); script.src = "https://telegram.org/js/telegram-widget.js?22"; script.async = true; script.setAttribute( "data-telegram-login", process.env.NEXT_PUBLIC_BOT_USERNAME || "ntrnr_vpn_bot", ); script.setAttribute("data-size", "large"); script.setAttribute("data-onauth", "onTelegramAuth(user)"); script.setAttribute("data-request-access", "write"); tgContainerRef.current.appendChild(script); } }, [status]); return (
{/* Мягкое фоновое свечение */}
{/* Заголовок и анимированные иконки статуса */}
{status === "processing" && (
)} {status === "granted" && (
)} {status === "denied" && (
)} {status === "awaiting" && (
)}

{status === "processing" ? dict.title : status === "granted" ? dict.granted : status === "awaiting" ? dict.awaiting : dict.denied}

{/* Терминал с логами процесса авторизации */}
{logs.map((log, i) => ( {log} ))} {/* Мигающий курсор загрузки */} {status === "processing" && (
_
)}
{/* Сообщение об ошибке и кнопка в бот (если доступ запрещен) */} {status === "denied" && (

{dict.noToken}

{/* При ошибке даем ссылку на телеграм бота для авторизации */} {dict.toBot}
)} {/* Блок логина виджетом Telegram (рендерится только если нет токена) */} {status === "awaiting" && (

{dict.authPrompt}

)}
); }