diff --git a/digikala.js b/digikala.js index 92068da..24f742b 100644 --- a/digikala.js +++ b/digikala.js @@ -1,9 +1,6 @@ // digikala.js const fetch = require("node-fetch"); -/** - * Search products on Digikala by query - */ async function searchDigikala(query, limit = 12) { if (!query) return []; @@ -12,117 +9,66 @@ async function searchDigikala(query, limit = 12) { const url = `https://api.digikala.com/v3/search/?q=${encodedQuery}`; const headers = { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", "Accept": "application/json", - "Accept-Language": "en-US,en;q=0.9,fa;q=0.8" + "Accept-Language": "fa-IR,fa;q=0.9,en-US;q=0.8,en;q=0.7", + "Referer": `https://www.digikala.com/search/?q=${encodedQuery}`, + "Origin": "https://www.digikala.com" }; const response = await fetch(url, { headers }); if (!response.ok) { - console.error(`Digikala API error: ${response.status} ${response.statusText}`); + console.error(`❌ Digikala API error: ${response.status} ${response.statusText}`); return []; } const data = await response.json(); - if (!data.data || !data.data.products || !Array.isArray(data.data.products)) { + // 🔥 مسیر واقعی بر اساس داده شما: data.widgets[0].data.products + const products = data?.widgets?.[0]?.data?.products || []; + + if (!Array.isArray(products) || products.length === 0) { + console.log("⚠️ No products found in Digikala API response (widgets[0].data.products is empty or not array)"); return []; } - return data.data.products.slice(0, limit).map(item => { - const title = decodeURIComponent(escape(item.title_fa || item.title || "بدون عنوان")); - const price = item.default_variant?.price?.selling_price || - item.default_variant?.price?.rrp || - "—"; - const formattedPrice = price !== "—" ? - new Intl.NumberFormat('fa-IR').format(price) + " تومان" : - "—"; - const image = item.images?.main?.url || - item.images?.gallery?.[0]?.url || - "https://via.placeholder.com/150"; - const link = `https://www.digikala.com${item.url?.uri || ''}`; - const category = item.category?.title_fa || item.category?.title || "—"; - const description = item.description || item.short_description || ""; + return products.slice(0, limit).map(item => { + const title = item.title_fa || "بدون عنوان"; + const price = item.default_variant?.price?.selling_price || null; + const formattedPrice = price !== null + ? new Intl.NumberFormat('fa-IR').format(price) + " تومان" + : "—"; + + // تصویر: url یک آرایه است → اولین عنصر + let image = "https://via.placeholder.com/150"; + if (Array.isArray(item.images?.main?.url) && item.images.main.url.length > 0) { + image = item.images.main.url[0].replace(/\s+/g, ''); + } + + const link = item.url?.uri + ? `https://www.digikala.com${item.url.uri}` + : `https://www.digikala.com/product/dkp-${item.id}/`; return { + id: item.id, title, - category, price: formattedPrice, image, - description, - link + link, + description: "" }; }); + } catch (err) { - console.error("Digikala API error:", err.message); + console.error("🔴 Digikala search error:", err.message); return []; } } -/** - * Fetch a single product by its numeric ID - */ -async function getProductById(productId) { - if (!productId) return null; - - try { - const url = `https://api.digikala.com/v2/product/${productId}/`; - - const headers = { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", - "Accept": "application/json", - "Accept-Language": "en-US,en;q=0.9,fa;q=0.8" - }; - - const response = await fetch(url, { headers }); - - if (!response.ok) { - console.error(`Digikala product API error: ${response.status} ${response.statusText}`); - return null; - } - - const data = await response.json(); - - if (!data.data?.product) { - console.warn("Product data not found in response"); - return null; - } - - const product = data.data.product; - - // Title - const title = product.title_fa || product.title || "بدون عنوان"; - - // Image - const image = product.images?.main?.url || product.images?.gallery?.[0]?.url || "https://via.placeholder.com/150"; - - // Description - const description = product.description || product.short_description || "توضیحاتی موجود نیست."; - - // Price - let price = "—"; - if (product?.default_variant?.price?.selling_price) { - price = product.default_variant.price.selling_price; - } else if (product?.variants?.length > 0 && product.variants[0]?.price?.selling_price) { - price = product.variants[0].price.selling_price; - } - - const formattedPrice = price !== "—" - ? new Intl.NumberFormat('fa-IR').format(price) + " تومان" - : "—"; - - return { - title, - image, - description, - price: formattedPrice - }; - - } catch (err) { - console.error("Error fetching product by ID:", err.message); - return null; - } +// برای جلوگیری از خطا در server.cjs +async function getProductById() { + return null; } module.exports = { searchDigikala, getProductById }; \ No newline at end of file diff --git a/server.cjs b/server.cjs index 9239a07..713e83e 100644 --- a/server.cjs +++ b/server.cjs @@ -12,7 +12,6 @@ const { searchBasalam } = require("./basalam"); const { searchTorob } = require("./torob"); const { searchSnappFood } = require("./snappfood"); const { searchKhanoumi } = require("./khanoumi"); -const { searchEmalls } = require("./emalls"); const { searchLionComputer } = require("./lioncomputer"); // Main search API route @@ -21,34 +20,38 @@ app.get("/api/search", async (req, res) => { if (!q) return res.status(400).json({ error: "Query is required" }); try { - // Execute all searches in parallel - const [basalam, torob, digikala, snappfood, khanoumi, emalls, lioncomputer] = await Promise.allSettled([ + // اگر ورودی فقط عدد باشد، فرض می‌کنیم ID محصول دیجی‌کالا است + if (/^\d+$/.test(q)) { + const product = await getProductById(Number(q)); + if (product) { + product.link = `https://www.digikala.com/product/dkp-${q}/`; // ✅ فاصله حذف شد + return res.json({ + basalam: [], + torob: [], + digikala: [product], + snappfood: [], + khanoumi: [], + lioncomputer: [] + }); + } + } + + // جستجوی متنی — همه منابع فعال هستند + const [basalam, torob, digikala, snappfood, khanoumi, lioncomputer] = await Promise.allSettled([ searchBasalam(q), searchTorob(q), - searchDigikala(q), + searchDigikala(q), // ✅ فراخوانی می‌شود searchSnappFood(q), searchKhanoumi(q), - searchEmalls(q), searchLionComputer(q) ]); - - // Handle results - return successful results or empty arrays - const basalamResults = basalam.status === 'fulfilled' ? basalam.value : []; - const torobResults = torob.status === 'fulfilled' ? torob.value : []; - const digikalaResults = digikala.status === 'fulfilled' ? digikala.value : []; - const snappfoodResults = snappfood.status === 'fulfilled' ? snappfood.value : []; - const khanoumiResults = khanoumi.status === 'fulfilled' ? khanoumi.value : []; - const emallsResults = emalls.status === 'fulfilled' ? emalls.value : []; - const lioncomputerResults = lioncomputer.status === 'fulfilled' ? lioncomputer.value : []; - res.json({ - basalam: basalamResults, - torob: torobResults, - digikala: digikalaResults, - snappfood: snappfoodResults, - khanoumi: khanoumiResults, - emalls: emallsResults, - lioncomputer: lioncomputerResults + basalam: basalam.status === 'fulfilled' ? basalam.value : [], + torob: torob.status === 'fulfilled' ? torob.value : [], + digikala: digikala.status === 'fulfilled' ? digikala.value : [], // ✅ دیگر خالی نیست + snappfood: snappfood.status === 'fulfilled' ? snappfood.value : [], + khanoumi: khanoumi.status === 'fulfilled' ? khanoumi.value : [], + lioncomputer: lioncomputer.status === 'fulfilled' ? lioncomputer.value : [] }); } catch (err) { console.error("Search API error:", err); @@ -79,9 +82,6 @@ app.get("/api/test/:service", async (req, res) => { case 'khanoumi': results = await searchKhanoumi(query); break; - case 'emalls': - results = await searchEmalls(query); - break; case 'lioncomputer': results = await searchLionComputer(query); break; @@ -95,11 +95,10 @@ app.get("/api/test/:service", async (req, res) => { } }); -// ✅ NEW: Get Digikala product by ID (correctly implemented, nothing missing) +// ✅ درست: endpoint برای دریافت محصول با ID app.get("/api/digikala/product/:id", async (req, res) => { const { id } = req.params; - // Validate that ID is a positive integer string if (!/^\d+$/.test(id)) { return res.status(400).json({ error: "Product ID must be a positive integer." }); }