@@ -9,6 +9,7 @@ import { IChainCastRepository } from "../../core/interfaces/repositories/chainCa
99import { ICommunityAdminRepository } from "../../core/interfaces/repositories/ICommunityAdminRepository" ;
1010import { IUserRepository } from "../../core/interfaces/repositories/IUser.repository" ;
1111import CommunityMemberModel from "../../models/communityMember.model" ;
12+ import { ILiveKitService } from "../../core/interfaces/services/livekit/ILiveKit.service" ;
1213import { ErrorMessages , SuccessMessages , LoggerMessages } from "../../enums/messages.enum" ;
1314import {
1415 CreateChainCastDto ,
@@ -44,7 +45,8 @@ export class ChainCastService implements IChainCastService {
4445 private _chainCastRepository : IChainCastRepository ,
4546 @inject ( TYPES . ICommunityAdminRepository )
4647 private _adminRepository : ICommunityAdminRepository ,
47- @inject ( TYPES . IUserRepository ) private _userRepository : IUserRepository
48+ @inject ( TYPES . IUserRepository ) private _userRepository : IUserRepository ,
49+ @inject ( TYPES . ILiveKitService ) private _liveKitService : ILiveKitService
4850 ) { }
4951
5052 // Admin ChainCast management
@@ -248,13 +250,41 @@ export class ChainCastService implements IChainCastService {
248250 }
249251
250252 const populatedAdmin = chainCast . adminId as unknown as PopulatedAdmin ;
251- return new ChainCastResponseDto (
253+ const response = new ChainCastResponseDto (
252254 chainCast ,
253255 populatedAdmin ,
254256 userRole ,
255257 canJoin ,
256258 canModerate
257259 ) ;
260+
261+ // If live and user is authenticated, provide a token
262+ if ( chainCast . status === "live" && userId ) {
263+ const roomName = `chaincast_${ chainCastId } ` ;
264+ const isHost = userRole === "admin" ;
265+
266+ let identityName = "Guest" ;
267+ if ( isHost ) {
268+ identityName = populatedAdmin . name || "Host" ;
269+ } else {
270+ try {
271+ const user = await this . _userRepository . findById ( userId ) ;
272+ identityName = user ?. name || user ?. username || `Guest_${ userId . substring ( 0 , 4 ) } ` ;
273+ } catch ( e ) {
274+ identityName = `Guest_${ userId . substring ( 0 , 4 ) } ` ;
275+ }
276+ }
277+
278+ response . livekitToken = await this . _generateLiveKitToken (
279+ roomName ,
280+ userId ,
281+ identityName ,
282+ isHost
283+ ) ;
284+ response . serverUrl = process . env . LIVE_KIT_WEBSOCKET_URL || process . env . LIVE_KIT_URL || process . env . LIVEKIT_URL ;
285+ }
286+
287+ return response ;
258288 } catch ( error ) {
259289 logger . error ( LoggerMessages . GET_CHAINCAST_BY_ID_ERROR , error ) ;
260290 if ( error instanceof CustomError ) {
@@ -440,6 +470,29 @@ export class ChainCastService implements IChainCastService {
440470 ) ;
441471 }
442472
473+ if ( chainCast . status === "live" ) {
474+ // Already live, just return with a fresh token
475+ const admin = await this . _adminRepository . findById ( adminId ) ;
476+ const roomName = `chaincast_${ chainCastId } ` ;
477+ const token = await this . _generateLiveKitToken (
478+ roomName ,
479+ adminId ,
480+ admin ?. name || 'Host' ,
481+ true
482+ ) ;
483+
484+ const response = new ChainCastResponseDto (
485+ chainCast ,
486+ admin ! ,
487+ "admin" ,
488+ true ,
489+ true
490+ ) ;
491+ response . livekitToken = token ;
492+ response . serverUrl = process . env . LIVE_KIT_WEBSOCKET_URL || process . env . LIVE_KIT_URL || process . env . LIVEKIT_URL ;
493+ return response ;
494+ }
495+
443496 if ( chainCast . status !== "scheduled" ) {
444497 throw new CustomError (
445498 ErrorMessages . CHAINCAST_NOT_SCHEDULED ,
@@ -472,13 +525,27 @@ export class ChainCastService implements IChainCastService {
472525 await this . _createAdminParticipant ( chainCastId , adminId ) ;
473526
474527 const admin = await this . _adminRepository . findById ( adminId ) ;
475- return new ChainCastResponseDto (
528+
529+ // Generate LiveKit token for host
530+ const roomName = `chaincast_${ chainCastId } ` ;
531+ const token = await this . _generateLiveKitToken (
532+ roomName ,
533+ adminId ,
534+ admin ?. name || 'Host' ,
535+ true
536+ ) ;
537+
538+ const response = new ChainCastResponseDto (
476539 updatedChainCast ,
477540 admin ,
478541 "admin" ,
479542 true ,
480543 true
481544 ) ;
545+ response . livekitToken = token ;
546+ response . serverUrl = process . env . LIVE_KIT_WEBSOCKET_URL || process . env . LIVE_KIT_URL || process . env . LIVEKIT_URL ;
547+
548+ return response ;
482549 } catch ( error ) {
483550 logger . error ( LoggerMessages . START_CHAINCAST_ERROR , error ) ;
484551 if ( error instanceof CustomError ) {
@@ -645,12 +712,12 @@ export class ChainCastService implements IChainCastService {
645712 * Joins a ChainCast.
646713 * @param {string } userId - User ID.
647714 * @param {JoinChainCastDto } data - Join data.
648- * @returns {Promise<{ success: boolean; message: string; streamUrl?: string }> } Join result.
715+ * @returns {Promise<{ success: boolean; message: string; streamUrl?: string; livekitToken?: string; serverUrl?: string }> } Join result.
649716 */
650717 async joinChainCast (
651718 userId : string ,
652719 data : JoinChainCastDto
653- ) : Promise < { success : boolean ; message : string ; streamUrl ?: string } > {
720+ ) : Promise < { success : boolean ; message : string ; streamUrl ?: string ; livekitToken ?: string ; serverUrl ?: string } > {
654721 try {
655722 const chainCast = await this . _chainCastRepository . findChainCastById (
656723 data . chainCastId
@@ -742,10 +809,22 @@ export class ChainCastService implements IChainCastService {
742809 } ;
743810 await this . _chainCastRepository . updateChainCast ( data . chainCastId , updateDataForStats as Partial < IChainCast > ) ;
744811
812+ // Generate LiveKit token for user
813+ const user = await this . _userRepository . findById ( userId ) ;
814+ const roomName = `chaincast_${ data . chainCastId } ` ;
815+ const token = await this . _generateLiveKitToken (
816+ roomName ,
817+ userId ,
818+ user ?. name || user ?. username || "Participant" ,
819+ false
820+ ) ;
821+
745822 return {
746823 success : true ,
747824 message : SuccessMessages . JOIN_CHAINCAST_SUCCESS ,
748- streamUrl : chainCast . streamData . streamUrl ,
825+ streamUrl : chainCast . streamData . streamUrl , // legacy
826+ livekitToken : token ,
827+ serverUrl : process . env . LIVE_KIT_WEBSOCKET_URL || process . env . LIVE_KIT_URL || process . env . LIVEKIT_URL ,
749828 } ;
750829 } catch ( error ) {
751830 logger . error ( LoggerMessages . JOIN_CHAINCAST_ERROR , error ) ;
@@ -1544,4 +1623,20 @@ export class ChainCastService implements IChainCastService {
15441623 // This would be done with a bulk update in MongoDB
15451624 // For now, we'll leave this as a placeholder
15461625 }
1626+ private async _generateLiveKitToken (
1627+ roomName : string ,
1628+ identity : string ,
1629+ username : string ,
1630+ isHost : boolean = false
1631+ ) : Promise < string > {
1632+ const grants = {
1633+ roomJoin : true ,
1634+ canPublish : isHost ,
1635+ canSubscribe : true ,
1636+ canPublishData : true ,
1637+ roomAdmin : isHost ,
1638+ } ;
1639+
1640+ return this . _liveKitService . generateToken ( roomName , identity , username , grants ) ;
1641+ }
15471642}
0 commit comments