Files
Tg-job/mtucijobsbot/dist/index.js

376 lines
18 KiB
JavaScript
Raw Permalink 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.
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
require("dotenv/config");
const telegraf_1 = require("telegraf");
const start_1 = require("./commands/start");
const menuScenes_1 = require("./modules/menuScenes");
const express_1 = __importDefault(require("express"));
const cors_1 = __importDefault(require("cors"));
const events_1 = require("./modules/scenes/events");
const form_data_1 = __importDefault(require("form-data"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const axios_1 = __importDefault(require("axios"));
const savevacansy_1 = require("./modules/scenes/savevacansy");
const accept_1 = require("./modules/scenes/accept");
const app = (0, express_1.default)();
const bot = new telegraf_1.Telegraf(process.env.BOT_TOKEN);
app.use((req, res, next) => {
req.bot = bot;
next();
});
app.use(express_1.default.json());
app.use((0, cors_1.default)());
bot.start(start_1.startCommand);
app.post('/api/resume', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
try {
const postData = req.body;
const resumeTemplatePath = path_1.default.resolve(__dirname, 'assets', 'шаблон МТУСИ.docx');
yield bot.telegram.sendDocument(postData.id, { source: resumeTemplatePath }, { caption: 'Пример резюме' });
yield bot.telegram.sendMessage(postData.id, `Ваша анкета заполнена! Отправьте своё резюме для завершения регистрации`, {
reply_markup: {
inline_keyboard: [
[
{ text: 'Загрузить резюме', callback_data: 'uploadresume' },
// { text: 'Пропустить загрузку', callback_data: 'skip' },
],
],
},
});
console.log(`Ваш id ${postData.id}`);
return res.json({ status: 'success' });
}
catch (e) {
console.error('Error:', e);
res.status(500).json({ error: 'An error occurred' });
throw e;
}
}));
// const resumeScene: Scenes.WizardScene<MyWizardContext> = new Scenes.WizardScene(
// 'resumeScene',
// async ctx => {
// await ctx.reply(
// 'Отправьте своё резюме в PDF формате или отправьте /cancel для отмены.'
// );
// return ctx.wizard.next();
// },
// async ctx => {
// if (
// ctx.message &&
// 'text' in ctx.message &&
// ctx.from &&
// ctx.message.text == '/cancel'
// ) {
// await ctx.reply('Отправка резюме отменена.');
// await ctx.reply(
// 'Меню',
// Markup.keyboard([
// ['Моя анкета'],
// ['Вакансии'],
// ['Уведомления: включены'],
// ]).resize()
// );
// return ctx.scene.leave();
// }
// if (ctx.message && 'document' in ctx.message && ctx.from) {
// const file = ctx.message.document;
// if (file.mime_type !== 'application/pdf') {
// ctx.reply('Пожалуйста, отправьте файл в формате PDF.');
// return;
// }
// try {
// const fileLink = await ctx.telegram.getFileLink(file.file_id);
// const filePath = path.join(__dirname, `${file.file_id}.pdf`);
// // Загрузка файла на локальную машину
// const response = await axios.get(fileLink.href, {
// responseType: 'stream',
// });
// response.data
// .pipe(fs.createWriteStream(filePath))
// .on('finish', async () => {
// // Создание формы данных
// const form = new FormData();
// form.append('file', fs.createReadStream(filePath));
// try {
// // Установка времени ожидания (в миллисекундах)
// const uploadResponse = await axios.post(
// `${process.env.API}services/resume/`,
// form,
// {
// headers: {
// ...form.getHeaders(),
// 'X-API-KEY':
// 'SbRHOVoK97GKCx3Lqx6hKXLbZZJEd0GTGbeglXdpK9PhSB9kpr4eWCsuIIwnD6F2mgpTDlVHFCRbeFmuSfqBVsb12lNwF3P1tmdxiktl7zH9sDS2YK7Pyj2DecCWAZ3n',
// },
// timeout: 10000, // Увеличьте время ожидания до 10 секунд
// }
// );
// const fileName = uploadResponse.data.filename;
// // Выполнение PUT-запроса для обновления поля Link у студента
// await axios.patch(
// `${process.env.API}students/${
// ctx.from?.id
// }?Link=${encodeURIComponent(fileName)}`,
// {},
// {
// headers: {
// 'X-API-KEY':
// 'SbRHOVoK97GKCx3Lqx6hKXLbZZJEd0GTGbeglXdpK9PhSB9kpr4eWCsuIIwnD6F2mgpTDlVHFCRbeFmuSfqBVsb12lNwF3P1tmdxiktl7zH9sDS2YK7Pyj2DecCWAZ3n',
// 'Content-Type': 'application/json',
// },
// }
// );
// await ctx.reply('Резюме успешно загружено.');
// await ctx.reply(
// 'Меню',
// Markup.keyboard([
// ['Моя анкета'],
// ['Вакансии'],
// ['Уведомления: включены'],
// ]).resize()
// );
// return ctx.scene.leave();
// } catch (uploadError) {
// console.error('Ошибка при загрузке резюме на API:', uploadError);
// await ctx.reply('Произошла ошибка при загрузке резюме.');
// return ctx.scene.leave();
// } finally {
// // Удаление временного файла после загрузки
// fs.unlinkSync(filePath);
// }
// });
// } catch (error) {
// console.error('Ошибка при загрузке файла:', error);
// await ctx.reply('Произошла ошибка при загрузке файла.');
// }
// } else {
// await ctx.reply('Отправьте файл в формате PDF');
// }
// }
// );
const resumeScene = new telegraf_1.Scenes.WizardScene('resumeScene', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
yield ctx.reply('Отправьте своё резюме в формате Word (DOC/DOCX) или отправьте /cancel для отмены.');
return ctx.wizard.next();
}), (ctx) => __awaiter(void 0, void 0, void 0, function* () {
if (ctx.message &&
'text' in ctx.message &&
ctx.from &&
ctx.message.text === '/cancel') {
yield ctx.reply('Отправка резюме отменена.');
yield ctx.reply('Меню', telegraf_1.Markup.keyboard([
['Моя анкета'],
['Вакансии'],
['Уведомления: включены'],
]).resize());
return ctx.scene.leave();
}
if (ctx.message && 'document' in ctx.message && ctx.from) {
const file = ctx.message.document;
const allowedMimeTypes = [
// 'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
];
if (!allowedMimeTypes.includes(file.mime_type || '')) {
yield ctx.reply('Пожалуйста, отправьте файл в формате DOC или DOCX.');
return;
}
try {
const fileLink = yield ctx.telegram.getFileLink(file.file_id);
const fileExtension = file.mime_type === 'application/pdf'
? 'pdf'
: file.mime_type === 'application/msword'
? 'doc'
: 'docx';
const filePath = path_1.default.join(__dirname, `${file.file_id}.${fileExtension}`);
// Загрузка файла на локальную машину
const response = yield axios_1.default.get(fileLink.href, {
responseType: 'stream',
});
response.data
.pipe(fs_1.default.createWriteStream(filePath))
.on('finish', () => __awaiter(void 0, void 0, void 0, function* () {
var _a;
const form = new form_data_1.default();
form.append('file', fs_1.default.createReadStream(filePath));
try {
const uploadResponse = yield axios_1.default.post(`${process.env.API}services/resume/`, form, {
headers: Object.assign(Object.assign({}, form.getHeaders()), { 'X-API-KEY': 'SbRHOVoK97GKCx3Lqx6hKXLbZZJEd0GTGbeglXdpK9PhSB9kpr4eWCsuIIwnD6F2mgpTDlVHFCRbeFmuSfqBVsb12lNwF3P1tmdxiktl7zH9sDS2YK7Pyj2DecCWAZ3n' }),
timeout: 10000,
});
const fileName = uploadResponse.data.filename;
yield axios_1.default.patch(`${process.env.API}students/${(_a = ctx.from) === null || _a === void 0 ? void 0 : _a.id}?Link=${encodeURIComponent(fileName)}`, {}, {
headers: {
'X-API-KEY': 'SbRHOVoK97GKCx3Lqx6hKXLbZZJEd0GTGbeglXdpK9PhSB9kpr4eWCsuIIwnD6F2mgpTDlVHFCRbeFmuSfqBVsb12lNwF3P1tmdxiktl7zH9sDS2YK7Pyj2DecCWAZ3n',
'Content-Type': 'application/json',
},
});
yield ctx.reply('Резюме успешно загружено.');
yield ctx.reply('Меню', telegraf_1.Markup.keyboard([
['Моя анкета'],
['Вакансии'],
['Уведомления: включены'],
]).resize());
return ctx.scene.leave();
}
catch (uploadError) {
console.error('Ошибка при загрузке резюме на API:', uploadError);
yield ctx.reply('Произошла ошибка при загрузке резюме.');
return ctx.scene.leave();
}
finally {
fs_1.default.unlinkSync(filePath);
}
}));
}
catch (error) {
console.error('Ошибка при загрузке файла:', error);
yield ctx.reply('Произошла ошибка при загрузке файла.');
}
}
else {
yield ctx.reply('Пожалуйста, отправьте файл в формате PDF, DOC или DOCX.');
}
}));
// app.post('/api/resume', async (req: Request, res: Response) => {
// try {
// const postData = req.body;
// // Проверяем наличие chatId в теле запроса
// if (!postData.StudentID) {
// throw new Error('Chat ID is missing in the request body');
// }
// const [userInstance, created] = await Resume.findOrCreate({
// where: { id: postData.StudentID },
// defaults: {
// id: postData.StudentID || 0,
// name: postData.Name,
// group: postData.Group,
// type: postData.Type,
// skills: '',
// softskills: postData.Soft_skills,
// email: postData.Email,
// },
// });
// await UserBase.update(
// { resume_id: postData.StudentID },
// { where: { id: postData.StudentID } }
// );
// if (userInstance instanceof Resume) {
// // userInstance теперь имеет тип User
// if (created) {
// console.log('New user created:', userInstance);
// } else {
// console.log('User already exists:', userInstance);
// }
// console.log('Привет! Вы успешно зарегистрированы.');
// } else {
// console.error('Ошибка: userInstance не является экземпляром User.');
// }
// console.log('Received data:', postData);
// res.status(200).json({ message: 'Data received successfully' });
// } catch (error) {
// console.error(error);
// res.status(500).json({ error: 'Internal Server Error' });
// }
// });
app.post('/webhook', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
try {
const postData = req.body;
const entityType = postData.data.entity_type;
const updatedMatches = postData.data.updated_matches;
console.log(postData);
if (entityType === 'job') {
for (const match of updatedMatches) {
const chatId = match.student_id;
const jobId = match.entity_id; // Получаем ID вакансии
const messageText = 'Ваше совпадение с вакансией было обновлено. Вот детали вакансии:';
if (!chatId) {
throw new Error('Неправильный Chat ID (student_id) в теле запроса.');
}
// Выполняем GET-запрос для получения данных о вакансии
const response = yield axios_1.default.get(`${process.env.API}jobs/${jobId}`, // Запрашиваем данные о вакансии по её ID
{
headers: {
'X-API-KEY': 'SbRHOVoK97GKCx3Lqx6hKXLbZZJEd0GTGbeglXdpK9PhSB9kpr4eWCsuIIwnD6F2mgpTDlVHFCRbeFmuSfqBVsb12lNwF3P1tmdxiktl7zH9sDS2YK7Pyj2DecCWAZ3n',
},
});
const vacancyData = response.data; // Данные о вакансии
console.log(vacancyData);
// Отправляем вакансию пользователю
yield sendVacancyToUser(chatId, vacancyData);
console.log(`Сообщение с вакансией отправлено пользователю с ID ${chatId}`);
}
}
return res.status(200).json({ status: 'success' });
}
catch (e) {
console.error('Error:', e);
res.status(500).json({ error: 'Произошла ошибка при отправке сообщения' });
}
}));
// Функция для отправки вакансии пользователю
function sendVacancyToUser(chatId, data) {
return __awaiter(this, void 0, void 0, function* () {
yield bot.telegram.sendMessage(chatId, `<b>${data.Job_name}</b>\n\n` +
`<b>Компания:</b> ${data.Company_name}\n` +
`<b>Заработная плата:</b> ${data.Salary} руб/мес\n` +
`<b>Контактные данные:</b> ${data.Email}\n\n` +
`<b>Требования к кандидату:</b>\n` +
` - ${data.Year} курс\n` +
` - Опыт работы по специальности: ${data.Qualification}\n` +
` - Soft skills: ${data.Soft_skills}\n` +
`<b>Обязанности:</b>\n` +
`${data.Responsibilities}`, {
parse_mode: 'HTML', // Используем HTML для форматирования текста
reply_markup: {
inline_keyboard: [
[
{
text: 'Сохранить вакансию',
callback_data: `savevacancy+${data.JobID}`,
},
],
],
},
});
});
}
// Обработчик для получения файла резюме
const stage = new telegraf_1.Scenes.Stage([resumeScene]);
bot.use((0, telegraf_1.session)());
bot.use(stage.middleware());
bot.use(menuScenes_1.menuSceneMiddleware);
(0, events_1.events)(bot);
(0, accept_1.accept)(bot);
bot.action('uploadresume', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
ctx.scene.enter('resumeScene');
ctx.answerCbQuery();
}));
(0, savevacansy_1.saveVacansy)(bot);
bot
.launch({
webhook: {
domain: process.env.DOMAIN || '',
port: parseInt(process.env.HOOKPORT || ''),
},
})
.then(() => console.log('Webhook bot listening on port', parseInt(process.env.HOOKPORT || '')));
// bot.launch().then(() => {
// console.log('Бот запущен');
// });
app.listen(process.env.PORT, () => {
console.log(`Server is running at http://localhost:${process.env.PORT}`);
});