mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-23 23:18:12 +02:00
Integrate Cloudinary for cloud-based image and video storage
Implement Cloudinary integration for uploading, storing, and transforming media files, including a new settings section for user configuration and API endpoints for media management. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/p0c5kxJ
This commit is contained in:
1 parent
66e20a83e7
commit
bee6f53f23
6 files changed
+363
-35
No files matched your search
@@ -0,0 +1,106 @@
|
||||
import { v2 as cloudinary } from 'cloudinary';
|
||||
import { storage } from '../storage';
|
||||
|
||||
class CloudinaryService {
|
||||
async uploadMedia(
|
||||
buffer: Buffer,
|
||||
fileName: string,
|
||||
userId: string,
|
||||
mimeType: string
|
||||
): Promise<{
|
||||
publicId: string;
|
||||
originalUrl: string;
|
||||
facebookFeedUrl: string | null;
|
||||
instagramFeedUrl: string | null;
|
||||
instagramStoryUrl: string | null;
|
||||
}> {
|
||||
// Get user's Cloudinary config
|
||||
const config = await storage.getCloudinaryConfig(userId);
|
||||
|
||||
if (!config) {
|
||||
throw new Error('Cloudinary configuration not found. Please configure Cloudinary in Settings.');
|
||||
}
|
||||
|
||||
// Configure Cloudinary with user's credentials
|
||||
cloudinary.config({
|
||||
cloud_name: config.cloudName,
|
||||
api_key: config.apiKey,
|
||||
api_secret: config.apiSecret,
|
||||
secure: true,
|
||||
});
|
||||
|
||||
const isVideo = mimeType.startsWith('video/');
|
||||
|
||||
// Upload to Cloudinary
|
||||
const uploadResult = await new Promise<any>((resolve, reject) => {
|
||||
const uploadStream = cloudinary.uploader.upload_stream(
|
||||
{
|
||||
folder: 'social-flow',
|
||||
public_id: `${Date.now()}-${fileName.replace(/\.[^/.]+$/, '')}`,
|
||||
resource_type: isVideo ? 'video' : 'image',
|
||||
},
|
||||
(error, result) => {
|
||||
if (error) reject(error);
|
||||
else resolve(result);
|
||||
}
|
||||
);
|
||||
|
||||
uploadStream.end(buffer);
|
||||
});
|
||||
|
||||
const publicId = uploadResult.public_id;
|
||||
const originalUrl = uploadResult.secure_url;
|
||||
|
||||
// Generate transformation URLs only for images
|
||||
let facebookFeedUrl = null;
|
||||
let instagramFeedUrl = null;
|
||||
let instagramStoryUrl = null;
|
||||
|
||||
if (!isVideo) {
|
||||
facebookFeedUrl = cloudinary.url(publicId, {
|
||||
transformation: [
|
||||
{ width: 1200, height: 630, crop: 'fill', gravity: 'auto' }
|
||||
]
|
||||
});
|
||||
instagramFeedUrl = cloudinary.url(publicId, {
|
||||
transformation: [
|
||||
{ width: 1080, height: 1080, crop: 'fill', gravity: 'auto' }
|
||||
]
|
||||
});
|
||||
instagramStoryUrl = cloudinary.url(publicId, {
|
||||
transformation: [
|
||||
{ width: 1080, height: 1920, crop: 'fill', gravity: 'auto' }
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
publicId,
|
||||
originalUrl,
|
||||
facebookFeedUrl,
|
||||
instagramFeedUrl,
|
||||
instagramStoryUrl,
|
||||
};
|
||||
}
|
||||
|
||||
async deleteMedia(publicId: string, userId: string, mediaType: 'image' | 'video'): Promise<void> {
|
||||
const config = await storage.getCloudinaryConfig(userId);
|
||||
|
||||
if (!config) {
|
||||
throw new Error('Cloudinary configuration not found');
|
||||
}
|
||||
|
||||
cloudinary.config({
|
||||
cloud_name: config.cloudName,
|
||||
api_key: config.apiKey,
|
||||
api_secret: config.apiSecret,
|
||||
secure: true,
|
||||
});
|
||||
|
||||
await cloudinary.uploader.destroy(publicId, {
|
||||
resource_type: mediaType,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const cloudinaryService = new CloudinaryService();
|
||||
Reference in new issue
Block a user