init commit
This commit is contained in:
802
src/handlers/callbackHandlers.ts
Normal file
802
src/handlers/callbackHandlers.ts
Normal file
@@ -0,0 +1,802 @@
|
||||
import TelegramBot, { CallbackQuery, InlineKeyboardMarkup } from 'node-telegram-bot-api';
|
||||
import { ProfileService } from '../services/profileService';
|
||||
import { MatchingService } from '../services/matchingService';
|
||||
import { ChatService } from '../services/chatService';
|
||||
import { Profile } from '../models/Profile';
|
||||
import { MessageHandlers } from './messageHandlers';
|
||||
|
||||
export class CallbackHandlers {
|
||||
private bot: TelegramBot;
|
||||
private profileService: ProfileService;
|
||||
private matchingService: MatchingService;
|
||||
private chatService: ChatService;
|
||||
private messageHandlers: MessageHandlers;
|
||||
|
||||
constructor(bot: TelegramBot, messageHandlers: MessageHandlers) {
|
||||
this.bot = bot;
|
||||
this.profileService = new ProfileService();
|
||||
this.matchingService = new MatchingService();
|
||||
this.chatService = new ChatService();
|
||||
this.messageHandlers = messageHandlers;
|
||||
}
|
||||
|
||||
register(): void {
|
||||
this.bot.on('callback_query', (query) => this.handleCallback(query));
|
||||
}
|
||||
|
||||
async handleCallback(query: CallbackQuery): Promise<void> {
|
||||
if (!query.data || !query.from || !query.message) return;
|
||||
|
||||
const telegramId = query.from.id.toString();
|
||||
const chatId = query.message.chat.id;
|
||||
const data = query.data;
|
||||
|
||||
try {
|
||||
// Основные действия профиля
|
||||
if (data === 'create_profile') {
|
||||
await this.handleCreateProfile(chatId, telegramId);
|
||||
} else if (data.startsWith('gender_')) {
|
||||
const gender = data.replace('gender_', '');
|
||||
await this.handleGenderSelection(chatId, telegramId, gender);
|
||||
} else if (data === 'view_my_profile') {
|
||||
await this.handleViewMyProfile(chatId, telegramId);
|
||||
} else if (data === 'edit_profile') {
|
||||
await this.handleEditProfile(chatId, telegramId);
|
||||
} else if (data === 'manage_photos') {
|
||||
await this.handleManagePhotos(chatId, telegramId);
|
||||
}
|
||||
|
||||
// Просмотр анкет и свайпы
|
||||
else if (data === 'start_browsing') {
|
||||
await this.handleStartBrowsing(chatId, telegramId);
|
||||
} else if (data === 'next_candidate') {
|
||||
await this.handleNextCandidate(chatId, telegramId);
|
||||
} else if (data.startsWith('like_')) {
|
||||
const targetUserId = data.replace('like_', '');
|
||||
await this.handleLike(chatId, telegramId, targetUserId);
|
||||
} else if (data.startsWith('dislike_')) {
|
||||
const targetUserId = data.replace('dislike_', '');
|
||||
await this.handleDislike(chatId, telegramId, targetUserId);
|
||||
} else if (data.startsWith('superlike_')) {
|
||||
const targetUserId = data.replace('superlike_', '');
|
||||
await this.handleSuperlike(chatId, telegramId, targetUserId);
|
||||
} else if (data.startsWith('view_profile_')) {
|
||||
const targetUserId = data.replace('view_profile_', '');
|
||||
await this.handleViewProfile(chatId, telegramId, targetUserId);
|
||||
} else if (data.startsWith('more_photos_')) {
|
||||
const targetUserId = data.replace('more_photos_', '');
|
||||
await this.handleMorePhotos(chatId, telegramId, targetUserId);
|
||||
}
|
||||
|
||||
// Матчи и чаты
|
||||
else if (data === 'view_matches') {
|
||||
await this.handleViewMatches(chatId, telegramId);
|
||||
} else if (data === 'open_chats') {
|
||||
await this.handleOpenChats(chatId, telegramId);
|
||||
} else if (data.startsWith('chat_')) {
|
||||
const matchId = data.replace('chat_', '');
|
||||
await this.handleOpenChat(chatId, telegramId, matchId);
|
||||
} else if (data.startsWith('send_message_')) {
|
||||
const matchId = data.replace('send_message_', '');
|
||||
await this.handleSendMessage(chatId, telegramId, matchId);
|
||||
} else if (data.startsWith('view_chat_profile_')) {
|
||||
const matchId = data.replace('view_chat_profile_', '');
|
||||
await this.handleViewChatProfile(chatId, telegramId, matchId);
|
||||
} else if (data.startsWith('unmatch_')) {
|
||||
const matchId = data.replace('unmatch_', '');
|
||||
await this.handleUnmatch(chatId, telegramId, matchId);
|
||||
} else if (data.startsWith('confirm_unmatch_')) {
|
||||
const matchId = data.replace('confirm_unmatch_', '');
|
||||
await this.handleConfirmUnmatch(chatId, telegramId, matchId);
|
||||
}
|
||||
|
||||
// Настройки
|
||||
else if (data === 'settings') {
|
||||
await this.handleSettings(chatId, telegramId);
|
||||
} else if (data === 'search_settings') {
|
||||
await this.handleSearchSettings(chatId, telegramId);
|
||||
} else if (data === 'notification_settings') {
|
||||
await this.handleNotificationSettings(chatId, telegramId);
|
||||
}
|
||||
|
||||
// Информация
|
||||
else if (data === 'how_it_works') {
|
||||
await this.handleHowItWorks(chatId);
|
||||
} else if (data === 'back_to_browsing') {
|
||||
await this.handleStartBrowsing(chatId, telegramId);
|
||||
}
|
||||
|
||||
else {
|
||||
await this.bot.answerCallbackQuery(query.id, {
|
||||
text: 'Функция в разработке!',
|
||||
show_alert: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await this.bot.answerCallbackQuery(query.id);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Callback handler error:', error);
|
||||
await this.bot.answerCallbackQuery(query.id, {
|
||||
text: 'Произошла ошибка. Попробуйте еще раз.',
|
||||
show_alert: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Создание профиля
|
||||
async handleCreateProfile(chatId: number, telegramId: string): Promise<void> {
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[{ text: '👨 Мужской', callback_data: 'gender_male' }],
|
||||
[{ text: '👩 Женский', callback_data: 'gender_female' }],
|
||||
[{ text: '🔀 Другой', callback_data: 'gender_other' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'👋 Давайте создадим ваш профиль!\n\n' +
|
||||
'🚹🚺 Сначала выберите ваш пол:',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
}
|
||||
|
||||
// Выбор пола
|
||||
async handleGenderSelection(chatId: number, telegramId: string, gender: string): Promise<void> {
|
||||
this.messageHandlers.startProfileCreation(telegramId, gender);
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'👍 Отлично!\n\n📝 Теперь напишите ваше имя:'
|
||||
);
|
||||
}
|
||||
|
||||
// Просмотр собственного профиля
|
||||
async handleViewMyProfile(chatId: number, telegramId: string): Promise<void> {
|
||||
const profile = await this.profileService.getProfileByTelegramId(telegramId);
|
||||
|
||||
if (!profile) {
|
||||
await this.bot.sendMessage(chatId, '❌ Профиль не найден');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.showProfile(chatId, profile, true);
|
||||
}
|
||||
|
||||
// Редактирование профиля
|
||||
async handleEditProfile(chatId: number, telegramId: string): Promise<void> {
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '📝 Имя', callback_data: 'edit_name' },
|
||||
{ text: '📅 Возраст', callback_data: 'edit_age' }
|
||||
],
|
||||
[
|
||||
{ text: '📍 Город', callback_data: 'edit_city' },
|
||||
{ text: '💼 Работа', callback_data: 'edit_job' }
|
||||
],
|
||||
[
|
||||
{ text: '📖 О себе', callback_data: 'edit_bio' },
|
||||
{ text: '🎯 Интересы', callback_data: 'edit_interests' }
|
||||
],
|
||||
[{ text: '👈 Назад к профилю', callback_data: 'view_my_profile' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'✏️ Что хотите изменить в профиле?',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
}
|
||||
|
||||
// Управление фотографиями
|
||||
async handleManagePhotos(chatId: number, telegramId: string): Promise<void> {
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '📷 Добавить фото', callback_data: 'add_photo' },
|
||||
{ text: '🗑 Удалить фото', callback_data: 'delete_photo' }
|
||||
],
|
||||
[
|
||||
{ text: '⭐ Сделать главным', callback_data: 'set_main_photo' },
|
||||
{ text: '🔄 Изменить порядок', callback_data: 'reorder_photos' }
|
||||
],
|
||||
[{ text: '👈 Назад к профилю', callback_data: 'view_my_profile' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'📸 Управление фотографиями\n\nВыберите действие:',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
}
|
||||
|
||||
// Начать просмотр анкет
|
||||
async handleStartBrowsing(chatId: number, telegramId: string): Promise<void> {
|
||||
const profile = await this.profileService.getProfileByTelegramId(telegramId);
|
||||
|
||||
if (!profile) {
|
||||
await this.bot.sendMessage(chatId, '❌ Сначала создайте профиль!');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.showNextCandidate(chatId, telegramId);
|
||||
}
|
||||
|
||||
// Следующий кандидат
|
||||
async handleNextCandidate(chatId: number, telegramId: string): Promise<void> {
|
||||
await this.showNextCandidate(chatId, telegramId);
|
||||
}
|
||||
|
||||
// Лайк
|
||||
async handleLike(chatId: number, telegramId: string, targetUserId: string): Promise<void> {
|
||||
try {
|
||||
const result = await this.matchingService.performSwipe(telegramId, targetUserId, 'like');
|
||||
|
||||
if (result.isMatch) {
|
||||
// Это матч!
|
||||
const targetProfile = await this.profileService.getProfileByUserId(targetUserId);
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '💬 Написать сообщение', callback_data: 'chat_' + targetUserId },
|
||||
{ text: '👤 Посмотреть профиль', callback_data: 'view_profile_' + targetUserId }
|
||||
],
|
||||
[{ text: '🔍 Продолжить поиск', callback_data: 'next_candidate' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'🎉 ЭТО МАТЧ! 💕\n\n' +
|
||||
'Вы понравились друг другу с ' + (targetProfile?.name || 'этим пользователем') + '!\n\n' +
|
||||
'Теперь вы можете начать общение!',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
} else {
|
||||
await this.bot.sendMessage(chatId, '👍 Лайк отправлен!');
|
||||
await this.showNextCandidate(chatId, telegramId);
|
||||
}
|
||||
} catch (error) {
|
||||
await this.bot.sendMessage(chatId, '❌ Ошибка при отправке лайка');
|
||||
console.error('Like error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Дизлайк
|
||||
async handleDislike(chatId: number, telegramId: string, targetUserId: string): Promise<void> {
|
||||
try {
|
||||
await this.matchingService.performSwipe(telegramId, targetUserId, 'pass');
|
||||
await this.showNextCandidate(chatId, telegramId);
|
||||
} catch (error) {
|
||||
await this.bot.sendMessage(chatId, '❌ Ошибка при отправке дизлайка');
|
||||
console.error('Dislike error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Супер лайк
|
||||
async handleSuperlike(chatId: number, telegramId: string, targetUserId: string): Promise<void> {
|
||||
try {
|
||||
const result = await this.matchingService.performSwipe(telegramId, targetUserId, 'superlike');
|
||||
|
||||
if (result.isMatch) {
|
||||
const targetProfile = await this.profileService.getProfileByUserId(targetUserId);
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '💬 Написать сообщение', callback_data: 'chat_' + targetUserId },
|
||||
{ text: '👤 Посмотреть профиль', callback_data: 'view_profile_' + targetUserId }
|
||||
],
|
||||
[{ text: '🔍 Продолжить поиск', callback_data: 'next_candidate' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'💖 СУПЕР МАТЧ! ⭐\n\n' +
|
||||
'Ваш супер лайк произвел впечатление на ' + (targetProfile?.name || 'этого пользователя') + '!\n\n' +
|
||||
'Начните общение первыми!',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
} else {
|
||||
await this.bot.sendMessage(chatId, '💖 Супер лайк отправлен!');
|
||||
await this.showNextCandidate(chatId, telegramId);
|
||||
}
|
||||
} catch (error) {
|
||||
await this.bot.sendMessage(chatId, '❌ Ошибка при отправке супер лайка');
|
||||
console.error('Superlike error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Просмотр профиля кандидата
|
||||
async handleViewProfile(chatId: number, telegramId: string, targetUserId: string): Promise<void> {
|
||||
const targetProfile = await this.profileService.getProfileByUserId(targetUserId);
|
||||
|
||||
if (!targetProfile) {
|
||||
await this.bot.sendMessage(chatId, '❌ Профиль не найден');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.showProfile(chatId, targetProfile, false, telegramId);
|
||||
}
|
||||
|
||||
// Показать больше фотографий
|
||||
async handleMorePhotos(chatId: number, telegramId: string, targetUserId: string): Promise<void> {
|
||||
const targetProfile = await this.profileService.getProfileByUserId(targetUserId);
|
||||
|
||||
if (!targetProfile || targetProfile.photos.length <= 1) {
|
||||
await this.bot.sendMessage(chatId, '📷 У пользователя нет дополнительных фотографий');
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 1; i < targetProfile.photos.length; i++) {
|
||||
const photoFileId = targetProfile.photos[i];
|
||||
await this.bot.sendPhoto(chatId, photoFileId);
|
||||
}
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '👎 Не нравится', callback_data: 'dislike_' + targetUserId },
|
||||
{ text: '💖 Супер лайк', callback_data: 'superlike_' + targetUserId },
|
||||
{ text: '👍 Нравится', callback_data: 'like_' + targetUserId }
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'📸 Все фотографии просмотрены!\n\nВаше решение?',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
}
|
||||
|
||||
// Просмотр матчей
|
||||
async handleViewMatches(chatId: number, telegramId: string): Promise<void> {
|
||||
const matches = await this.matchingService.getUserMatches(telegramId);
|
||||
|
||||
if (matches.length === 0) {
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[{ text: '🔍 Начать поиск', callback_data: 'start_browsing' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'💔 У вас пока нет матчей\n\n' +
|
||||
'Попробуйте просмотреть больше анкет!',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let matchText = 'Ваши матчи (' + matches.length + '):\n\n';
|
||||
|
||||
for (const match of matches) {
|
||||
const otherUserId = match.userId1 === telegramId ? match.userId2 : match.userId1;
|
||||
const otherProfile = await this.profileService.getProfileByUserId(otherUserId);
|
||||
|
||||
if (otherProfile) {
|
||||
matchText += '💖 ' + otherProfile.name + ', ' + otherProfile.age + '\n';
|
||||
matchText += '📍 ' + (otherProfile.city || 'Не указан') + '\n\n';
|
||||
}
|
||||
}
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[{ text: '💬 Открыть чаты', callback_data: 'open_chats' }],
|
||||
[{ text: '🔍 Найти еще', callback_data: 'start_browsing' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(chatId, matchText, { reply_markup: keyboard });
|
||||
}
|
||||
|
||||
// Открыть чаты
|
||||
// Открыть список чатов
|
||||
async handleOpenChats(chatId: number, telegramId: string): Promise<void> {
|
||||
const chats = await this.chatService.getUserChats(telegramId);
|
||||
|
||||
if (chats.length === 0) {
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[{ text: '🔍 Найти матчи', callback_data: 'start_browsing' }],
|
||||
[{ text: '💕 Мои матчи', callback_data: 'view_matches' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'💬 У вас пока нет активных чатов\n\n' +
|
||||
'Начните просматривать анкеты и получите первые матчи!',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let messageText = '💬 Ваши чаты:\n\n';
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: []
|
||||
};
|
||||
|
||||
for (const chat of chats.slice(0, 10)) { // Показываем только первые 10 чатов
|
||||
const unreadBadge = chat.unreadCount > 0 ? ` (${chat.unreadCount})` : '';
|
||||
const lastMessagePreview = chat.lastMessage
|
||||
? (chat.lastMessage.length > 30
|
||||
? chat.lastMessage.substring(0, 30) + '...'
|
||||
: chat.lastMessage)
|
||||
: 'Новый матч';
|
||||
|
||||
messageText += `💕 ${chat.otherUserName}${unreadBadge}\n`;
|
||||
messageText += `💬 ${lastMessagePreview}\n\n`;
|
||||
|
||||
keyboard.inline_keyboard.push([
|
||||
{ text: `💬 ${chat.otherUserName}${unreadBadge}`, callback_data: `chat_${chat.matchId}` }
|
||||
]);
|
||||
}
|
||||
|
||||
if (chats.length > 10) {
|
||||
messageText += `...и еще ${chats.length - 10} чатов`;
|
||||
}
|
||||
|
||||
keyboard.inline_keyboard.push([
|
||||
{ text: '🔍 Найти еще', callback_data: 'start_browsing' },
|
||||
{ text: '💕 Матчи', callback_data: 'view_matches' }
|
||||
]);
|
||||
|
||||
await this.bot.sendMessage(chatId, messageText, { reply_markup: keyboard });
|
||||
}
|
||||
|
||||
// Открыть конкретный чат
|
||||
async handleOpenChat(chatId: number, telegramId: string, matchId: string): Promise<void> {
|
||||
const matchInfo = await this.chatService.getMatchInfo(matchId, telegramId);
|
||||
|
||||
if (!matchInfo) {
|
||||
await this.bot.sendMessage(chatId, '❌ Чат не найден или недоступен');
|
||||
return;
|
||||
}
|
||||
|
||||
// Отмечаем сообщения как прочитанные
|
||||
await this.chatService.markMessagesAsRead(matchId, telegramId);
|
||||
|
||||
// Получаем последние сообщения
|
||||
const messages = await this.chatService.getChatMessages(matchId, 10);
|
||||
|
||||
let chatText = `💬 Чат с ${matchInfo.otherUserProfile?.name}\n\n`;
|
||||
|
||||
if (messages.length === 0) {
|
||||
chatText += '📝 Начните общение! Напишите первое сообщение.\n\n';
|
||||
} else {
|
||||
chatText += '📝 Последние сообщения:\n\n';
|
||||
|
||||
for (const message of messages.slice(-5)) { // Показываем последние 5 сообщений
|
||||
const currentUserId = await this.profileService.getUserIdByTelegramId(telegramId);
|
||||
const isFromMe = message.senderId === currentUserId;
|
||||
const sender = isFromMe ? 'Вы' : matchInfo.otherUserProfile?.name;
|
||||
const time = message.createdAt.toLocaleTimeString('ru-RU', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
|
||||
chatText += `${sender} (${time}):\n${message.content}\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '✍️ Написать сообщение', callback_data: `send_message_${matchId}` }
|
||||
],
|
||||
[
|
||||
{ text: '👤 Профиль', callback_data: `view_chat_profile_${matchId}` },
|
||||
{ text: '💔 Удалить матч', callback_data: `unmatch_${matchId}` }
|
||||
],
|
||||
[
|
||||
{ text: '← Назад к чатам', callback_data: 'open_chats' }
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(chatId, chatText, { reply_markup: keyboard });
|
||||
}
|
||||
|
||||
// Отправить сообщение
|
||||
async handleSendMessage(chatId: number, telegramId: string, matchId: string): Promise<void> {
|
||||
const matchInfo = await this.chatService.getMatchInfo(matchId, telegramId);
|
||||
|
||||
if (!matchInfo) {
|
||||
await this.bot.sendMessage(chatId, '❌ Чат не найден или недоступен');
|
||||
return;
|
||||
}
|
||||
|
||||
// Устанавливаем состояние ожидания сообщения
|
||||
this.messageHandlers.setWaitingForMessage(telegramId, matchId);
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[{ text: '❌ Отмена', callback_data: `chat_${matchId}` }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
`✍️ Напишите сообщение для ${matchInfo.otherUserProfile?.name}:\n\n` +
|
||||
'💡 Просто отправьте текст в этот чат',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
}
|
||||
|
||||
// Просмотр профиля в чате
|
||||
async handleViewChatProfile(chatId: number, telegramId: string, matchId: string): Promise<void> {
|
||||
const matchInfo = await this.chatService.getMatchInfo(matchId, telegramId);
|
||||
|
||||
if (!matchInfo || !matchInfo.otherUserProfile) {
|
||||
await this.bot.sendMessage(chatId, '❌ Профиль не найден');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.showProfile(chatId, matchInfo.otherUserProfile, false, telegramId);
|
||||
}
|
||||
|
||||
// Удалить матч (размэтчиться)
|
||||
async handleUnmatch(chatId: number, telegramId: string, matchId: string): Promise<void> {
|
||||
const matchInfo = await this.chatService.getMatchInfo(matchId, telegramId);
|
||||
|
||||
if (!matchInfo) {
|
||||
await this.bot.sendMessage(chatId, '❌ Матч не найден');
|
||||
return;
|
||||
}
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '✅ Да, удалить', callback_data: `confirm_unmatch_${matchId}` },
|
||||
{ text: '❌ Отмена', callback_data: `chat_${matchId}` }
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
`💔 Вы уверены, что хотите удалить матч с ${matchInfo.otherUserProfile?.name}?\n\n` +
|
||||
'⚠️ Это действие нельзя отменить. Вся переписка будет удалена.',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
}
|
||||
|
||||
// Подтвердить удаление матча
|
||||
async handleConfirmUnmatch(chatId: number, telegramId: string, matchId: string): Promise<void> {
|
||||
const success = await this.chatService.unmatch(matchId, telegramId);
|
||||
|
||||
if (success) {
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'💔 Матч удален\n\n' +
|
||||
'Вы больше не увидите этого пользователя в своих матчах.'
|
||||
);
|
||||
|
||||
// Возвращаемся к списку чатов
|
||||
setTimeout(() => {
|
||||
this.handleOpenChats(chatId, telegramId);
|
||||
}, 2000);
|
||||
} else {
|
||||
await this.bot.sendMessage(chatId, '❌ Не удалось удалить матч. Попробуйте еще раз.');
|
||||
}
|
||||
}
|
||||
|
||||
// Настройки
|
||||
async handleSettings(chatId: number, telegramId: string): Promise<void> {
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '🔍 Настройки поиска', callback_data: 'search_settings' },
|
||||
{ text: '🔔 Уведомления', callback_data: 'notification_settings' }
|
||||
],
|
||||
[
|
||||
{ text: '🚫 Скрыть профиль', callback_data: 'hide_profile' },
|
||||
{ text: '🗑 Удалить профиль', callback_data: 'delete_profile' }
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'⚙️ Настройки профиля\n\nВыберите что хотите изменить:',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
}
|
||||
|
||||
// Настройки поиска
|
||||
async handleSearchSettings(chatId: number, telegramId: string): Promise<void> {
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'🔍 Настройки поиска будут доступны в следующем обновлении!'
|
||||
);
|
||||
}
|
||||
|
||||
// Настройки уведомлений
|
||||
async handleNotificationSettings(chatId: number, telegramId: string): Promise<void> {
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'🔔 Настройки уведомлений будут доступны в следующем обновлении!'
|
||||
);
|
||||
}
|
||||
|
||||
// Как это работает
|
||||
async handleHowItWorks(chatId: number): Promise<void> {
|
||||
const helpText =
|
||||
'🎯 Как работает Telegram Tinder Bot?\n\n' +
|
||||
'1️⃣ Создайте профиль\n' +
|
||||
' • Добавьте фото и описание\n' +
|
||||
' • Укажите ваши предпочтения\n\n' +
|
||||
'2️⃣ Просматривайте анкеты\n' +
|
||||
' • Ставьте лайки понравившимся\n' +
|
||||
' • Используйте супер лайки для особых случаев\n\n' +
|
||||
'3️⃣ Получайте матчи\n' +
|
||||
' • Когда ваш лайк взаимен - это матч!\n' +
|
||||
' • Начинайте общение\n\n' +
|
||||
'4️⃣ Общайтесь и знакомьтесь\n' +
|
||||
' • Находите общие интересы\n' +
|
||||
' • Договаривайтесь о встрече\n\n' +
|
||||
'<27><> Советы:\n' +
|
||||
'• Используйте качественные фото\n' +
|
||||
'• Напишите интересное описание\n' +
|
||||
'• Будьте вежливы в общении\n\n' +
|
||||
'❤️ Удачи в поиске любви!';
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[{ text: '🚀 Создать профиль', callback_data: 'create_profile' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(chatId, helpText, { reply_markup: keyboard });
|
||||
}
|
||||
|
||||
// Вспомогательные методы
|
||||
async showProfile(chatId: number, profile: Profile, isOwner: boolean = false, viewerId?: string): Promise<void> {
|
||||
const mainPhotoFileId = profile.photos[0]; // Первое фото - главное
|
||||
|
||||
let profileText = '👤 ' + profile.name + ', ' + profile.age + '\n';
|
||||
profileText += '📍 ' + (profile.city || 'Не указан') + '\n';
|
||||
if (profile.job) profileText += '💼 ' + profile.job + '\n';
|
||||
if (profile.education) profileText += '🎓 ' + profile.education + '\n';
|
||||
if (profile.height) profileText += '📏 ' + profile.height + ' см\n';
|
||||
profileText += '\n📝 ' + (profile.bio || 'Описание не указано') + '\n';
|
||||
|
||||
if (profile.interests.length > 0) {
|
||||
profileText += '\n🎯 Интересы: ' + profile.interests.join(', ');
|
||||
}
|
||||
|
||||
let keyboard: InlineKeyboardMarkup;
|
||||
|
||||
if (isOwner) {
|
||||
keyboard = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '✏️ Редактировать', callback_data: 'edit_profile' },
|
||||
{ text: '📸 Фото', callback_data: 'manage_photos' }
|
||||
],
|
||||
[{ text: '🔍 Начать поиск', callback_data: 'start_browsing' }]
|
||||
]
|
||||
};
|
||||
} else {
|
||||
keyboard = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '👎 Не нравится', callback_data: 'dislike_' + profile.userId },
|
||||
{ text: '💖 Супер лайк', callback_data: 'superlike_' + profile.userId },
|
||||
{ text: '👍 Нравится', callback_data: 'like_' + profile.userId }
|
||||
],
|
||||
[{ text: '🔍 Продолжить поиск', callback_data: 'next_candidate' }]
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
// Проверяем, есть ли валидное фото (file_id или URL)
|
||||
const hasValidPhoto = mainPhotoFileId &&
|
||||
(mainPhotoFileId.startsWith('http') ||
|
||||
mainPhotoFileId.startsWith('AgAC') ||
|
||||
mainPhotoFileId.length > 20); // file_id обычно длинные
|
||||
|
||||
if (hasValidPhoto) {
|
||||
try {
|
||||
await this.bot.sendPhoto(chatId, mainPhotoFileId, {
|
||||
caption: profileText,
|
||||
reply_markup: keyboard
|
||||
});
|
||||
} catch (error) {
|
||||
// Если не удалось отправить фото, отправляем текст
|
||||
await this.bot.sendMessage(chatId, '🖼 Фото недоступно\n\n' + profileText, {
|
||||
reply_markup: keyboard
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Отправляем как текстовое сообщение
|
||||
await this.bot.sendMessage(chatId, profileText, {
|
||||
reply_markup: keyboard
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async showNextCandidate(chatId: number, telegramId: string): Promise<void> {
|
||||
const candidate = await this.matchingService.getNextCandidate(telegramId);
|
||||
|
||||
if (!candidate) {
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[{ text: '🔄 Попробовать еще раз', callback_data: 'start_browsing' }],
|
||||
[{ text: '💕 Мои матчи', callback_data: 'view_matches' }]
|
||||
]
|
||||
};
|
||||
|
||||
await this.bot.sendMessage(
|
||||
chatId,
|
||||
'🎉 Вы просмотрели всех доступных кандидатов!\n\n' +
|
||||
'⏰ Попробуйте позже - возможно появятся новые анкеты!',
|
||||
{ reply_markup: keyboard }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const candidatePhotoFileId = candidate.photos[0]; // Первое фото - главное
|
||||
|
||||
let candidateText = candidate.name + ', ' + candidate.age + '\n';
|
||||
candidateText += '📍 ' + (candidate.city || 'Не указан') + '\n';
|
||||
if (candidate.job) candidateText += '💼 ' + candidate.job + '\n';
|
||||
if (candidate.education) candidateText += '🎓 ' + candidate.education + '\n';
|
||||
if (candidate.height) candidateText += '<27><> ' + candidate.height + ' см\n';
|
||||
candidateText += '\n📝 ' + (candidate.bio || 'Описание отсутствует') + '\n';
|
||||
|
||||
if (candidate.interests.length > 0) {
|
||||
candidateText += '\n🎯 Интересы: ' + candidate.interests.join(', ');
|
||||
}
|
||||
|
||||
const keyboard: InlineKeyboardMarkup = {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{ text: '👎 Не нравится', callback_data: 'dislike_' + candidate.userId },
|
||||
{ text: '💖 Супер лайк', callback_data: 'superlike_' + candidate.userId },
|
||||
{ text: '👍 Нравится', callback_data: 'like_' + candidate.userId }
|
||||
],
|
||||
[
|
||||
{ text: '👤 Профиль', callback_data: 'view_profile_' + candidate.userId },
|
||||
{ text: '📸 Еще фото', callback_data: 'more_photos_' + candidate.userId }
|
||||
],
|
||||
[{ text: '⏭ Следующий', callback_data: 'next_candidate' }]
|
||||
]
|
||||
};
|
||||
|
||||
// Проверяем, есть ли валидное фото (file_id или URL)
|
||||
const hasValidPhoto = candidatePhotoFileId &&
|
||||
(candidatePhotoFileId.startsWith('http') ||
|
||||
candidatePhotoFileId.startsWith('AgAC') ||
|
||||
candidatePhotoFileId.length > 20); // file_id обычно длинные
|
||||
|
||||
if (hasValidPhoto) {
|
||||
try {
|
||||
await this.bot.sendPhoto(chatId, candidatePhotoFileId, {
|
||||
caption: candidateText,
|
||||
reply_markup: keyboard
|
||||
});
|
||||
} catch (error) {
|
||||
// Если не удалось отправить фото, отправляем текст
|
||||
await this.bot.sendMessage(chatId, '🖼 Фото недоступно\n\n' + candidateText, {
|
||||
reply_markup: keyboard
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Отправляем как текстовое сообщение
|
||||
await this.bot.sendMessage(chatId, '📝 ' + candidateText, {
|
||||
reply_markup: keyboard
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user