const crypto = require("crypto"); const { authenticator } = require("otplib"); const dotenv = require("dotenv").config({ path: __dirname + "/.env" }); const { DateTime } = require("luxon"); /** * get crypto config */ const getCryptoConfig = function () { const ivStr = "1851aa2e5f98522bbe1b8ac1f8305d8a"; return { key: "tD0!wR6^cH8!mO0)wJ7;bZ0&eW6;iT6>", iv: Buffer.from(ivStr, "hex"), algo: "aes-256-cbc", }; }; exports.getCryptoConfig = getCryptoConfig; /** * encrypt string */ const encryptString = function (str, algo, key, iv) { // create cipher const cipher = crypto.createCipheriv(algo, Buffer.from(key), iv); // encrypt data let encryptedStr = cipher.update(str); encryptedStr = Buffer.concat([encryptedStr, cipher.final()]); return encryptedStr.toString("hex"); }; exports.encryptString = encryptString; /** * decrypt string */ const decryptString = function (encryptedStr, algo, key, iv) { // create decipher const decipher = crypto.createDecipheriv(algo, Buffer.from(key), iv); // decrypt string let decryptedStr = decipher.update(Buffer.from(encryptedStr, "hex")); decryptedStr = Buffer.concat([decryptedStr, decipher.final()]); return decryptedStr.toString(); }; exports.decryptString = decryptString; /** * get browser config */ const getBrowserConfig = function (profilePath, env) { let browserConfig = {}; browserConfig["ignoreDefaultArgs"] = ["--disable-extensions"]; browserConfig["timeout"] = 60000; browserConfig["headless"] = true; // prod specific if (env === "prod") { browserConfig["args"] = [ "--disable-gpu", "--disable-setuid-sandbox", "--no-sandbox", "--no-zygote", "--incognito", ]; // `--user-data-dir=${profilePath}`, browserConfig["executablePath"] = "/usr/bin/chromium-browser"; } // dev specific if (env === "dev") { browserConfig["headless"] = false; browserConfig["args"] = [`--user-data-dir=${profilePath}`]; } return browserConfig; }; exports.getBrowserConfig = getBrowserConfig; /** * try temu login */ const tryTemuLogin = async function (page, username, password) { try { // if login required if( ! page.url().includes('seller.temu.com/login.html') ){ console.log( 'No Login Required' ); return; } // if already account added const differentAccountSelector = "body > div.MDL_outerWrapper_123.MDL_modal_123 > div > div > div > div.MDL_body_123 > div > div._1RYwO6mj > span:nth-child(1)" await page.waitForSelector(differentAccountSelector, { timeout: 5000 }).catch(() => {}); const differentAccountSelectorExists = (await page.$(differentAccountSelector)) !== null; if (differentAccountSelectorExists) { await page.click(differentAccountSelector); } // click on Sign in link const selector = "div._31ia9mDL._3n05KUVj._1fE9CAB_"; await page.waitForSelector(selector, { timeout: 5000 }).catch(() => {}); const elementExists = (await page.$(selector)) !== null; if (elementExists) { await page.click(selector); } // email input const inputSelectors = "input._3s66f8p-"; await page.waitForSelector(inputSelectors, { timeout: 5000 }).catch((e) => { console.log(e) }); const elements = await page.$$(inputSelectors); console.log( elements ) for (let element of elements) { const type = await page.evaluate((el) => el.type, element); if ( type === "password" ) { await element.type(password); } else { await element.type(username); } } const loginBtn = "span._1YdMCUKt" await page.waitForSelector(loginBtn, { timeout: 5000 }).catch(() => {}); let loginBtnElement = (await page.$(loginBtn)) !== null; if (loginBtnElement) { await page.click(loginBtn); } } catch (e) { console.log(e); } }; exports.tryTemuLogin = tryTemuLogin; /** * try login */ const tryLogin = async function (page, username, password, finalUrl, secret) { try { // see if email is required to login const requireEmail = await page.evaluate(async function () { return document.querySelector("#ap_email") !== null; }); if (requireEmail) { console.log("Login: Email is required"); await page.evaluate(async function () { document.querySelector("#ap_email").value = ""; }); await page.type("#ap_email", username); } // see if continue button is required const continueBtn = await page.evaluate(async function () { return document.querySelector("#continue") !== null; }); if (continueBtn) { console.log("Login: Continue button is required"); await page.click("#continue"); // wait 5s to page to load await new Promise((resolve) => setTimeout(resolve, 5000)); } // see if password is required to login const requirePassword = await page.evaluate(async function () { return document.querySelector("#ap_password") !== null; }); if (requirePassword) { await page.evaluate(async function () { document.querySelector("#ap_password").value = ""; }); await page.type("#ap_password", password); } // check if it has remember me button const rememberMeBtn = await page.evaluate(async function () { return document.querySelector('[name="rememberMe"]') !== null; }); if (rememberMeBtn) { await page.click('[name="rememberMe"]'); } // check if we need to click on sign-in button const requireSubmit = await page.evaluate(async function () { return document.querySelector("#signInSubmit") !== null; }); if (requireSubmit) { console.log("Login: Submit button is required"); await Promise.all([ page.click("#signInSubmit"), page.waitForNavigation({ waitUntil: "networkidle0" }), ]); } // check if device option is required const requireDeviceOption = await page.evaluate(async function () { return document.querySelector("#auth-select-device-form") !== null; }); if (requireDeviceOption) { // select device option console.log("Login: Device option is required"); await page.click('.a-radio.auth-TOTP [type="radio"]'); } // check if send code option is required const requireSendCode = await page.evaluate(async function () { return document.querySelector("#auth-send-code") !== null; }); if (requireSendCode) { await Promise.all([ page.click("#auth-send-code"), page.waitForNavigation({ waitUntil: "networkidle0" }), ]); } // check if mfa is required const requireMfa = await page.evaluate(async function () { return document.querySelector("#auth-mfa-otpcode") !== null; }); if (requireMfa) { console.log("Login: MFA is required"); // wait 30s to manually enter mfa const toptCode = generateotpzfromHash(process.env["totp"]); await page.type("#auth-mfa-otpcode", toptCode); await page.click("#auth-signin-button"), await new Promise((resolve) => setTimeout(resolve, 45 * 1000)); } // see if we have skip phone number button const requireSkipPhone = await page.evaluate(async function () { return ( document.querySelector("#ap-account-fixup-phone-skip-link") !== null ); }); if (requireSkipPhone) { await Promise.all([ page.click("#ap-account-fixup-phone-skip-link"), page.waitForNavigation({ waitUntil: "networkidle0" }), ]); } // goto final url if ( requireEmail || requirePassword || requireSubmit || requireSkipPhone || rememberMeBtn ) { await page.goto(finalUrl, { waitUntil: ["domcontentloaded"], }); } } catch (e) { console.log(e); } }; exports.tryLogin = tryLogin; /** * generate code */ const generateotpzfromHash = function (secret) { return authenticator.generate(secret); }; /** * get sellercentral home url */ const getSellerCentralHomeUrl = function (marketplace) { const marketplaceObj = marketplaces["marketplaces"][marketplace]; return `https://sellercentral.${marketplaceObj["url"]}/home?mons_sel_dir_mcid=${marketplaceObj["monsSelDirMcid"]}&mons_sel_mkid=${marketplaceObj["marketplaceId"]}&mons_sel_dir_paid=${marketplaceObj["monsSelDirPaid"]}&ignore_selection_changed=true`; }; exports.getSellerCentralHomeUrl = getSellerCentralHomeUrl; /** * get sellercentral inventory url */ const getSellerCentralInventoryUrl = function (marketplace) { const marketplaceObj = marketplaces["marketplaces"][marketplace]; return `https://sellercentral.${marketplaceObj["url"]}/myinventory/inventory?fulfilledBy=all&page=1&pageSize=25&sort=date_created_desc&status=all`; }; exports.getSellerCentralInventoryUrl = getSellerCentralInventoryUrl; /* * temu image url */ const getLabelImageUrl = function (imageUrl) { return `https://aimg.kwcdn.com/upload_aimg/temu/${imageUrl}`; }; exports.getLabelImageUrl = getLabelImageUrl; /* * temu order page */ const getTemuOrderPage = function( poNumber ){ return `https://seller.temu.com/order-detail.html?parent_order_sn=${poNumber}` } exports.getTemuOrderPage = getTemuOrderPage; /* * temu orders page */ const getTemuOrdersPage = function( pageNumber ){ return `https://seller.temu.com/orders.html?activeTab=${pageNumber}`; } exports.getTemuOrdersPage = getTemuOrdersPage; /* * check list */ const isEmpty = function (arr) { return arr === undefined || arr.length === 0; } exports.isEmpty = isEmpty; /** * daily pick pack from cosmos ( dimensions ) */ const getSkuDailyPickPack = function( skuStr, date){ return `https://cosmos.utopiadeals.com/cosmos/daily-pick-packs-json?marketplace=AMAZON_USA&skus=${skuStr}&from=${date}&to=${date}` } exports.getSkuDailyPickPack = getSkuDailyPickPack; /* * */ const getFirstDayToCurrentMonth = function( ){ const now = new Date(); const firstDay = new Date(now.getFullYear(), now.getMonth(), 2); return firstDay.toISOString().split('T')[0]; } exports.getFirstDayToCurrentMonth = getFirstDayToCurrentMonth; /** * write a function to convert UTC into pakistan standard time using luxon libraryy in 12 hour */ const getPakistanStandardTime = function( utcTime ){ return DateTime.fromISO( utcTime ).setZone('Asia/Karachi').toFormat('dd-MMM-yyyy hh:mm:ss a'); } exports.getPakistanStandardTime = getPakistanStandardTime;