← back to Animate Museum Posts

src/scheduledPoster.js

77 lines

import { getPendingPosts, markAsPosted, markAsFailed, isPaused } from './database.js';
import { postToX } from './postToX.js';
import fs from 'fs';
import { fileURLToPath } from 'url';

/**
 * Check for and post any pending scheduled posts
 */
export async function checkAndPost() {
  if (isPaused()) {
    console.log('Posting is paused');
    return;
  }

  const pendingPosts = await getPendingPosts();

  if (pendingPosts.length === 0) {
    console.log('No posts ready to be posted');
    return;
  }

  console.log(`Found ${pendingPosts.length} post(s) ready to post`);

  for (const post of pendingPosts) {
    console.log(`\nPosting: ${post.title} by ${post.artist}`);

    try {
      if (!fs.existsSync(post.video_path)) {
        throw new Error(`Video file not found: ${post.video_path}`);
      }

      const animationResult = {
        animatedVideo: post.video_path,
        artworkMetadata: {
          title: post.title,
          artist: post.artist,
          year: post.year,
          museum: post.museum
        },
        isAnimated: true
      };

      const result = await postToX(animationResult);
      const tweetId = result.data.id;
      const tweetUrl = `https://twitter.com/goodquestionai/status/${tweetId}`;

      await markAsPosted(post.id, tweetId, tweetUrl);
      console.log(`  Posted successfully! ${tweetUrl}`);

    } catch (err) {
      console.error(`  Failed: ${err.message}`);
      await markAsFailed(post.id, err.message);
    }
  }
}

/**
 * Start the posting loop (checks every minute)
 */
export function startPostingLoop(intervalMs = 60000) {
  console.log('Starting scheduled poster loop...');
  console.log(`Checking every ${intervalMs / 1000} seconds`);

  // Check immediately
  checkAndPost().catch(console.error);

  // Then check on interval
  setInterval(() => {
    checkAndPost().catch(console.error);
  }, intervalMs);
}

// Run if called directly
if (process.argv[1] === fileURLToPath(import.meta.url)) {
  startPostingLoop();
}