Skip to content

Commit

Permalink
feat(all): 添加终端显示,添加脚本执行,添加文件属性
Browse files Browse the repository at this point in the history
  • Loading branch information
enncy committed Mar 5, 2022
1 parent 9f2f4fb commit cf5dc9a
Show file tree
Hide file tree
Showing 36 changed files with 761 additions and 275 deletions.
5 changes: 4 additions & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
node-linker=hoisted
node-linker=hoisted
hoist-pattern[]=*!node-pty*
hoist-pattern[]=*!nan*
hoist-pattern[]=*
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
"dayjs": "^1.10.7",
"depcheck": "^1.4.3",
"electron-store": "^8.0.1",
"playwright": "^1.18.1"
"get-port": "^5.1.1",
"nan": "^2.15.0",
"playwright": "^1.18.1",
"ws": "^8.5.0"
},
"devDependencies": {
"@types/node": "^17.0.16",
Expand Down
2 changes: 2 additions & 0 deletions packages/app/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# customize

*.local.test.js

pnpm-lock.yaml
package-lock.json

Expand Down
6 changes: 4 additions & 2 deletions packages/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ function handleError() {
async function open() {
return new Promise((resolve) => {
app.whenReady().then(async () => {
const win = await openWindow();
const win = await openWindow((win) => {
return app.isPackaged ? win.loadFile("./public/index.html") : win.loadURL("http://localhost:3000");
});

win.setAlwaysOnTop(Boolean(store.get("alwaysOnTop") || false));

Expand All @@ -68,6 +70,6 @@ async function open() {
async function task(name, func) {
const time = Date.now();
const res = await func();
logger.debug(name, "耗时:", Date.now() - time);
logger.debug(name, " 耗时:", Date.now() - time);
return res;
}
7 changes: 6 additions & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@
},
"dependencies": {
"@ocsjs/scripts": "workspace:^1.0.0",
"@types/node-forge": "^1.0.0",
"@types/ws": "^8.5.2",
"dayjs": "^1.10.7",
"electron-store": "^8.0.1",
"get-port": "^5.1.1",
"node-forge": "1.0.0",
"pino": "^7.8.0",
"trash": "7.2.0"
"trash": "7.2.0",
"ws": "^8.5.0"
},
"repository": {
"type": "git",
Expand Down
76 changes: 76 additions & 0 deletions packages/app/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// @ts-check

const ocs = require("@ocsjs/scripts");
const { loggerPrefix } = require("@ocsjs/scripts");
const { Instance: Chalk } = require("chalk");
const { Logger } = require("./src/logger.core");
const { redBright, bgRedBright, bgBlueBright, bgYellowBright, bgGray } = new Chalk({ level: 2 });

/** @type { Logger} */
let logger;

/** @type {import("playwright").BrowserContext | import("playwright").Browser} */
let browser;
/** @type {import("playwright").Page} */
let page;

process.on("message", async (message) => {
// @ts-ignore
const { action, data, uid, logsPath } = JSON.parse(message);
if (logger === undefined) {
logger = new Logger(logsPath, false, "script", uid);
logger.info("日志 : " + logger.dest);
}

try {
if (action === "open") {
if (browser === undefined) {
logger.info("任务启动 : ", action, data, uid, logsPath);

/** @type {import("@ocsjs/scripts").LaunchScriptsOptions} */
const options = JSON.parse(data);
const { userDataDir, launchOptions, scripts } = options;
console.log("\n");
debug("任务启动", uid);
debug("隐身模式 ", launchOptions.headless === true ? bgBlueBright("开启") : bgRedBright("关闭"));
debug("无痕浏览 ", userDataDir === "" ? bgBlueBright("开启") : bgRedBright("关闭"));

function debug(...msg) {
console.log(bgGray(loggerPrefix("debug")), ...msg);
}

launchOptions.logger = {
isEnabled: () => true,
log(name, severity, message, args) {
const str = [severity, new Date().toLocaleTimeString(), name, message, args].join(" ");
console.log(str);
logger.info(str);
},
};

const { browser: _browser, page: _page } = await ocs.launchScripts({
userDataDir,
launchOptions,
scripts,
});
browser = _browser;
page = _page;
} else {
console.log(bgYellowBright(loggerPrefix("warn")), "任务已开启,请勿重复开启。", uid);
logger.info("任务已开启,请勿重复开启。");
}
} else if (action === "close") {
console.log(bgBlueBright(loggerPrefix("info")), "任务已关闭!");
logger.info("任务已关闭!");
await browser.close();
browser = undefined;
page = undefined;
} else if (action === "call") {
const { name, args } = JSON.parse(data);
await page[name](args);
}
} catch (e) {
console.log(bgRedBright(loggerPrefix("error")), "任务发生未知错误 : ", e);
logger.info("任务发生未知错误!", e);
}
});
61 changes: 61 additions & 0 deletions packages/app/src/logger.core.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// @ts-check
const path = require("path");
const util = require("util");
const fs = require("fs");

function formatDate() {
const date = new Date();
return [
date.getFullYear(),
String(date.getMonth() + 1).padStart(2, "0"),
date.getDate().toString().padStart(2, "0"),
].join("-");
}

/**
* 日志对象
* ```js
* const l = new logger(app.getPath("logs"), true, 'test') // create `${logs}/YYYY-MM-DD/test.log`
* const l2 = new logger(app.getPath("logs"), true,'project','error','1') // create `${logs}/YYYY-MM-DD/project/error/1.log`
* ```
* @param {string} basePath 根路径
* @param {boolean} withConsole 是否同时使用 console 输出
* @param {string[]} name 日志名,每个代表一个路径
*/
exports.Logger = class Logger {
basePath;
withConsole;
dest;
constructor(basePath, withConsole = true, ...name) {
this.basePath = basePath;
this.withConsole = withConsole;
this.dest = path.join(this.basePath, "/", formatDate(), "/", name.join("/") + ".log");
}

log = (...msg) => this._log(this.dest, "信息", ...msg);
info = (...msg) => this._log(this.dest, "信息", ...msg);
error = (...msg) => this._log(this.dest, "错误", ...msg);
debug = (...msg) => this._log(this.dest, "调试", ...msg);
warn = (...msg) => this._log(this.dest, "警告", ...msg);

_log(dest, level, ...msg) {
const data = msg
.map((s) => {
if (typeof s === "object" || typeof s === "function") {
s = util.inspect(s);
}
return s;
})
.join("");
const txt = `[${level}] ${new Date().toLocaleString()} \t ` + data;

if (this.withConsole) {
console.log(txt);
}

if (!fs.existsSync(path.dirname(dest))) {
fs.mkdirSync(path.dirname(dest), { recursive: true });
}
fs.appendFileSync(dest, txt + "\n");
}
};
35 changes: 3 additions & 32 deletions packages/app/src/logger.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,7 @@
//@ts-check

const { Logger } = require("./logger.core");
const { app } = require("electron");
const path = require("path");
const dayjs = require("dayjs");
const util = require("util");
const fs = require("fs");

module.exports = function logger(name) {
const dest = path.join(app.getPath("logs"), "/", dayjs().format("YYYY-MM-DD"), "/", name + ".log");

function log(level, ...msg) {
const data = msg
.map((s) => {
if (typeof s === "object" || typeof s === "function") {
s = util.inspect(s);
}
return s;
})
.join("");
const txt = `[${level}] ${new Date().toLocaleString()} \t ` + data;
console.log(txt);
if (!fs.existsSync(path.dirname(dest))) {
fs.mkdirSync(path.dirname(dest), { recursive: true });
}
fs.appendFileSync(dest, txt + "\n");
}

return {
log: (...msg) => log("信息", ...msg),
info: (...msg) => log("信息", ...msg),
error: (...msg) => log("错误", ...msg),
debug: (...msg) => log("调试", ...msg),
warn: (...msg) => log("警告", ...msg),
};
module.exports = function logger(...name) {
return new Logger(app.getPath("logs"), true, ...name);
};
13 changes: 7 additions & 6 deletions packages/app/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ function createWindow() {
});
}

async function openWindow() {
/**
*
* @param {{(win:BrowserWindow):Promise<any>}} opener
* @returns
*/
async function openWindow(opener) {
const win = createWindow();

if (!app.isPackaged) {
await win.loadURL("http://localhost:3000");
} else {
await win.loadFile("./public/index.html");
}
await opener(win);

app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
Expand Down
1 change: 0 additions & 1 deletion packages/app/test.js

This file was deleted.

6 changes: 5 additions & 1 deletion packages/scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"publishConfig": {
"access": "public"
},
"bin": {
"ocs": "./lib/nodejs/cli.js"
},
"scripts": {
"test": "playwright test --config=playwright.config.ts",
"build": "tsc && npm run pack",
Expand All @@ -21,7 +24,8 @@
"chalk": "4.1.0",
"commander": "^9.0.0",
"dotenv": "^16.0.0",
"playwright": "^1.18.1"
"playwright": "^1.18.1",
"ws": "^8.5.0"
},
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/scripts/src/browser/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createLog } from "./logger";
import { createLog } from "../logger";

export async function sleep(period: number) {
return new Promise((resolve) => {
Expand Down
1 change: 1 addition & 0 deletions packages/scripts/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./nodejs";
export { loggerPrefix } from "./logger";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function prefix(level: "info" | "error" | "warn" | "debug") {
export function loggerPrefix(level: "info" | "error" | "warn" | "debug") {
let extra = level === "error" ? "[错误]" : level === "warn" ? "[警告]" : undefined;

if (typeof global === "undefined") {
Expand All @@ -22,5 +22,5 @@ export function prefix(level: "info" | "error" | "warn" | "debug") {
}

export function createLog(level: "info" | "error" | "warn" | "debug", ...msg: any[]) {
return [...prefix(level), ...msg];
return [...loggerPrefix(level), ...msg];
}
33 changes: 24 additions & 9 deletions packages/scripts/src/nodejs/cli.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#! /usr/bin/env node

import { Command } from "commander";
import { launchScripts } from "./script";
import { launchScripts, LaunchScriptsOptions } from "./script";
import fs from "fs";
import path from "path";
import { prefix } from "../browser/logger";
import chalk from "chalk";
import { loggerPrefix } from "../logger";
import { Instance as Chalk } from "chalk";

const chalk = new Chalk({ level: 2 });

const ocs = new Command();

Expand All @@ -24,13 +28,24 @@ Example:
try {
const file = fs.readFileSync(filePath).toString();
try {
const data = JSON.parse(file);
await launchScripts(data.launch, data.scripts);
} catch {
console.log(`\n\t${chalk.bgRedBright(prefix("error"))} 文件格式错误 : ${filePath}\n`);
const { userDataDir, launchOptions, scripts }: LaunchScriptsOptions = JSON.parse(file);

try {
await launchScripts({ userDataDir, launchOptions, scripts });
} catch (e) {
error("运行错误", e);
}
} catch (e) {
error("文件格式错误", e);
}
} catch {
console.log(`\n\t${chalk.bgRedBright(prefix("error"))} 文件不存在 : ${filePath}\n`);
} catch (e) {
error("文件不存在", e);
}

function error(msg: string, e: any) {
console.log(
`\n${chalk.bgRedBright(loggerPrefix("error"))} ${msg} : ${filePath}\n\n${(e as Error).stack}\n`
);
}
})

Expand Down
17 changes: 15 additions & 2 deletions packages/scripts/src/nodejs/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ import { CX, ZHS } from ".";
import { ScriptFunction, ScriptOptions } from "./types";

export { LaunchOptions };

export interface Script {
name: keyof ScriptOptions;
options: ScriptOptions[keyof ScriptOptions];
}

export interface LaunchScriptsOptions {
userDataDir: string | undefined;
launchOptions: LaunchOptions;
scripts: Script[];
}

export const scripts: Record<keyof ScriptOptions, ScriptFunction> = {
"cx-login-other": CX.otherLogin,
"cx-login-phone": CX.phoneLogin,
Expand All @@ -28,8 +35,14 @@ export const scriptNames = [
["zhs-login-school", "智慧树学校登录"],
];

export async function launchScripts(launchOptions: LaunchOptions, ...scripts: Script[]) {
const browser = await chromium.launch(launchOptions);
export async function launchScripts({ userDataDir, launchOptions, scripts }: LaunchScriptsOptions) {
let browser;
if (userDataDir && userDataDir !== "") {
browser = await chromium.launchPersistentContext(userDataDir, launchOptions);
} else {
browser = await chromium.launch(launchOptions);
}

let page = await browser.newPage();

for (const item of scripts) {
Expand Down
Loading

0 comments on commit cf5dc9a

Please sign in to comment.