]>
Commit | Line | Data |
---|---|---|
a5cf76af | 1 | import { Socket } from 'dgram' |
cef534ed | 2 | import { Server } from 'http' |
a5cf76af C |
3 | import * as SocketIO from 'socket.io' |
4 | import { MVideo } from '@server/types/models' | |
26d6bf65 | 5 | import { UserNotificationModelForApi } from '@server/types/models/user' |
a5cf76af C |
6 | import { LiveVideoEventPayload, LiveVideoEventType } from '@shared/models' |
7 | import { logger } from '../helpers/logger' | |
8 | import { authenticateSocket } from '../middlewares' | |
cef534ed C |
9 | |
10 | class PeerTubeSocket { | |
11 | ||
12 | private static instance: PeerTubeSocket | |
13 | ||
1b42d73f | 14 | private userNotificationSockets: { [ userId: number ]: SocketIO.Socket[] } = {} |
a5cf76af | 15 | private liveVideosNamespace: SocketIO.Namespace |
cef534ed C |
16 | |
17 | private constructor () {} | |
18 | ||
19 | init (server: Server) { | |
20 | const io = SocketIO(server) | |
21 | ||
22 | io.of('/user-notifications') | |
23 | .use(authenticateSocket) | |
24 | .on('connection', socket => { | |
25 | const userId = socket.handshake.query.user.id | |
26 | ||
27 | logger.debug('User %d connected on the notification system.', userId) | |
28 | ||
1b42d73f C |
29 | if (!this.userNotificationSockets[userId]) this.userNotificationSockets[userId] = [] |
30 | ||
31 | this.userNotificationSockets[userId].push(socket) | |
cef534ed C |
32 | |
33 | socket.on('disconnect', () => { | |
34 | logger.debug('User %d disconnected from SocketIO notifications.', userId) | |
35 | ||
1b42d73f | 36 | this.userNotificationSockets[userId] = this.userNotificationSockets[userId].filter(s => s !== socket) |
cef534ed C |
37 | }) |
38 | }) | |
a5cf76af C |
39 | |
40 | this.liveVideosNamespace = io.of('/live-videos') | |
41 | .on('connection', socket => { | |
42 | socket.on('subscribe', ({ videoId }) => socket.join(videoId)) | |
43 | socket.on('unsubscribe', ({ videoId }) => socket.leave(videoId)) | |
44 | }) | |
cef534ed C |
45 | } |
46 | ||
453e83ea | 47 | sendNotification (userId: number, notification: UserNotificationModelForApi) { |
1b42d73f | 48 | const sockets = this.userNotificationSockets[userId] |
1b42d73f | 49 | if (!sockets) return |
cef534ed | 50 | |
a5cf76af C |
51 | logger.debug('Sending user notification to user %d.', userId) |
52 | ||
20ec0384 | 53 | const notificationMessage = notification.toFormattedJSON() |
1b42d73f | 54 | for (const socket of sockets) { |
20ec0384 | 55 | socket.emit('new-notification', notificationMessage) |
1b42d73f | 56 | } |
cef534ed C |
57 | } |
58 | ||
a5cf76af C |
59 | sendVideoLiveNewState (video: MVideo) { |
60 | const data: LiveVideoEventPayload = { state: video.state } | |
61 | const type: LiveVideoEventType = 'state-change' | |
62 | ||
63 | logger.debug('Sending video live new state notification of %s.', video.url) | |
64 | ||
65 | this.liveVideosNamespace | |
66 | .in(video.id) | |
67 | .emit(type, data) | |
68 | } | |
69 | ||
cef534ed C |
70 | static get Instance () { |
71 | return this.instance || (this.instance = new this()) | |
72 | } | |
73 | } | |
74 | ||
75 | // --------------------------------------------------------------------------- | |
76 | ||
77 | export { | |
78 | PeerTubeSocket | |
79 | } |