@daiyu-5577/quickbuild
Version:
front-end build service
245 lines (244 loc) • 10.7 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import dayjs from "dayjs";
import { Buffer } from "node:buffer";
import { formatMsg } from "../commandBuild/type.js";
import { decrypt } from '../../utils/crypto.js';
import { generateUid } from '../../database/index.js';
import logger from "../../utils/log.js";
import { getWriteStream } from "../../utils/fileLog.js";
import { catchImagePath } from '../config.js';
import { baseRoute } from '../config.js';
import { updateDatabaseFile } from '../../database/index.js';
import { getFromatTime } from '../../utils/time.js';
import { IdType } from '../commandBuild/type.js';
const __dirname = new URL('.', import.meta.url).pathname;
const getCommondMsg = (data) => {
return Object.assign(Object.assign({ socketId: '', msg: '', ctxType: 'ctx:txt' }, data), { id: generateUid(IdType.M), name: '系统消息', time: getFromatTime(), timestamp: +dayjs() });
};
export const commands = [
{
command: '/getAllCommand',
desc: '查询所有命令',
fn(buildServer, socket) {
const { io } = buildServer;
const list = commands.map(v => {
return {
command: v.command,
desc: v.desc
};
});
socket.emit('on:msg-chat', formatMsg('on:msg-chat', getCommondMsg({
msg: JSON.stringify(list, null, 2)
})));
}
},
{
command: '/getAllTask',
desc: '查询任务队列',
fn(buildServer, socket) {
const { io, builder } = buildServer;
const buildTasks = builder.buildTasks;
socket.emit('on:msg-chat', formatMsg('on:msg-chat', getCommondMsg({
msg: !!buildTasks.length ? JSON.stringify(buildTasks, null, 2) : '暂无任务队列',
})));
}
},
{
command: '/getCurTask',
desc: '查询当前执行任务',
fn(buildServer, socket) {
const { io, builder } = buildServer;
const curTask = builder.curTask;
socket.emit('on:msg-chat', formatMsg('on:msg-chat', getCommondMsg({
msg: !!curTask ? JSON.stringify(curTask, null, 2) : '当前暂无任务执行',
})));
}
},
{
command: '/getAllPackage',
desc: '查询当前可构建目录',
fn(buildServer, socket) {
const { io, builder } = buildServer;
const packages = builder.packages;
socket.emit('on:msg-chat', formatMsg('on:msg-chat', getCommondMsg({
msg: !!packages.length ? JSON.stringify(packages, null, 2) : '当前暂无可构建目录',
})));
}
},
];
class Websocket {
constructor() {
this.buildServer = null;
this.chatMsgCache = new Set();
this.buildMsgCatch = new Set();
this.socketSet = new Set();
}
use(inst) {
this.buildServer = inst;
return this;
}
start() {
const buildServer = this.buildServer;
const { io, database } = buildServer;
const chatTable = database.get('message_chat') || new Set();
const buildTable = database.get('message_build') || new Set();
for (const v of chatTable) {
this.chatMsgCache.add(v);
}
for (const v of buildTable) {
this.buildMsgCatch.add(v);
}
io.use((socket, next) => {
const { database } = buildServer;
const token = socket.handshake.auth.token;
if (!token) {
return next(new Error('invalid token'));
}
decrypt(token)
.then(txt => {
const { id, name, time } = JSON.parse(txt);
const table_user = database.get('user');
const curUser = table_user.find(v => v.id === id);
if (!curUser) {
return next(new Error('invalid token'));
}
if (curUser.name !== name) {
return next(new Error('invalid token'));
}
if (+dayjs() - time > 1000 * 60 * 60 * 24 * 7) {
return next(new Error('invalid token'));
}
socket.data.user = curUser;
this.socketSet.add(socket);
})
.catch(err => {
return next(new Error('invalid token'));
})
.finally(() => {
next();
});
});
io.on('connection', (socket) => {
const lastChatId = socket.handshake.auth.lastChatId;
const lastBuildId = socket.handshake.auth.lastBuildId;
if (!!lastChatId) {
const curMsgIndex = [...this.chatMsgCache].findIndex(v => v.id == lastChatId);
if (curMsgIndex != -1) {
socket.emit('on:msg-getAllChat', [...this.chatMsgCache].splice(curMsgIndex + 1));
}
}
else {
socket.emit('on:msg-getAllChat', [...this.chatMsgCache]);
}
if (!!lastBuildId) {
const curBuildMsgIndex = [...this.buildMsgCatch].findIndex(v => v.id == lastBuildId);
if (curBuildMsgIndex != -1) {
socket.emit('on:msg-getAllBuild', [...this.buildMsgCatch].splice(curBuildMsgIndex + 1));
}
}
else {
socket.emit('on:msg-getAllBuild', [...this.buildMsgCatch]);
}
socket.onAny((event, data, ...args) => {
var _a;
let _data = data;
if ((data === null || data === void 0 ? void 0 : data.ctxType) === 'ctx:imgs' && ((_a = data === null || data === void 0 ? void 0 : data.files) === null || _a === void 0 ? void 0 : _a.length)) {
try {
const files = data.files || [];
_data = Object.assign(Object.assign({}, data), { files: files.map((v) => ({
name: v.name,
size: v.size,
type: v.type,
})) });
}
catch (error) {
console.log(error);
}
}
logger.log({
level: 'socket',
message: `OnEvent: ${event}`,
user: {
name: socket.data.user.name,
id: socket.data.user.id
},
data: _data,
args
});
});
socket.on('disconnect', () => {
this.socketSet.delete(socket);
});
socket.on('on:msg-chat', (data) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d;
const curCommand = commands.find(v => v.command === (data === null || data === void 0 ? void 0 : data.msg));
if (!!curCommand) {
curCommand.fn(buildServer, socket);
return;
}
if ((data === null || data === void 0 ? void 0 : data.ctxType) === 'ctx:imgs') {
try {
const files = data.files;
const filePaths = [];
if (!(files === null || files === void 0 ? void 0 : files.length))
return;
for (const item of files) {
if (!Buffer.isBuffer(item.file))
continue;
const { writeStream, localFileName } = yield getWriteStream(catchImagePath, item.name);
writeStream.end(item.file);
filePaths.push(`${baseRoute}/api/showLog?type=image&name=${localFileName}`);
}
data.files = filePaths;
}
catch (error) {
console.log(error);
return;
}
}
this.sendMsg('on:msg-chat', formatMsg('on:msg-chat', Object.assign(Object.assign({ id: generateUid(IdType.M), userId: ((_b = (_a = socket.data) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.id) || '', socketId: socket.id, name: ((_d = (_c = socket.data) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.name) || '匿名用户' }, data), { time: getFromatTime(), timestamp: +dayjs() })));
}));
socket.on('disconnect', () => { });
});
}
sendMsg(type, data) {
clearTimeout(Websocket.catchTimer);
const buildServer = this.buildServer;
const { io, database } = buildServer;
if (type == 'on:msg-chat') {
const _data = data;
this.chatMsgCache.add(_data);
if (this.chatMsgCache.size > 100) {
this.chatMsgCache = new Set([...this.chatMsgCache].slice(-100));
}
}
if (type == 'on:msg-build') {
const _data = data;
const curMsg = [...this.buildMsgCatch].find(v => v.taskId == _data.taskId);
if (!!curMsg) {
curMsg.msg = curMsg.msg + _data.msg;
curMsg.status = _data.status;
}
else {
this.buildMsgCatch.add(data);
}
if (this.buildMsgCatch.size > 10) {
this.buildMsgCatch = new Set([...this.buildMsgCatch].slice(-10));
}
}
Websocket.catchTimer = setTimeout(() => {
updateDatabaseFile('message_chat', [...this.chatMsgCache]);
updateDatabaseFile('message_build', [...this.buildMsgCatch]);
}, 10000);
io.emit(type, data);
}
}
export default new Websocket;