Refactor GitCode daily bot

This commit is contained in:
2026-07-06 09:34:39 +08:00
parent 120ae7d3f9
commit 77a07aae0a
19 changed files with 2251 additions and 533 deletions

98
utils/browser.js Normal file
View File

@@ -0,0 +1,98 @@
/**
* 浏览器管理模块
* 负责:启动浏览器、创建上下文、加载/保存登录状态
*/
const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');
const config = require('../config');
const logger = require('./logger');
/**
* 启动浏览器实例
* @returns {Promise<import('playwright').Browser>}
*/
async function launchBrowser() {
const headless = config.browser.headless;
logger.info(`启动浏览器... (headless: ${headless})`);
logger.info(' → 调用 chromium.launch()...');
const browser = await chromium.launch({
headless,
});
logger.info('✅ 浏览器启动成功');
return browser;
}
/**
* 创建浏览器上下文
* - 如果 state.json 存在且有效,加载登录状态
* - 否则创建干净的上下文
* @param {import('playwright').Browser} browser
* @returns {Promise<{context: import('playwright').BrowserContext, stateLoaded: boolean}>}
*/
async function createContext(browser) {
let stateLoaded = false;
const statePath = path.resolve(config.statePath);
logger.info('检查 state.json...');
logger.info(` → 路径: ${statePath}`);
if (fs.existsSync(statePath)) {
logger.info(' → state.json 文件存在,开始验证内容...');
try {
const raw = fs.readFileSync(statePath, 'utf-8');
logger.info(` → 文件大小: ${raw.length} 字节`);
const state = JSON.parse(raw);
const hasCookies = Array.isArray(state.cookies) && state.cookies.length > 0;
const hasOrigins = Array.isArray(state.origins) && state.origins.length > 0;
logger.info(` → cookies: ${hasCookies ? state.cookies.length + '条' : '空'}`);
logger.info(` → origins: ${hasOrigins ? state.origins.length + '条' : '空'}`);
if (!hasCookies && !hasOrigins) {
logger.warn(' → state.json 内容无效(空 cookies 和 origins将重新登录');
stateLoaded = false;
} else {
logger.info(' → state.json 有效,将加载登录状态');
stateLoaded = true;
}
} catch (err) {
logger.warn(` → state.json 解析失败: ${err.message},将重新登录`);
stateLoaded = false;
}
} else {
logger.info(' → state.json 不存在,将创建新上下文');
stateLoaded = false;
}
const contextOptions = {
locale: config.browser.locale,
};
if (stateLoaded) {
contextOptions.storageState = statePath;
}
logger.info('正在创建浏览器上下文...');
const context = await browser.newContext(contextOptions);
logger.info(stateLoaded ? '✅ 上下文已创建(已加载登录状态)' : '✅ 上下文已创建(未登录)');
return { context, stateLoaded };
}
/**
* 保存登录状态到 state.json
* @param {import('playwright').BrowserContext} context
*/
async function saveState(context) {
const statePath = path.resolve(config.statePath);
logger.info(' → 正在保存 state.json...');
await context.storageState({ path: statePath });
logger.info(` → state.json 已保存到 ${statePath}`);
}
module.exports = {
launchBrowser,
createContext,
saveState,
};