import CONSTANTS from './constants.js'; import fs from 'fs'; import path from 'path'; import { updateStatusWork } from './apis/bid.js'; export const isNumber = (value) => !isNaN(value) && !isNaN(parseFloat(value)); export const takeSnapshot = async (page, item, imageName, type = CONSTANTS.TYPE_IMAGE.ERRORS) => { if (!page || page.isClosed()) return; try { global.IS_CLEANING = false; const baseDir = path.join(CONSTANTS.ERROR_IMAGES_PATH, item.type, String(item.id)); // Thư mục theo lot_id const typeDir = path.join(baseDir, type); // Thư mục con theo type // Tạo tên file, nếu type === 'work' thì không có timestamp const fileName = type === CONSTANTS.TYPE_IMAGE.WORK ? `${imageName}.png` : `${imageName}_${new Date().toISOString().replace(/[:.]/g, '-')}.png`; const filePath = path.join(typeDir, fileName); // Kiểm tra và tạo thư mục nếu chưa tồn tại if (!fs.existsSync(typeDir)) { fs.mkdirSync(typeDir, { recursive: true }); console.log(`📂 Save at folder: ${typeDir}`); } // await page.waitForSelector('body', { visible: true, timeout: 5000 }); // Kiểm tra có thể điều hướng trang không const isPageResponsive = await page.evaluate(() => document.readyState === 'complete'); if (!isPageResponsive) { console.log('🚫 Page is unresponsive, skipping snapshot.'); return; } // Chờ tối đa 15 giây, nếu không thấy thì bỏ qua await page.waitForSelector('body', { visible: true, timeout: 15000 }).catch(() => { console.log('⚠️ Body selector not found, skipping snapshot.'); return; }); // Chụp ảnh màn hình và lưu vào filePath await page.screenshot({ path: filePath }); console.log(`📸 Image saved at: ${filePath}`); // Nếu type === 'work', gửi ảnh lên API if (type === CONSTANTS.TYPE_IMAGE.WORK) { await updateStatusWork(item, filePath); } } catch (error) { console.log('Error when snapshot: ' + error.message); } }; export const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); export async function safeClosePage(item) { try { const page = item.page_context; if (!page?.isClosed() && page?.close) { await page.close(); } item.page_context = undefined; if (item?.page_context) { item.page_context = undefined; } } catch (error) { console.log("Can't close item: " + item.id); } } export function isTimeReached(targetTime) { if (!targetTime) return false; const targetDate = new Date(targetTime); const now = new Date(); return now >= targetDate; } export function extractNumber(str) { const match = str.match(/\d+(\.\d+)?/); return match ? parseFloat(match[0]) : null; } export const sanitizeFileName = (url) => { return url.replace(/[:\/]/g, '_'); }; export const getPathProfile = (origin_url) => { return path.join(CONSTANTS.PROFILE_PATH, sanitizeFileName(origin_url) + '.json'); }; export function removeFalsyValues(obj, excludeKeys = []) { return Object.entries(obj).reduce((acc, [key, value]) => { if (value || excludeKeys.includes(key)) { acc[key] = value; } return acc; }, {}); }