diff --git a/api/user-cards.js b/api/user-cards.js index 5fbb920..2c85085 100644 --- a/api/user-cards.js +++ b/api/user-cards.js @@ -12,6 +12,38 @@ export async function GET(request) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } + // Check if tables exist first + try { + const tableCheck = await sql.query(` + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_name = 'user_cards' + ) as user_cards_exists, + EXISTS ( + SELECT FROM information_schema.tables + WHERE table_name = 'cards' + ) as cards_exists + `); + + const { user_cards_exists, cards_exists } = tableCheck.rows[0]; + + if (!user_cards_exists || !cards_exists) { + console.log('Tables do not exist, returning empty array'); + return NextResponse.json({ + success: true, + data: [], + message: 'No cards found (tables not initialized)' + }); + } + } catch (error) { + console.error('Error checking table existence:', error); + return NextResponse.json({ + success: true, + data: [], + message: 'Database not initialized' + }); + } + const { searchParams } = new URL(request.url); const game = searchParams.get('game'); const rarity = searchParams.get('rarity'); diff --git a/src/services/cardDataSources.ts b/src/services/cardDataSources.ts index 556ab2b..0f5c011 100644 --- a/src/services/cardDataSources.ts +++ b/src/services/cardDataSources.ts @@ -5,6 +5,7 @@ const SCRYFALL_BASE_URL = 'https://api.scryfall.com'; const POKEMON_API_BASE_URL = 'https://api.pokemontcg.io/v2'; const YUGIOH_API_BASE_URL = 'https://db.ygoprodeck.com/api/v7'; const LORCAST_API_BASE_URL = 'https://api.lorcast.com/v0'; +const LORCANA_API_BASE_URL = 'https://lorcana-api.com/api/v1'; // Rate limiting utilities @@ -286,7 +287,46 @@ export const lorcanaService = { await lorcastLimiter.waitForSlot(); try { - // Try different search endpoints + // Try Lorcana API first (more reliable) + try { + const response = await fetch(`${LORCANA_API_BASE_URL}/cards?search=${encodeURIComponent(query)}`); + + if (response.ok) { + const data = await response.json(); + const cards = data.cards || data.data || data || []; + + if (cards.length > 0) { + console.log(`✅ Found ${cards.length} Lorcana cards from Lorcana API`); + return cards.map((card: any) => ({ + id: card.id || card.uuid || `lorcana-${Math.random()}`, + name: card.name, + set_name: card.set?.name || card.set_name || '', + set_code: card.set?.code || card.set_code || '', + card_number: card.number || card.card_number || '', + rarity: card.rarity, + game: 'LORCANA', + mana_cost: card.cost?.toString() || card.mana_cost, + cmc: card.cost || card.cmc, + card_type: card.type || card.card_type, + colors: card.colors || [], + oracle_text: card.text || card.oracle_text || '', + power: card.strength?.toString() || card.power, + toughness: card.willpower?.toString() || card.toughness, + image_url: card.image_url || card.images?.small || card.images?.png, + stock_image_url: card.image_url || card.images?.small || card.images?.png, + current_price: card.price?.market || card.current_price || undefined, + market_price: card.price?.low || card.market_price || undefined, + verified: true, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + })); + } + } + } catch (e) { + console.log('❌ Lorcana API failed, trying Lorcast API'); + } + + // Fallback to Lorcast API with multiple endpoints const searchEndpoints = [ `/cards?q=${encodeURIComponent(query)}`, `/cards?search=${encodeURIComponent(query)}`, @@ -306,7 +346,7 @@ export const lorcanaService = { const cards = data.cards || data.data || data || []; if (cards.length > 0) { - console.log(`✅ Found ${cards.length} Lorcana cards from ${endpoint}`); + console.log(`✅ Found ${cards.length} Lorcana cards from Lorcast ${endpoint}`); return cards.map((card: any) => ({ id: card.id || card.uuid || `lorcana-${Math.random()}`, name: card.name, @@ -333,12 +373,12 @@ export const lorcanaService = { } } } catch (e) { - console.log(`❌ Failed to search from ${endpoint}:`, e); + console.log(`❌ Failed to search from Lorcast ${endpoint}:`, e); continue; } } - console.log('⚠️ No Lorcana cards found from any search endpoint'); + console.log('⚠️ No Lorcana cards found from any API'); return []; } catch (error) { console.error('Error searching Lorcana cards:', error); @@ -350,7 +390,47 @@ export const lorcanaService = { await lorcastLimiter.waitForSlot(); try { - // Try different search endpoints for exact name match + // Try Lorcana API first + try { + const response = await fetch(`${LORCANA_API_BASE_URL}/cards?search=${encodeURIComponent(name)}`); + + if (response.ok) { + const data = await response.json(); + const cards = data.cards || data.data || data || []; + + if (cards.length > 0) { + const card = cards[0]; + console.log(`✅ Found Lorcana card "${name}" from Lorcana API`); + return { + id: card.id || card.uuid || `lorcana-${Math.random()}`, + name: card.name, + set_name: card.set?.name || card.set_name || '', + set_code: card.set?.code || card.set_code || '', + card_number: card.number || card.card_number || '', + rarity: card.rarity, + game: 'LORCANA', + mana_cost: card.cost?.toString() || card.mana_cost, + cmc: card.cost || card.cmc, + card_type: card.type || card.card_type, + colors: card.colors || [], + oracle_text: card.text || card.oracle_text || '', + power: card.strength?.toString() || card.power, + toughness: card.willpower?.toString() || card.toughness, + image_url: card.image_url || card.images?.small || card.images?.png, + stock_image_url: card.image_url || card.images?.small || card.images?.png, + current_price: card.price?.market || card.current_price || undefined, + market_price: card.price?.low || card.market_price || undefined, + verified: true, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + } + } + } catch (e) { + console.log('❌ Lorcana API failed for card lookup, trying Lorcast API'); + } + + // Fallback to Lorcast API const searchEndpoints = [ `/cards?q=name:${encodeURIComponent(name)}`, `/cards?search=${encodeURIComponent(name)}`, @@ -371,7 +451,7 @@ export const lorcanaService = { if (cards.length > 0) { const card = cards[0]; - console.log(`✅ Found Lorcana card "${name}" from ${endpoint}`); + console.log(`✅ Found Lorcana card "${name}" from Lorcast ${endpoint}`); return { id: card.id || card.uuid || `lorcana-${Math.random()}`, name: card.name, @@ -398,12 +478,12 @@ export const lorcanaService = { } } } catch (e) { - console.log(`❌ Failed to fetch card from ${endpoint}:`, e); + console.log(`❌ Failed to fetch card from Lorcast ${endpoint}:`, e); continue; } } - console.log(`⚠️ Lorcana card "${name}" not found from any endpoint`); + console.log(`⚠️ Lorcana card "${name}" not found from any API`); return null; } catch (error) { console.error('Error fetching Lorcana card:', error); @@ -415,7 +495,51 @@ export const lorcanaService = { await lorcastLimiter.waitForSlot(); try { - // Try different endpoints for Lorcana cards + // Try Lorcana API first + try { + const response = await fetch(`${LORCANA_API_BASE_URL}/cards?limit=${count}`); + + if (response.ok) { + const data = await response.json(); + const allCards = data.cards || data.data || data || []; + + if (allCards.length > 0) { + console.log(`✅ Found ${allCards.length} cards from Lorcana API`); + + // Randomly select cards + const shuffled = allCards.sort(() => 0.5 - Math.random()); + const selectedCards = shuffled.slice(0, count); + + return selectedCards.map((card: any) => ({ + id: card.id || card.uuid || `lorcana-${Math.random()}`, + name: card.name, + set_name: card.set?.name || card.set_name || '', + set_code: card.set?.code || card.set_code || '', + card_number: card.number || card.card_number || '', + rarity: card.rarity, + game: 'LORCANA', + mana_cost: card.cost?.toString() || card.mana_cost, + cmc: card.cost || card.cmc, + card_type: card.type || card.card_type, + colors: card.colors || [], + oracle_text: card.text || card.oracle_text || '', + power: card.strength?.toString() || card.power, + toughness: card.willpower?.toString() || card.toughness, + image_url: card.image_url || card.images?.small || card.images?.png, + stock_image_url: card.image_url || card.images?.small || card.images?.png, + current_price: card.price?.market || card.current_price || undefined, + market_price: card.price?.low || card.market_price || undefined, + verified: true, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + })); + } + } + } catch (e) { + console.log('❌ Lorcana API failed for random cards, trying Lorcast API'); + } + + // Fallback to Lorcast API const endpoints = [ '/cards', '/api/cards', @@ -432,11 +556,11 @@ export const lorcanaService = { if (response.ok) { const data = await response.json(); allCards = data.cards || data.data || data || []; - console.log(`✅ Found ${allCards.length} cards from ${endpoint}`); + console.log(`✅ Found ${allCards.length} cards from Lorcast ${endpoint}`); break; } } catch (e) { - console.log(`❌ Failed to fetch from ${endpoint}:`, e); + console.log(`❌ Failed to fetch from Lorcast ${endpoint}:`, e); continue; } }