feat(notifications): Add bot owner notifications for interactions

- Create new botOwnerNotify module with notifyBotOwnerForPost and notifyBotOwnerForFollow functions
- Add bot owner notifications to local post interactions (likes, reposts)
- Add bot owner notifications to swarm post interactions (likes, reposts, mentions)
- Add bot owner notifications to follow interactions (local and swarm)
- Implement mention notification creation for local mentions in post creation
- Notify bot owners when their bots receive interactions from other users
- Ensure bot owners are alerted to engagement on their bot accounts across federated network
This commit is contained in:
Christomatt
2026-01-26 10:57:32 +01:00
parent 5efd3adbfd
commit 1c235e2027
9 changed files with 177 additions and 1 deletions
+4
View File
@@ -83,6 +83,10 @@ export async function POST(request: Request, context: RouteContext) {
postId,
type: 'like',
});
// Also notify bot owner if this is a bot's post
const { notifyBotOwnerForPost } = await import('@/lib/notifications/botOwnerNotify');
await notifyBotOwnerForPost(post.userId, user.id, 'like', postId);
}
// SWARM-FIRST: Check if this is a swarm post and deliver directly
+4
View File
@@ -93,6 +93,10 @@ export async function POST(request: Request, context: RouteContext) {
postId,
type: 'repost',
});
// Also notify bot owner if this is a bot's post
const { notifyBotOwnerForPost } = await import('@/lib/notifications/botOwnerNotify');
await notifyBotOwnerForPost(originalPost.userId, user.id, 'repost', postId);
}
// SWARM-FIRST: Deliver repost to swarm node
+37 -1
View File
@@ -1,5 +1,5 @@
import { NextResponse } from 'next/server';
import { db, posts, users, media, follows, mutes, blocks, likes, remoteFollows, remotePosts } from '@/db';
import { db, posts, users, media, follows, mutes, blocks, likes, remoteFollows, remotePosts, notifications } from '@/db';
import { requireAuth } from '@/lib/auth';
import { eq, desc, and, inArray, isNull, notInArray, or } from 'drizzle-orm';
import type { SQL } from 'drizzle-orm';
@@ -134,6 +134,42 @@ export async function POST(request: Request) {
})();
}
// Handle local mentions (create notifications for users on this node)
(async () => {
try {
const { extractMentions } = await import('@/lib/swarm/interactions');
const { notifications } = await import('@/db');
const mentions = extractMentions(data.content);
for (const mention of mentions) {
// Only handle local mentions (no domain)
if (mention.domain) continue;
// Find the mentioned user
const mentionedUser = await db.query.users.findFirst({
where: eq(users.handle, mention.handle.toLowerCase()),
});
if (mentionedUser && mentionedUser.id !== user.id && !mentionedUser.isSuspended) {
// Create notification for the mentioned user
await db.insert(notifications).values({
userId: mentionedUser.id,
actorId: user.id,
postId: post.id,
type: 'mention',
});
// Also notify bot owner if this is a bot being mentioned
const { notifyBotOwnerForPost } = await import('@/lib/notifications/botOwnerNotify');
await notifyBotOwnerForPost(mentionedUser.id, user.id, 'mention', post.id);
}
}
} catch (err) {
console.error('[Local] Error creating mention notifications:', err);
}
})();
// SWARM-FIRST: Deliver mentions to swarm nodes
(async () => {
try {
@@ -110,6 +110,10 @@ export async function POST(request: NextRequest) {
type: 'follow',
});
// Also notify bot owner if this is a bot being followed
const { notifyBotOwnerForFollow } = await import('@/lib/notifications/botOwnerNotify');
await notifyBotOwnerForFollow(targetUser.id, remoteUser.id);
console.log(`[Swarm] Received follow from ${remoteHandle} for @${data.targetHandle}`);
return NextResponse.json({
@@ -84,6 +84,10 @@ export async function POST(request: NextRequest) {
type: 'like',
});
// Also notify bot owner if this is a bot's post
const { notifyBotOwnerForPost } = await import('@/lib/notifications/botOwnerNotify');
await notifyBotOwnerForPost(post.userId, remoteUser.id, 'like', data.postId);
console.log(`[Swarm] Received like from ${remoteHandle} on post ${data.postId}`);
return NextResponse.json({
@@ -94,6 +94,10 @@ export async function POST(request: NextRequest) {
type: 'mention',
});
// Also notify bot owner if this is a bot being mentioned
const { notifyBotOwnerForPost } = await import('@/lib/notifications/botOwnerNotify');
await notifyBotOwnerForPost(mentionedUser.id, remoteUser.id, 'mention', post.id);
console.log(`[Swarm] Received mention from ${remoteHandle} for @${data.mentionedHandle}`);
return NextResponse.json({
@@ -79,6 +79,10 @@ export async function POST(request: NextRequest) {
type: 'repost',
});
// Also notify bot owner if this is a bot's post
const { notifyBotOwnerForPost } = await import('@/lib/notifications/botOwnerNotify');
await notifyBotOwnerForPost(post.userId, remoteUser.id, 'repost', data.postId);
console.log(`[Swarm] Received repost from ${remoteHandle} on post ${data.postId}`);
return NextResponse.json({
@@ -268,6 +268,10 @@ export async function POST(request: Request, context: RouteContext) {
actorId: currentUser.id,
type: 'follow',
});
// Also notify bot owner if this is a bot being followed
const { notifyBotOwnerForFollow } = await import('@/lib/notifications/botOwnerNotify');
await notifyBotOwnerForFollow(targetUser.id, currentUser.id);
}
// Update counts