import fs from "fs"; import type { HttpContextContract } from "@ioc:Adonis/Core/HttpContext"; import axios from "axios"; import Env from "@ioc:Adonis/Core/Env"; import LogDetectFile from "App/Models/LogDetectFile"; const path = require("path"); const BASE_URL = Env.get("BASE_URL_LOG"); const BASE_URL_AUTO = `${BASE_URL}/`; const LOG_DIR = "home/logs"; export default class ErpsController { /** * Controller do tim cac serial number trong cac log trong khoang thoi gian xac dinh * @param {Integer} from thoi gian bat dau YYYYMMDD (vd: 20230130) * @param {Integer} to thoi gian ket thuc YYYYMMDD (vd: 20230230) */ public async getIndexSerialNumber({ request, response, }: HttpContextContract) { const { from, to } = request.all(); const getListLogOld = async (from, to) => { try { const listLog: string[] = []; const response = await axios.get(BASE_URL); // const responseAUTO = await axios.get(BASE_URL_AUTO); console.log("check!!!!!!!!!!!!!!!!!!!!!") let data1 = response.data .split("\n") .filter((i) => i.search(" { let fileName = u.slice(u.search("")).split(">")[1]; if ( parseInt(fileName?.split("-")[0]) >= parseInt(from) && parseInt(fileName?.split("-")[0]) <= parseInt(to) ) { listLog.push( (BASE_URL + "/") + fileName + " " ); const record = await LogDetectFile.firstOrCreate( { file_name: fileName }, { file_name: fileName } ); console.log(record.toJSON()) } }); return listLog; } catch (error) { console.log(error); } }; const getListLog = async (from: string, to: string) => { try { const listLog: string[] = []; // đọc danh sách file trong thư mục const files = await fs.readdirSync(LOG_DIR); // lọc file .log const logFiles = files.filter((file) => file.endsWith(".log")); // dùng Promise.all để xử lý async đúng cách await Promise.all( logFiles.map(async (fileName) => { const prefixNumber = parseInt(fileName.split("-")[0]); if ( prefixNumber >= parseInt(from) && prefixNumber <= parseInt(to) ) { listLog.push(path.join(LOG_DIR, fileName)); const record = await LogDetectFile.firstOrCreate( { file_name: fileName }, { file_name: fileName } ); console.log(record.toJSON()); } }) ); return listLog; } catch (error) { console.log(error); return []; } }; const fetchWithRetry = async (url) => { let retries = 0; const MAX_RETRIES = 10; while (retries < MAX_RETRIES) { try { const response = await axios.get(url); return response.data; } catch (error) { if (error.code) { retries++; continue; } else { console.error("Error fetching file:", error); return null; } } } return null; }; const extractInfoFromLine = (cleanedLine, index, fName, lines, brand, PID) => { const results: any = []; const getWarehouse = (fileName) => /(US(?!A)|-US|\.US|US-)/.test(fileName) ? "US" : "AU"; const extractSN = (str) => str?.replace(/[!@#$%^&*()_+{}\[\]:;<>,.?~\\/]/g, "").trim(); // PID & SN if ( cleanedLine.includes("PID:") && cleanedLine.includes("SN:") && !cleanedLine.includes("%") ) { const parts = cleanedLine.split(","); const SN = extractSN( parts.find((p) => p.includes("SN:"))?.split(":")[1] ?? "" ); PID = extractSN( parts.find((p) => p.includes("PID:"))?.split(":")[1] ?? "" ); const VID = extractSN( parts.find((p) => p.includes("VID:"))?.split(":")[1] ?? "" ); if (SN && SN !== "N/A" && SN.length > 4) { results.push({ PID, VID, SN, line: [index + 1], brand, fileName: fName, warehouse: getWarehouse(fName), }); } } // Serial Number if (cleanedLine.includes("Serial Number")) { const PCB_SN = extractSN(cleanedLine.split(":")[1]); if (PCB_SN) { results.push({ PID, VID: "", SN: PCB_SN, line: [index + 1], brand, fileName: fName, warehouse: getWarehouse(fName), }); } } // Vendor Serial (SN) if (cleanedLine.includes("Vendor Serial (SN)")) { const PCB_SN = extractSN(cleanedLine.split(":")[1]); if (PCB_SN) { results.push({ PID, VID: "", SN: PCB_SN.trim(), line: [index + 1], brand, fileName: fName, warehouse: getWarehouse(fName), }); } } if (cleanedLine.includes("System serial num")) { const PCB_SN = extractSN(cleanedLine.split(":")[1]); if (PCB_SN) { results.push({ PID, VID: "", SN: PCB_SN, line: [index + 1], brand, fileName: fName, warehouse: getWarehouse(fName), }); } } // Processor board ID if (cleanedLine.includes("Processor board ID") || cleanedLine.includes("Processor Board ID")) { const PBID = extractSN(cleanedLine.split(" ").pop()); if (PBID?.length >= 8) { results.push({ PID, VID: "", SN: PBID, line: [index + 1], brand, fileName: fName, warehouse: getWarehouse(fName), }); } } return results; }; const mergeLines = (output, lineResult) => { lineResult.forEach((entry) => { const existing = output.find((o) => o.SN === entry.SN); if (existing) { existing.line = [...new Set([...existing.line, ...entry.line])]; if (entry.PID) existing.PID = entry.PID; if (entry.VID) existing.VID = entry.VID; } else { output.push(entry); } }); }; const fetchFiles = async (from, to) => { try { const urls = await getListLog(from, to); if (!urls || urls.length === 0) { console.log("No logs found"); return []; } const fileContents = await Promise.all( urls.map((u) => fetchWithRetry(u?.split(".log")[0] + ".log")) ); let report: any = []; fileContents.forEach((content, index) => { const lines = content?.split("\n"); if (!lines) return; const fName = path.basename(urls[index] ?? "").trim(); const output = []; //Vendor Description: --> brand let currentBrand = "" let currentPID = "" lines.forEach((line, i) => { const cleanedLine = line.replace(/\r/g, ""); if (cleanedLine.includes("Vendor Description")) { currentBrand = cleanedLine.split("Vendor Description:")[1]?.trim(); } if (cleanedLine.includes("Vendor Part Number")) { // console.log("Brand: ", cleanedLine) // console.log("Brand1: ", cleanedLine.split("Vendor Part Number:")[1]) currentPID = cleanedLine.split("Vendor Part Number:")[1]?.trim(); } const lineResult = extractInfoFromLine(cleanedLine, i, fName, lines, currentBrand, currentPID); // Nếu dòng này tạo ra SN nào đó -> coi như brand đã được dùng xong if (lineResult.length > 0 && currentBrand) { currentBrand = ""; } if (lineResult.length > 0 && currentPID) { currentPID = ""; } mergeLines(output, lineResult); }); report = [...report, ...output]; }); const finalReport = report.filter( (i) => i.SN && /^[A-Z0-9-]{5,}$/.test(i.SN) ); fs.writeFileSync( "./app/utils/indexSN.txt", JSON.stringify(finalReport, null, 2).replace(/\\u0000/g, ""), "utf-8" ); console.log("Write loggg !"); return finalReport; } catch (error) { console.error("GET INFORMATION FAIL", error); throw error; } }; const result = await fetchFiles(from, to); response.status(200).json(result); } /** * Controller lay noi dung file log theo so dong * @param {String} fileName url file log tren server log * @param {Integer} line dong chua serial number trong log * @param {Integer} range khoang dong truoc/sau line * @author {Token} req.headers.authorization //token xac thuc */ public async getParagraphOld({ request, response }: HttpContextContract) { const { fileName, line, range } = request.all(); try { let fName = fileName; const res = await axios.get(BASE_URL + "/" + fName); const arrayLine = res?.data?.split("\n"); if (Number(range) >= Number(line)) { response.status(200).json({ content: arrayLine?.slice(0, line + range)?.join("\n"), }); } else { response.status(200).json({ content: arrayLine?.slice(line - range - 1, line + range)?.join("\n"), }); } } catch (error) { console.log(error); response.status(202).send({ mess: "FILE NOT FOUND", error: error }); } } public async getParagraph({ request, response }: HttpContextContract) { const { fileName, line, range } = request.all(); try { let fName = fileName; // const res = await axios.get(BASE_URL + "/" + fName); const LOG_DIR = "/home/logs"; const filePath = path.join(LOG_DIR, fileName); const res = await fs.readFileSync(filePath, "utf-8"); const arrayLine = res?.split("\n"); if (Number(range) >= Number(line)) { response.status(200).json({ content: arrayLine?.slice(0, line + range)?.join("\n"), }); } else { response.status(200).json({ content: arrayLine?.slice(line - range - 1, line + range)?.join("\n"), }); } } catch (error) { console.log(error); response.status(202).send({ mess: "FILE NOT FOUND", error: error }); } } public async store({ request, response }: HttpContextContract) { } public async show({ }: HttpContextContract) { } public async edit({ }: HttpContextContract) { } public async update({ }: HttpContextContract) { } public async destroy({ }: HttpContextContract) { } }