Files
backspace/packages/server/src/routes/livekit.ts
T
Jannis Braun 7168149d98 feat: DM infrastructure overhaul + volume sliders + LiveKit dynamic URL
- Add DM edit/delete endpoints (REST + WebSocket)
- Add DM typing indicators with real-time broadcast
- Fix volume sliders to control LiveKit mic/speaker
- Fix Send Message button on user profile popout
- Add New DM modal with user search
- Fix message pagination (SQL cursor instead of in-memory)
- Guard optional attachments on DM messages
- Dynamic LiveKit URL from request Host header
- DM sidebar auto-sorts by most recent message
2026-02-18 17:29:39 +01:00

58 lines
1.8 KiB
TypeScript

import type { FastifyInstance } from 'fastify';
import { AccessToken } from 'livekit-server-sdk';
import { authenticate } from '../utils/auth.js';
import { config } from '../config.js';
import { getChannelServerId, isMember } from '../utils/permissions.js';
import type { LiveKitTokenRequest, LiveKitTokenResponse } from '@opencord/shared';
export async function livekitRoutes(app: FastifyInstance): Promise<void> {
app.post<{ Body: LiveKitTokenRequest }>('/api/livekit/token', {
preHandler: authenticate,
}, async (request, reply) => {
const { channelId } = request.body;
if (!channelId || typeof channelId !== 'string') {
return reply.code(400).send({ error: 'channelId is required', statusCode: 400 });
}
const serverId = getChannelServerId(channelId);
if (!serverId) {
return reply.code(404).send({ error: 'Channel not found', statusCode: 404 });
}
if (!isMember(serverId, request.userId)) {
return reply.code(403).send({ error: 'You are not a member of this server', statusCode: 403 });
}
const identity = `${request.userId}:${request.username}`;
const token = new AccessToken(config.livekit.apiKey, config.livekit.apiSecret, {
identity,
ttl: '1h',
});
token.addGrant({
room: channelId,
roomJoin: true,
canPublish: true,
canSubscribe: true,
canPublishData: true,
});
const jwt = await token.toJwt();
// Use the request's Host header so the LiveKit WSS URL matches however
// the client reached us (domain or direct IP).
const requestHost = request.headers.host?.replace(/:\d+$/, '') || '';
const livekitUrl = requestHost
? `wss://${requestHost}/livekit`
: config.livekit.url;
const response: LiveKitTokenResponse = {
token: jwt,
url: livekitUrl
};
return reply.code(200).send(response);
});
}