Package: hh-applicant-tool
HH Applicant ToolУтилита для автоматизации действий на HH.RU таких как рассылка откликов на подходящие вакансии и обновление всех резюме.Системные требования:socatpython >= 3.10Нужную версию можно поставить через asdf/pyenv, а вот socat придется доставить.Данная утилита не может работать от root. Я не планирую добавлять поддержку Windows, но никто не мешает вам ее реализовать.Предыстория.Был один знакомый знакомого, который работал хером. Этот чувак не заморачивался с чтением резюме, а тупо скриптами рассылал предложения о работе... Бывают, конечно, филологини, которые не могут отлчить Java от JavaScript, но я думаю, что в значительном числе случаев, тут имеют место такие вот рассылки... И я перенял эту порочную практику. Мне уже просто лень читать весь этот бред, что пишут в описании вакансий. Там стандартное ООП, алгоритмы и прочая хуета... Вроде все подходят, а вроде хз — все не мое. Поэтому тупло спамлю в надежде на идеальную работу. Долгое время (пару недель в октябре 2022) я делал массовые заявки с помощью консоли браузера:$$('[data-qa="vacancy-serp__vacancy_response"]').forEach((el)=>el.click());И оно работает, хоть и не идеально. Я даже пробовал автоматизировать рассылки черезp[yu]ppeeter, пока не прочиталдокументацию. И не обнаружил, чтоAPI(интерфейс) содержит все необходимые мне методы. Headhunter позволяет создать свое приложение, но там ручная модерация, и наврядли кто-то разрешит мне создать приложение для спама заявками. Ядекомпилировалофициальное приложение дляAndroidи получилCLIENT_IDиCLIENT_SECRET, необходимые для работы черезAPI.Установка:# Через pypi# Можно использовать и обычный pip$pipxinstallhh-applicant-tool# Если хочется использовать самую последнюю версию, то можно установить ее через git$pipxinstallgit+https://github.com/s3rgeym/hh-applicant-toolИспользование:$hh-applicant-tool[GLOBAL_FLAGS][OPERATION[OPERATION_FLAGS]]# Справка по глобальным флагам и список операций$hh-applicant-tool-h# Справка по операции$hh-applicant-toolapply-similar-h# Добавляем обработчик$hh-applicant-tooladd-handler# Авторизуемся$hh-applicant-toolauthorize# Рассылаем заявки$hh-applicant-toolapply-similar# Поднимаем резюме$hh-applicant-toolupdate-resumes# Чистим заявки и баним за отказы говноконторы, нанявших на работу филолохинь,# астралохинь и прочих 3.14дарасов по блату, считающих, что погроммистом может# быть только ДОЦЕНТ МАТЕМАТИЧЕСКИХ НАУК 🤡$hh-applicant-toolclear-negotiations--blacklist-discardМожно вызвать любой метод API:$hh-applicant-toolcall-api/employerstext="IT"only_with_vacancies=true|jq-r'.items[].alternate_url'https://hh.ru/employer/1966364
https://hh.ru/employer/4679771
https://hh.ru/employer/8932785
https://hh.ru/employer/9451699
https://hh.ru/employer/766478
https://hh.ru/employer/4168187
https://hh.ru/employer/9274777
https://hh.ru/employer/1763330
https://hh.ru/employer/5926815
https://hh.ru/employer/1592535
https://hh.ru/employer/9627641
https://hh.ru/employer/4073857
https://hh.ru/employer/2667859
https://hh.ru/employer/4053700
https://hh.ru/employer/5190600
https://hh.ru/employer/607484
https://hh.ru/employer/9386615
https://hh.ru/employer/80660
https://hh.ru/employer/6078902
https://hh.ru/employer/1918903Данная возможность полезна для написания Bash-скриптов.Глобальные флаги:-vиспользуется для вывода отладочной информации. Два таких флага, например, выводят запросы кAPI.-c <path>можно создать путь до конфига. С помощью этого флага можно одновременно использовать несколько профилей.ОперацияОписаниеadd-handlerДобавляет обработчик протоколаhhandroidauthorizeОткрывает сайт hh.ru для авторизации и перехватывает перенаправление наhhadnroid://oauthresponsewhoamiВыводит информацию об авторизованном пользователеlist-resumesСписок резюмеupdate-resumesОбновить все резюме. Аналогично нажатию кнопки «Обновить дату».apply-similarОткликнуться на все подходящие вакансии. Лимит = 200 в деньclear-negotiationsУдаляет отказы и отменяет заявки, которые долго висятcall-apiВызов произвольного метода API с вводом результата.refresh-tokenОбновляет access_token.Для начала нужно добавить обработчик протоколаhhandroid, который используется Android-приложением для усложнения жизни честным автоматизаторам:$hh-applicant-tool-vvadd-handler[I]saved/home/sergey/.local/share/applications/hhandroid.desktop
✅Обработчикдобавлен!Авторизуемся:$hh-applicant-tool-vvauthorize
Пробуемоткрытьвбраузере:https://hh.ru/oauth/authorize?client_id=HIOMIAS39CA9DICTA7JIO64LQKQJF5AGIK74G9ITJKLNEDAOH5FHS5G1JI7FOEGD&response_type=code
Авторизуйтесьинажмите<Подтвердить>[I]🚀ЗапускаемTCP-серверислушаемunix:///tmp/hhandroid.sock
Gtk-Message:20:52:59.280:Failedtoloadmodule"canberra-gtk-module"Gtk-Message:20:52:59.975:Failedtoloadmodule"canberra-gtk-module"[54:54:0305/205300.038812:ERROR:gl_factory.cc(128)]RequestedGLimplementation(gl=desktop-gl,angle=none)notfoundinallowedimplementations:[(gl=egl-angle,angle=default),(gl=egl-gles2,angle=none),(gl=egl-angle,angle=swiftshader)].[54:54:0305/205300.041723:ERROR:viz_main_impl.cc(186)]ExitingGPUprocessduetoerrorsduringinitialization
Openinginexistingbrowsersession.[D]hhandroid://oauthresponse?code=99Q9G1RII75D8R2FTU06BF2FDNI7JF16MGBIB4OEQ973819OOJI90S69I1CL9U96[D]200POSThttps://hh.ru/oauth/token[D]Сохраняемтокен
🔓Авторизацияпрошлауспешно!Тут надо выбиратьOpen xdg-open.После смотрим в терминал и если видим сообщение об успехе, закрываем вкладку.В случае успешной авторизации токены будут сохранены~/.config/hh-applicant-tool/config.json:{"token":{"access_token":"...","created_at":1678151427,"expires_in":1209599,"refresh_token":"...","token_type":"bearer"}}Через этот файл можно задать кастомныйuser_agent:{"user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0"}Проверка авторизации:$hh-applicant-toolwhoami{"auth_type":"applicant","counters":{"new_resume_views":1488,"resumes_count":1,"unread_negotiations":228},"email":"vasya.pupkin@gmail.com","employer":null,"first_name":"Вася","id":"1234567890","is_admin":false,"is_anonymous":false,"is_applicant":true,"is_application":false,"is_employer":false,"is_in_search":true,"last_name":"Пупкин","manager":null,"mid_name":null,"middle_name":null,"negotiations_url":"https://api.hh.ru/negotiations","personal_manager":null,"phone":"79012345678","profile_videos":{"items":[]},"resumes_url":"https://api.hh.ru/resumes/mine"}Далее идут заметки для разработчиков...Токен выдается на две недели:Python3.10.9(main,Dec192022,17:35:49)[GCC12.2.0]onlinuxType"help","copyright","credits"or"license"formoreinformation.>>>fromdatetimeimportdatetime,timedelta>>>datetime.now()+timedelta(seconds=1209599)datetime.datetime(2023,3,23,6,36,15,596290)>>>После нужно вызватьrefresh-token.При авторизации можно указатьredirect_uri, но любые адреса кроме того, что с протоколомhhandroid, будут приводить к ошибке. Поэтому и нужно добавление обработчика кастомного протокола. При котором создается desktop-файл, где в секцииExecвсего пару команд для того чтобы записать полученный uri в сокет. TCP-сервер, который запускается при авторизации, как раз слушает этот сокет... Использование АВТОРИЗАЦИИ ДЛЯ САЙТОВ в мобильном приложении выглядит странной, так как десктопные и мобильные приложения обычно авторизуются напрямую, но у чуваков свое понимание не только протокола OAuth...Удаление хвостов:rm-rf~/.config/hh-applicant-tool
rm-f~/.local/share/applications/hhandroid.desktopУтилита использует систему плагинов. Все они лежат вoperations. Модули расположенные там автоматически добавляются как доступные операции. За основу для своего плагина можно взятьwhoami.py.Отдельные замечания у меня к API HH. Оно пиздец какое кривое. Например, при создании заявки возвращается пустой ответ либо редирект, хотя по логике должен возвраться созданный объект. Так же в ответах сервера нетContent-Length. Из-за этого нельзя узнать есть тело у ответа сервера нужно его пробовать прочитать. Я так понял там какой-то прокси оборачивает все запросы и отдает всегдаTransfer-Encoding: Chunked. А еще он возвращает 502 ошибку, когда бекенд на Java падает либо долго отвечает (таймаут)? А вотязык запросовмне понравился. Можно что-то типа этого использоватьNOT (!ID:123 OR !ID:456 OR !ID:789)что бы отсеить какие-то вакансии.