import fs from "fs"; import type { HttpContextContract } from "@ioc:Adonis/Core/HttpContext"; import axios from "axios"; import Env from "@ioc:Adonis/Core/Env"; const path = require("path"); const BASE_URL = Env.get("BASE_URL_LOG"); const BASE_URL_AUTO = `${BASE_URL}/AUTOlog/`; 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 getListLog = 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(" i.search(" i.search(" { let temp = u .slice(u.search("")) .split(">")[1]; if ( parseInt(temp?.split("-")[0]) >= from && parseInt(temp?.split("-")[0]) <= to ) { listLog.push( (BASE_URL + "/") + u.slice(u.search("")).split(">")[1] + " " ); } }); return listLog; } catch (error) { console.log(error); } }; 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 = (line, index, fName) => { const cleanedLine = line.replace(/\r/g, ""); 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] ?? "" ); const 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], 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], 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], 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], fileName: fName, warehouse: getWarehouse(fName), }); } } // Processor board ID if (cleanedLine.includes("Processor board ID")) { const PBID = extractSN(cleanedLine.split(" ").pop()); if (PBID?.length >= 8) { results.push({ PID: "", VID: "", SN: PBID, line: [index + 1], 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 = []; lines.forEach((line, i) => { const lineResult = extractInfoFromLine(line, i, fName); mergeLines(output, lineResult); }); report = [...report, ...output]; }); const finalReport = report.filter( (i) => i.SN && /^[A-Z0-9-]{5,}$/.test(i.SN) && i.PID ); 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 getParagraph({ request, response }: HttpContextContract) { const { fileName, line, range } = request.all(); try { let fName = fileName.search("AUTO") !== -1 ? "AUTOlog/" + fileName : 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 store({ request, response }: HttpContextContract) {} public async show({}: HttpContextContract) {} public async edit({}: HttpContextContract) {} public async update({}: HttpContextContract) {} public async destroy({}: HttpContextContract) {} }