← 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();
}