diff --git a/packages/geek-auto-start-chat-with-boss/default-config-file/boss.json b/packages/geek-auto-start-chat-with-boss/default-config-file/boss.json index ee0f425..7d5d931 100644 --- a/packages/geek-auto-start-chat-with-boss/default-config-file/boss.json +++ b/packages/geek-auto-start-chat-with-boss/default-config-file/boss.json @@ -7,6 +7,7 @@ "industryList": [] }, "expectJobRegExpStr": "", + "jobNotMatchStrategy": 1, "autoReminder": { "throttleIntervalMinutes": 10, "rechatLimitDay": 21, diff --git a/packages/geek-auto-start-chat-with-boss/index.mjs b/packages/geek-auto-start-chat-with-boss/index.mjs index 4666484..51e8f12 100644 --- a/packages/geek-auto-start-chat-with-boss/index.mjs +++ b/packages/geek-auto-start-chat-with-boss/index.mjs @@ -16,7 +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/enums' +import { MarkAsNotSuitReason, MarkAsNotSuitOp } from '@geekgeekrun/sqlite-plugin/dist/enums' const jobFilterConditionsMapByCode = {} Object.values(jobFilterConditions).forEach(arr => { @@ -79,6 +79,7 @@ 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 let { expectJobNameRegExpStr, expectJobTypeRegExpStr, @@ -624,20 +625,37 @@ async function toRecommendPage (hooks) { !testIfJobTitleOrDescriptionSuit(targetJobData.jobInfo) ) { blockJobNotSuit.add(targetJobData.jobInfo.encryptId) - try { - const { chosenReasonInUi } = await markJobAsNotSuitInRecommendPage(MarkAsNotSuitReason.JOB_NOT_SUIT) - await hooks.jobMarkedAsNotSuit.promise( - targetJobData, - { - markFrom: ChatStartupFrom.AutoFromRecommendList, - markReason: MarkAsNotSuitReason.JOB_NOT_SUIT, - extInfo: { - bossActiveTimeDesc: targetJobData.bossInfo.activeTimeDesc, - chosenReasonInUi + if (jobNotMatchStrategy === MarkAsNotSuitOp.MARK_AS_NOT_SUIT_ON_BOSS) { + try { + const { chosenReasonInUi } = await markJobAsNotSuitInRecommendPage(MarkAsNotSuitReason.JOB_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 { + ) + } catch { + } + } + else if (jobNotMatchStrategy === 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 } @@ -773,7 +791,6 @@ export async function mainLoop (hooks) { } }) hooks.puppeteerLaunched?.call() - page = (await browser.pages())[0] //set cookies hooks.cookieWillSet?.call(bossCookies) @@ -782,6 +799,10 @@ export async function mainLoop (hooks) { } await setDomainLocalStorage(browser, localStoragePageUrl, bossLocalStorage) await page.bringToFront() + await hooks.mainFlowWillLaunch?.callAsync({ + jobNotMatchStrategy, + blockJobNotSuit + }) await toRecommendPage(hooks) // goto search diff --git a/packages/run-core-of-geek-auto-start-chat-with-boss/main.mjs b/packages/run-core-of-geek-auto-start-chat-with-boss/main.mjs index 94c5f3b..473e0a4 100644 --- a/packages/run-core-of-geek-auto-start-chat-with-boss/main.mjs +++ b/packages/run-core-of-geek-auto-start-chat-with-boss/main.mjs @@ -51,6 +51,7 @@ const main = async () => { pageLoaded: new SyncHook(), cookieWillSet: new SyncHook(['cookies']), userInfoResponse: new AsyncSeriesHook(['userInfo']), + mainFlowWillLaunch: new AsyncSeriesHook(['args']), newChatWillStartup: new AsyncSeriesHook(['positionInfoDetail']), newChatStartup: new AsyncSeriesHook(['positionInfoDetail', 'chatRunningContext']), noPositionFoundForCurrentJob: new SyncHook(), diff --git a/packages/sqlite-plugin/src/entity/MarkAsNotSuitLog.ts b/packages/sqlite-plugin/src/entity/MarkAsNotSuitLog.ts index 20b4e4e..163035c 100644 --- a/packages/sqlite-plugin/src/entity/MarkAsNotSuitLog.ts +++ b/packages/sqlite-plugin/src/entity/MarkAsNotSuitLog.ts @@ -1,4 +1,4 @@ -import { MarkAsNotSuitReason } from "../enums"; +import { MarkAsNotSuitOp, MarkAsNotSuitReason } from "../enums"; import { requireTypeorm } from "../utils/module-loader"; import { ChatStartupFrom } from "./ChatStartupLog"; const { Entity, Column, PrimaryGeneratedColumn } = requireTypeorm() @@ -27,6 +27,11 @@ export class MarkAsNotSuitLog { }) markReason?: MarkAsNotSuitReason + @Column({ + nullable: true + }) + markOp?: MarkAsNotSuitOp + @Column({ nullable: true }) diff --git a/packages/sqlite-plugin/src/enums.ts b/packages/sqlite-plugin/src/enums.ts index a791d00..53df1da 100644 --- a/packages/sqlite-plugin/src/enums.ts +++ b/packages/sqlite-plugin/src/enums.ts @@ -3,4 +3,10 @@ export enum MarkAsNotSuitReason { BOSS_INACTIVE = 1, USER_MANUAL_OPERATION_WITH_UNKNOWN_REASON = 2, JOB_NOT_SUIT = 3, -} \ No newline at end of file +} + +export enum MarkAsNotSuitOp { + MARK_AS_NOT_SUIT_ON_BOSS = 1, + MARK_AS_NOT_SUIT_ON_LOCAL = 2, + NO_OP = 3 +} diff --git a/packages/sqlite-plugin/src/handlers.ts b/packages/sqlite-plugin/src/handlers.ts index 89bca04..fcda892 100644 --- a/packages/sqlite-plugin/src/handlers.ts +++ b/packages/sqlite-plugin/src/handlers.ts @@ -1,4 +1,4 @@ -import { DataSource } from "typeorm"; +import { DataSource, Raw } from "typeorm"; import { BossActiveStatusRecord } from "./entity/BossActiveStatusRecord"; import { BossInfo } from "./entity/BossInfo"; import { CompanyInfo } from "./entity/CompanyInfo"; @@ -270,7 +270,7 @@ export async function saveMarkAsNotSuitRecord( ds: DataSource, _jobInfo, { encryptUserId }, - { autoStartupChatRecordId = undefined, markFrom = undefined, extInfo = undefined, markReason = undefined } = {} + { autoStartupChatRecordId = undefined, markFrom = undefined, extInfo = undefined, markReason = undefined, markOp = undefined } = {} ) { const { jobInfo } = _jobInfo; @@ -283,7 +283,8 @@ export async function saveMarkAsNotSuitRecord( autoStartupChatRecordId, markFrom, markReason, - extInfo: extInfo ? JSON.stringify(extInfo) : undefined + extInfo: extInfo ? JSON.stringify(extInfo) : undefined, + markOp } Object.assign(markAsNotSuitLog, markAsNotSuitLogPayload) @@ -326,3 +327,15 @@ export async function saveGptCompletionRequestRecord( //#endregion return } + +export async function getNotSuitMarkRecordsInLastSomeDays (ds: DataSource, days = 0) { + const repo = ds.getRepository(MarkAsNotSuitLog) + const result = await repo.findBy({ + date: Raw(alias => `DATE(${alias}) >= DATE('${ + new Date( + Number(new Date()) - 7 * 24 * 60 * 60 * 1000 + ).toISOString() + }')`) + }) + return result +} diff --git a/packages/sqlite-plugin/src/index.ts b/packages/sqlite-plugin/src/index.ts index 555b859..c271e12 100644 --- a/packages/sqlite-plugin/src/index.ts +++ b/packages/sqlite-plugin/src/index.ts @@ -22,10 +22,12 @@ import { ChatMessageRecord } from './entity/ChatMessageRecord' import { LlmModelUsageRecord } from './entity/LlmModelUsageRecord' import sqlite3 from 'sqlite3'; -import { saveChatStartupRecord, saveJobInfoFromRecommendPage, saveMarkAsNotSuitRecord } from "./handlers"; +import { saveChatStartupRecord, saveJobInfoFromRecommendPage, saveMarkAsNotSuitRecord, getNotSuitMarkRecordsInLastSomeDays } from "./handlers"; import { UpdateChatStartupLogTable1729182577167 } from "./migrations/1729182577167-UpdateChatStartupLogTable"; import minimist from 'minimist' import { UpdateBossInfoTable1732032381304 } from "./migrations/1732032381304-UpdateBossInfoTable"; +import { MarkAsNotSuitOp } from "./enums"; +import { AddColumnForMarkAsNotSuitLog1746092370665 } from "./migrations/1746092370665-AddColumnForMarkAsNotSuitLog"; export function initDb(dbFilePath) { const { DataSource } = requireTypeorm() @@ -59,6 +61,7 @@ export function initDb(dbFilePath) { migrations: [ UpdateChatStartupLogTable1729182577167, UpdateBossInfoTable1732032381304, + AddColumnForMarkAsNotSuitLog1746092370665, ], migrationsRun: true }); @@ -97,6 +100,19 @@ export default class SqlitePlugin { return await userInfoRepository.save(user); } ); + hooks.mainFlowWillLaunch.tapPromise( + "SqlitePlugin", + async ({ + jobNotMatchStrategy, + blockJobNotSuit + }) => { + if (jobNotMatchStrategy === MarkAsNotSuitOp.MARK_AS_NOT_SUIT_ON_LOCAL) { + const ds = await this.initPromise; + const last7DayMarkRecords = (await getNotSuitMarkRecordsInLastSomeDays(ds, 7) ?? []).map(it => it.encryptJobId); + last7DayMarkRecords.forEach(id => blockJobNotSuit.add(id)) + } + } + ); hooks.jobDetailIsGetFromRecommendList.tapPromise("SqlitePlugin", async (_jobInfo) => { const ds = await this.initPromise; @@ -111,13 +127,14 @@ export default class SqlitePlugin { }); }); - hooks.jobMarkedAsNotSuit.tapPromise("SqlitePlugin", async (_jobInfo, { markFrom = ChatStartupFrom.AutoFromRecommendList, markReason = undefined, extInfo = undefined } = {}) => { + hooks.jobMarkedAsNotSuit.tapPromise("SqlitePlugin", async (_jobInfo, { markFrom = ChatStartupFrom.AutoFromRecommendList, markReason = undefined, extInfo = undefined, markOp = undefined } = {}) => { const ds = await this.initPromise; return await saveMarkAsNotSuitRecord(ds, _jobInfo, this.userInfo, { autoStartupChatRecordId: this.runRecordId, markFrom, markReason, - extInfo + extInfo, + markOp }); }); } diff --git a/packages/sqlite-plugin/src/migrations/1746092370665-AddColumnForMarkAsNotSuitLog.ts b/packages/sqlite-plugin/src/migrations/1746092370665-AddColumnForMarkAsNotSuitLog.ts new file mode 100644 index 0000000..536ed7f --- /dev/null +++ b/packages/sqlite-plugin/src/migrations/1746092370665-AddColumnForMarkAsNotSuitLog.ts @@ -0,0 +1,31 @@ +import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; + +const viewNames = [ + "v_boss_library", + "v_chat_startup_log", + "v_company_library", + "v_job_library", + "v_mark_as_not_suit_log", +]; + +export class AddColumnForMarkAsNotSuitLog1746092370665 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + for (const viewName of viewNames) { + await queryRunner.query(`DROP VIEW IF EXISTS "${viewName}"`); + } + if (await queryRunner.hasTable("mark_as_not_suit_log")) { + if (!await queryRunner.hasColumn("mark_as_not_suit_log", "markOp")) { + await queryRunner.addColumn( + "mark_as_not_suit_log", + new TableColumn({ + name: "markOp", + type: "number", + isNullable: true, + }) + ); + } + } + } + + public async down(queryRunner: QueryRunner): Promise {} +} diff --git a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index.ts b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index.ts index ff3e2d2..0ec7ff4 100644 --- a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index.ts +++ b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index.ts @@ -86,6 +86,7 @@ const runAutoChat = async () => { pageLoaded: new SyncHook(), cookieWillSet: new SyncHook(['cookies']), userInfoResponse: new AsyncSeriesHook(['userInfo']), + mainFlowWillLaunch: new AsyncSeriesHook(['args']), jobDetailIsGetFromRecommendList: new AsyncSeriesHook(['userInfo']), newChatWillStartup: new AsyncSeriesHook(['positionInfoDetail']), newChatStartup: new AsyncSeriesHook(['positionInfoDetail', 'chatRunningContext']), diff --git a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts index 45aafdb..1e9596b 100644 --- a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts +++ b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts @@ -95,6 +95,9 @@ export default function initIpc() { if (hasOwn(payload, 'expectJobDescRegExpStr')) { bossConfig.expectJobDescRegExpStr = payload.expectJobDescRegExpStr } + if (hasOwn(payload, 'jobNotMatchStrategy')) { + bossConfig.jobNotMatchStrategy = payload.jobNotMatchStrategy + } if (hasOwn(payload, 'autoReminder')) { bossConfig.autoReminder = payload.autoReminder } diff --git a/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss.vue b/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss.vue index 7816696..60b2405 100644 --- a/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss.vue +++ b/packages/ui/src/renderer/src/page/MainLayout/GeekAutoStartChatWithBoss.vue @@ -71,7 +71,7 @@
- 查看职位详情后,是发起投递还是标记不合适的条件 + 查看职位详情后,认为合适并发起投递的条件 (以下条件为空表示不筛选)
如下各信息位置图示 - - - 标记不合适机制 -
+
+ +
+ 当查看职位详情后,发现职位不满足如上设置的条件时 + + + 标记不合适机制 + +
+ + + {{ op.name }} + +
+
- + 仅保存配置 保存配置,并开始求职! @@ -211,7 +239,7 @@