diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..45c758a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +node_modules +npm-debug.log +.dockerignore +.git +Dockerfile +.logs +.vscode +src/logs/* +.history \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2bd342c..d18583c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ .local_chromium -node_modules \ No newline at end of file +node_modules +dist +.history +src/logs/*.log +package-lock.json \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bcfa5ec --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +FROM node:16-bullseye-slim + +ENV DEBIAN_FRONTEND noninteractive +ENV TZ Asia/Shanghai +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# 配置环境变量,跳过 npm 安装时候的 chromium 的下载 +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true +# 指定浏览器的路径 +ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium + +# 替换几个镜像源,以及安装 pm2,如果你不想使用 pm2 来运行,可以删掉 +RUN sed -i 's#http://deb.debian.org#http://mirrors.aliyun.com#g;s#http://security.debian.org#http://mirrors.aliyun.com#g' /etc/apt/sources.list \ + && npm c set registry="https://registry.npmmirror.com" \ + && echo "puppeteer_download_host=https://registry.npmmirror.com/-/binary" >> ~/.npmrc \ + && npm install pm2 -g + +# 安装必要的库 +RUN apt-get update && apt-get -y upgrade +RUN apt-get install -y wget gnupg \ + fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \ + libgtk2.0-0 libnss3 libatk-bridge2.0-0 libdrm2 libxkbcommon0 libgbm1 libasound2 && \ + apt-get install -y chromium && \ + apt-get clean + +# debug 用 +# RUN apt-get update \ +# && apt-get -y install procps \ +# && apt-get install -y vim + +WORKDIR /data/srv/ + +COPY . ./ + +RUN npm install && npm run build + +CMD ["pm2-runtime", "ecosystem.config.js"] diff --git a/README.md b/README.md index aee69f9..4411c7c 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ ### 安装与运行 Install and Run +#### 手动安装 Manual installation + 1. 安装依赖 ``` @@ -325,6 +327,26 @@ pnpm start - 开启 `PushPlus` 推送,保存微信公众发送消息里的二维码,扫码登录 +#### Docker + + ``` + docker run --name=xuexiqiangguo -d \ + -e SCHEDULE_CONFIG='{"nick":"nick","token":"xxxxxxxx","cron":"0 0 12 * * ?","taskConfig":[true,true,true],"paperExitAfterWrong":false,"refreshCookieInterval":[60,120]}' \ + -e PUSH_PLUS_ENABLED=true \ + -e PUSH_PLUS_NICK=nick \ + -e PUSH_PLUS_SERVER_NAME=server \ + -e PUSH_PLUS_ADMIN_TOKEN=xxxxxx \ + helios74/ilovestudysomuch + ``` + 参数说明: + SCHEDULE_CONFIG: `src/config/schedule.ts` 中的任务配置。注意是单个的序列化后的配置 + PUSH_PLUS_ENABLED: 是否启用 pushplus + PUSH_PLUS_NICK: pushplus 的配置,nick + PUSH_PLUS_SERVER_NAME: pushplus 的配置,服务器名称 + PUSH_PLUS_ADMIN_TOKEN: pushplus 的配置,管理员 token + + 请注意,这个镜像只支持了配置 pushplus ,如果你需要使用其他的方式,请参照 `Dockerfile` 自行构建。 + ### 配置 Configuration - Puppeteer 配置 `src/config/pup.ts` ([官方文档配置](https://pptr.dev/api/puppeteer.launchoptions 'Puppeteer 使用和配置')) diff --git a/bin/index.ts b/bin/index.ts index 8fb5058..a146d11 100644 --- a/bin/index.ts +++ b/bin/index.ts @@ -393,6 +393,10 @@ const startScheduleJobs = () => { }; (() => { + if (SCHEDULE_CONFIG.length === 0) { + console.warn('当前没有配置的任务信息,中断执行。'); + return; + } // 开始定时任务 startScheduleJobs(); // 执行清除日志任务 diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 0000000..899496a --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,14 @@ +module.exports = { + apps: [ + { + name: 'xuexiqiangguo', + script: './dist/bin/index.js', + cwd: './', + watch: false, + instances: 1, + autorestart: true, + max_memory_restart: '1024M', + env: { NODE_ENV: 'production' }, + } + ], +}; diff --git a/package.json b/package.json index f6bf3dd..823ce36 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "start": "ts-node bin/index.ts", "dev": "nodemon bin/index.ts", + "build": "./node_modules/typescript/bin/tsc", "test": "vitest" }, "keywords": [], diff --git a/src/config/pup.ts b/src/config/pup.ts index 9754d3a..78b19ad 100644 --- a/src/config/pup.ts +++ b/src/config/pup.ts @@ -40,9 +40,9 @@ const PUP_CONFIG: pup.PuppeteerLaunchOptions = { // dumpio: true, /** * @description 可执行文件的路径 - * @example 'google-chrome' for linux, '.local_chromium/chrome.exe' from win + * @example 'google-chrome' for linux, '.local_chromium/chrome.exe' from win, '/usr/bin/chromium' for docker */ - executablePath: '.local_chromium/chrome.exe', + executablePath: '/usr/bin/chromium', /** * @description 忽略默认配置 */ diff --git a/src/config/push.ts b/src/config/push.ts index cc9d984..f1ecbe4 100644 --- a/src/config/push.ts +++ b/src/config/push.ts @@ -7,18 +7,18 @@ const PUSH_CONFIG = { * @description 启用推送 * @example true 启用推送 false 禁用推送 */ - enabled: false, + enabled: process.env.PUSH_PLUS_ENABLED === 'true', /** * @description 发送服务消息昵称 */ - nick: '管理员', + nick: process.env.PUSH_PLUS_NICK || '管理员', /** * @description 发送服务消息来源 */ - from: 'tech-study-node', + from: process.env.PUSH_PLUS_SERVER_NAME || 'tech-study-node', /** * @description 管理员的token */ - token: 'xxxxxxxxxxxxxxxxxxxxxxxxxx', + token: process.env.PUSH_PLUS_ADMIN_TOKEN || 'xxxxxxxxxxxxxxxxxxxxxxxxxx', }; export default PUSH_CONFIG; diff --git a/src/config/schedule.ts b/src/config/schedule.ts index cbe9266..a3a944c 100644 --- a/src/config/schedule.ts +++ b/src/config/schedule.ts @@ -1,3 +1,9 @@ +import { Log } from '../utils/logs'; + +const scheduleConfigLogger = new Log(); + +scheduleConfigLogger.start(); + /** * @description 定时任务 */ @@ -27,15 +33,28 @@ export type Schedule = { refreshCookieInterval: [number, number]; }; +const myScheduleConfig: Schedule[] = []; + +const envScheduleConfig = process.env.SCHEDULE_CONFIG; + +scheduleConfigLogger.info(`GET config: ${process.env.SCHEDULE_CONFIG}`); + +if (typeof envScheduleConfig === 'string') { + try { + // 这里不保证参数的正确性,如果是错误参数则后面流程中进行校验 + const configData = JSON.parse(envScheduleConfig); + myScheduleConfig.push(configData); + scheduleConfigLogger.info(`当前配置:${Object.keys(configData).map(configKey => `[${configKey}: ${configData[configKey]}]`).join('\t')}`); + } catch (error) { + scheduleConfigLogger.fail('任务参数可能不是有效的 JSON 字符串,请检查 ENV 参数。'); + } +} else { + scheduleConfigLogger.fail('任务参数不合法,请检查 ENV 参数。'); +} + +scheduleConfigLogger.finish(); + /** * @description 定时任务配置 */ -export const SCHEDULE_CONFIG: Schedule[] = [ - { - nick: 'xxx', - token: 'xxxxxxxxxxxxxxxxxxxxxxxxxx', - cron: '0 0 12 * * ?', - taskConfig: [true, true, true], - refreshCookieInterval: [60, 120], - }, -]; +export const SCHEDULE_CONFIG: Schedule[] = myScheduleConfig; diff --git a/tsconfig.json b/tsconfig.json index b55217a..0279fa5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,9 +3,11 @@ "target": "ESNext", "lib": ["DOM", "ESNext"], "module": "commonjs", + "types": ["node"], "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, - "skipLibCheck": true + "skipLibCheck": true, + "outDir": "dist" } }