import { Server as HTTPServer } from 'http' ; import { Namespace , Server as SocketServer , Socket } from 'socket.io' ; import { isIdValid } from '@server/helpers/custom-validators/misc' ; import { MVideo , MVideoImmutable } from '@server/types/models' ; import { UserNotificationModelForApi } from '@server/types/models/user' ; import { LiveVideoEventPayload , LiveVideoEventType } from '@shared/models' ; import { logger } from '../helpers/logger' ; import { authenticateSocket } from '../middlewares' ; class PeerTubeSocket { private static instance : PeerTubeSocket ; private userNotificationSockets : { [ userId ] : Socket [ ] ; } = { } ; private liveVideosNamespace : Namespace ; private constructor ( ) { } init ( server ) { const io = new SocketServer ( server ) ; io . of ( '/user-notifications' ) . use ( authenticateSocket ) . on ( 'connection' , socket => { const userId = socket . handshake . auth . user . id ; logger . debug ( 'User %d connected on the notification system.' , userId ) ; if ( ! this . userNotificationSockets [ userId ] ) this . userNotificationSockets [ userId ] = [ ] ; this . userNotificationSockets [ userId ] . push ( socket ) ; socket . on ( 'disconnect' , ( ) => { logger . debug ( 'User %d disconnected from SocketIO notifications.' , userId ) ; this . userNotificationSockets [ userId ] = this . userNotificationSockets [ userId ] . filter ( s => s !== socket ) ; } ) ; } ) ; this . liveVideosNamespace = io . of ( '/live-videos' ) . on ( 'connection' , socket => { socket . on ( 'subscribe' , ( { videoId } ) => { if ( ! isIdValid ( videoId ) ) return ; socket . join ( videoId ) ; } ) ; socket . on ( 'unsubscribe' , ( { videoId } ) => { if ( ! isIdValid ( videoId ) ) return ; socket . leave ( videoId ) ; } ) ; } ) ; } sendNotification ( userId , notification ) { const sockets = this . userNotificationSockets [ userId ] ; if ( ! sockets ) return ; logger . debug ( 'Sending user notification to user %d.' , userId ) ; const notificationMessage = notification . toFormattedJSON ( ) ; for ( const socket of sockets ) { socket . emit ( 'new-notification' , notificationMessage ) ; } } sendVideoLiveNewState ( video ) { const data = { state : video . state } ; const type = 'state-change' ; logger . debug ( 'Sending video live new state notification of %s.' , video . url , { state : video . state } ) ; this . liveVideosNamespace . in ( video . id ) . emit ( type , data ) ; } sendVideoViewsUpdate ( video , numViewers ) { const data = { viewers : numViewers , views : numViewers } ; const type = 'views-change' ; logger . debug ( 'Sending video live views update notification of %s.' , video . url , { viewers : numViewers } ) ; this . liveVideosNamespace . in ( video . id ) . emit ( type , data ) ; } static get Instance ( ) { return this . instance || ( this . instance = new this ( ) ) ; } } export { PeerTubeSocket } ;