106 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
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, fullPage: true });
 | 
						|
 | 
						|
        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);
 | 
						|
    } finally {
 | 
						|
        global.IS_CLEANING = true;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
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;
 | 
						|
    }, {});
 | 
						|
}
 |