From 23899a377a032b27220673288d6dc18df5b7d56c Mon Sep 17 00:00:00 2001 From: Oscar Date: Wed, 27 May 2026 14:40:26 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20refactor(bot-commands):=20=D0=B8?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE?= =?UTF-8?q?=D1=88=D0=B8=D0=B1=D0=BA=D0=B0=20=D0=BE=D1=82=D0=B2=D0=B5=D1=82?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B0=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8F,=20=D1=82=D0=B5=D0=BA=D1=81=D1=82=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B1ira=D0=B5=D1=82=D1=81=D1=8F=20=D0=BFo=20LIMIT?= =?UTF-8?q?280=E4=B8=AA=20=D1=81=D0=B8=D0=BC=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hh/bot-commands.ts | 18 +++++++++++------- src/hh/scraper.ts | 19 +++++++++++++++---- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/hh/bot-commands.ts b/src/hh/bot-commands.ts index fb9e4d5..d93907e 100644 --- a/src/hh/bot-commands.ts +++ b/src/hh/bot-commands.ts @@ -160,7 +160,7 @@ export function registerHHCommands() { const messageId = query.message.message_id const state = getState(chatId) - await bot.answerCallbackQuery(query.id) + await bot.answerCallbackQuery(query.id).catch(() => {}) const user = await prisma.user.findUnique({ where: { telegramId: chatId }, @@ -205,10 +205,14 @@ export function registerHHCommands() { result.errors.forEach(v => lines.push(`• ${v.title} — ${v.message}`)) } - await bot.sendMessage(chatId, lines.join('\n'), { - parse_mode: 'HTML', - disable_web_page_preview: true, - }) + const fullText = lines.join('\n') + const LIMIT = 4000 + for (let i = 0; i < fullText.length; i += LIMIT) { + await bot.sendMessage(chatId, fullText.slice(i, i + LIMIT), { + parse_mode: 'HTML', + disable_web_page_preview: true, + }) + } } await showMenu(chatId) }) @@ -234,12 +238,12 @@ export function registerHHCommands() { await showResult(chatId, messageId, '📋 Резюме не найдено.\n\nВыбери резюме через кнопку 📄 Выбрать резюме.') break } - const MAX = 10000 + const MAX = 3500 const text = resume.data.length > MAX ? `${resume.data.slice(0, MAX)}\n\n… (текст обрезан)` : resume.data await bot.editMessageText( - `📋 Твоё резюме\n
${escapeHtml(text)}
`, + `📋 Твоё резюме:\n ${resume.title}\n
${escapeHtml(text)}
`, { chat_id: chatId, message_id: messageId, diff --git a/src/hh/scraper.ts b/src/hh/scraper.ts index ef5b61d..d5d7df8 100644 --- a/src/hh/scraper.ts +++ b/src/hh/scraper.ts @@ -141,6 +141,7 @@ export async function saveResume(chatId: number, resumeItem: ResumeListItem): Pr let resume: string | undefined try { resume = await page.locator('.resume').innerText() + await prisma.resume.deleteMany({ where: { telegramId: chatId, NOT: { id } } }) await prisma.resume.upsert({ where: { id }, create: { data: resume, id, telegramId: chatId, title }, @@ -238,10 +239,20 @@ export async function applyToJobs( console.log('Ожидаемое резюме из БД:', resume.title) if (currentResumeTitle !== resume.title) { - // TODO: добавить логику смены резюме console.log('Резюме не совпадает, нужно сменить') - currentResumeEl?.focus() - currentResumeEl?.click() + await currentResumeEl?.click() + await page.waitForSelector('[data-qa="magritte-select-option-list"]', { timeout: 5000 }) + await page.pause() + const options = await page.$$('label[role="option"]') + for (const option of options) { + const titleEl = await option.$('[data-qa="resume-title"] [data-qa="cell-text-content"]') + const title = (await titleEl?.innerText())?.trim() + if (title === resume.title) { + await option.click() + await page.waitForTimeout(randomDelay()) + break + } + } } await page.pause() @@ -252,8 +263,8 @@ export async function applyToJobs( await addLetter?.click() } - await keep(`✅ ${vacancy.title}\n\n${letter}`) const letter = await letterPromise + await keep(`✅ ${vacancy.title}\n\n${letter}`) if (letter) { const letterInput = await page.$('[data-qa="vacancy-response-popup-form-letter-input"]')