feat: VIP search now shows only opposite gender - Modified VIP search filtering to always show opposite gender regardless of user's interested_in preference - Male users see only female profiles - Female users see only male profiles - Improved gender filtering logic in vipService.ts

This commit is contained in:
2025-09-13 08:45:41 +09:00
parent 321547bf27
commit 975eb348dd
5 changed files with 807 additions and 14 deletions

View File

@@ -0,0 +1,291 @@
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] || 'Не указано';
}
}