← back to Dear Bubbe Nextjs

archived/social-posters/instagram-business-poster.js

215 lines

#!/usr/bin/env node

const fs = require('fs').promises;
const path = require('path');
const axios = require('axios');
const FormData = require('form-data');
const { exec } = require('child_process');
const util = require('util');
const execPromise = util.promisify(exec);
const { generateInstagramImage, generateCaption } = require('./instagram-image-generator');

// Configuration for Instagram Business API
const CONFIG = {
    // You'll need to get these from Facebook Developer Console
    // 1. Create Facebook App at developers.facebook.com
    // 2. Add Instagram Basic Display or Instagram Graph API
    // 3. Get access tokens
    
    INSTAGRAM_BUSINESS_ID: process.env.INSTAGRAM_BUSINESS_ID || 'YOUR_IG_BUSINESS_ID',
    FACEBOOK_PAGE_ID: process.env.FACEBOOK_PAGE_ID || 'YOUR_FB_PAGE_ID', 
    ACCESS_TOKEN: process.env.META_ACCESS_TOKEN || 'YOUR_ACCESS_TOKEN',
    
    // API endpoints
    GRAPH_API_URL: 'https://graph.facebook.com/v18.0',
    
    // Local config
    STATE_FILE: '/root/Projects/dear-bubbe-admin/logs/instagram-business-state.json',
    POSTS_PER_DAY: 3
};

// Get random user message
async function getRandomMessage() {
    try {
        const { stdout } = await execPromise(
            `pm2 logs bubbe-ai --lines 1000 --nostream | grep -E "message:" | grep -v "__" | grep -v "test" | head -30`
        );
        
        const messages = [];
        const lines = stdout.split('\n').filter(line => line.trim());
        
        for (const line of lines) {
            const match = line.match(/message:\s*["'](.+?)["']/);
            if (match && match[1] && match[1].length > 20) {
                messages.push(match[1].trim());
            }
        }
        
        return messages.length > 0 ? 
            messages[Math.floor(Math.random() * messages.length)] :
            "Should I quit my job without another lined up?";
    } catch (error) {
        return "My mother-in-law criticizes everything I do";
    }
}

// Upload image to Instagram via Graph API
async function uploadToInstagram(imagePath, caption) {
    try {
        // First, upload image to get media ID
        const imageUrl = `http://45.61.58.125:7902/${path.basename(imagePath)}`;
        
        // Step 1: Create media object
        const createMediaUrl = `${CONFIG.GRAPH_API_URL}/${CONFIG.INSTAGRAM_BUSINESS_ID}/media`;
        const createResponse = await axios.post(createMediaUrl, {
            image_url: imageUrl,
            caption: caption,
            access_token: CONFIG.ACCESS_TOKEN
        });
        
        const mediaId = createResponse.data.id;
        console.log('✅ Media uploaded, ID:', mediaId);
        
        // Step 2: Publish the media
        const publishUrl = `${CONFIG.GRAPH_API_URL}/${CONFIG.INSTAGRAM_BUSINESS_ID}/media_publish`;
        const publishResponse = await axios.post(publishUrl, {
            creation_id: mediaId,
            access_token: CONFIG.ACCESS_TOKEN
        });
        
        console.log('✅ Posted to Instagram!');
        return { success: true, id: publishResponse.data.id };
        
    } catch (error) {
        console.error('❌ API Error:', error.response?.data || error.message);
        return { success: false, error: error.message };
    }
}

// Alternative: Use Creator Studio scheduling
async function scheduleViaCreatorStudio() {
    console.log('\n📅 SCHEDULE VIA CREATOR STUDIO:');
    console.log('========================================');
    console.log('1. Go to: https://business.facebook.com/creatorstudio');
    console.log('2. Click "Create Post" → "Instagram Feed"');
    console.log('3. Upload the generated image');
    console.log('4. Paste the caption');
    console.log('5. Schedule for optimal time');
    console.log('\n✨ Creator Studio allows:');
    console.log('   - Scheduling posts in advance');
    console.log('   - Cross-posting to Facebook');
    console.log('   - Analytics and insights');
    console.log('   - Bulk uploading');
}

// Generate webhook for automation tools
async function generateWebhook(imagePath, caption) {
    const webhookData = {
        platform: 'instagram',
        image_url: `http://45.61.58.125:7902/${path.basename(imagePath)}`,
        caption: caption,
        hashtags: caption.match(/#\w+/g) || [],
        timestamp: new Date().toISOString(),
        webhook_url: 'http://45.61.58.125:7902/instagram-webhook.json'
    };
    
    const webhookPath = '/root/Projects/dear-bubbe-admin/public/instagram-webhook.json';
    await fs.writeFile(webhookPath, JSON.stringify(webhookData, null, 2));
    
    console.log('\n🔗 WEBHOOK DATA READY:');
    console.log('   http://45.61.58.125:7902/instagram-webhook.json');
    console.log('\n   Use with:');
    console.log('   - Zapier (Instagram Business)');
    console.log('   - IFTTT Pro');
    console.log('   - Make (Integromat)');
    console.log('   - Buffer API');
    console.log('   - Later API');
}

// Main posting function
async function postToInstagramBusiness() {
    console.log('📸 Instagram Business Poster');
    console.log('========================================');
    
    // Get message
    const message = await getRandomMessage();
    console.log(`📝 Message: "${message}"`);
    
    // Generate image
    const timestamp = Date.now();
    const imagePath = `/root/Projects/dear-bubbe-admin/public/instagram-${timestamp}.png`;
    await generateInstagramImage(message, imagePath);
    console.log('🎨 Image created');
    
    // Generate caption
    const caption = generateCaption(message);
    console.log('📝 Caption ready');
    
    // Save files for easy access
    await fs.writeFile(
        `/root/Projects/dear-bubbe-admin/public/instagram-latest-caption.txt`, 
        caption
    );
    
    // Check if API credentials are configured
    if (CONFIG.ACCESS_TOKEN === 'YOUR_ACCESS_TOKEN') {
        console.log('\n⚠️ Instagram Business API not configured');
        console.log('\nTo set up:');
        console.log('1. Go to https://developers.facebook.com');
        console.log('2. Create new app → Business');
        console.log('3. Add Instagram Graph API');
        console.log('4. Get Access Token');
        console.log('5. Set environment variables:');
        console.log('   export INSTAGRAM_BUSINESS_ID=xxx');
        console.log('   export FACEBOOK_PAGE_ID=xxx');
        console.log('   export META_ACCESS_TOKEN=xxx');
        
        await scheduleViaCreatorStudio();
        await generateWebhook(imagePath, caption);
        
    } else {
        // Try to post via API
        const result = await uploadToInstagram(imagePath, caption);
        if (!result.success) {
            await scheduleViaCreatorStudio();
            await generateWebhook(imagePath, caption);
        }
    }
    
    // Create scheduling file for Buffer/Later
    const scheduleData = {
        posts: [{
            text: caption,
            media: {
                photo: `http://45.61.58.125:7902/instagram-${timestamp}.png`,
                thumbnail: `http://45.61.58.125:7902/instagram-${timestamp}.png`
            },
            platforms: ['instagram'],
            scheduled_at: new Date(Date.now() + 2 * 60 * 60 * 1000).toISOString() // 2 hours from now
        }]
    };
    
    await fs.writeFile(
        '/root/Projects/dear-bubbe-admin/public/instagram-schedule.json',
        JSON.stringify(scheduleData, null, 2)
    );
    
    console.log('\n✅ INSTAGRAM CONTENT READY:');
    console.log(`📸 Image: http://45.61.58.125:7902/instagram-${timestamp}.png`);
    console.log(`📝 Caption: http://45.61.58.125:7902/instagram-latest-caption.txt`);
    console.log(`📅 Schedule: http://45.61.58.125:7902/instagram-schedule.json`);
    console.log(`🔗 Webhook: http://45.61.58.125:7902/instagram-webhook.json`);
    
    return {
        image: `http://45.61.58.125:7902/instagram-${timestamp}.png`,
        caption: caption,
        success: true
    };
}

// Run if called directly
if (require.main === module) {
    postToInstagramBusiness().catch(console.error);
}

module.exports = { postToInstagramBusiness };