import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3'; const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', }; Deno.serve(async (req) => { if (req.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } try { const supabaseUrl = Deno.env.get('SUPABASE_URL')!; const supabaseKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; const supabase = createClient(supabaseUrl, supabaseKey); console.log('Starting price check...'); // Get all enabled alert profiles const { data: alertProfiles, error: profilesError } = await supabase .from('alert_profiles') .select('*') .eq('enabled', true); if (profilesError) { throw profilesError; } console.log(`Found ${alertProfiles?.length || 0} active alert profiles`); // Get all products const { data: products, error: productsError } = await supabase .from('products') .select('*'); if (productsError) { throw productsError; } console.log(`Found ${products?.length || 0} products`); const alerts = []; // Check each alert profile against products for (const profile of alertProfiles || []) { for (const product of products || []) { // Match category if (product.category !== profile.category) continue; // Check if product meets specification requirements const specsFilter = profile.specs_filter; const productSpecs = product.specs; let meetsRequirements = true; // Check minimum size (for harddrives/ram) if (specsFilter.min_size) { const minSizeValue = parseFloat(specsFilter.min_size); const productSizeValue = parseFloat(productSpecs.size || '0'); if (productSizeValue < minSizeValue) { meetsRequirements = false; } } // Check type (SSD/HDD/etc) if (specsFilter.type && productSpecs.type !== specsFilter.type) { meetsRequirements = false; } // Check if price is below target if (!meetsRequirements || product.current_price > profile.target_price) { continue; } // Found a match! Log the alert const message = `🎯 Alert: ${profile.name}\n` + `Product: ${product.name}\n` + `Price: ${product.current_price} ${product.currency}\n` + `Target: ${profile.target_price} ${product.currency}\n` + `Store: ${product.store}\n` + `URL: ${product.url}`; const { error: logError } = await supabase .from('alerts_log') .insert({ alert_profile_id: profile.id, product_id: product.id, triggered_price: product.current_price, message, sent_to_discord: false }); if (logError) { console.error('Error logging alert:', logError); } alerts.push({ profile, product, message }); // Send Discord notification if webhook URL is set if (profile.discord_webhook_url) { try { await fetch(profile.discord_webhook_url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: message, embeds: [{ title: '💰 Price Alert!', description: message, color: 0x00ff00, fields: [ { name: 'Current Price', value: `${product.current_price} ${product.currency}`, inline: true }, { name: 'Target Price', value: `${profile.target_price} ${product.currency}`, inline: true }, { name: 'Savings', value: `${(profile.target_price - product.current_price).toFixed(2)} ${product.currency}`, inline: true } ], timestamp: new Date().toISOString() }] }) }); // Update log to mark as sent await supabase .from('alerts_log') .update({ sent_to_discord: true }) .eq('alert_profile_id', profile.id) .eq('product_id', product.id); console.log(`Sent Discord notification for ${product.name}`); } catch (discordError) { console.error('Error sending Discord notification:', discordError); } } } } console.log(`Price check complete. Found ${alerts.length} matching alerts`); return new Response( JSON.stringify({ success: true, alertsTriggered: alerts.length, alerts }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } catch (error) { console.error('Error in check-prices function:', error); const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return new Response( JSON.stringify({ error: errorMessage }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } });