292 lines
12 KiB
TypeScript
292 lines
12 KiB
TypeScript
import TelegramBot, { InlineKeyboardMarkup } from 'node-telegram-bot-api';
|
||
import { VipService, VipSearchFilters } from '../services/vipService';
|
||
import { ProfileService } from '../services/profileService';
|
||
|
||
interface VipSearchState {
|
||
filters: VipSearchFilters;
|
||
currentStep: string;
|
||
}
|
||
|
||
export class VipController {
|
||
private bot: TelegramBot;
|
||
private vipService: VipService;
|
||
private profileService: ProfileService;
|
||
private vipSearchStates: Map<string, VipSearchState> = new Map();
|
||
|
||
constructor(bot: TelegramBot) {
|
||
this.bot = bot;
|
||
this.vipService = new VipService();
|
||
this.profileService = new ProfileService();
|
||
}
|
||
|
||
// Показать VIP поиск или информацию о премиум
|
||
async showVipSearch(chatId: number, telegramId: string): Promise<void> {
|
||
try {
|
||
const premiumInfo = await this.vipService.checkPremiumStatus(telegramId);
|
||
|
||
if (!premiumInfo.isPremium) {
|
||
// Показываем информацию о премиум
|
||
await this.showPremiumInfo(chatId);
|
||
} else {
|
||
// Показываем VIP поиск
|
||
await this.showVipSearchMenu(chatId, telegramId, premiumInfo);
|
||
}
|
||
} catch (error) {
|
||
console.error('Error showing VIP search:', error);
|
||
await this.bot.sendMessage(chatId, '❌ Ошибка при загрузке VIP поиска');
|
||
}
|
||
}
|
||
|
||
// Показать информацию о премиум подписке
|
||
private async showPremiumInfo(chatId: number): Promise<void> {
|
||
const premiumText = this.vipService.getPremiumFeatures();
|
||
|
||
const keyboard: InlineKeyboardMarkup = {
|
||
inline_keyboard: [
|
||
[{ text: '💎 Купить VIP', url: 'https://t.me/admin_bot' }],
|
||
[{ text: '🔙 Назад в меню', callback_data: 'main_menu' }]
|
||
]
|
||
};
|
||
|
||
await this.bot.sendMessage(chatId, premiumText, {
|
||
reply_markup: keyboard
|
||
});
|
||
}
|
||
|
||
// Показать меню VIP поиска
|
||
private async showVipSearchMenu(chatId: number, telegramId: string, premiumInfo: any): Promise<void> {
|
||
const daysText = premiumInfo.daysLeft ? ` (остался ${premiumInfo.daysLeft} дн.)` : '';
|
||
|
||
const text = `💎 VIP ПОИСК 💎\n\n` +
|
||
`✅ Премиум статус активен${daysText}\n\n` +
|
||
`🎯 Выберите тип поиска:`;
|
||
|
||
const keyboard: InlineKeyboardMarkup = {
|
||
inline_keyboard: [
|
||
[{ text: '🔍 Быстрый VIP поиск', callback_data: 'vip_quick_search' }],
|
||
[{ text: '⚙️ Расширенный поиск с фильтрами', callback_data: 'vip_advanced_search' }],
|
||
[{ text: '🎯 Поиск по целям знакомства', callback_data: 'vip_dating_goal_search' }],
|
||
[{ text: '🎨 Поиск по хобби', callback_data: 'vip_hobbies_search' }],
|
||
[{ text: '🔙 Назад в меню', callback_data: 'main_menu' }]
|
||
]
|
||
};
|
||
|
||
await this.bot.sendMessage(chatId, text, {
|
||
reply_markup: keyboard
|
||
});
|
||
}
|
||
|
||
// Быстрый VIP поиск
|
||
async performQuickVipSearch(chatId: number, telegramId: string): Promise<void> {
|
||
try {
|
||
const filters: VipSearchFilters = {
|
||
hasPhotos: true,
|
||
isOnline: true
|
||
};
|
||
|
||
const results = await this.vipService.vipSearch(telegramId, filters);
|
||
await this.showSearchResults(chatId, telegramId, results, 'Быстрый VIP поиск');
|
||
} catch (error) {
|
||
console.error('Error in quick VIP search:', error);
|
||
await this.bot.sendMessage(chatId, '❌ Ошибка при выполнении поиска');
|
||
}
|
||
}
|
||
|
||
// Начать настройку фильтров для расширенного поиска
|
||
async startAdvancedSearch(chatId: number, telegramId: string): Promise<void> {
|
||
const state: VipSearchState = {
|
||
filters: {},
|
||
currentStep: 'age_min'
|
||
};
|
||
|
||
this.vipSearchStates.set(telegramId, state);
|
||
|
||
await this.bot.sendMessage(
|
||
chatId,
|
||
'⚙️ Расширенный VIP поиск\n\n' +
|
||
'🔢 Укажите минимальный возраст (18-65) или отправьте "-" чтобы пропустить:',
|
||
{ }
|
||
);
|
||
}
|
||
|
||
// Поиск по целям знакомства
|
||
async showDatingGoalSearch(chatId: number, telegramId: string): Promise<void> {
|
||
const keyboard: InlineKeyboardMarkup = {
|
||
inline_keyboard: [
|
||
[{ text: '💕 Серьёзные отношения', callback_data: 'vip_goal_serious' }],
|
||
[{ text: '🎉 Лёгкие отношения', callback_data: 'vip_goal_casual' }],
|
||
[{ text: '👥 Дружба', callback_data: 'vip_goal_friends' }],
|
||
[{ text: '🔥 Одна ночь', callback_data: 'vip_goal_one_night' }],
|
||
[{ text: '😏 FWB', callback_data: 'vip_goal_fwb' }],
|
||
[{ text: '💎 Спонсорство', callback_data: 'vip_goal_sugar' }],
|
||
[{ text: '💍 Брак с переездом', callback_data: 'vip_goal_marriage_abroad' }],
|
||
[{ text: '💫 Полиамория', callback_data: 'vip_goal_polyamory' }],
|
||
[{ text: '🤷♀️ Пока не определился', callback_data: 'vip_goal_unsure' }],
|
||
[{ text: '🔙 Назад', callback_data: 'vip_search' }]
|
||
]
|
||
};
|
||
|
||
await this.bot.sendMessage(
|
||
chatId,
|
||
'🎯 Поиск по целям знакомства\n\nВыберите цель:',
|
||
{
|
||
reply_markup: keyboard
|
||
}
|
||
);
|
||
}
|
||
|
||
// Выполнить поиск по цели знакомства
|
||
async performDatingGoalSearch(chatId: number, telegramId: string, goal: string): Promise<void> {
|
||
try {
|
||
// Используем значения из базы данных как есть
|
||
const filters: VipSearchFilters = {
|
||
datingGoal: goal,
|
||
hasPhotos: true
|
||
};
|
||
|
||
const results = await this.vipService.vipSearch(telegramId, filters);
|
||
|
||
const goalNames: { [key: string]: string } = {
|
||
'serious': 'Серьёзные отношения',
|
||
'casual': 'Лёгкие отношения',
|
||
'friends': 'Дружба',
|
||
'one_night': 'Одна ночь',
|
||
'fwb': 'FWB',
|
||
'sugar': 'Спонсорство',
|
||
'marriage_abroad': 'Брак с переездом',
|
||
'polyamory': 'Полиамория',
|
||
'unsure': 'Пока не определился'
|
||
};
|
||
|
||
const goalName = goalNames[goal] || goal;
|
||
await this.showSearchResults(chatId, telegramId, results, `Поиск: ${goalName}`);
|
||
} catch (error) {
|
||
console.error('Error in dating goal search:', error);
|
||
await this.bot.sendMessage(chatId, '❌ Ошибка при выполнении поиска');
|
||
}
|
||
}
|
||
|
||
// Показать результаты поиска
|
||
private async showSearchResults(chatId: number, telegramId: string, results: any[], searchType: string): Promise<void> {
|
||
if (results.length === 0) {
|
||
const keyboard: InlineKeyboardMarkup = {
|
||
inline_keyboard: [
|
||
[{ text: '🔍 Новый поиск', callback_data: 'vip_search' }],
|
||
[{ text: '🔙 Главное меню', callback_data: 'main_menu' }]
|
||
]
|
||
};
|
||
|
||
await this.bot.sendMessage(
|
||
chatId,
|
||
`😔 ${searchType}\n\n` +
|
||
'К сожалению, никого не найдено по вашим критериям.\n\n' +
|
||
'💡 Попробуйте изменить фильтры или выполнить обычный поиск.',
|
||
{
|
||
reply_markup: keyboard,
|
||
|
||
}
|
||
);
|
||
return;
|
||
}
|
||
|
||
await this.bot.sendMessage(
|
||
chatId,
|
||
`🎉 ${searchType}\n\n` +
|
||
`Найдено: ${results.length} ${this.getCountText(results.length)}\n\n` +
|
||
'Начинаем просмотр профилей...',
|
||
{ }
|
||
);
|
||
|
||
// Показываем первый профиль из результатов
|
||
const firstProfile = results[0];
|
||
await this.showVipSearchProfile(chatId, telegramId, firstProfile, results, 0);
|
||
}
|
||
|
||
// Показать профиль из VIP поиска
|
||
private async showVipSearchProfile(chatId: number, telegramId: string, profile: any, allResults: any[], currentIndex: number): Promise<void> {
|
||
try {
|
||
let profileText = `💎 VIP Поиск (${currentIndex + 1}/${allResults.length})\n\n`;
|
||
profileText += `👤 ${profile.name}, ${profile.age}\n`;
|
||
profileText += `📍 ${profile.city || 'Не указан'}\n`;
|
||
|
||
if (profile.dating_goal) {
|
||
const goalText = this.getDatingGoalText(profile.dating_goal);
|
||
profileText += `🎯 ${goalText}\n`;
|
||
}
|
||
|
||
if (profile.bio) {
|
||
profileText += `\n📝 ${profile.bio}\n`;
|
||
}
|
||
|
||
if (profile.is_online) {
|
||
profileText += `\n🟢 Онлайн\n`;
|
||
}
|
||
|
||
const keyboard: InlineKeyboardMarkup = {
|
||
inline_keyboard: [
|
||
[
|
||
{ text: '❤️', callback_data: `vip_like_${profile.telegram_id}` },
|
||
{ text: '⭐', callback_data: `vip_superlike_${profile.telegram_id}` },
|
||
{ text: '👎', callback_data: `vip_dislike_${profile.telegram_id}` }
|
||
],
|
||
[{ text: '👤 Полный профиль', callback_data: `view_profile_${profile.user_id}` }],
|
||
[
|
||
{ text: '⬅️ Предыдущий', callback_data: `vip_prev_${currentIndex}` },
|
||
{ text: '➡️ Следующий', callback_data: `vip_next_${currentIndex}` }
|
||
],
|
||
[{ text: '🔍 Новый поиск', callback_data: 'vip_search' }],
|
||
[{ text: '🔙 Главное меню', callback_data: 'main_menu' }]
|
||
]
|
||
};
|
||
|
||
// Проверяем есть ли фотографии
|
||
if (profile.photos && Array.isArray(profile.photos) && profile.photos.length > 0) {
|
||
await this.bot.sendPhoto(chatId, profile.photos[0], {
|
||
caption: profileText,
|
||
reply_markup: keyboard,
|
||
|
||
});
|
||
} else {
|
||
await this.bot.sendMessage(chatId, profileText, {
|
||
reply_markup: keyboard,
|
||
|
||
});
|
||
}
|
||
|
||
// Сохраняем результаты поиска для навигации
|
||
// Можно сохранить в Redis или временной переменной
|
||
|
||
} catch (error) {
|
||
console.error('Error showing VIP search profile:', error);
|
||
await this.bot.sendMessage(chatId, '❌ Ошибка при показе профиля');
|
||
}
|
||
}
|
||
|
||
private getCountText(count: number): string {
|
||
const lastDigit = count % 10;
|
||
const lastTwoDigits = count % 100;
|
||
|
||
if (lastTwoDigits >= 11 && lastTwoDigits <= 14) {
|
||
return 'пользователей';
|
||
}
|
||
|
||
switch (lastDigit) {
|
||
case 1: return 'пользователь';
|
||
case 2:
|
||
case 3:
|
||
case 4: return 'пользователя';
|
||
default: return 'пользователей';
|
||
}
|
||
}
|
||
|
||
private getDatingGoalText(goal: string): string {
|
||
const goals: { [key: string]: string } = {
|
||
'serious_relationship': 'Серьезные отношения',
|
||
'friendship': 'Общение и дружба',
|
||
'fun': 'Развлечения',
|
||
'networking': 'Деловые знакомства'
|
||
};
|
||
return goals[goal] || 'Не указано';
|
||
}
|
||
}
|