feat: Implement Phase 2 features including blog, collections, saved listings, manifest, and api cron sync

This commit is contained in:
AyrisAI
2026-07-12 20:49:41 +03:00
parent 862544b5a1
commit f696d359b0
29 changed files with 3066 additions and 194 deletions
+65
View File
@@ -0,0 +1,65 @@
import { NextRequest, NextResponse } from 'next/server'
import { mockDb } from '@/lib/mockDb'
export async function POST(req: NextRequest) {
const authHeader = req.headers.get('Authorization')
const secret = process.env.CRON_SECRET || 'secret-token-key-123'
if (authHeader !== `Bearer ${secret}`) {
return new NextResponse('Unauthorized', { status: 401 })
}
// Get listings that have instagram handle filled
const listings = await mockDb.getListings()
const activeListings = listings.filter(l => l.instagram)
const syncResults = []
for (const listing of activeListings) {
const handle = listing.instagram!
let posts = []
if (process.env.USE_MOCK === 'true') {
// In mock/demo mode, return simulated posts with high quality Unsplash placeholders
posts = [
{ imageUrl: 'https://images.unsplash.com/photo-1544025162-d76694265947?w=500&auto=format&fit=crop&q=80', caption: `Mezelerimiz taze taze hazırlandı! 🐟 @${handle}`, permalink: '#', postedAt: new Date().toISOString() },
{ imageUrl: 'https://images.unsplash.com/photo-1519708227418-c8fd9a32b7a2?w=500&auto=format&fit=crop&q=80', caption: `Bu akşam iskelede gün batımı bir başka güzel... 🌅 @${handle}`, permalink: '#', postedAt: new Date().toISOString() },
{ imageUrl: 'https://images.unsplash.com/photo-1476224203421-9ac39bcb3327?w=500&auto=format&fit=crop&q=80', caption: `Marmaris'in lezzet keyfini kaçırmayın! 🍽️ @${handle}`, permalink: '#', postedAt: new Date().toISOString() }
]
} else {
const apiKey = process.env.RAPIDAPI_KEY
const host = process.env.RAPIDAPI_INSTAGRAM_HOST || 'instagram-scraper-api2.p.rapidapi.com'
if (apiKey) {
try {
const res = await fetch(`https://${host}/v1/user/posts?username=${handle}`, {
headers: {
'x-rapidapi-key': apiKey,
'x-rapidapi-host': host
}
})
if (res.ok) {
const resultData = await res.json()
const items = resultData?.data?.items || []
posts = items.slice(0, 3).map((item: any) => ({
imageUrl: item.image_versions2?.candidates?.[0]?.url || item.thumbnail_url,
caption: item.caption?.text || '',
permalink: `https://instagram.com/p/${item.code}`,
postedAt: new Date(item.taken_at * 1000).toISOString()
}))
}
} catch (e) {
console.error(`Error scraping Instagram for @${handle}:`, e)
}
}
}
if (posts.length > 0) {
await mockDb.updateInstagramFeedCache(listing.id, handle, posts)
syncResults.push({ id: listing.id, handle, postsCount: posts.length })
}
}
return NextResponse.json({ success: true, synced: syncResults })
}