diff --git a/packages/geek-auto-start-chat-with-boss/index.mjs b/packages/geek-auto-start-chat-with-boss/index.mjs index 3a6256f..2b3f291 100644 --- a/packages/geek-auto-start-chat-with-boss/index.mjs +++ b/packages/geek-auto-start-chat-with-boss/index.mjs @@ -80,6 +80,10 @@ const targetCompanyList = readConfigFile('target-company-list.json').filter(it = const anyCombineRecommendJobFilter = readConfigFile('boss.json').anyCombineRecommendJobFilter const expectJobRegExpStr = readConfigFile('boss.json').expectJobRegExpStr const jobNotMatchStrategy = readConfigFile('boss.json').jobNotMatchStrategy ?? MarkAsNotSuitOp.MARK_AS_NOT_SUIT_ON_BOSS + +const expectCityNotMatchStrategy = readConfigFile('boss.json').expectCityNotMatchStrategy ?? MarkAsNotSuitOp.MARK_AS_NOT_SUIT_ON_BOSS +const expectCityList = readConfigFile('boss.json').expectCityList ?? [] + const markAsNotActiveSelectedTimeRange = (() => { let n = readConfigFile('boss.json').markAsNotActiveSelectedTimeRange if ( @@ -183,6 +187,22 @@ async function markJobAsNotSuitInRecommendPage (reasonCode) { } break } + case MarkAsNotSuitReason.JOB_CITY_NOT_SUIT: { + const bossNotActiveOptionProxy = await chooseReasonDialogProxy.$(`.zp-type-item[title$="城市"]`) + if (bossNotActiveOptionProxy) { + await bossNotActiveOptionProxy.click() + isOptionChosen = true + } else { + const fallbackOptionProxy = (await chooseReasonDialogProxy.$(`.zp-type-item[title="同城距离远"]`)) + ?? (await chooseReasonDialogProxy.$(`.zp-type-item[title="公司不感兴趣"]`)) + ?? (await chooseReasonDialogProxy.$(`.zp-type-item[title="面试过/入职过"]`)) + if (fallbackOptionProxy) { + await fallbackOptionProxy.click() + isOptionChosen = true + } + } + break + } case MarkAsNotSuitReason.JOB_NOT_SUIT: default: { const jobNotSuitOptionProxy = (await chooseReasonDialogProxy.$(`.zp-type-item[title$="职位"]`)) ?? (await chooseReasonDialogProxy.$(`.zp-type-item[title="面试过/入职过"]`)) @@ -514,21 +534,25 @@ async function toRecommendPage (hooks) { let jobListData = await page.evaluate(`document.querySelector('.page-jobs-main')?.__vue__?.jobList`) let hasReachLastPage = false let targetJobIndex = -1 - let targetJobData + let targetJobData, selectedJobData // they show be same; one is from list, another is from detail function getTempTargetJobIndexToCheckDetail () { - return jobListData.findIndex(it => - !blockBossNotNewChat.has(it.encryptBossId) && - !blockBossNotActive.has(it.encryptBossId) && - !blockJobNotSuit.has(it.encryptJobId) && - ( - enableCompanyAllowList ? - [...expectCompanySet].find( - name => it.brandName?.toLowerCase?.()?.includes(name.toLowerCase()) + return jobListData.findIndex(it => { + return !blockBossNotNewChat.has(it.encryptBossId) && + !blockBossNotActive.has(it.encryptBossId) && + !blockJobNotSuit.has(it.encryptJobId) && + ( + ( + enableCompanyAllowList ? + [...expectCompanySet].find( + name => it.brandName?.toLowerCase?.()?.includes(name.toLowerCase()) + ) + : + true + ) || ( + (Array.isArray(expectCityList) && expectCityList.length) ? !expectCityList.includes(it.cityName) : false ) - : - true - ) - ) + ) + }) } continueFind: while (targetJobIndex < 0 && !hasReachLastPage) { // when disable company allow list, we will believe that the first one in the list is your expect job. @@ -609,6 +633,7 @@ async function toRecommendPage (hooks) { await sleepWithRandomDelay(2000) } targetJobData = await page.evaluate('document.querySelector(".job-detail-box").__vue__.data') + selectedJobData = await page.evaluate('document.querySelector(".page-jobs-main").__vue__.currentJob') // save the job detail info await hooks.jobDetailIsGetFromRecommendList?.promise(targetJobData) @@ -658,6 +683,44 @@ async function toRecommendPage (hooks) { } continue continueFind } + if ( + (Array.isArray(expectCityList) && expectCityList.length) && !expectCityList.includes(selectedJobData.cityName) + ) { + blockJobNotSuit.add(targetJobData.jobInfo.encryptId) + if (expectCityNotMatchStrategy === MarkAsNotSuitOp.MARK_AS_NOT_SUIT_ON_BOSS) { + try { + const { chosenReasonInUi } = await markJobAsNotSuitInRecommendPage(MarkAsNotSuitReason.JOB_CITY_NOT_SUIT) + await hooks.jobMarkedAsNotSuit.promise( + targetJobData, + { + markFrom: ChatStartupFrom.AutoFromRecommendList, + markReason: MarkAsNotSuitReason.JOB_NOT_SUIT, + extInfo: { + bossActiveTimeDesc: targetJobData.bossInfo.activeTimeDesc, + chosenReasonInUi + }, + markOp: MarkAsNotSuitOp.MARK_AS_NOT_SUIT_ON_BOSS + } + ) + } catch { + } + } + else if (expectCityNotMatchStrategy === MarkAsNotSuitOp.MARK_AS_NOT_SUIT_ON_LOCAL) { + try { + await hooks.jobMarkedAsNotSuit.promise( + targetJobData, + { + markFrom: ChatStartupFrom.AutoFromRecommendList, + markReason: MarkAsNotSuitReason.JOB_NOT_SUIT, + extInfo: null, + markOp: MarkAsNotSuitOp.MARK_AS_NOT_SUIT_ON_LOCAL + } + ) + } catch { + } + } + continue continueFind + } if ( !testIfJobTitleOrDescriptionSuit(targetJobData.jobInfo) ) { @@ -696,6 +759,15 @@ async function toRecommendPage (hooks) { } continue continueFind } + // test company again - when allow list not include target company, just skip + if ( + enableCompanyAllowList && ![...expectCompanySet].find( + name => selectedJobData.brandName?.toLowerCase?.()?.includes(name.toLowerCase()) + ) + ) { + // just skip + continue continueFind + } const startChatButtonInnerHTML = await page.evaluate('document.querySelector(".job-detail-box .op-btn.op-btn-chat")?.innerHTML.trim()') if (startChatButtonInnerHTML !== '立即沟通') { blockBossNotNewChat.add(targetJobData.jobInfo.encryptUserId) diff --git a/packages/sqlite-plugin/src/enums.ts b/packages/sqlite-plugin/src/enums.ts index 53df1da..3c59f8d 100644 --- a/packages/sqlite-plugin/src/enums.ts +++ b/packages/sqlite-plugin/src/enums.ts @@ -3,6 +3,7 @@ export enum MarkAsNotSuitReason { BOSS_INACTIVE = 1, USER_MANUAL_OPERATION_WITH_UNKNOWN_REASON = 2, JOB_NOT_SUIT = 3, + JOB_CITY_NOT_SUIT = 4, } export enum MarkAsNotSuitOp {