Fix like/dislike errors and implement native chat system

This commit is contained in:
2025-09-13 07:51:02 +09:00
parent 8893b4ad22
commit 321547bf27
14 changed files with 1236 additions and 39 deletions

View File

@@ -5,6 +5,7 @@ import { ChatService } from '../services/chatService';
import { Profile } from '../models/Profile';
import { MessageHandlers } from './messageHandlers';
import { ProfileEditController } from '../controllers/profileEditController';
import { EnhancedChatHandlers } from './enhancedChatHandlers';
export class CallbackHandlers {
private bot: TelegramBot;
@@ -13,6 +14,7 @@ export class CallbackHandlers {
private chatService: ChatService;
private messageHandlers: MessageHandlers;
private profileEditController: ProfileEditController;
private enhancedChatHandlers: EnhancedChatHandlers;
constructor(bot: TelegramBot, messageHandlers: MessageHandlers) {
this.bot = bot;
@@ -21,6 +23,7 @@ export class CallbackHandlers {
this.chatService = new ChatService();
this.messageHandlers = messageHandlers;
this.profileEditController = new ProfileEditController(this.profileService);
this.enhancedChatHandlers = new EnhancedChatHandlers(bot);
}
register(): void {
@@ -156,6 +159,14 @@ export class CallbackHandlers {
await this.handleViewMatches(chatId, telegramId);
} else if (data === 'open_chats') {
await this.handleOpenChats(chatId, telegramId);
} else if (data === 'native_chats') {
await this.enhancedChatHandlers.showChatsNative(chatId, telegramId);
} else if (data.startsWith('open_native_chat_')) {
const matchId = data.replace('open_native_chat_', '');
await this.enhancedChatHandlers.openNativeChat(chatId, telegramId, matchId);
} else if (data.startsWith('chat_history_')) {
const matchId = data.replace('chat_history_', '');
await this.enhancedChatHandlers.showChatHistory(chatId, telegramId, matchId);
} else if (data.startsWith('chat_')) {
const matchId = data.replace('chat_', '');
await this.handleOpenChat(chatId, telegramId, matchId);
@@ -180,6 +191,18 @@ export class CallbackHandlers {
await this.handleSearchSettings(chatId, telegramId);
} else if (data === 'notification_settings') {
await this.handleNotificationSettings(chatId, telegramId);
} else if (data === 'view_stats') {
await this.handleViewStats(chatId, telegramId);
} else if (data === 'view_profile_viewers') {
await this.handleViewProfileViewers(chatId, telegramId);
} else if (data === 'hide_profile') {
await this.handleHideProfile(chatId, telegramId);
} else if (data === 'delete_profile') {
await this.handleDeleteProfile(chatId, telegramId);
} else if (data === 'main_menu') {
await this.handleMainMenu(chatId, telegramId);
} else if (data === 'confirm_delete_profile') {
await this.handleConfirmDeleteProfile(chatId, telegramId);
}
// Информация
@@ -187,6 +210,8 @@ export class CallbackHandlers {
await this.handleHowItWorks(chatId);
} else if (data === 'back_to_browsing') {
await this.handleStartBrowsing(chatId, telegramId);
} else if (data === 'get_vip') {
await this.handleGetVip(chatId, telegramId);
}
else {
@@ -278,7 +303,13 @@ export class CallbackHandlers {
// Лайк
async handleLike(chatId: number, telegramId: string, targetUserId: string): Promise<void> {
try {
const result = await this.matchingService.performSwipe(telegramId, targetUserId, 'like');
// Получаем telegram_id целевого пользователя
const targetTelegramId = await this.profileService.getTelegramIdByUserId(targetUserId);
if (!targetTelegramId) {
throw new Error('Target user not found');
}
const result = await this.matchingService.performSwipe(telegramId, targetTelegramId, 'like');
if (result.isMatch) {
// Это матч!
@@ -314,7 +345,13 @@ export class CallbackHandlers {
// Дизлайк
async handleDislike(chatId: number, telegramId: string, targetUserId: string): Promise<void> {
try {
await this.matchingService.performSwipe(telegramId, targetUserId, 'pass');
// Получаем telegram_id целевого пользователя
const targetTelegramId = await this.profileService.getTelegramIdByUserId(targetUserId);
if (!targetTelegramId) {
throw new Error('Target user not found');
}
await this.matchingService.performSwipe(telegramId, targetTelegramId, 'pass');
await this.showNextCandidate(chatId, telegramId);
} catch (error) {
await this.bot.sendMessage(chatId, '❌ Ошибка при отправке дизлайка');
@@ -325,7 +362,13 @@ export class CallbackHandlers {
// Супер лайк
async handleSuperlike(chatId: number, telegramId: string, targetUserId: string): Promise<void> {
try {
const result = await this.matchingService.performSwipe(telegramId, targetUserId, 'superlike');
// Получаем telegram_id целевого пользователя
const targetTelegramId = await this.profileService.getTelegramIdByUserId(targetUserId);
if (!targetTelegramId) {
throw new Error('Target user not found');
}
const result = await this.matchingService.performSwipe(telegramId, targetTelegramId, 'superlike');
if (result.isMatch) {
const targetProfile = await this.profileService.getProfileByUserId(targetUserId);
@@ -366,6 +409,12 @@ export class CallbackHandlers {
return;
}
// Записываем просмотр профиля
const targetTelegramId = await this.profileService.getTelegramIdByUserId(targetProfile.userId);
if (targetTelegramId) {
await this.profileService.recordProfileView(telegramId, targetTelegramId, 'profile_view');
}
await this.showProfile(chatId, targetProfile, false, telegramId);
}
@@ -643,7 +692,11 @@ export class CallbackHandlers {
{ text: '🔔 Уведомления', callback_data: 'notification_settings' }
],
[
{ text: '🚫 Скрыть профиль', callback_data: 'hide_profile' },
{ text: '<EFBFBD> Статистика', callback_data: 'view_stats' },
{ text: '👀 Кто смотрел', callback_data: 'view_profile_viewers' }
],
[
{ text: '<27>🚫 Скрыть профиль', callback_data: 'hide_profile' },
{ text: '🗑 Удалить профиль', callback_data: 'delete_profile' }
]
]
@@ -812,6 +865,12 @@ export class CallbackHandlers {
return;
}
// Записываем просмотр кандидата
const candidateTelegramId = await this.profileService.getTelegramIdByUserId(candidate.userId);
if (candidateTelegramId) {
await this.profileService.recordProfileView(telegramId, candidateTelegramId, 'browse');
}
const candidatePhotoFileId = candidate.photos[0]; // Первое фото - главное
let candidateText = candidate.name + ', ' + candidate.age + '\n';
@@ -1577,4 +1636,254 @@ export class CallbackHandlers {
return parts.join(', ');
}
// Просмотр статистики профиля
async handleViewStats(chatId: number, telegramId: string): Promise<void> {
try {
const profile = await this.profileService.getProfileByTelegramId(telegramId);
if (!profile) {
await this.bot.sendMessage(chatId, '❌ Профиль не найден');
return;
}
const stats = await this.profileService.getProfileStats(profile.userId);
const statsText = `📊 Статистика вашего профиля\n\n` +
`💖 Ваши лайки: ${stats.totalLikes}\n` +
`💕 Матчи: ${stats.totalMatches}\n` +
`👀 Просмотры профиля: ${stats.profileViews}\n` +
`❤️ Лайки получено: ${stats.likesReceived}\n\n` +
`💡 Совет: Заполните все поля профиля и добавьте качественные фото для большего успеха!`;
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[{ text: '👀 Кто смотрел профиль', callback_data: 'view_profile_viewers' }],
[{ text: '🔙 Назад', callback_data: 'settings' }]
]
};
await this.bot.sendMessage(chatId, statsText, { reply_markup: keyboard });
} catch (error) {
console.error('Error viewing stats:', error);
await this.bot.sendMessage(chatId, '❌ Произошла ошибка при получении статистики');
}
}
// Просмотр кто смотрел профиль
async handleViewProfileViewers(chatId: number, telegramId: string): Promise<void> {
try {
const profile = await this.profileService.getProfileByTelegramId(telegramId);
if (!profile) {
await this.bot.sendMessage(chatId, '❌ Профиль не найден');
return;
}
const viewers = await this.profileService.getProfileViewers(profile.userId, 10);
if (viewers.length === 0) {
await this.bot.sendMessage(
chatId,
'👁️ Пока никто не просматривал ваш профиль\n\n' +
'Начните искать анкеты, чтобы другие пользователи тоже могли вас найти!',
{
reply_markup: {
inline_keyboard: [
[{ text: '🔍 Начать поиск', callback_data: 'start_browsing' }],
[{ text: '🔙 Назад', callback_data: 'settings' }]
]
}
}
);
return;
}
let viewersText = '👀 Последние просмотры вашего профиля:\n\n';
viewers.forEach((viewer, index) => {
viewersText += `${index + 1}. ${viewer.name}, ${viewer.age}\n`;
if (viewer.city) viewersText += ` 📍 ${viewer.city}\n`;
viewersText += '\n';
});
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[{ text: '📊 Статистика', callback_data: 'view_stats' }],
[{ text: '🔙 Назад', callback_data: 'settings' }]
]
};
await this.bot.sendMessage(chatId, viewersText, { reply_markup: keyboard });
} catch (error) {
console.error('Error viewing profile viewers:', error);
await this.bot.sendMessage(chatId, '❌ Произошла ошибка при получении информации о просмотрах');
}
}
// Возврат в главное меню
async handleMainMenu(chatId: number, telegramId: string): Promise<void> {
// Используем существующий метод handleStart из CommandHandlers
const profile = await this.profileService.getProfileByTelegramId(telegramId);
if (profile) {
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[
{ text: '👤 Мой профиль', callback_data: 'view_my_profile' },
{ text: '🔍 Просмотр анкет', callback_data: 'start_browsing' }
],
[
{ text: '💕 Мои матчи', callback_data: 'view_matches' },
{ text: '⭐ VIP поиск', callback_data: 'vip_search' }
],
[
{ text: '⚙️ Настройки', callback_data: 'settings' }
]
]
};
await this.bot.sendMessage(
chatId,
`🎉 Добро пожаловать, ${profile.name}!\n\n` +
`💖 Telegram Tinder Bot готов к работе!\n\n` +
`Что хотите сделать?`,
{ reply_markup: keyboard }
);
} else {
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[{ text: '✨ Создать профиль', callback_data: 'create_profile' }],
[{ text: ' Как это работает?', callback_data: 'how_it_works' }]
]
};
await this.bot.sendMessage(
chatId,
`🎉 Добро пожаловать в Telegram Tinder Bot!\n\n` +
`💕 Здесь вы можете найти свою вторую половинку!\n\n` +
`Для начала создайте свой профиль:`,
{ reply_markup: keyboard }
);
}
}
// Скрыть/показать профиль
async handleHideProfile(chatId: number, telegramId: string): Promise<void> {
try {
const profile = await this.profileService.getProfileByTelegramId(telegramId);
if (!profile) {
await this.bot.sendMessage(chatId, '❌ Профиль не найден');
return;
}
const newVisibility = !profile.isVisible;
await this.profileService.toggleVisibility(profile.userId);
const statusText = newVisibility ? 'видимым' : 'скрытым';
const emoji = newVisibility ? '👁️' : '🙈';
await this.bot.sendMessage(
chatId,
`${emoji} Ваш профиль теперь ${statusText}!\n\n` +
(newVisibility
? '✅ Другие пользователи смогут найти вас в поиске'
: '🔒 Ваш профиль скрыт и не отображается в поиске'),
{
reply_markup: {
inline_keyboard: [
[{ text: '🔙 Назад к настройкам', callback_data: 'settings' }]
]
}
}
);
} catch (error) {
console.error('Error toggling profile visibility:', error);
await this.bot.sendMessage(chatId, '❌ Произошла ошибка при изменении видимости профиля');
}
}
// Удаление профиля
async handleDeleteProfile(chatId: number, telegramId: string): Promise<void> {
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[
{ text: '✅ Да, удалить', callback_data: 'confirm_delete_profile' },
{ text: '❌ Отмена', callback_data: 'settings' }
]
]
};
await this.bot.sendMessage(
chatId,
'⚠️ ВНИМАНИЕ!\n\n' +
'🗑️ Вы действительно хотите удалить свой профиль?\n\n' +
'❗ Это действие нельзя отменить:\n' +
'• Все ваши фото будут удалены\n' +
'• Все матчи и переписки исчезнут\n' +
'• Придется создавать профиль заново\n\n' +
'🤔 Подумайте еще раз!',
{ reply_markup: keyboard }
);
}
// Подтверждение удаления профиля
async handleConfirmDeleteProfile(chatId: number, telegramId: string): Promise<void> {
try {
const profile = await this.profileService.getProfileByTelegramId(telegramId);
if (!profile) {
await this.bot.sendMessage(chatId, '❌ Профиль не найден');
return;
}
// Удаляем профиль (это также удалит связанные данные через CASCADE)
await this.profileService.deleteProfile(profile.userId);
await this.bot.sendMessage(
chatId,
'💔 Ваш профиль успешно удален\n\n' +
'😢 Мы будем скучать! Но вы всегда можете вернуться и создать новый профиль.\n\n' +
'👋 До свидания!',
{
reply_markup: {
inline_keyboard: [
[{ text: '✨ Создать новый профиль', callback_data: 'create_profile' }]
]
}
}
);
} catch (error) {
console.error('Error deleting profile:', error);
await this.bot.sendMessage(chatId, '❌ Произошла ошибка при удалении профиля');
}
}
// Получение VIP статуса
async handleGetVip(chatId: number, telegramId: string): Promise<void> {
await this.bot.sendMessage(
chatId,
'💎 *VIP Статус*\n\n' +
'✨ VIP дает вам дополнительные возможности:\n\n' +
'🔍 *Расширенный поиск* - найти людей по интересам\n' +
'📊 *Подробная статистика* - кто смотрел ваш профиль\n' +
'💕 *Больше лайков* - отправляйте до 100 лайков в день\n' +
'⭐ *Приоритет в поиске* - ваш профиль показывается первым\n' +
'🎯 *Суперлайки* - выделите себя среди других\n\n' +
'💰 *Стоимость:*\n' +
'• 1 месяц - 299₽\n' +
'• 3 месяца - 699₽ (экономия 200₽)\n' +
'• 6 месяцев - 1199₽ (экономия 600₽)\n\n' +
'📞 Для получения VIP свяжитесь с администратором: @admin',
{
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[
{ text: '📞 Связаться с админом', url: 'https://t.me/admin' }
],
[
{ text: '🔙 Назад', callback_data: 'vip_search' }
]
]
}
}
);
}
}