copied the code from the working repo
This commit is contained in:
375
mtucijobsbot/dist/index.js
vendored
Normal file
375
mtucijobsbot/dist/index.js
vendored
Normal file
@@ -0,0 +1,375 @@
|
||||
"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}`);
|
||||
});
|
||||
Reference in New Issue
Block a user