This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
"@fastify/autoload": "^6.3.1",
|
||||
"@fastify/cookie": "^11.0.2",
|
||||
"@fastify/cors": "^11.1.0",
|
||||
"@fastify/multipart": "^10.0.0",
|
||||
"@lucia-auth/adapter-prisma": "^4.0.1",
|
||||
"@prisma/client": "^6.17.0",
|
||||
"bcrypt": "^6.0.0",
|
||||
@@ -21,6 +22,7 @@
|
||||
"mediasoup": "^3.19.3",
|
||||
"prisma": "^6.17.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"uuid": "^13.0.0",
|
||||
"ws": "^8.18.3",
|
||||
"zod": "^4.1.12"
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { FastifyInstance } from 'fastify'
|
||||
import type { ServerOptions } from 'socket.io'
|
||||
import fp from 'fastify-plugin'
|
||||
import { Server } from 'socket.io'
|
||||
import registerChatSocket from '../socket/chat.ts'
|
||||
import registerWebrtcSocket from '../socket/webrtc.ts'
|
||||
|
||||
declare module 'fastify' {
|
||||
@@ -24,6 +25,7 @@ export default fp<Partial<ServerOptions>>(
|
||||
|
||||
fastify.ready(async () => {
|
||||
await registerWebrtcSocket(fastify.io, fastify.mediasoupRouter)
|
||||
await registerChatSocket(fastify.io)
|
||||
})
|
||||
},
|
||||
{ name: 'socket-io', dependencies: ['mediasoup-worker', 'mediasoup-router'] },
|
||||
|
||||
33
server/routes/attachments.ts
Normal file
33
server/routes/attachments.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { FastifyInstance } from 'fastify'
|
||||
import bcrypt from 'bcrypt'
|
||||
import { z } from 'zod'
|
||||
|
||||
export default function (fastify: FastifyInstance) {
|
||||
fastify.post('/attachments/upload', async (req, reply) => {
|
||||
try {
|
||||
const schema = z.object({
|
||||
file: z.file(),
|
||||
})
|
||||
const input = schema.parse(req.body)
|
||||
|
||||
// const file = req.file({ limits: { } })
|
||||
|
||||
const id = await bcrypt.hash(input.file, 10)
|
||||
|
||||
return {
|
||||
id,
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
fastify.log.error(err)
|
||||
reply.code(400)
|
||||
|
||||
if (err instanceof z.ZodError) {
|
||||
reply.send({ error: z.prettifyError(err) })
|
||||
}
|
||||
else {
|
||||
reply.send({ error: err.message })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -3,9 +3,12 @@ import { fileURLToPath } from 'node:url'
|
||||
import FastifyAutoLoad from '@fastify/autoload'
|
||||
import FastifyCookie from '@fastify/cookie'
|
||||
import FastifyCors from '@fastify/cors'
|
||||
import FastifyMultipart from '@fastify/multipart'
|
||||
import Fastify from 'fastify'
|
||||
import prisma from './prisma/client.ts'
|
||||
|
||||
console.log(process.env.DATABASE_URL)
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = dirname(__filename)
|
||||
|
||||
@@ -25,6 +28,7 @@ fastify.register(FastifyCors, {
|
||||
})
|
||||
|
||||
fastify.register(FastifyCookie)
|
||||
fastify.register(FastifyMultipart)
|
||||
|
||||
fastify.register(FastifyAutoLoad, {
|
||||
dir: join(__dirname, 'plugins'),
|
||||
|
||||
28
server/socket/chat.ts
Normal file
28
server/socket/chat.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { Server as SocketServer } from 'socket.io'
|
||||
import type { ChatClientMessage, ChatMessage } from '../types/chat.ts'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
export default async function (io: SocketServer) {
|
||||
const messages: ChatMessage[] = []
|
||||
|
||||
io.on('connection', async (socket) => {
|
||||
socket.on('chat:message', async (clientMessage: ChatClientMessage, cb) => {
|
||||
const message: ChatMessage = {
|
||||
id: uuidv4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
sender: socket.data.username,
|
||||
text: clientMessage.text,
|
||||
}
|
||||
|
||||
console.log(message)
|
||||
|
||||
messages.push(message)
|
||||
|
||||
if (messages.length > 5000) {
|
||||
messages.shift()
|
||||
}
|
||||
|
||||
io.emit('chat:new-message', message)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -2,7 +2,6 @@ import type { types } from 'mediasoup'
|
||||
import type { Server as SocketServer } from 'socket.io'
|
||||
import type {
|
||||
ChadClient,
|
||||
Namespace,
|
||||
SomeSocket,
|
||||
} from '../types/webrtc.ts'
|
||||
import { consola } from 'consola'
|
||||
@@ -10,8 +9,6 @@ import prisma from '../prisma/client.ts'
|
||||
import { socketToClient } from '../utils/socket-to-client.ts'
|
||||
|
||||
export default async function (io: SocketServer, router: types.Router) {
|
||||
const namespace: Namespace = io.of('/webrtc')
|
||||
|
||||
const audioLevelObserver = await router.createAudioLevelObserver({
|
||||
maxEntries: 10,
|
||||
threshold: -80,
|
||||
@@ -21,7 +18,7 @@ export default async function (io: SocketServer, router: types.Router) {
|
||||
const activeSpeakerObserver = await router.createActiveSpeakerObserver()
|
||||
|
||||
audioLevelObserver.on('volumes', async (volumes: types.AudioLevelObserverVolume[]) => {
|
||||
namespace.emit('speakingPeers', volumes.map(({ producer, volume }) => {
|
||||
io.emit('speakingPeers', volumes.map(({ producer, volume }) => {
|
||||
const { socketId } = producer.appData as { socketId: ChadClient['socketId'] }
|
||||
|
||||
return {
|
||||
@@ -32,17 +29,17 @@ export default async function (io: SocketServer, router: types.Router) {
|
||||
})
|
||||
|
||||
audioLevelObserver.on('silence', () => {
|
||||
namespace.emit('speakingPeers', [])
|
||||
namespace.emit('activeSpeaker', undefined)
|
||||
io.emit('speakingPeers', [])
|
||||
io.emit('activeSpeaker', undefined)
|
||||
})
|
||||
|
||||
activeSpeakerObserver.on('dominantspeaker', ({ producer }) => {
|
||||
const { socketId } = producer.appData as { socketId: ChadClient['socketId'] }
|
||||
|
||||
namespace.emit('activeSpeaker', socketId)
|
||||
io.emit('activeSpeaker', socketId)
|
||||
})
|
||||
|
||||
namespace.on('connection', async (socket) => {
|
||||
io.on('connection', async (socket) => {
|
||||
consola.info('[WebRtc]', 'Client connected', socket.id)
|
||||
|
||||
socket.data.joined = false
|
||||
@@ -350,7 +347,7 @@ export default async function (io: SocketServer, router: types.Router) {
|
||||
|
||||
cb(socketToClient(socket))
|
||||
|
||||
namespace.emit('clientChanged', socket.id, socketToClient(socket))
|
||||
io.emit('clientChanged', socket.id, socketToClient(socket))
|
||||
})
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
@@ -367,7 +364,7 @@ export default async function (io: SocketServer, router: types.Router) {
|
||||
})
|
||||
|
||||
async function getJoinedSockets(excludeId?: string) {
|
||||
const sockets = await namespace.fetchSockets()
|
||||
const sockets = await io.fetchSockets()
|
||||
|
||||
return sockets.filter(socket => socket.data.joined && (excludeId ? excludeId !== socket.id : true))
|
||||
}
|
||||
|
||||
18
server/types/chat.ts
Normal file
18
server/types/chat.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export interface ChatClientMessage {
|
||||
text: string
|
||||
replyTo?: {
|
||||
messageId: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string
|
||||
sender: string
|
||||
text: string
|
||||
createdAt: string
|
||||
replyTo?: {
|
||||
messageId: string
|
||||
sender: string
|
||||
text: string
|
||||
}
|
||||
}
|
||||
@@ -331,6 +331,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fastify/busboy@npm:^3.0.0":
|
||||
version: 3.2.0
|
||||
resolution: "@fastify/busboy@npm:3.2.0"
|
||||
checksum: 10c0/3e4fb00a27e3149d1c68de8ff14007d2bbcbbc171a9d050d0a8772e836727329d4d3f130995ebaa19cf537d5d2f5ce2a88000366e6192e751457bfcc2125f351
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fastify/cookie@npm:^11.0.2":
|
||||
version: 11.0.2
|
||||
resolution: "@fastify/cookie@npm:11.0.2"
|
||||
@@ -351,6 +358,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fastify/deepmerge@npm:^3.0.0":
|
||||
version: 3.2.1
|
||||
resolution: "@fastify/deepmerge@npm:3.2.1"
|
||||
checksum: 10c0/2c0f8b627537834822ec761842e3a57965d3fb59e011ac5f2215b618ce34698e277bcbe4f586b09e4f03347391f292cfef9dccb6bda7b019ea9420d8767ade49
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fastify/error@npm:^4.0.0":
|
||||
version: 4.2.0
|
||||
resolution: "@fastify/error@npm:4.2.0"
|
||||
@@ -383,6 +397,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fastify/multipart@npm:^10.0.0":
|
||||
version: 10.0.0
|
||||
resolution: "@fastify/multipart@npm:10.0.0"
|
||||
dependencies:
|
||||
"@fastify/busboy": "npm:^3.0.0"
|
||||
"@fastify/deepmerge": "npm:^3.0.0"
|
||||
"@fastify/error": "npm:^4.0.0"
|
||||
fastify-plugin: "npm:^5.0.0"
|
||||
secure-json-parse: "npm:^4.0.0"
|
||||
checksum: 10c0/49e09135599a59aab761b71f65ab5f9ad63c3ea28ede04389c308dea1149b1fd7779693230f5bc0ffc9063c42484e99a2d1d38c0fd73b074c9ed3216db12e9da
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@fastify/proxy-addr@npm:^5.0.0":
|
||||
version: 5.1.0
|
||||
resolution: "@fastify/proxy-addr@npm:5.1.0"
|
||||
@@ -4265,6 +4292,7 @@ __metadata:
|
||||
"@fastify/autoload": "npm:^6.3.1"
|
||||
"@fastify/cookie": "npm:^11.0.2"
|
||||
"@fastify/cors": "npm:^11.1.0"
|
||||
"@fastify/multipart": "npm:^10.0.0"
|
||||
"@lucia-auth/adapter-prisma": "npm:^4.0.1"
|
||||
"@prisma/client": "npm:^6.17.0"
|
||||
"@types/bcrypt": "npm:^6"
|
||||
@@ -4281,6 +4309,7 @@ __metadata:
|
||||
socket.io: "npm:^4.8.1"
|
||||
ts-node: "npm:^10.9.2"
|
||||
typescript: "npm:^5.9.3"
|
||||
uuid: "npm:^13.0.0"
|
||||
ws: "npm:^8.18.3"
|
||||
zod: "npm:^4.1.12"
|
||||
languageName: unknown
|
||||
@@ -4787,6 +4816,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"uuid@npm:^13.0.0":
|
||||
version: 13.0.0
|
||||
resolution: "uuid@npm:13.0.0"
|
||||
bin:
|
||||
uuid: dist-node/bin/uuid
|
||||
checksum: 10c0/950e4c18d57fef6c69675344f5700a08af21e26b9eff2bf2180427564297368c538ea11ac9fb2e6528b17fc3966a9fd2c5049361b0b63c7d654f3c550c9b3d67
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"v8-compile-cache-lib@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "v8-compile-cache-lib@npm:3.0.1"
|
||||
|
||||
Reference in New Issue
Block a user