diff --git a/fix-openinary-v2.ts b/fix-openinary-v2.ts new file mode 100644 index 0000000..abdd31c --- /dev/null +++ b/fix-openinary-v2.ts @@ -0,0 +1,142 @@ +import { PrismaClient } from '@prisma/client' +import crypto from 'crypto' +import fs from 'fs' +import path from 'path' +import axios from 'axios' +import FormData from 'form-data' + +const prisma = new PrismaClient() + +const baseUrl = process.env.OPENINARY_API_URL?.replace(/\/+$/, '') || 'https://media.ayris.tech'; +const key = process.env.OPENINARY_API_KEY; + +function getSafeFolder(folder: string): string { + return folder + .split('/') + .filter(Boolean) + .map(part => { + if (part.length > 25) { + const hash = crypto.createHash('md5').update(part).digest('hex').substring(0, 5); + return `${part.substring(0, 20)}-${hash}`; + } + return part; + }) + .join('/'); +} + +function getSafeFileName(fileName: string): string { + const lastDotIndex = fileName.lastIndexOf('.'); + const ext = lastDotIndex !== -1 ? fileName.substring(lastDotIndex) : ''; + let nameWithoutExt = lastDotIndex !== -1 ? fileName.substring(0, lastDotIndex) : fileName; + + if (nameWithoutExt.length > 25) { + const hash = crypto.createHash('md5').update(nameWithoutExt).digest('hex').substring(0, 5); + nameWithoutExt = `${nameWithoutExt.substring(0, 20)}-${hash}`; + } + return `${nameWithoutExt}${ext}`; +} + +async function uploadFile(filePath: string, folder: string, safeFileName: string): Promise { + const form = new FormData(); + form.append('files', fs.createReadStream(filePath), { filename: safeFileName, contentType: 'image/jpeg' }); + form.append('folder', folder); + + const res = await axios.post(`${baseUrl}/api/upload`, form, { + headers: { + ...form.getHeaders(), + "Authorization": `Bearer ${key}` + } + }); + + const data = res.data; + if (Array.isArray(data) && data.length > 0) { + const fileUrl = data[0].url || data[0].secure_url; + return fileUrl.startsWith('/') ? `${baseUrl}${fileUrl}` : fileUrl; + } else if (data && typeof data === "object") { + const fileUrl = data.url || data.secure_url || (data.files && data.files[0]?.url); + return fileUrl.startsWith('/') ? `${baseUrl}${fileUrl}` : fileUrl; + } + throw new Error("Invalid response format"); +} + +async function processUrl(url: string): Promise { + if (!url || !url.startsWith(baseUrl)) return null; + + try { + const urlObj = new URL(url); + const pathParts = urlObj.pathname.split('/').filter(Boolean); + + // Check if it has a part longer than 25 characters + const isBad = pathParts.some(p => p.length > 25); + + if (!isBad) return null; + + console.log(`Found long URL: ${url}`); + + const originalFileName = decodeURIComponent(pathParts.pop() || 'image.jpg'); + let folderParts = pathParts; + if (folderParts[0] === 't') { + folderParts.shift(); + } + const originalFolder = decodeURIComponent(folderParts.join('/')); + + const safeFolder = getSafeFolder(originalFolder); + const safeFileName = getSafeFileName(originalFileName); + + if (safeFolder === originalFolder && safeFileName === originalFileName) { + return null; + } + + console.log(`-> Safe folder: ${safeFolder}`); + console.log(`-> Safe filename: ${safeFileName}`); + + const res = await axios.get(url, { responseType: 'arraybuffer' }); + const buffer = Buffer.from(res.data); + const tmpPath = path.join('/tmp', safeFileName); + fs.writeFileSync(tmpPath, buffer); + + const newUrl = await uploadFile(tmpPath, safeFolder, safeFileName); + console.log(`-> New URL: ${newUrl}`); + + fs.unlinkSync(tmpPath); + + return newUrl; + } catch (error) { + console.error(`Error processing ${url}:`, error.message); + return null; + } +} + +async function main() { + const galleries = await prisma.gallery.findMany(); + for (const g of galleries) { + const newUrl = await processUrl(g.url); + if (newUrl) await prisma.gallery.update({ where: { id: g.id }, data: { url: newUrl }}); + } + + const posts = await prisma.blogPost.findMany({ where: { coverImage: { not: null } } }); + for (const p of posts) { + if (p.coverImage) { + const newUrl = await processUrl(p.coverImage); + if (newUrl) await prisma.blogPost.update({ where: { id: p.id }, data: { coverImage: newUrl }}); + } + } + + const events = await prisma.event.findMany({ where: { coverImage: { not: null } } }); + for (const e of events) { + if (e.coverImage) { + const newUrl = await processUrl(e.coverImage); + if (newUrl) await prisma.event.update({ where: { id: e.id }, data: { coverImage: newUrl }}); + } + } + + const collections = await prisma.collection.findMany({ where: { coverImage: { not: null } } }); + for (const c of collections) { + if (c.coverImage) { + const newUrl = await processUrl(c.coverImage); + if (newUrl) await prisma.collection.update({ where: { id: c.id }, data: { coverImage: newUrl }}); + } + } +} + +main().catch(console.error).finally(() => prisma.$disconnect()); diff --git a/lib/openinary.ts b/lib/openinary.ts index 0a2abd5..87c9d40 100644 --- a/lib/openinary.ts +++ b/lib/openinary.ts @@ -14,9 +14,9 @@ export async function uploadToOpeninary(file: File, folder: string = "marmarislo .split('/') .filter(Boolean) // Avoid double slashes in folder path .map(part => { - if (part.length > 50) { - const hash = crypto.createHash('md5').update(part).digest('hex').substring(0, 8); - return `${part.substring(0, 40)}-${hash}`; + if (part.length > 25) { + const hash = crypto.createHash('md5').update(part).digest('hex').substring(0, 5); + return `${part.substring(0, 20)}-${hash}`; } return part; }) @@ -27,9 +27,9 @@ export async function uploadToOpeninary(file: File, folder: string = "marmarislo const ext = lastDotIndex !== -1 ? file.name.substring(lastDotIndex) : ''; let nameWithoutExt = lastDotIndex !== -1 ? file.name.substring(0, lastDotIndex) : file.name; - if (nameWithoutExt.length > 50) { - const hash = crypto.createHash('md5').update(nameWithoutExt).digest('hex').substring(0, 8); - nameWithoutExt = `${nameWithoutExt.substring(0, 40)}-${hash}`; + if (nameWithoutExt.length > 25) { + const hash = crypto.createHash('md5').update(nameWithoutExt).digest('hex').substring(0, 5); + nameWithoutExt = `${nameWithoutExt.substring(0, 20)}-${hash}`; } const safeFileName = `${nameWithoutExt}${ext}`;