mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-05-07 04:22:41 +08:00
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:
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"3": "学历不匹配",
|
||||
"5": "其他反馈",
|
||||
"13": "同城距离远",
|
||||
"30": "公司不感兴趣",
|
||||
"34": "BOSS活跃度低",
|
||||
"41": "职位停招/招满",
|
||||
"42": "面试过/入职过"
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'])
|
||||
|
||||
Reference in New Issue
Block a user