Files
price-bot/index.js

143 lines
3.9 KiB
JavaScript

const cheerio = require("cheerio");
const cron = require("node-cron");
const axios = require("axios");
const fs = require("fs");
const { chromium } = require("playwright");
const discordWebhook =
"https://discord.com/api/webhooks/1439286509390921749/t2Hb8XloF6zhDRYD1yh_QlkHHa9eHUyXvd9TxZRHwqR_b_OxxbnwDgsm4em8TwA9NQIa";
function sendMessage(message) {
axios.post(discordWebhook, {
content: message,
});
}
let isFirstRun = true;
async function compareAndSave(productsPrice) {
if (!fs.existsSync("productsPrice.json")) {
fs.writeFileSync("productsPrice.json", "[]");
}
const productsPriceJson = fs.readFileSync("productsPrice.json", "utf8");
const oldProductsPrice = JSON.parse(productsPriceJson);
const diffProducts = [];
for (const product of productsPrice) {
const oldProduct = oldProductsPrice.find(
(oldProduct) => oldProduct.name === product.name
);
if (oldProduct && oldProduct.price !== product.price) {
diffProducts.push({
name: product.name,
newPrice: product.price,
oldPrice: oldProduct.price,
link: product.link,
shop: product.shop,
});
}
}
for (const product of diffProducts) {
sendMessage(
`Zmiana ceny **${product.name}**: ${product.oldPrice} -> ${product.newPrice}\nLink: ${product.link}`
);
}
if (isFirstRun) {
for (const product of productsPrice) {
sendMessage(`Początkowa cena **${product.name}**: ${product.price}`);
}
isFirstRun = false;
}
fs.writeFileSync(
"productsPrice.json",
JSON.stringify(productsPrice, null, 2)
);
}
async function getProducts() {
const products = await axios
.get(
"https://db.maciaszek.ovh/api/collections/gifts_items/records?fields=ceneo_id&filter=ceneo_id!=''"
)
.then((response) => response.data.items.map((item) => item.ceneo_id));
return products;
}
async function init() {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
userAgent:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
});
const page = await context.newPage();
const productsIds = await getProducts();
const products = [];
for (const productId of productsIds) {
try {
await page.goto(`https://www.ceneo.pl/${productId}`, {
waitUntil: "networkidle",
timeout: 30000,
});
// Wait for bot detection to pass and content to load
await page
.waitForSelector(".product-offer__container, .product-top", {
timeout: 10000,
})
.catch(() => {
console.log(`Timeout waiting for content on ${productId}`);
});
const html = await page.content();
const $ = cheerio.load(html);
const items = $(".product-offer__container").first();
for (const item of items) {
let name = $(item).data("productname");
let price = $(item).data("price");
let link = `https://www.ceneo.pl/${$(item).data("click-url")}`;
const shop = $(item).data("shopurl") || "ceneo.pl";
if (!name || !price) {
name = $(item).find(".short-name__txt").text();
price = $(item).find(".price").text();
link = `https://www.ceneo.pl/${productId}`;
}
if (!name || !price || !link) {
continue;
}
products.push({ name, price, link, shop });
}
} catch (error) {
console.error(`Error fetching product ${productId}:`, error.message);
}
}
await browser.close();
await compareAndSave(products);
console.log("Aktualne ceny zapisane w productsPrice.json");
}
sendMessage("Startuję monitoring cen");
const task = cron.schedule("*/15 7-23 * * *", init, {
timezone: "Europe/Warsaw",
});
cron.schedule("0 7 * * *", () => {
const date = new Date().toLocaleDateString("pl-PL");
sendMessage(`Zaczynamy monitoring ${date}`);
});
task.execute();