Files
Umbrix Dev 33b20b979f 🔒 Аудит: безопасность, TypeScript, UI, BottomNav
Безопасность:
- proxy: белый список путей (только /sub/*), POST заблокирован
- console.log заменён на logger (утечки URL/данных)
- OnboardingFlow: убраны --tg-theme-* (не существуют в проекте)

TypeScript (0 ошибок):
- tsconfig target es5→es2017 (regex /u flag fix)
- layout.tsx: viewport перенесён в metadata (Next.js 13.5)
- telegram-webhook: fix text possibly undefined
- hooks/useTelegramWebApp: fix Object possibly undefined
- types/telegram: убрана дублирующая Window декларация

UI:
- BottomNav: новый компонент (Назад/Главная/Помощь)
- safe-area-bottom CSS класс добавлен в globals.css
- dashboard: spacer h-20, toast поднят над BottomNav
- OnboardingFlow: цены 149/249/350₽ (были 200/350/500₽)

Очистка:
- page_NEW.tsx удалён локально (не был в git)
2026-02-08 18:59:02 +03:00

190 lines
5.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Telegram Bot Webhook Handler
// POST /api/telegram-webhook
// Принимает вебхуки от Telegram и обрабатывает команды
import { NextRequest, NextResponse } from 'next/server';
import { logger } from '@/lib/logger';
const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN || '';
const WEBAPP_URL = process.env.NEXT_PUBLIC_APP_URL || 'https://app.umbrix.net';
interface TelegramUpdate {
message?: {
message_id: number;
from: {
id: number;
first_name: string;
last_name?: string;
username?: string;
};
chat: {
id: number;
};
text?: string;
};
}
interface InlineKeyboardButton {
text: string;
web_app?: { url: string };
url?: string;
}
async function sendMessage(
chatId: number,
text: string,
replyMarkup?: { inline_keyboard: InlineKeyboardButton[][] }
) {
const url = `https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`;
const body = {
chat_id: chatId,
text: text,
parse_mode: 'HTML',
reply_markup: replyMarkup,
};
try {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!response.ok) {
logger.error('Telegram API error:', await response.text());
}
} catch (error) {
logger.error('Failed to send Telegram message:', error);
}
}
export async function POST(request: NextRequest) {
try {
const update: TelegramUpdate = await request.json();
logger.debug('📨 Telegram webhook received:', update);
if (!update.message || !update.message.text) {
return NextResponse.json({ ok: true });
}
const { message } = update;
const { chat, from } = message;
const text = message.text!;
// Обработка команды /start
if (text.startsWith('/start')) {
const parts = text.split(' ');
const startParam = parts[1]; // Например: "ref_john_doe"
let webAppUrl = WEBAPP_URL;
let welcomeText = `👋 Привет, ${from.first_name}!\n\n`;
// Если есть реферальный параметр
if (startParam && startParam.startsWith('ref_')) {
const referrerId = startParam.replace('ref_', '');
webAppUrl = `${WEBAPP_URL}?ref=${encodeURIComponent(referrerId)}`;
welcomeText += `🎁 Вы перешли по реферальной ссылке от <b>${referrerId}</b>!\n\n`;
welcomeText += `При регистрации вы получите:\n`;
welcomeText += `✅ <b>7 дней бесплатно</b>\n`;
welcomeText += `А ваш друг получит <b>+7 дней</b> к подписке!\n\n`;
logger.info(`🎁 Referral link opened: ${from.id} -> ${referrerId}`);
} else {
welcomeText += `🚀 <b>Umbrix VPN</b> - быстрый и безопасный VPN!\n\n`;
welcomeText += `✅ Надежная защита данных\n`;
welcomeText += `✅ Высокая скорость соединения\n`;
welcomeText += `✅ Простая настройка\n\n`;
}
welcomeText += `Нажмите кнопку ниже, чтобы начать:`;
const keyboard = {
inline_keyboard: [
[
{
text: '🚀 Открыть Umbrix',
web_app: { url: webAppUrl },
},
],
],
};
await sendMessage(chat.id, welcomeText, keyboard);
return NextResponse.json({ ok: true });
}
// Обработка других команд
if (text === '/help') {
const helpText = `
<b>Доступные команды:</b>
/start - Открыть приложение
/help - Показать эту справку
/referral - Получить свою реферальную ссылку
<b>Как получить реферальную ссылку?</b>
1. Откройте приложение
2. Перейдите в раздел "Реферальная программа"
3. Скопируйте ссылку и отправьте друзьям!
<b>Условия реферальной программы:</b>
За каждого друга: <b>+7 дней</b> бесплатно
За 5 друзей: <b>1 месяц в подарок</b>
• При оплате: <b>10% скидка</b>
`;
await sendMessage(chat.id, helpText.trim());
return NextResponse.json({ ok: true });
}
if (text === '/referral') {
const referralText = `
🎁 <b>Ваша реферальная ссылка:</b>
Чтобы получить ссылку, откройте приложение и перейдите в раздел "Пригласить друга".
Там вы найдете свою уникальную ссылку и сможете поделиться ей!
`;
const keyboard = {
inline_keyboard: [
[
{
text: '🚀 Открыть приложение',
web_app: { url: WEBAPP_URL },
},
],
],
};
await sendMessage(chat.id, referralText.trim(), keyboard);
return NextResponse.json({ ok: true });
}
// Неизвестная команда
await sendMessage(
chat.id,
'Неизвестная команда. Используйте /help для списка команд.'
);
return NextResponse.json({ ok: true });
} catch (error) {
logger.error('❌ Telegram webhook error:', error);
return NextResponse.json(
{ ok: false, error: 'Internal server error' },
{ status: 500 }
);
}
}
// Для проверки что webhook работает
export async function GET() {
return NextResponse.json({
status: 'ok',
message: 'Telegram webhook endpoint is running'
});
}