import { Router } from 'express'; import { getUserById } from '../cqrs'; import { ServerPayload } from '../cqrs/types'; import { getActiveServerInvite } from '../services/server-access.service'; import { buildAppInviteUrl, buildBrowserInviteUrl, buildInviteUrl, getRequestOrigin } from './invite-utils'; export const invitesApiRouter = Router(); export const invitePageRouter = Router(); async function enrichServer(server: ServerPayload, sourceUrl: string) { const owner = await getUserById(server.ownerId); const { passwordHash, ...publicServer } = server; return { ...publicServer, hasPassword: server.hasPassword ?? !!passwordHash, ownerName: owner?.displayName, sourceUrl, userCount: server.currentUsers }; } function renderInvitePage(options: { appUrl?: string; browserUrl?: string; error?: string; expiresAt?: number; inviteUrl?: string; isExpired: boolean; ownerName?: string; serverDescription?: string; serverName: string; }) { const expiryLabel = options.expiresAt ? new Date(options.expiresAt).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' }) : null; const statusLabel = options.isExpired ? 'Expired' : 'Active'; const statusColor = options.isExpired ? '#f87171' : '#4ade80'; const buttonOpacity = options.isExpired ? 'opacity:0.5;pointer-events:none;' : ''; const errorBlock = options.error ? `
${options.error}
` : ''; const description = options.serverDescription ? `

${options.serverDescription}

` : '

You have been invited to join a Toju server.

'; return ` Invite to ${options.serverName}
${statusLabel} invite

Join ${options.serverName}

${description}
${errorBlock}
Server
${options.serverName}
Owner
${options.ownerName || 'Unknown'}
Expires
${expiryLabel || 'Expired'}
Invite links bypass private and password restrictions, but banned users still cannot join. If Toju is not installed yet, use the desktop button after installing from toju.app/downloads.
`; } invitesApiRouter.get('/:id', async (req, res) => { const signalOrigin = getRequestOrigin(req); const bundle = await getActiveServerInvite(req.params['id']); if (!bundle) { return res.status(404).json({ error: 'Invite link has expired or is invalid', errorCode: 'INVITE_EXPIRED' }); } const server = bundle.server; res.json({ id: bundle.invite.id, serverId: bundle.invite.serverId, createdAt: bundle.invite.createdAt, expiresAt: bundle.invite.expiresAt, inviteUrl: buildInviteUrl(signalOrigin, bundle.invite.id), browserUrl: buildBrowserInviteUrl(signalOrigin, bundle.invite.id), appUrl: buildAppInviteUrl(signalOrigin, bundle.invite.id), sourceUrl: signalOrigin, createdBy: bundle.invite.createdBy, createdByDisplayName: bundle.invite.createdByDisplayName ?? undefined, isExpired: bundle.invite.expiresAt <= Date.now(), server: await enrichServer(server, signalOrigin) }); }); invitePageRouter.get('/:id', async (req, res) => { const signalOrigin = getRequestOrigin(req); const bundle = await getActiveServerInvite(req.params['id']); if (!bundle) { res.status(404).send(renderInvitePage({ error: 'This invite has expired or is no longer available.', isExpired: true, serverName: 'Toju server' })); return; } const server = bundle.server; const owner = await getUserById(server.ownerId); res.send(renderInvitePage({ serverName: server.name, serverDescription: server.description, ownerName: owner?.displayName, expiresAt: bundle.invite.expiresAt, inviteUrl: buildInviteUrl(signalOrigin, bundle.invite.id), browserUrl: buildBrowserInviteUrl(signalOrigin, bundle.invite.id), appUrl: buildAppInviteUrl(signalOrigin, bundle.invite.id), isExpired: bundle.invite.expiresAt <= Date.now() })); });