feat(bots): Consolidate bot posting into autonomous module and improve caching

- Remove scheduled posting logic and consolidate all bot posting into autonomous module
- Simplify cron endpoint to only call processAllAutonomousBots with cleaner response format
- Add background post caching for swarm follow operations via cacheSwarmUserPosts
- Update background scheduler to remove scheduled posting references and streamline logging
- Improve autonomous module documentation to clarify schedule-based posting with optional sources
- Enhance error tracking and reporting across bot task execution
- Reduce code duplication by eliminating separate scheduled/autonomous processing paths
This commit is contained in:
Christomatt
2026-01-26 09:39:12 +01:00
parent 731838dd48
commit e98221e81a
6 changed files with 354 additions and 193 deletions
+70
View File
@@ -362,6 +362,76 @@ export async function fetchSwarmUserProfile(
}
}
/**
* Cache swarm user posts in the remotePosts table
* Similar to cacheRemoteUserPosts but for swarm nodes
*/
export async function cacheSwarmUserPosts(
handle: string,
domain: string,
fullHandle: string, // e.g., "user@domain.com"
limit: number = 20
): Promise<{ cached: number; skipped: number }> {
try {
const profileData = await fetchSwarmUserProfile(handle, domain, limit);
if (!profileData || !profileData.posts) {
return { cached: 0, skipped: 0 };
}
const { db, remotePosts } = await import('@/db');
const { eq } = await import('drizzle-orm');
if (!db) {
return { cached: 0, skipped: 0 };
}
let cached = 0;
let skipped = 0;
const actorUrl = `swarm://${domain}/${handle}`;
const profile = profileData.profile;
for (const post of profileData.posts) {
// Generate a unique AP-style ID for the post
const apId = `swarm://${domain}/posts/${post.id}`;
// Check if we already have this post
const existing = await db.query.remotePosts.findFirst({
where: eq(remotePosts.apId, apId),
});
if (existing) {
skipped++;
continue;
}
// Cache the post
await db.insert(remotePosts).values({
apId,
authorHandle: fullHandle,
authorActorUrl: actorUrl,
authorDisplayName: profile.displayName || handle,
authorAvatarUrl: profile.avatarUrl || null,
content: post.content,
publishedAt: new Date(post.createdAt),
linkPreviewUrl: post.linkPreviewUrl || null,
linkPreviewTitle: post.linkPreviewTitle || null,
linkPreviewDescription: post.linkPreviewDescription || null,
linkPreviewImage: post.linkPreviewImage || null,
mediaJson: post.media ? JSON.stringify(post.media) : null,
});
cached++;
}
return { cached, skipped };
} catch (error) {
console.error(`[Swarm] Error caching posts for ${fullHandle}:`, error);
return { cached: 0, skipped: 0 };
}
}
/**
* Fetch a single post from a swarm node
*/