import { PrismaClient } from '@prisma/client'; import fs from 'fs'; import path from 'path'; const prisma = new PrismaClient(); const OPENINARY_API_URL = process.env.OPENINARY_API_URL; const OPENINARY_API_KEY = process.env.OPENINARY_API_KEY; const NEXT_PUBLIC_OPENINARY_URL = process.env.NEXT_PUBLIC_OPENINARY_URL; async function downloadImageAsBlob(url: string, filename: string): Promise { const response = await fetch(url); if (!response.ok) throw new Error(`Failed to download ${url}`); const arrayBuffer = await response.arrayBuffer(); // Create a Blob from the ArrayBuffer return new Blob([arrayBuffer], { type: response.headers.get('content-type') || 'application/octet-stream' }); } async function uploadToOpeninary(blob: Blob, filename: string): Promise { const formData = new FormData(); // Next.js node fetch environment allows passing Blob to FormData formData.append('files', blob, filename); formData.append('folder', 'moybeach'); const res = await fetch(`${OPENINARY_API_URL}/api/upload`, { method: 'POST', headers: { Authorization: `Bearer ${OPENINARY_API_KEY}` }, body: formData, }); if (!res.ok) { const text = await res.text(); console.error('Openinary upload error:', text); throw new Error('Upload başarısız'); } const data = await res.json(); return `${NEXT_PUBLIC_OPENINARY_URL}${data.files[0].url}`; } async function migrateImage(url: string | null): Promise { if (!url || !url.includes('cloudinary.com')) return url; try { console.log(`Migrating: ${url}`); const filename = url.split('/').pop() || 'image.jpg'; const blob = await downloadImageAsBlob(url, filename); const newUrl = await uploadToOpeninary(blob, filename); console.log(`Success: ${newUrl}`); return newUrl; } catch (error) { console.error(`Error migrating ${url}:`, error); return url; } } async function main() { if (!OPENINARY_API_URL || !OPENINARY_API_KEY) { console.error('Missing Openinary Env Variables!'); process.exit(1); } console.log('Starting migration from Cloudinary to Openinary...'); // 1. Gallery const galleries = await prisma.gallery.findMany(); for (const item of galleries) { if (item.imageUrl.includes('cloudinary.com')) { const newUrl = await migrateImage(item.imageUrl); if (newUrl && newUrl !== item.imageUrl) { await prisma.gallery.update({ where: { id: item.id }, data: { imageUrl: newUrl } }); } } } // 2. Service const services = await prisma.service.findMany(); for (const item of services) { if (item.iconUrl && item.iconUrl.includes('cloudinary.com')) { const newUrl = await migrateImage(item.iconUrl); if (newUrl && newUrl !== item.iconUrl) { await prisma.service.update({ where: { id: item.id }, data: { iconUrl: newUrl } }); } } } // 3. HeroMedia const heroMedias = await prisma.heroMedia.findMany(); for (const item of heroMedias) { if (item.url.includes('cloudinary.com')) { const newUrl = await migrateImage(item.url); if (newUrl && newUrl !== item.url) { await prisma.heroMedia.update({ where: { id: item.id }, data: { url: newUrl } }); } } } // 4. SiteSettings const siteSettings = await prisma.siteSettings.findMany(); for (const item of siteSettings) { let changed = false; let newLogoUrl = item.logoUrl; let newOgImage = item.ogImage; if (item.logoUrl && item.logoUrl.includes('cloudinary.com')) { newLogoUrl = await migrateImage(item.logoUrl) ?? item.logoUrl; if (newLogoUrl !== item.logoUrl) changed = true; } if (item.ogImage && item.ogImage.includes('cloudinary.com')) { newOgImage = await migrateImage(item.ogImage) ?? item.ogImage; if (newOgImage !== item.ogImage) changed = true; } if (changed) { await prisma.siteSettings.update({ where: { id: item.id }, data: { logoUrl: newLogoUrl, ogImage: newOgImage } }); } } console.log('Migration completed!'); } main() .catch(e => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });