const axios = require('axios') const PostModel = require('../models/PostModel') const InstagramImportedPostModel = require('../models/InstagramImportedPostModel') const { saveBase64PostFiles } = require('./postBase64Files') const { resolvePostModerationStatus } = require('./contentModeration') const { savePostWithModerationStatus } = require('./postStatusSave') const path = require('path') const imageDir = path.join(__dirname, '../storage/posts/images') const videoDir = path.join(__dirname, '../storage/posts/videos') /** * CAROUSEL_ALBUM items need a second Graph API call (children edge) to resolve * each slide's own media_url — intentionally out of scope for v1, single * image/video posts only. */ const SUPPORTED_MEDIA_TYPES = ['IMAGE', 'VIDEO'] async function downloadMediaAsFile (mediaUrl, mediaType) { const response = await axios.get(mediaUrl, { responseType: 'arraybuffer', timeout: 20000, }) const contentType = response.headers['content-type'] || (mediaType === 'VIDEO' ? 'video/mp4' : 'image/jpeg') const base64Data = `data:${contentType};base64,${Buffer.from(response.data).toString('base64')}` const ext = mediaType === 'VIDEO' ? 'mp4' : 'jpg' return { data: base64Data, type: contentType, name: `instagram-import.${ext}`, } } /** * Imports one Instagram media item as a Modstagram post, if not already imported * and if its type is supported. Shared by the manual/automatic import endpoints * and the recurring sync cron — same dedup + storage + moderation path either way. * Returns the created post, or null if the item was skipped (already imported / * unsupported type). */ async function importInstagramMedia (user, mediaItem) { if (!SUPPORTED_MEDIA_TYPES.includes(mediaItem.media_type)) { return null } if (!mediaItem.media_url) { return null } const alreadyImported = await InstagramImportedPostModel.findOne({ user: user._id, instagram_media_id: String(mediaItem.id), }) if (alreadyImported) { return null } const file = await downloadMediaAsFile(mediaItem.media_url, mediaItem.media_type) const [savedFile] = await saveBase64PostFiles([file], imageDir, videoDir) const filePaths = [ { path: savedFile.path, type: savedFile.mimetype.startsWith('video/') ? 'video' : 'image', }, ] const captionText = mediaItem.caption ? String(mediaItem.caption).trim().slice(0, 2000) : null const moderation = resolvePostModerationStatus({ caption: captionText, filePaths }) if (moderation.status === 'reject') { return null } const post = await savePostWithModerationStatus(PostModel, { user_id: user._id, caption: captionText, files: filePaths, type: filePaths[0].type, status: moderation.status, }) await InstagramImportedPostModel.create({ user: user._id, instagram_media_id: String(mediaItem.id), post: post._id, }) return post } module.exports = { importInstagramMedia, SUPPORTED_MEDIA_TYPES }