WIP: add the logic to save job mark as not suit to db TODO: fix issue about retrieving and showing items

This commit is contained in:
geekgeekrun
2024-10-20 11:25:41 +08:00
parent 7f0ae45758
commit 6b28a9d0ed
7 changed files with 106 additions and 7 deletions

View File

@@ -0,0 +1,9 @@
{
"3": "学历不匹配",
"5": "其他反馈",
"13": "同城距离远",
"30": "公司不感兴趣",
"34": "BOSS活跃度低",
"41": "职位停招/招满",
"42": "面试过/入职过"
}

View File

@@ -16,6 +16,7 @@ import { calculateTotalCombinations, combineFiltersWithConstraintsGenerator } fr
import { default as jobFilterConditions } from './internal-config/job-filter-conditions-20241002.json'
import { default as rawIndustryFilterExemption } from './internal-config/job-filter-industry-filter-exemption-20241002.json'
import { ChatStartupFrom } from '@geekgeekrun/sqlite-plugin/dist/entity/ChatStartupLog'
import { MarkAsNotSuitReason } from '@geekgeekrun/sqlite-plugin/dist/entity/MarkAsNotSuitLog'
const jobFilterConditionsMapByCode = {}
Object.values(jobFilterConditions).forEach(arr => {
@@ -113,10 +114,14 @@ const blockBossNotNewChat = new Set()
const blockBossNotActive = new Set()
async function markJobAsNotSuitInRecommendPage () {
/**
* @type {{chosenReasonInUi?: { code: number, text: string}}}
*/
const result = {}
const notSuitableFeedbackButtonProxy = await page.$('.job-detail-box .job-detail-operate .not-suitable')
if (notSuitableFeedbackButtonProxy) {
await notSuitableFeedbackButtonProxy.click()
const rawRes = await (await page.waitForResponse(
const rawReasonResData = (await (await page.waitForResponse(
response => {
if (
response.url().startsWith('https://www.zhipin.com/wapi/zpgeek/negativefeedback/reasons.json')
@@ -125,7 +130,12 @@ async function markJobAsNotSuitInRecommendPage () {
}
return false
}
)).json();
)).json())?.zpData?.result ?? [];
const reasonCodeToTextMap = await readStorageFile('job-not-suit-reason-code-to-text-cache.json')
for(const it of rawReasonResData) {
reasonCodeToTextMap[it.code] = it.text?.content ?? ''
}
await writeStorageFile('job-not-suit-reason-code-to-text-cache.json', reasonCodeToTextMap)
await sleepWithRandomDelay(2000)
const chooseReasonDialogProxy = await(async() => {
const alls = await page.$$('.zp-dialog-wrap.zp-feedback-dialog.v-transfer-dom')
@@ -149,7 +159,7 @@ async function markJobAsNotSuitInRecommendPage () {
await sleepWithRandomDelay(1500)
const confirmButtonProxy = await chooseReasonDialogProxy.$(`.zp-dialog-footer .zp-btn.zp-btn-sure`)
await confirmButtonProxy.click()
await page.waitForResponse(
const response = await page.waitForResponse(
response => {
if (
response.url().startsWith('https://www.zhipin.com/wapi/zpgeek/negativefeedback/save.json')
@@ -159,6 +169,17 @@ async function markJobAsNotSuitInRecommendPage () {
return false
}
)
/**
* scene=4&code=41&feedbackReason=&securityId=
*/
const requestBody = response.request().postData()
const chosenCode = Number(new URLSearchParams(requestBody).get('code'))
if (chosenCode) {
result.chosenReasonInUi = {
code: chosenCode,
text: reasonCodeToTextMap[chosenCode]
}
}
} else {
const cancelButtonProxy = await chooseReasonDialogProxy.$(`.zp-close`)
await cancelButtonProxy.click()
@@ -167,6 +188,7 @@ async function markJobAsNotSuitInRecommendPage () {
await sleepWithRandomDelay(2500)
}
}
return result
}
async function setFilterCondition (selectedFilters) {
@@ -528,7 +550,18 @@ async function toRecommendPage (hooks) {
blockBossNotActive.add(targetJobData.jobInfo.encryptUserId)
// click prevent recommend button
try {
await markJobAsNotSuitInRecommendPage()
const { chosenReasonInUi } = await markJobAsNotSuitInRecommendPage()
await hooks.jobMarkedAsNotSuit.promise(
targetJobData,
{
markFrom: ChatStartupFrom.AutoFromRecommendList,
markReason: MarkAsNotSuitReason.BOSS_INACTIVE,
extInfo: {
bossActiveTimeDesc: targetJobData.bossInfo.activeTimeDesc,
chosenReasonInUi
}
}
)
} catch {
}
continue continueFind

View File

@@ -9,6 +9,7 @@ import defaultTargetCompanyListConf from './default-config-file/target-company-l
import defaultBossCookieStorage from './default-storage-file/boss-cookies.json' assert { type: 'json' }
import defaultBossLocalStorageStorage from './default-storage-file/boss-local-storage.json' assert { type: 'json' }
import defaultJobNotSuitReasonCodeToTextCacheStorage from './default-storage-file/job-not-suit-reason-code-to-text-cache.json' assert { type: 'json' }
export const configFileNameList = ['boss.json', 'dingtalk.json', 'target-company-list.json']
const defaultConfigFileContentMap = {
@@ -88,11 +89,12 @@ export const storageFilePath = path.join(
runtimeFolderPath,
'storage'
)
export const storageFileNameList = ['boss-cookies.json', 'boss-local-storage.json']
export const storageFileNameList = ['boss-cookies.json', 'boss-local-storage.json', 'job-not-suit-reason-code-to-text-cache.json']
const defaultStorageFileContentMap = {
'boss-cookies.json': JSON.stringify(defaultBossCookieStorage),
'boss-local-storage.json': JSON.stringify(defaultBossLocalStorageStorage)
'boss-local-storage.json': JSON.stringify(defaultBossLocalStorageStorage),
'job-not-suit-reason-code-to-text-cache.json': JSON.stringify(defaultJobNotSuitReasonCodeToTextCacheStorage)
}
export const ensureStorageFileExist = () => {
ensureRuntimeFolderPathExist()

View File

@@ -2,6 +2,12 @@ import { requireTypeorm } from "../utils/module-loader";
import { ChatStartupFrom } from "./ChatStartupLog";
const { Entity, Column, PrimaryGeneratedColumn } = requireTypeorm()
export enum MarkAsNotSuitReason {
UNKNOWN = 0,
BOSS_INACTIVE = 1,
OTHER = 2
}
@Entity()
export class MarkAsNotSuitLog {
@PrimaryGeneratedColumn()
@@ -21,6 +27,16 @@ export class MarkAsNotSuitLog {
})
markFrom?: ChatStartupFrom;
@Column({
nullable: true
})
markReason?: MarkAsNotSuitReason
@Column({
nullable: true
})
extInfo?: string
@Column({
nullable: true
})

View File

@@ -8,6 +8,7 @@ import { ChatStartupLog } from "./entity/ChatStartupLog";
import { BossInfoChangeLog } from "./entity/BossInfoChangeLog";
import { CompanyInfoChangeLog } from "./entity/CompanyInfoChangeLog";
import { JobInfoChangeLog } from "./entity/JobInfoChangeLog";
import { MarkAsNotSuitLog } from "./entity/MarkAsNotSuitLog";
function getBossInfoIfIsEqual (savedOne, currentOne) {
if (savedOne === currentOne) {
@@ -262,3 +263,30 @@ export async function saveChatStartupRecord(
//#endregion
return
}
export async function saveMarkAsNotSuitRecord(
ds: DataSource,
_jobInfo,
{ encryptUserId },
{ autoStartupChatRecordId = undefined, markFrom = undefined, extInfo = undefined, markReason = undefined } = {}
) {
const { jobInfo } = _jobInfo;
//#region mark-as-not-suit-log
const markAsNotSuitLog = new MarkAsNotSuitLog()
const markAsNotSuitLogPayload: Partial<MarkAsNotSuitLog> = {
date: new Date(),
encryptCurrentUserId: encryptUserId,
encryptJobId: jobInfo.encryptId,
autoStartupChatRecordId,
markFrom,
markReason,
extInfo: extInfo ? JSON.stringify(extInfo) : undefined
}
Object.assign(markAsNotSuitLog, markAsNotSuitLogPayload)
const markAsNotSuitLogRepository = ds.getRepository(MarkAsNotSuitLog);
await markAsNotSuitLogRepository.save(markAsNotSuitLog);
//#endregion
return
}

View File

@@ -21,7 +21,7 @@ import { VMarkAsNotSuitLog } from "./entity/VMarkAsNotSuitLog"
import sqlite3 from 'sqlite3';
import * as cliHighlight from 'cli-highlight';
import { saveChatStartupRecord, saveJobInfoFromRecommendPage } from "./handlers";
import { saveChatStartupRecord, saveJobInfoFromRecommendPage, saveMarkAsNotSuitRecord } from "./handlers";
import { UpdateChatStartupLogTable1729182577167 } from "./migrations/1729182577167-UpdateChatStartupLogTable";
Boolean(cliHighlight);
@@ -119,5 +119,15 @@ export default class SqlitePlugin {
chatStartupFrom
});
});
hooks.jobMarkedAsNotSuit.tapPromise("SqlitePlugin", async (_jobInfo, { markFrom = ChatStartupFrom.AutoFromRecommendList, markReason = undefined, extInfo = undefined } = {}) => {
const ds = await this.initPromise;
return await saveMarkAsNotSuitRecord(ds, _jobInfo, this.userInfo, {
autoStartupChatRecordId: this.runRecordId,
markFrom,
markReason,
extInfo
});
});
}
}

View File

@@ -87,6 +87,7 @@ const runAutoChat = async () => {
jobDetailIsGetFromRecommendList: new AsyncSeriesHook(['userInfo']),
newChatWillStartup: new AsyncSeriesHook(['positionInfoDetail']),
newChatStartup: new AsyncSeriesHook(['positionInfoDetail', 'chatRunningContext']),
jobMarkedAsNotSuit: new AsyncSeriesHook(['positionInfoDetail', 'markDetail']),
noPositionFoundForCurrentJob: new SyncHook(),
noPositionFoundAfterTraverseAllJob: new SyncHook(),
errorEncounter: new SyncHook(['errorInfo'])