import fs from 'node:fs' import path from 'node:path' /** * Function to clean up unwanted characters from the output data. * @param {string} data - The raw data to be cleaned. * @returns {string} - The cleaned data. */ export const cleanData = (data: string) => { return ( data // 1️⃣ Xóa chuỗi "--More--" (Cisco/Unix pager) .replace(/--More--[\s\x08\x1b\[K]*/g, '') // 2️⃣ Xóa toàn bộ chuỗi ANSI escape sequences // Ví dụ: ESC[2J, ESC[K, ESC[?25h, ESC[0m, ... .replace(/\x1B\[[0-9;?]*[A-Za-z]/g, '') // 3️⃣ Xóa ký tự Backspace (BS) hoặc Delete (DEL) .replace(/[\x08\x7F]/g, '') // 4️⃣ Xóa ký tự NUL và các control char khác (trừ \r, \n, \t) .replace(/[^\x09\x0A\x0D\x20-\x7E]/g, '') ) // 5️⃣ Chuẩn hóa xuống dòng nếu cần // .replace(/\r\n/g, '\n') } export function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)) } // 20250527-AUTO-Session.Station_1-13-192.168.171.9-2.log // {DATE}-AUTO-Session.{Station name}-{Station ID}-{Station IP}-{Line number}.log export function appendLog( output: string, stationId: number, stationName: string, stationIP: string, lineNumber: number ) { const date = new Date().toISOString().slice(0, 10).replace(/-/g, '') // YYYYMMDD const logDir = path.join('storage', 'system_logs') const logFile = path .join(logDir, `${date}-AUTO-Session.${stationName}-${stationId}-${stationIP}-${lineNumber}.log`) .replaceAll(' ', '_') // Ensure folder exists if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }) } fs.appendFile(logFile, output, (err) => { if (err) { console.error('❌ Failed to write log:', err.message) } }) } export const getPathLog = (stationId: number, lineNumber: number, port: number) => { const date = new Date().toISOString().slice(0, 10).replace(/-/g, '') // YYYYMMDD const logDir = path.join('storage', 'system_logs') const logFile = path.join(logDir, `${date}-Station_${stationId}-Line_${lineNumber}_${port}.log`) // Ensure folder exists if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }) return null } else return logFile } /** * Utility function get scope log with timestamp. * @param {string} text - content log. * @param {number} time - Timestamp. */ export const getLogWithTimeScenario = (text: string, time: number) => { try { // Match all start and end blocks const regex = /---(start|end)-scenarios---(\d+)---/g let match const blocks = [] while ((match = regex.exec(text)) !== null) { blocks.push({ type: match[1], timestamp: match[2], index: match.index, }) } // Find the matching block for the end timestamp let result = null for (let i = 0; i < blocks.length; i++) { const block = blocks[i] if (block.type === 'end' && block.timestamp === time.toString()) { // Find nearest preceding "start" for (let j = i - 1; j >= 0; j--) { if (blocks[j].type === 'start') { const startIndex = blocks[j].index const endIndex = block.index + text.slice(block.index).indexOf('\n') // or manually offset length of the line result = text.slice(startIndex, endIndex).trim() break } } break } } return result } catch (err) { console.error('Error get log:', err) return '' } } export function isValidJson(string: string) { try { JSON.parse(string) return true // Chuỗi là định dạng JSON hợp lệ } catch (e) { return false // Chuỗi không phải là định dạng JSON hợp lệ } }