diff --git a/src/app/api/swarm/announce/route.ts b/src/app/api/swarm/announce/route.ts index 7547230..4cb8629 100644 --- a/src/app/api/swarm/announce/route.ts +++ b/src/app/api/swarm/announce/route.ts @@ -13,11 +13,20 @@ import { buildAnnouncement } from '@/lib/swarm/discovery'; import { verifySwarmRequest } from '@/lib/swarm/signature'; import type { SwarmNodeInfo } from '@/lib/swarm/types'; +const optionalUrlSchema = z.preprocess((value) => { + if (typeof value !== 'string') { + return value; + } + + const trimmed = value.trim(); + return trimmed.length > 0 ? trimmed : undefined; +}, z.string().url().optional()); + const announcementSchema = z.object({ domain: z.string().min(1), name: z.string().optional(), description: z.string().optional(), - logoUrl: z.string().url().optional(), + logoUrl: optionalUrlSchema, publicKey: z.string().optional(), softwareVersion: z.string().optional(), userCount: z.number().optional(), diff --git a/src/lib/background/scheduler.ts b/src/lib/background/scheduler.ts index dc6e2f7..154883e 100644 --- a/src/lib/background/scheduler.ts +++ b/src/lib/background/scheduler.ts @@ -64,9 +64,21 @@ async function runBotTasks() { async function runSwarmGossip() { try { + const stats = await getSwarmStats(); + + // Recover from empty peer lists by periodically re-announcing to seeds. + if (stats.activeNodes === 0) { + const announceResult = await announceToSeeds(); + if (announceResult.successful.length > 0 || announceResult.failed.length > 0) { + log('SWARM', `Re-announced to seeds: ${announceResult.successful.length} successful, ${announceResult.failed.length} failed`); + } + } + const result = await runGossipRound(); if (result.contacted > 0) { log('SWARM', `Gossip: contacted ${result.contacted}, successful ${result.successful}, received ${result.totalNodesReceived} nodes`); + } else if (stats.activeNodes === 0) { + log('SWARM', 'No active swarm peers yet'); } } catch (error) { log('SWARM', `Gossip error: ${error}`); diff --git a/src/lib/swarm/discovery.ts b/src/lib/swarm/discovery.ts index bc1f8dd..726bb32 100644 --- a/src/lib/swarm/discovery.ts +++ b/src/lib/swarm/discovery.ts @@ -9,6 +9,15 @@ import { eq, sql } from 'drizzle-orm'; import type { SwarmAnnouncement, SwarmNodeInfo, SwarmCapability } from './types'; import { upsertSwarmNode, getSeedNodes, markNodeSuccess, markNodeFailure } from './registry'; +function normalizeOptionalUrl(value: string | null | undefined): string | undefined { + if (!value) { + return undefined; + } + + const trimmed = value.trim(); + return trimmed.length > 0 ? trimmed : undefined; +} + /** * Build this node's announcement payload */ @@ -32,7 +41,7 @@ export async function buildAnnouncement(): Promise { if (node) { name = node.name; description = node.description ?? undefined; - logoUrl = node.logoUrl ?? undefined; + logoUrl = normalizeOptionalUrl(node.logoUrl); publicKey = node.publicKey ?? ''; isNsfw = node.isNsfw; }