Files
tg_tinder_bot/src/controllers/vipController.ts

292 lines
12 KiB
TypeScript
Raw 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.

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] || 'Не указано';
}
}