286 lines
8.2 KiB
TypeScript
286 lines
8.2 KiB
TypeScript
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("<a href") !== -1 && i.search(".log") !== -1);
|
|
// let data2 = responseAUTO.data
|
|
// .split("\n")
|
|
// .filter((i) => i.search("<a href") !== -1 && i.search(".log") !== -1);
|
|
|
|
const arrayLine = data1;
|
|
|
|
// const arrayLineAUTO = data
|
|
// .split("\n")
|
|
// .filter((i) => i.search("<a href") !== -1 && i.search(".log") !== -1);
|
|
|
|
arrayLine.map((u) => {
|
|
let temp = u
|
|
.slice(u.search("<a ") + 9, u.search("</a>"))
|
|
.split(">")[1];
|
|
|
|
if (
|
|
parseInt(temp?.split("-")[0]) >= from &&
|
|
parseInt(temp?.split("-")[0]) <= to
|
|
) {
|
|
listLog.push(
|
|
(BASE_URL + "/") +
|
|
u.slice(u.search("<a ") + 9, u.search("</a>")).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) {}
|
|
}
|