← back to Flockedwallpaper

check-recent-flock.js

224 lines

require('dotenv').config();
const axios = require('axios');
const fs = require('fs');

const SHOPIFY_STORE = process.env.SHOPIFY_STORE_NAME;
const ACCESS_TOKEN = process.env.SHOPIFY_ACCESS_TOKEN;
const API_VERSION = process.env.SHOPIFY_API_VERSION || '2024-10';

// Shopify Admin API GraphQL endpoint
const GRAPHQL_ENDPOINT = `https://${SHOPIFY_STORE}.myshopify.com/admin/api/${API_VERSION}/graphql.json`;

async function fetchRecentFlockProducts() {
    console.log('🔍 Fetching recently updated/created flock products from Shopify...');

    const allProducts = [];
    let hasNextPage = true;
    let cursor = null;

    // Get date 30 days ago for comparison
    const thirtyDaysAgo = new Date();
    thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

    while (hasNextPage) {
        const query = `
            query ($cursor: String) {
                products(first: 250, after: $cursor, query: "flock status:active", sortKey: UPDATED_AT, reverse: true) {
                    edges {
                        cursor
                        node {
                            id
                            title
                            handle
                            description
                            productType
                            vendor
                            tags
                            createdAt
                            updatedAt
                            status
                            variants(first: 10) {
                                edges {
                                    node {
                                        id
                                        title
                                        sku
                                        price
                                    }
                                }
                            }
                            featuredImage {
                                url
                                altText
                            }
                            images(first: 5) {
                                edges {
                                    node {
                                        url
                                        altText
                                    }
                                }
                            }
                        }
                    }
                    pageInfo {
                        hasNextPage
                        endCursor
                    }
                }
            }
        `;

        try {
            const response = await axios.post(
                GRAPHQL_ENDPOINT,
                {
                    query: query,
                    variables: { cursor: cursor }
                },
                {
                    headers: {
                        'Content-Type': 'application/json',
                        'X-Shopify-Access-Token': ACCESS_TOKEN
                    }
                }
            );

            if (response.data.errors) {
                console.error('GraphQL Errors:', response.data.errors);
                break;
            }

            const products = response.data.data.products.edges;
            allProducts.push(...products);

            hasNextPage = response.data.data.products.pageInfo.hasNextPage;
            cursor = response.data.data.products.pageInfo.endCursor;

            console.log(`  Fetched ${allProducts.length} products so far...`);

            // Rate limiting: wait 500ms between requests
            await new Promise(resolve => setTimeout(resolve, 500));

        } catch (error) {
            console.error('❌ Error fetching products:', error.message);
            if (error.response) {
                console.error('Response data:', error.response.data);
            }
            break;
        }
    }

    console.log(`\n✅ Total products fetched: ${allProducts.length}`);
    return allProducts;
}

function findNewProducts(allProducts) {
    console.log('\n🔍 Checking for new products...');

    // Load existing products
    let existingProducts = [];
    try {
        const data = fs.readFileSync('./flocked-products.json', 'utf8');
        existingProducts = JSON.parse(data);
        console.log(`  Loaded ${existingProducts.length} existing products`);
    } catch (error) {
        console.log('  No existing products file found or error reading it');
    }

    // Create a set of existing product IDs
    const existingIds = new Set(existingProducts.map(p => p.id));

    // Find products that are new (not in existing list)
    const newProducts = [];
    const recentlyUpdated = [];

    const thirtyDaysAgo = new Date();
    thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

    allProducts.forEach(product => {
        const node = product.node;
        const createdDate = new Date(node.createdAt);
        const updatedDate = new Date(node.updatedAt);

        if (!existingIds.has(node.id)) {
            newProducts.push(node);
        } else if (updatedDate > thirtyDaysAgo) {
            recentlyUpdated.push(node);
        }
    });

    return { newProducts, recentlyUpdated, thirtyDaysAgo };
}

function formatProduct(node) {
    const variants = node.variants.edges;
    const skus = variants.map(v => v.node.sku).filter(sku => sku);

    return {
        id: node.id,
        title: node.title,
        handle: node.handle,
        primarySku: skus[0] || 'N/A',
        image: node.featuredImage?.url || node.images.edges[0]?.node.url,
        productUrl: `https://designerwallcoverings.com/products/${node.handle}`,
        createdAt: node.createdAt,
        updatedAt: node.updatedAt
    };
}

async function main() {
    try {
        console.log('🚀 Checking for Recent Flock Product Updates\n');
        console.log(`Store: ${SHOPIFY_STORE}`);
        console.log(`API Version: ${API_VERSION}\n`);

        // Fetch all products sorted by updated date
        const allProducts = await fetchRecentFlockProducts();

        // Find new products
        const { newProducts, recentlyUpdated, thirtyDaysAgo } = findNewProducts(allProducts);

        console.log('\n📊 RESULTS:');
        console.log(`  Total flock products in Shopify: ${allProducts.length}`);
        console.log(`  New products (not in existing JSON): ${newProducts.length}`);
        console.log(`  Recently updated (last 30 days): ${recentlyUpdated.length}`);

        if (newProducts.length > 0) {
            console.log('\n🆕 NEW PRODUCTS FOUND:');
            console.log('=' .repeat(80));
            newProducts.forEach((product, index) => {
                const formatted = formatProduct(product);
                console.log(`\n${index + 1}. ${formatted.title}`);
                console.log(`   SKU: ${formatted.primarySku}`);
                console.log(`   Created: ${new Date(formatted.createdAt).toLocaleDateString()}`);
                console.log(`   URL: ${formatted.productUrl}`);
                console.log(`   Image: ${formatted.image ? '✓' : '✗ Missing'}`);
            });
        } else {
            console.log('\n✓ No new products found - all products are already in flocked-products.json');
        }

        if (recentlyUpdated.length > 0) {
            console.log('\n\n📝 RECENTLY UPDATED PRODUCTS (Last 30 days):');
            console.log('=' .repeat(80));
            recentlyUpdated.slice(0, 10).forEach((product, index) => {
                const formatted = formatProduct(product);
                console.log(`\n${index + 1}. ${formatted.title}`);
                console.log(`   SKU: ${formatted.primarySku}`);
                console.log(`   Updated: ${new Date(formatted.updatedAt).toLocaleDateString()}`);
            });

            if (recentlyUpdated.length > 10) {
                console.log(`\n   ... and ${recentlyUpdated.length - 10} more`);
            }
        }

    } catch (error) {
        console.error('\n❌ Fatal Error:', error.message);
        process.exit(1);
    }
}

main();