-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
1 lines (1 loc) · 17 KB
/
Copy pathscript.js
File metadata and controls
1 lines (1 loc) · 17 KB
1
(()=>{"use strict";const e={naviItems:".supernova-navi-item.supernova-navi-item_lvl-2",blacklist:"[data-qa=vacancy__blacklist-show-add]",addBlacklist:"[data-qa=vacancy__blacklist-menu-add-vacancy]",pagerNext:'[data-qa="pager-next"]',modalOverlay:'[data-qa="modal-overlay"]',alertBox:'[data-qa="magritte-alert"]',countryConfirmBtn:'[data-qa="relocation-warning-confirm"]',chatikCloseBtn:'[data-qa="chatik-close-chatik"]',vacancyCards:'[data-qa="vacancy-serp__vacancy"]',vacancyCard:'[data-qa="vacancy-response-link-top"]',vacancyTitle:"[data-qa='serp-item__title']",addCoverLetter:'[data-qa="vacancy-response-letter-toggle-text"]',coverLetterInput:"#cover-letter textarea",coverLetterInputAlt:'form[id^="cover-letter-"] textarea[name="text"], [data-qa="textarea-native-wrapper"] textarea',respondBtn:'[data-qa="vacancy-serp__vacancy_response"]',sendBtn:'[data-qa="vacancy-response-letter-submit"]',vacancyTitlePopup:'[data-qa="title-description"]',resumeDropdown:'[data-qa="resume-title"]',addCoverLetterPopup:'[data-qa="add-cover-letter"]',coverLetterInputPopup:'[data-qa="vacancy-response-popup-form-letter-input"]',respondBtnPopup:'[data-qa="vacancy-response-submit-popup"]'},t=e=>new Promise((t=>setTimeout(t,e)));let n=!1;function a(){return n}function r(e){n=e}const o="hh.ru/vacancy",i=["hh.ru/vacancies","hh.ru/search/vacancy"],s={coverLetter_1:"Добрый день! \n\nМеня заинтересовала предложенная Вами вакансия {#vacancyName}. Ознакомившись с перечнем требований к кандидатам, пришел к выводу, что мой опыт работы позволяют мне претендовать на данную должность. \n\nОбладаю высоким уровнем фронтенд-разработки, свободно говорю по-английски. В работе ответствен, пунктуален и коммуникабелен.\n\nБуду с нетерпением ждать ответа и возможности обсудить условия работы и взаимные ожидания на собеседовании. Спасибо, что уделили время. \n\nКонтактные данные прилагаю.",coverLetter_2:".",coverLetter_3:"",coverLetter_4:"",coverLetter_5:""};function c(e,t=""){if([window.HTMLInputElement,window.HTMLSelectElement,window.HTMLTextAreaElement].includes(e?.__proto__?.constructor)){Object.getOwnPropertyDescriptor(e.__proto__,"value").set.call(e,t);const n=new Event("input",{bubbles:!0});e.dispatchEvent(n)}}const l="hhAgentSettings",u={resumeSelector:'[data-qa="magritte-select-option-ВАШ_ID_РЕЗЮМЕ"]',coverLetter:"coverLetter_1",delayMs:1500,aiApiKey:"",aiBaseUrl:"https://neuroapi.host/v1",aiModel:"gpt-4o-mini",aiProfile:"",aiLanguage:"ru",resumeAutoRaise:!1,resumeAutoRaiseIntervalHours:4,resumeRaiseUrl:"",resumeAutoOpen:!1,resumeLastRaisedAt:0};function d(e){const t={...u,...e||{}},n=Number(t.delayMs),a=Number(t.resumeAutoRaiseIntervalHours);return{...t,delayMs:Number.isFinite(n)&&n>0?n:u.delayMs,resumeAutoRaiseIntervalHours:Number.isFinite(a)&&a>0?a:u.resumeAutoRaiseIntervalHours}}function p(){try{const e=localStorage.getItem(l);return e?d(JSON.parse(e)):d()}catch(e){return console.warn("HH Agent: failed to parse settings, using defaults.",e),d()}}function h(e){const t=d({...p(),...e||{}});return localStorage.setItem(l,JSON.stringify(t)),t}function m(){return p().delayMs}function g(){return p().coverLetter}function y(){return p().resumeSelector}function v(e,t,n){const a=[];return a.push(`Write a personalized cover letter for the vacancy: "${e}".`),t&&a.push(`Candidate profile: ${t}`),a.push("Length: 5-9 sentences."),a.push("Mention why this role is a fit and highlight relevant skills."),a.push("Do not include placeholders or markdown."),n&&a.push(`Language: ${n}.`),a.join(" ")}async function b(t,n){const a=document.querySelector(e.coverLetterInput)||document.querySelector(e.coverLetterInputAlt)||document.querySelector(e.coverLetterInputPopup);if(!a)return;const r=n||"";if("ai"===t){c(a,"Генерирую сопроводительное письмо...");try{c(a,await async function(e){const{apiKey:t,baseUrl:n,model:a,profile:r,language:o}=function(){const e=p();return{apiKey:e.aiApiKey,baseUrl:e.aiBaseUrl,model:e.aiModel,profile:e.aiProfile,language:e.aiLanguage}}();if(!t)throw new Error("AI API key is not set.");const i=`${n.replace(/\/$/,"")}/chat/completions`,s={model:a,messages:[{role:"system",content:"You write short, professional cover letters for job applications. Keep it concise, polite, and specific."},{role:"user",content:v(e,r,o)}],temperature:.6},c=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(s)});if(!c.ok){const e=await c.text();throw new Error(`AI request failed (${c.status}): ${e}`)}const l=await c.json(),u=l?.choices?.[0]?.message?.content?.trim();if(!u)throw new Error("AI returned an empty response.");return u}(r))}catch(e){console.error("AI cover letter failed:",e),c(a,"Не удалось сгенерировать письмо. Проверьте API ключ и модель.")}return}const o=s[t];o&&c(a,o.replace("{#vacancyName}",r))}async function f(){document.querySelector(e.countryConfirmBtn)?.click()}async function x(){const n=document.querySelector(e.alertBox),a=n?.nextElementSibling?.querySelectorAll("button");a?.[1]?.click(),await t(m())}async function w(n){const a=document.querySelector(e.addCoverLetter);a?.click(),await t(m());const r=document.querySelector(e.sendBtn);await b(g(),n),r?.click(),await t(m()),document.querySelector(e.chatikCloseBtn)?.click()}async function A(n){const a=document.querySelector(e.respondBtnPopup);await async function(){const n=document.querySelector(e.vacancyTitlePopup),a=document.querySelector(e.resumeDropdown),r=document.querySelector(e.addCoverLetterPopup);if(a){a.click(),await t(m());const e=y();if(e){const t=document.querySelector(e);t?.click()}}r?.click()||n?.click()}(),await t(m()),await b(g(),n),a?.click(),await t(m())}async function q(){const n=Array.from(document.querySelectorAll('[data-action="submit-responses"]')),s=e=>n.forEach((t=>t.textContent=e));if(a())return r(!1),s("Отправить отклики"),void console.log("⏹️ Отправка откликов остановлена");r(!0),s("Остановить отправку"),console.log("▶️ Начата отправка откликов");try{await async function(){const n=window.location.href,r=o,s=i;n.includes(r)?await async function(){const t=document.querySelector(e.singleVacancy);t&&(t.click(),await w())}():s.some((e=>n.includes(e)))&&(await async function(){const n=document.querySelectorAll(e.vacancyCards);if(n.length)for(const r of n){if(!a())break;r.scrollIntoView({behavior:"smooth",block:"center"}),r.style.boxShadow="0 0 8px #0059b3";const n=r.querySelector(e.vacancyTitle)?.innerText,o=r.querySelector(e.respondBtn),i=(o?.innerText||o?.getAttribute("aria-label")||"").toLowerCase().replace(/\s+/g," ").trim(),s=i.includes("откликнуться")||i.includes("respond"),c=o?.disabled||"true"===o?.getAttribute("aria-disabled");o&&s&&!c&&(o.click(),await t(m()),await f(),await x(),document.querySelector(e.modalOverlay)?await A(n):await w(n)),r.style.boxShadow=""}}(),a()&&function(){const t=document.querySelector(e.pagerNext);t&&(sessionStorage.setItem("resumeAfterNextPage","true"),t.click())}())}()}catch(e){console.error("Ошибка при отправке откликов:",e)}finally{r(!1),s("Отправить отклики"),console.log("✅ Отправка откликов завершена")}}function S(e,t="div",n="Помощь"){return Array.from(e.querySelectorAll(t)).find((e=>e.textContent.trim()===n&&0===e.children.length))}const L="hh-agent-panel",k="hh-agent-panel-style";function I(e,t){const n=document.createElement("option");return n.value=e,n.textContent=t,n}const E=/поднять|обновить|raise/i,C="hhAgentAutoRaiseOpen";!async function(){await async function(){await t(m());const n=document.querySelectorAll(e.naviItems);if(!n?.length||!n[4])return;const a=n[4].cloneNode(!0),r=S(a);if(!r)return;r.setAttribute("data-action","submit-responses"),r.textContent="Отправить отклики",n[4].insertAdjacentElement("afterend",a);const o=a.querySelector('[data-action="submit-responses"]');o?.addEventListener("click",q)}(),await async function(){const t=document.querySelectorAll(e.naviItems);if(!t?.length||!t[4]||!t[5])return;const n=t[4].cloneNode(!0),a=S(n);a&&(a.textContent="Поддержать автора",n.removeAttribute("href"),n.style.cursor="pointer",n.addEventListener("click",(()=>{window.open("https://boosty.to/ia-stepanov/donate","_blank")})),t[5].insertAdjacentElement("afterend",n))}(),function(){if(document.getElementById(L))return;!function(){if(document.getElementById(k))return;const e=document.createElement("style");e.id=k,e.textContent=`\n #${L} {\n position: fixed;\n right: 16px;\n bottom: 16px;\n z-index: 999999;\n width: 320px;\n background: #0f172a;\n color: #e2e8f0;\n border: 1px solid rgba(148, 163, 184, 0.2);\n border-radius: 10px;\n box-shadow: 0 10px 30px rgba(15, 23, 42, 0.35);\n font-family: Arial, sans-serif;\n }\n #${L} * { box-sizing: border-box; }\n #${L} .hh-agent-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n background: #1e293b;\n border-bottom: 1px solid rgba(148, 163, 184, 0.2);\n border-radius: 10px 10px 0 0;\n font-size: 14px;\n font-weight: 600;\n }\n #${L} .hh-agent-body { padding: 10px 12px; display: block; }\n #${L}.is-collapsed .hh-agent-body { display: none; }\n #${L} label { display: block; font-size: 12px; margin: 8px 0 4px; color: #cbd5f5; }\n #${L} input,\n #${L} select,\n #${L} textarea {\n width: 100%;\n padding: 6px 8px;\n border-radius: 6px;\n border: 1px solid rgba(148, 163, 184, 0.3);\n background: #0b1220;\n color: #e2e8f0;\n font-size: 12px;\n }\n #${L} textarea { min-height: 70px; resize: vertical; }\n #${L} .hh-agent-row { display: flex; gap: 6px; }\n #${L} .hh-agent-row > * { flex: 1; }\n #${L} .hh-agent-button {\n padding: 6px 8px;\n border-radius: 6px;\n border: 1px solid rgba(148, 163, 184, 0.4);\n background: #1e40af;\n color: #e2e8f0;\n font-size: 12px;\n cursor: pointer;\n }\n #${L} .hh-agent-button.secondary {\n background: #0f172a;\n }\n #${L} .hh-agent-small { font-size: 11px; color: #94a3b8; margin-top: 4px; }\n #${L} .hh-agent-inline {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n `,document.head.appendChild(e)}();const e=document.createElement("div");e.id=L,e.innerHTML='\n <div class="hh-agent-header">\n <span>HH Agent</span>\n <button type="button" class="hh-agent-button secondary" data-action="toggle">Скрыть</button>\n </div>\n <div class="hh-agent-body">\n <button type="button" class="hh-agent-button" data-action="submit-responses">Отправить отклики</button>\n\n <label>Резюме (список)</label>\n <div class="hh-agent-row">\n <select id="hh-agent-resume-select"></select>\n <button type="button" class="hh-agent-button secondary" data-action="refresh-resumes">Обновить</button>\n </div>\n <label>Селектор резюме</label>\n <input id="hh-agent-resume-selector" type="text" placeholder=\'[data-qa="magritte-select-option-..."]\' />\n <div class="hh-agent-small">Откройте отклик и раскройте список резюме, затем нажмите «Обновить».</div>\n\n <label>Задержка (мс)</label>\n <input id="hh-agent-delay" type="number" min="300" step="100" />\n\n <label>Сопроводительное письмо</label>\n <select id="hh-agent-cover-letter"></select>\n\n <label>AI API ключ (NeuroAPI)</label>\n <input id="hh-agent-ai-key" type="password" placeholder="sk-..." />\n\n <label>AI модель</label>\n <input id="hh-agent-ai-model" type="text" placeholder="gpt-4o-mini" />\n\n <label>AI профиль кандидата</label>\n <textarea id="hh-agent-ai-profile" placeholder="Коротко о себе: навыки, опыт, стек."></textarea>\n\n <div class="hh-agent-row">\n <div>\n <label>Язык AI письма</label>\n <select id="hh-agent-ai-language">\n <option value="ru">Русский</option>\n <option value="en">English</option>\n </select>\n </div>\n <div>\n <label>AI base URL</label>\n <input id="hh-agent-ai-base" type="text" placeholder="https://neuroapi.host/v1" />\n </div>\n </div>\n\n <label class="hh-agent-inline">\n <input id="hh-agent-auto-raise" type="checkbox" />\n Авто-поднятие резюме\n </label>\n\n <label>Интервал поднятия (часы)</label>\n <input id="hh-agent-auto-raise-interval" type="number" min="1" step="1" />\n\n <label>URL страницы резюме</label>\n <input id="hh-agent-raise-url" type="text" placeholder="https://hh.ru/resume/..." />\n\n <label class="hh-agent-inline">\n <input id="hh-agent-auto-open" type="checkbox" />\n Авто-открывать страницу резюме\n </label>\n </div>\n ',document.body.appendChild(e);const t=e.querySelector('[data-action="toggle"]');t.addEventListener("click",(()=>{e.classList.toggle("is-collapsed"),t.textContent=e.classList.contains("is-collapsed")?"Показать":"Скрыть"})),e.querySelector('[data-action="submit-responses"]').addEventListener("click",q);const n=e.querySelector("#hh-agent-resume-select"),a=e.querySelector("#hh-agent-resume-selector"),r=e.querySelector("#hh-agent-delay"),o=e.querySelector("#hh-agent-cover-letter"),i=e.querySelector("#hh-agent-ai-key"),c=e.querySelector("#hh-agent-ai-model"),l=e.querySelector("#hh-agent-ai-profile"),u=e.querySelector("#hh-agent-ai-language"),d=e.querySelector("#hh-agent-ai-base"),v=e.querySelector("#hh-agent-auto-raise"),b=e.querySelector("#hh-agent-auto-raise-interval"),f=e.querySelector("#hh-agent-raise-url"),x=e.querySelector("#hh-agent-auto-open"),w=p();function A(){const e=Array.from(document.querySelectorAll('[data-qa^="magritte-select-option-"]')).map((e=>({value:e.getAttribute("data-qa"),label:(e.textContent||"").trim()||e.getAttribute("data-qa")})));if(n.innerHTML="",!e.length)return void n.appendChild(I("","Нет данных"));n.appendChild(I("","Выберите резюме")),e.forEach((e=>n.appendChild(I(e.value,e.label))));const t=y().match(/\[data-qa="([^"]+)"\]/);t&&e.some((e=>e.value===t[1]))&&(n.value=t[1])}a.value=y(),r.value=m(),i.value=w.aiApiKey||"",c.value=w.aiModel||"",l.value=w.aiProfile||"",u.value=w.aiLanguage||"ru",d.value=w.aiBaseUrl||"",v.checked=!!w.resumeAutoRaise,b.value=w.resumeAutoRaiseIntervalHours||4,f.value=w.resumeRaiseUrl||"",x.checked=!!w.resumeAutoOpen,[...Object.keys(s),"ai"].forEach((e=>{o.appendChild(I(e,"ai"===e?"AI (NeuroAPI)":e))})),o.value=g(),A(),e.querySelector('[data-action="refresh-resumes"]').addEventListener("click",A),n.addEventListener("change",(()=>{if(!n.value)return;const e=`[data-qa="${n.value}"]`;a.value=e,h({resumeSelector:e})})),a.addEventListener("change",(()=>h({resumeSelector:a.value.trim()}))),r.addEventListener("change",(()=>h({delayMs:r.value}))),o.addEventListener("change",(()=>h({coverLetter:o.value}))),i.addEventListener("change",(()=>h({aiApiKey:i.value.trim()}))),c.addEventListener("change",(()=>h({aiModel:c.value.trim()}))),l.addEventListener("change",(()=>h({aiProfile:l.value.trim()}))),u.addEventListener("change",(()=>h({aiLanguage:u.value}))),d.addEventListener("change",(()=>h({aiBaseUrl:d.value.trim()}))),v.addEventListener("change",(()=>h({resumeAutoRaise:v.checked}))),b.addEventListener("change",(()=>h({resumeAutoRaiseIntervalHours:b.value}))),f.addEventListener("change",(()=>h({resumeRaiseUrl:f.value.trim()}))),x.addEventListener("change",(()=>h({resumeAutoOpen:x.checked})))}(),await async function(){const e=function(){const e=p();return{enabled:e.resumeAutoRaise,intervalHours:e.resumeAutoRaiseIntervalHours,raiseUrl:e.resumeRaiseUrl,autoOpen:e.resumeAutoOpen,lastRaisedAt:e.resumeLastRaisedAt}}();if(!e.enabled)return;const n=Date.now(),a=60*e.intervalHours*60*1e3;if(e.lastRaisedAt&&n-e.lastRaisedAt<a)return;if(!/resume/i.test(window.location.pathname))return void(e.autoOpen&&e.raiseUrl&&!sessionStorage.getItem(C)&&(sessionStorage.setItem(C,"true"),window.open(e.raiseUrl,"_blank")));await t(1500);const r=Array.from(document.querySelectorAll("button, a")).find((e=>{const t=(e.textContent||"").trim().toLowerCase();return t&&E.test(t)&&/резюм|поиск/.test(t)}));var o;!r||(o=r).disabled||"true"===o.getAttribute("aria-disabled")||o.classList.contains("disabled")||(r.click(),h({resumeLastRaisedAt:n}),sessionStorage.removeItem(C))}()}()})();