Files
tg_tinder_bot/src/services/vipService.ts
2025-09-18 13:46:35 +09:00

254 lines
9.5 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 { query } from '../database/connection';
import { BotError } from '../types/index';
export interface VipSearchFilters {
ageMin?: number;
ageMax?: number;
city?: string;
datingGoal?: string;
hobbies?: string[];
lifestyle?: string[];
distance?: number;
hasPhotos?: boolean;
isOnline?: boolean;
}
export interface PremiumInfo {
isPremium: boolean;
expiresAt?: Date;
daysLeft?: number;
}
export class VipService {
// Проверить премиум статус пользователя
async checkPremiumStatus(telegramId: string): Promise<PremiumInfo> {
try {
// Проверяем существование пользователя и получаем его премиум статус
const result = await query(`
SELECT id, premium
FROM users
WHERE telegram_id = $1
`, [telegramId]);
if (result.rows.length === 0) {
throw new BotError('User not found', 'USER_NOT_FOUND', 404);
}
// Получаем актуальное значение премиум статуса из базы данных
const isPremium = result.rows[0].premium || false;
return {
isPremium: isPremium,
expiresAt: undefined, // Пока не используем дату истечения
daysLeft: undefined // Пока не используем количество дней
};
} catch (error) {
console.error('Error checking premium status:', error);
throw error;
}
}
// Добавить премиум статус
async addPremium(telegramId: string, durationDays: number = 30): Promise<void> {
try {
console.log(`[VIP] Добавление премиум для ${telegramId} на ${durationDays} дней`);
// Обновляем статус premium в базе данных
await query(`
UPDATE users
SET premium = true
WHERE telegram_id = $1
RETURNING id, telegram_id, premium
`, [telegramId]);
console.log(`[VIP] Премиум успешно добавлен для пользователя ${telegramId}`);
} catch (error) {
console.error('Error adding premium:', error);
throw error;
}
}
// Удалить премиум статус
async removePremium(telegramId: string): Promise<void> {
try {
console.log(`[VIP] Удаление премиум для ${telegramId}`);
// Обновляем статус premium в базе данных
await query(`
UPDATE users
SET premium = false
WHERE telegram_id = $1
RETURNING id, telegram_id, premium
`, [telegramId]);
console.log(`[VIP] Премиум успешно удален для пользователя ${telegramId}`);
} catch (error) {
console.error('Error removing premium:', error);
throw error;
}
}
// VIP поиск с фильтрами
async vipSearch(telegramId: string, filters: VipSearchFilters): Promise<any[]> {
try {
// Проверяем премиум статус
const premiumInfo = await this.checkPremiumStatus(telegramId);
if (!premiumInfo.isPremium) {
throw new BotError('Premium subscription required', 'PREMIUM_REQUIRED', 403);
}
// Получаем профиль пользователя
const userProfile = await query(`
SELECT p.*, u.telegram_id
FROM profiles p
JOIN users u ON p.user_id = u.id
WHERE u.telegram_id = $1
`, [telegramId]);
if (userProfile.rows.length === 0) {
throw new BotError('Profile not found', 'PROFILE_NOT_FOUND', 404);
}
const currentUser = userProfile.rows[0];
// Строим запрос с фильтрами
let query_text = `
SELECT p.*, u.telegram_id,
CASE WHEN u.updated_at > NOW() - INTERVAL '15 minutes' THEN true ELSE false END as is_online
FROM profiles p
JOIN users u ON p.user_id = u.id
LEFT JOIN swipes s ON (
s.swiper_id = $1 AND s.swiped_id = u.id
)
WHERE u.telegram_id != $2
AND s.id IS NULL
AND p.is_active = true
`;
let params = [currentUser.user_id, telegramId];
let paramIndex = 3;
// Фильтр по противоположному полу
if (currentUser.gender === 'male') {
query_text += ` AND p.gender = 'female'`;
} else if (currentUser.gender === 'female') {
query_text += ` AND p.gender = 'male'`;
} else {
// Если пол не определен или 'other', показываем всех кроме того же пола
query_text += ` AND p.gender != $${paramIndex}`;
params.push(currentUser.gender);
paramIndex++;
}
// Фильтр по возрасту
if (filters.ageMin) {
query_text += ` AND p.age >= $${paramIndex}`;
params.push(filters.ageMin);
paramIndex++;
}
if (filters.ageMax) {
query_text += ` AND p.age <= $${paramIndex}`;
params.push(filters.ageMax);
paramIndex++;
}
// Фильтр по городу
if (filters.city) {
query_text += ` AND LOWER(p.city) LIKE LOWER($${paramIndex})`;
params.push(`%${filters.city}%`);
paramIndex++;
}
// Фильтр по цели знакомства
if (filters.datingGoal) {
query_text += ` AND p.dating_goal = $${paramIndex}`;
params.push(filters.datingGoal);
paramIndex++;
}
// Фильтр по хобби
if (filters.hobbies && filters.hobbies.length > 0) {
const hobbyConditions = filters.hobbies.map((_, index) => {
return `LOWER(p.hobbies) LIKE LOWER($${paramIndex + index})`;
});
query_text += ` AND (${hobbyConditions.join(' OR ')})`;
filters.hobbies.forEach(hobby => {
params.push(`%${hobby}%`);
});
paramIndex += filters.hobbies.length;
}
// Фильтр по образу жизни
if (filters.lifestyle && filters.lifestyle.length > 0) {
const lifestyleConditions = filters.lifestyle.map((field) => {
const condition = `p.lifestyle ? $${paramIndex}`;
params.push(field);
paramIndex++;
return condition;
});
query_text += ` AND (${lifestyleConditions.join(' OR ')})`;
}
// Фильтр по наличию фото
if (filters.hasPhotos) {
query_text += ` AND p.photos IS NOT NULL AND array_length(p.photos, 1) > 0`;
}
// Фильтр по онлайн статусу
if (filters.isOnline) {
query_text += ` AND u.updated_at > NOW() - INTERVAL '15 minutes'`;
}
query_text += ` ORDER BY
CASE WHEN u.updated_at > NOW() - INTERVAL '15 minutes' THEN 0 ELSE 1 END,
u.updated_at DESC,
p.created_at DESC
LIMIT 50`;
const result = await query(query_text, params);
return result.rows;
} catch (error) {
console.error('Error in VIP search:', error);
throw error;
}
}
// Получить информацию о премиум возможностях
getPremiumFeatures(): string {
return `💎 ПРЕМИУМ ПОДПИСКА 💎
🔥 Что дает VIP статус:
🎯 VIP Поиск с фильтрами:
• Поиск по возрасту
• Поиск по городу
• Фильтр по целям знакомства
• Поиск по хобби и интересам
• Фильтр по образу жизни
• Только пользователи с фото
• Только онлайн пользователи
⚡ Дополнительные возможности:
• Неограниченные супер-лайки
• Просмотр кто лайкнул вас
• Возможность отменить свайп
• Приоритет в показе другим
• Расширенная статистика
• Скрытый режим просмотра
💰 Тарифы:
• 1 месяц - 299₽
• 3 месяца - 699₽ (экономия 25%)
• 6 месяцев - 1199₽ (экономия 33%)
• 1 год - 1999₽ (экономия 44%)
📞 Для покупки обратитесь к администратору:
@admin_bot
✨ Попробуйте VIP уже сегодня!`;
}
}