Replit-Commit-Author: Deployment Replit-Commit-Session-Id: 23852c00-4779-460a-9e0c-d09fee4b6c92 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 2b7650db-b0d4-4415-b9bb-cc11e719c2b7 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/23852c00-4779-460a-9e0c-d09fee4b6c92/ncMMRQ9 Replit-Commit-Deployment-Build-Id: 55db64a6-94a6-4850-b7bf-6b5712a636c3 Replit-Helium-Checkpoint-Created: true
95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
import { v2 as cloudinary } from "cloudinary";
|
|
|
|
cloudinary.config({
|
|
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
|
|
api_key: process.env.CLOUDINARY_API_KEY,
|
|
api_secret: process.env.CLOUDINARY_API_SECRET,
|
|
});
|
|
|
|
const GALLERY_FOLDER = "folx-gallery";
|
|
|
|
export interface CloudinaryGalleryImage {
|
|
publicId: string;
|
|
fileName: string;
|
|
artist: string;
|
|
thumb: string;
|
|
large: string;
|
|
mobile: string;
|
|
full: string;
|
|
}
|
|
|
|
function buildUrl(publicId: string, transforms: string): string {
|
|
return cloudinary.url(publicId, {
|
|
transformation: transforms,
|
|
secure: true,
|
|
});
|
|
}
|
|
|
|
export function generateImageUrls(publicId: string): { thumb: string; large: string; mobile: string; full: string } {
|
|
return {
|
|
thumb: buildUrl(publicId, "c_fill,g_face:center,w_300,h_300,q_auto,f_auto"),
|
|
mobile: buildUrl(publicId, "c_fill,g_auto,w_600,h_338,q_auto,f_auto"),
|
|
large: buildUrl(publicId, "c_fit,w_1200,q_auto,f_auto"),
|
|
full: buildUrl(publicId, "c_fit,w_1800,q_auto,f_auto"),
|
|
};
|
|
}
|
|
|
|
export async function uploadToCloudinary(imageUrl: string, fileName: string): Promise<string | null> {
|
|
const publicId = `${GALLERY_FOLDER}/${fileName.replace(/\.\w+$/, "").replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
|
|
try {
|
|
const existing = await cloudinary.api.resource(publicId).catch(() => null);
|
|
if (existing) {
|
|
return publicId;
|
|
}
|
|
} catch {}
|
|
|
|
try {
|
|
const result = await cloudinary.uploader.upload(imageUrl, {
|
|
public_id: publicId,
|
|
overwrite: false,
|
|
resource_type: "image",
|
|
});
|
|
return result.public_id;
|
|
} catch (err: any) {
|
|
console.error(`Cloudinary upload failed for ${fileName}:`, err.message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function checkCloudinaryImage(publicId: string): Promise<boolean> {
|
|
try {
|
|
await cloudinary.api.resource(publicId);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export async function listCloudinaryGallery(): Promise<string[]> {
|
|
try {
|
|
const result = await cloudinary.api.resources({
|
|
type: "upload",
|
|
prefix: GALLERY_FOLDER + "/",
|
|
max_results: 500,
|
|
resource_type: "image",
|
|
});
|
|
return result.resources.map((r: any) => r.public_id);
|
|
} catch (err: any) {
|
|
console.error("Cloudinary list failed:", err.message);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export function extractArtistFromPublicId(publicId: string): string {
|
|
const name = publicId.replace(`${GALLERY_FOLDER}/`, "").replace(/_/g, " ");
|
|
if (/^DSC\d/i.test(name) || /^IMG[\s_]\d/i.test(name)) return "";
|
|
const cleaned = name
|
|
.replace(/\s*\(\d+\)\s*$/, "")
|
|
.replace(/\s*\d+\s*$/, "")
|
|
.replace(/\s*\(\d+\)\s*$/, "");
|
|
return cleaned.trim();
|
|
}
|
|
|
|
export { cloudinary };
|