init commit

This commit is contained in:
2025-09-12 21:25:54 +09:00
commit 17efb2fb53
37 changed files with 12637 additions and 0 deletions

View File

@@ -0,0 +1,302 @@
import TelegramBot, { Message, InlineKeyboardMarkup } from 'node-telegram-bot-api';
import { ProfileService } from '../services/profileService';
import { MatchingService } from '../services/matchingService';
import { Profile } from '../models/Profile';
export class CommandHandlers {
private bot: TelegramBot;
private profileService: ProfileService;
private matchingService: MatchingService;
constructor(bot: TelegramBot) {
this.bot = bot;
this.profileService = new ProfileService();
this.matchingService = new MatchingService();
}
register(): void {
this.bot.onText(/\/start/, (msg: Message) => this.handleStart(msg));
this.bot.onText(/\/help/, (msg: Message) => this.handleHelp(msg));
this.bot.onText(/\/profile/, (msg: Message) => this.handleProfile(msg));
this.bot.onText(/\/browse/, (msg: Message) => this.handleBrowse(msg));
this.bot.onText(/\/matches/, (msg: Message) => this.handleMatches(msg));
this.bot.onText(/\/settings/, (msg: Message) => this.handleSettings(msg));
this.bot.onText(/\/create_profile/, (msg: Message) => this.handleCreateProfile(msg));
}
async handleStart(msg: Message): Promise<void> {
const userId = msg.from?.id.toString();
if (!userId) return;
// Проверяем есть ли у пользователя профиль
const existingProfile = await this.profileService.getProfileByTelegramId(userId);
if (existingProfile) {
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[
{ text: '👤 Мой профиль', callback_data: 'view_my_profile' },
{ text: '🔍 Просмотр анкет', callback_data: 'start_browsing' }
],
[
{ text: '💕 Мои матчи', callback_data: 'view_matches' },
{ text: '⚙️ Настройки', callback_data: 'settings' }
]
]
};
await this.bot.sendMessage(
msg.chat.id,
`🎉 С возвращением, ${existingProfile.name}!\n\n` +
`💖 Telegram Tinder Bot готов к работе!\n\n` +
`Что хотите сделать?`,
{ reply_markup: keyboard }
);
} else {
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[{ text: '<27> Создать профиль', callback_data: 'create_profile' }],
[{ text: ' Как это работает?', callback_data: 'how_it_works' }]
]
};
await this.bot.sendMessage(
msg.chat.id,
`🎉 Добро пожаловать в Telegram Tinder Bot!\n\n` +
`💕 Здесь вы можете найти свою вторую половинку!\n\n` +
`Для начала создайте свой профиль:`,
{ reply_markup: keyboard }
);
}
}
async handleHelp(msg: Message): Promise<void> {
const helpText = `
🤖 Telegram Tinder Bot - Справка
📋 Доступные команды:
/start - Главное меню
/profile - Управление профилем
/browse - Просмотр анкет
/matches - Ваши матчи
/settings - Настройки
/help - Эта справка
<EFBFBD> Как использовать:
1. Создайте профиль с фото и описанием
2. Просматривайте анкеты других пользователей
3. Ставьте лайки понравившимся
4. Общайтесь с взаимными матчами!
❤️ Удачи в поиске любви!
`;
await this.bot.sendMessage(msg.chat.id, helpText.trim());
}
async handleProfile(msg: Message): Promise<void> {
const userId = msg.from?.id.toString();
if (!userId) return;
const profile = await this.profileService.getProfileByTelegramId(userId);
if (!profile) {
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[{ text: '🚀 Создать профиль', callback_data: 'create_profile' }]
]
};
await this.bot.sendMessage(
msg.chat.id,
'❌ У вас пока нет профиля.\nСоздайте его для начала использования бота!',
{ reply_markup: keyboard }
);
return;
}
// Показываем профиль пользователя
await this.showUserProfile(msg.chat.id, profile, true);
}
async handleBrowse(msg: Message): Promise<void> {
const userId = msg.from?.id.toString();
if (!userId) return;
const profile = await this.profileService.getProfileByTelegramId(userId);
if (!profile) {
await this.bot.sendMessage(
msg.chat.id,
'❌ Сначала создайте профиль!\nИспользуйте команду /start'
);
return;
}
await this.showNextCandidate(msg.chat.id, userId);
}
async handleMatches(msg: Message): Promise<void> {
const userId = msg.from?.id.toString();
if (!userId) return;
// Получаем матчи пользователя
const matches = await this.matchingService.getUserMatches(userId);
if (matches.length === 0) {
await this.bot.sendMessage(
msg.chat.id,
'<27> У вас пока нет матчей.\n\n' +
'🔍 Попробуйте просмотреть больше анкет!\n' +
'Используйте /browse для поиска.'
);
return;
}
let matchText = `💕 Ваши матчи (${matches.length}):\n\n`;
for (const match of matches) {
const otherUserId = match.userId1 === userId ? match.userId2 : match.userId1;
const otherProfile = await this.profileService.getProfileByUserId(otherUserId);
if (otherProfile) {
matchText += `💖 ${otherProfile.name}, ${otherProfile.age}\n`;
matchText += `📍 ${otherProfile.city || 'Не указан'}\n`;
matchText += `💌 Матч: ${new Date(match.createdAt).toLocaleDateString()}\n\n`;
}
}
const keyboard: InlineKeyboardMarkup = {
inline_keyboard: [
[{ text: '💬 Открыть чаты', callback_data: 'open_chats' }],
[{ text: '🔍 Найти еще', callback_data: 'start_browsing' }]
]
};
await this.bot.sendMessage(msg.chat.id, matchText, { reply_markup: keyboard });
}
async handleSettings(msg: Message): 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(
msg.chat.id,
'⚙️ Настройки профиля\n\nВыберите что хотите изменить:',
{ reply_markup: keyboard }
);
}
async handleCreateProfile(msg: Message): Promise<void> {
const userId = msg.from?.id.toString();
if (!userId) return;
await this.bot.sendMessage(
msg.chat.id,
'👋 Давайте создадим ваш профиль!\n\n' +
'📝 Сначала напишите ваше имя:'
);
// Устанавливаем состояние ожидания имени
// Это будет обрабатываться в messageHandlers
}
// Вспомогательные методы
async showUserProfile(chatId: number, profile: Profile, isOwner: boolean = false): 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(', ')}`;
}
const keyboard: InlineKeyboardMarkup = isOwner ? {
inline_keyboard: [
[
{ text: '✏️ Редактировать', callback_data: 'edit_profile' },
{ text: '📸 Фото', callback_data: 'manage_photos' }
],
[{ text: '🔍 Начать поиск', callback_data: 'start_browsing' }]
]
} : {
inline_keyboard: [
[{ text: '👈 Назад', callback_data: 'back_to_browsing' }]
]
};
if (mainPhotoFileId) {
await this.bot.sendPhoto(chatId, mainPhotoFileId, {
caption: profileText,
reply_markup: keyboard
});
} else {
await this.bot.sendMessage(chatId, profileText, { reply_markup: keyboard });
}
}
async showNextCandidate(chatId: number, userId: string): Promise<void> {
const candidate = await this.matchingService.getNextCandidate(userId);
if (!candidate) {
await this.bot.sendMessage(
chatId,
'🎉 Вы просмотрели всех доступных кандидатов!\n\n' +
'⏰ Попробуйте позже - возможно появятся новые анкеты!'
);
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 += `📏 ${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' }]
]
};
if (candidatePhotoFileId) {
await this.bot.sendPhoto(chatId, candidatePhotoFileId, {
caption: candidateText,
reply_markup: keyboard
});
} else {
await this.bot.sendMessage(chatId, candidateText, { reply_markup: keyboard });
}
}
}