diff --git a/testapp/public/ts/webcomponent.ts b/testapp/public/ts/webcomponent.ts index bd28596..9f50214 100644 --- a/testapp/public/ts/webcomponent.ts +++ b/testapp/public/ts/webcomponent.ts @@ -1,9 +1,10 @@ const socket = (window as any).io(); let meet: { - endMeeting: () => void; - leaveRoom: () => void; - on: (event: string, callback: (event: CustomEvent) => void) => void; + endMeeting: () => void; + leaveRoom: () => void; + kickParticipant: (participantIdentity: string) => void; + on: (event: string, callback: (event: CustomEvent) => void) => void; }; let roomId: string | undefined; let showAllWebhooksCheckbox: HTMLInputElement | null; @@ -12,238 +13,243 @@ let showAllWebhooksCheckbox: HTMLInputElement | null; * Add a component event to the events log */ const addEventToLog = (eventType: string, eventMessage: string): void => { - const eventsList = document.getElementById('events-list'); - if (eventsList) { - const li = document.createElement('li'); - li.className = `event-${eventType}`; - li.textContent = `[ ${eventType} ] : ${eventMessage}`; - eventsList.insertBefore(li, eventsList.firstChild); - } + const eventsList = document.getElementById('events-list'); + if (eventsList) { + const li = document.createElement('li'); + li.className = `event-${eventType}`; + li.textContent = `[ ${eventType} ] : ${eventMessage}`; + eventsList.insertBefore(li, eventsList.firstChild); + } }; const escapeHtml = (unsafe: string): string => { - return unsafe - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); + return unsafe + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); }; const getWebhookEventsFromStorage = (roomId: string): any[] => { - const data = localStorage.getItem('webhookEventsByRoom'); - if (!data) return []; - const map = JSON.parse(data); - return map[roomId] || []; + const data = localStorage.getItem('webhookEventsByRoom'); + if (!data) { + return []; + } + + const map = JSON.parse(data); + return map[roomId] || []; }; const saveWebhookEventToStorage = (roomId: string, event: any): void => { - const data = localStorage.getItem('webhookEventsByRoom'); - const map = data ? JSON.parse(data) : {}; - if (!map[roomId]) map[roomId] = []; - map[roomId].push(event); - localStorage.setItem('webhookEventsByRoom', JSON.stringify(map)); + const data = localStorage.getItem('webhookEventsByRoom'); + const map = data ? JSON.parse(data) : {}; + if (!map[roomId]) { + map[roomId] = []; + } + + map[roomId].push(event); + localStorage.setItem('webhookEventsByRoom', JSON.stringify(map)); }; const clearWebhookEventsByRoom = (roomId: string): void => { - const data = localStorage.getItem('webhookEventsByRoom'); - if (!data) return; - const map = JSON.parse(data); - if (map[roomId]) { - map[roomId] = []; - localStorage.setItem('webhookEventsByRoom', JSON.stringify(map)); - } + const data = localStorage.getItem('webhookEventsByRoom'); + if (!data) return; + + const map = JSON.parse(data); + if (map[roomId]) { + map[roomId] = []; + localStorage.setItem('webhookEventsByRoom', JSON.stringify(map)); + } }; const shouldShowWebhook = (event: any): boolean => { - return showAllWebhooksCheckbox?.checked || event.data.roomId === roomId; + return showAllWebhooksCheckbox?.checked || event.data.roomId === roomId; }; + const listenWebhookServerEvents = () => { - socket.on('webhookEvent', (event: any) => { - console.log('Webhook received:', event); - const webhookRoomId = event.data.roomId; + socket.on('webhookEvent', (event: any) => { + console.log('Webhook received:', event); + const webhookRoomId = event.data.roomId; - if (webhookRoomId) { - saveWebhookEventToStorage(webhookRoomId, event); - } + if (webhookRoomId) { + saveWebhookEventToStorage(webhookRoomId, event); + } - if (!shouldShowWebhook(event)) { - console.log('Ignoring webhook event:', event); - return; - } + if (!shouldShowWebhook(event)) { + console.log('Ignoring webhook event:', event); + return; + } - addWebhookEventElement(event); + addWebhookEventElement(event); - // Clean up the previous events - const isMeetingEnded = event.event === 'meetingEnded'; - if (isMeetingEnded) clearWebhookEventsByRoom(webhookRoomId); - }); + // Clean up the previous events + const isMeetingEnded = event.event === 'meetingEnded'; + if (isMeetingEnded) clearWebhookEventsByRoom(webhookRoomId); + }); }; const renderStoredWebhookEvents = (roomId: string) => { - const webhookLogList = document.getElementById('webhook-log-list'); - if (webhookLogList) { - while (webhookLogList.firstChild) { - webhookLogList.removeChild(webhookLogList.firstChild); - } - } - const events = getWebhookEventsFromStorage(roomId); - events.forEach((event) => addWebhookEventElement(event)); + const webhookLogList = document.getElementById('webhook-log-list'); + if (webhookLogList) { + while (webhookLogList.firstChild) { + webhookLogList.removeChild(webhookLogList.firstChild); + } + } + + const events = getWebhookEventsFromStorage(roomId); + events.forEach((event) => addWebhookEventElement(event)); }; const addWebhookEventElement = (event: any) => { - const webhookLogList = document.getElementById('webhook-log-list'); - if (webhookLogList) { - // Create unique IDs for this accordion item - const itemId = event.creationDate; - const headerClassName = `webhook-${event.event}`; - const collapseId = `collapse-${itemId}`; + const webhookLogList = document.getElementById('webhook-log-list'); + if (webhookLogList) { + // Create unique IDs for this accordion item + const itemId = event.creationDate; + const headerClassName = `webhook-${event.event}`; + const collapseId = `collapse-${itemId}`; - // Create accordion item container - const accordionItem = document.createElement('div'); - accordionItem.className = 'accordion-item'; + // Create accordion item container + const accordionItem = document.createElement('div'); + accordionItem.className = 'accordion-item'; - // Create header - const header = document.createElement('h2'); - header.classList.add(headerClassName, 'accordion-header'); + // Create header + const header = document.createElement('h2'); + header.classList.add(headerClassName, 'accordion-header'); - // Create header button - const button = document.createElement('button'); - button.className = 'accordion-button'; - button.type = 'button'; - button.setAttribute('data-bs-toggle', 'collapse'); - button.setAttribute('data-bs-target', `#${collapseId}`); - button.setAttribute('aria-expanded', 'true'); - button.setAttribute('aria-controls', collapseId); - button.style.padding = '10px'; + // Create header button + const button = document.createElement('button'); + button.className = 'accordion-button'; + button.type = 'button'; + button.setAttribute('data-bs-toggle', 'collapse'); + button.setAttribute('data-bs-target', `#${collapseId}`); + button.setAttribute('aria-expanded', 'true'); + button.setAttribute('aria-controls', collapseId); + button.style.padding = '10px'; - if (event.event === 'meetingStarted') { - button.classList.add('bg-success'); - } - if (event.event === 'meetingEnded') { - button.classList.add('bg-danger'); - } - if (event.event.includes('recording')) { - button.classList.add('bg-warning'); - } - // Format the header text with event name and timestamp - const date = new Date(event.creationDate); + if (event.event === 'meetingStarted') { + button.classList.add('bg-success'); + } + if (event.event === 'meetingEnded') { + button.classList.add('bg-danger'); + } + if (event.event.includes('recording')) { + button.classList.add('bg-warning'); + } - const formattedDate = date.toLocaleString('es-ES', { - // year: 'numeric', - // month: '2-digit', - // day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - hour12: false, - }); - button.innerHTML = `[${formattedDate}] ${event.event}`; + // Format the header text with event name and timestamp + const date = new Date(event.creationDate); + const formattedDate = date.toLocaleString('es-ES', { + // year: 'numeric', + // month: '2-digit', + // day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false + }); + button.innerHTML = `[${formattedDate}] ${event.event}`; - // Create collapsible content container - const collapseDiv = document.createElement('div'); - collapseDiv.id = collapseId; - collapseDiv.className = 'accordion-collapse collapse'; - collapseDiv.setAttribute('aria-labelledby', headerClassName); - collapseDiv.setAttribute('data-bs-parent', '#webhook-log-list'); + // Create collapsible content container + const collapseDiv = document.createElement('div'); + collapseDiv.id = collapseId; + collapseDiv.className = 'accordion-collapse collapse'; + collapseDiv.setAttribute('aria-labelledby', headerClassName); + collapseDiv.setAttribute('data-bs-parent', '#webhook-log-list'); - // Create body content - const bodyDiv = document.createElement('div'); - bodyDiv.className = 'accordion-body'; + // Create body content + const bodyDiv = document.createElement('div'); + bodyDiv.className = 'accordion-body'; - // Format JSON with syntax highlighting if possible - const formattedJson = JSON.stringify(event, null, 2); - bodyDiv.innerHTML = `
${escapeHtml(
-			formattedJson
-		)}
`; + // Format JSON with syntax highlighting if possible + const formattedJson = JSON.stringify(event, null, 2); + bodyDiv.innerHTML = `
${escapeHtml(formattedJson)}
`; - // Assemble the components - header.appendChild(button); - collapseDiv.appendChild(bodyDiv); - accordionItem.appendChild(header); - accordionItem.appendChild(collapseDiv); + // Assemble the components + header.appendChild(button); + collapseDiv.appendChild(bodyDiv); + accordionItem.appendChild(header); + accordionItem.appendChild(collapseDiv); - // Insert at the top of the list (latest events first) - if (webhookLogList.firstChild) { - webhookLogList.insertBefore(accordionItem, webhookLogList.firstChild); - } else { - webhookLogList.appendChild(accordionItem); - } + // Insert at the top of the list (latest events first) + if (webhookLogList.firstChild) { + webhookLogList.insertBefore(accordionItem, webhookLogList.firstChild); + } else { + webhookLogList.appendChild(accordionItem); + } - // Limit the number of items to prevent performance issues - const maxItems = 50; - while (webhookLogList.children.length > maxItems) { - webhookLogList.removeChild(webhookLogList.lastChild!); - } - } + // Limit the number of items to prevent performance issues + const maxItems = 50; + while (webhookLogList.children.length > maxItems) { + webhookLogList.removeChild(webhookLogList.lastChild!); + } + } }; // Listen to events from openvidu-meet - const listenWebComponentEvents = () => { - const meet = document.querySelector('openvidu-meet') as any; - if (!meet) { - console.error('openvidu-meet component not found'); - alert('openvidu-meet component not found in the DOM'); - return; - } + const meet = document.querySelector('openvidu-meet') as any; + if (!meet) { + console.error('openvidu-meet component not found'); + alert('openvidu-meet component not found in the DOM'); + return; + } - meet.on('JOIN', (event: CustomEvent) => { - console.log('JOIN event received:', event); - addEventToLog('JOIN', JSON.stringify(event)); - }); - meet.on('LEFT', (event: CustomEvent) => { - console.log('LEFT event received:', event); - addEventToLog('LEFT', JSON.stringify(event)); - }); - - meet.on('MEETING_ENDED', (event: CustomEvent) => { - console.log('MEETING_ENDED event received:', event); - addEventToLog('MEETING_ENDED', JSON.stringify(event)); - }); + meet.on('JOIN', (event: CustomEvent) => { + console.log('JOIN event received:', event); + addEventToLog('JOIN', JSON.stringify(event)); + }); + meet.on('LEFT', (event: CustomEvent) => { + console.log('LEFT event received:', event); + addEventToLog('LEFT', JSON.stringify(event)); + }); + meet.on('MEETING_ENDED', (event: CustomEvent) => { + console.log('MEETING_ENDED event received:', event); + addEventToLog('MEETING_ENDED', JSON.stringify(event)); + }); }; // Set up commands for the web component const setUpWebComponentCommands = () => { - if (!meet) { - console.error('openvidu-meet component not found'); - alert('openvidu-meet component not found in the DOM'); - return; - } + if (!meet) { + console.error('openvidu-meet component not found'); + alert('openvidu-meet component not found in the DOM'); + return; + } - // End meeting button click handler - document - .getElementById('end-meeting-btn') - ?.addEventListener('click', () => meet.endMeeting()); + // End meeting button click handler + document.getElementById('end-meeting-btn')?.addEventListener('click', () => meet.endMeeting()); - // Leave room button click handler - document - .getElementById('leave-room-btn') - ?.addEventListener('click', () => meet.leaveRoom()); + // Leave room button click handler + document.getElementById('leave-room-btn')?.addEventListener('click', () => meet.leaveRoom()); - // Toggle chat button click handler - // document - // .getElementById('toggle-chat-btn') - // ?.addEventListener('click', () => meet.toggleChat()); + // Kick participant button click handler + document.getElementById('kick-participant-btn')?.addEventListener('click', () => { + const participantIdentity = ( + document.getElementById('participant-identity-input') as HTMLInputElement + ).value.trim(); + if (participantIdentity) { + meet.kickParticipant(participantIdentity); + } + }); }; document.addEventListener('DOMContentLoaded', () => { - roomId = document.getElementById('room-id')?.textContent?.trim(); - showAllWebhooksCheckbox = document.getElementById( - 'show-all-webhooks' - ) as HTMLInputElement; - meet = document.querySelector('openvidu-meet') as any; + roomId = document.getElementById('room-id')?.textContent?.trim(); + showAllWebhooksCheckbox = document.getElementById('show-all-webhooks') as HTMLInputElement; + meet = document.querySelector('openvidu-meet') as any; - if (!roomId) { - console.error('Room ID not found in the DOM'); - alert('Room ID not found in the DOM'); - return; - } - renderStoredWebhookEvents(roomId); - listenWebhookServerEvents(); - listenWebComponentEvents(); - setUpWebComponentCommands(); + if (!roomId) { + console.error('Room ID not found in the DOM'); + alert('Room ID not found in the DOM'); + return; + } - showAllWebhooksCheckbox?.addEventListener('change', () => { - if (roomId) renderStoredWebhookEvents(roomId); - }); + renderStoredWebhookEvents(roomId); + listenWebhookServerEvents(); + listenWebComponentEvents(); + setUpWebComponentCommands(); + + showAllWebhooksCheckbox?.addEventListener('change', () => { + if (roomId) renderStoredWebhookEvents(roomId); + }); }); diff --git a/testapp/public/views/index.mustache b/testapp/public/views/index.mustache index 5bdec74..ba0c20f 100644 --- a/testapp/public/views/index.mustache +++ b/testapp/public/views/index.mustache @@ -109,24 +109,29 @@ - {{! ONLY RECORDINGS LINK }} + {{! SHOW ONLY RECORDINGS LINK }}
  • + - + {{#isModerator}} + + + {{/isModerator}} @@ -82,7 +90,9 @@ diff --git a/testapp/src/controllers/homeController.ts b/testapp/src/controllers/homeController.ts index 5719471..3b35c4b 100644 --- a/testapp/src/controllers/homeController.ts +++ b/testapp/src/controllers/homeController.ts @@ -1,124 +1,112 @@ import { Request, Response } from 'express'; -import { - getAllRooms, - createRoom, - deleteRoom, - deleteAllRooms, -} from '../services/roomService'; -import { - deleteAllRecordings, - getAllRecordings, -} from '../services/recordingService'; +import { getAllRooms, createRoom, deleteRoom, deleteAllRooms } from '../services/roomService'; +import { deleteAllRecordings, getAllRecordings } from '../services/recordingService'; -export const getHome = async (req: Request, res: Response) => { - try { - const { rooms } = await getAllRooms(); +export const getHome = async (_req: Request, res: Response) => { + try { + const { rooms } = await getAllRooms(); - //sort rooms by newest first - rooms.sort((a, b) => { - const dateA = new Date(a.creationDate); - const dateB = new Date(b.creationDate); - return dateB.getTime() - dateA.getTime(); - }); + // Sort rooms by newest first + rooms.sort((a, b) => { + const dateA = new Date(a.creationDate); + const dateB = new Date(b.creationDate); + return dateB.getTime() - dateA.getTime(); + }); - console.log(`Rooms fetched: ${rooms.length}`); - res.render('index', { rooms }); - } catch (error) { - console.error('Error fetching rooms:', error); - res.status(500).send('Internal Server Error'); - return; - } + console.log(`Rooms fetched: ${rooms.length}`); + res.render('index', { rooms }); + } catch (error) { + console.error('Error fetching rooms:', error); + res.status(500).send('Internal Server Error'); + return; + } }; export const postCreateRoom = async (req: Request, res: Response) => { - try { - const { roomIdPrefix, autoDeletionDate } = req.body; - const preferences = processFormPreferences(req.body); + try { + const { roomIdPrefix, autoDeletionDate } = req.body; + const preferences = processFormPreferences(req.body); - await createRoom({ roomIdPrefix, autoDeletionDate, preferences }); - res.redirect('/'); - } catch (error) { - console.error('Error creating room:', error); - res.status(500).send('Internal Server Error'); - return; - } + await createRoom({ roomIdPrefix, autoDeletionDate, preferences }); + res.redirect('/'); + } catch (error) { + console.error('Error creating room:', error); + res.status(500).send('Internal Server Error'); + return; + } }; export const deleteRoomCtrl = async (req: Request, res: Response) => { - try { - const { roomId } = req.body; - await deleteRoom(roomId); - res.redirect('/'); - } catch (error) { - console.error('Error deleting room:', error); - res.status(500).send('Internal Server Error'); - return; - } + try { + const { roomId } = req.body; + await deleteRoom(roomId); + res.redirect('/'); + } catch (error) { + console.error('Error deleting room:', error); + res.status(500).send('Internal Server Error'); + return; + } }; export const deleteAllRoomsCtrl = async (_req: Request, res: Response) => { - try { - const allRooms = await getAllRooms(); - if (allRooms.rooms.length === 0) { - console.log('No rooms to delete'); - res.render('index', { rooms: [] }); - return; - } - const roomIds = allRooms.rooms.map((room) => room.roomId); - console.log(`Deleting ${roomIds.length} rooms`, roomIds); - await deleteAllRooms(roomIds); - res.render('index', { rooms: [] }); - } catch (error) { - console.error('Error deleting all rooms:', error); - res.status(500).send('Internal Server Error ' + JSON.stringify(error)); - return; - } + try { + const allRooms = await getAllRooms(); + if (allRooms.rooms.length === 0) { + console.log('No rooms to delete'); + res.render('index', { rooms: [] }); + return; + } + + const roomIds = allRooms.rooms.map((room) => room.roomId); + console.log(`Deleting ${roomIds.length} rooms`, roomIds); + await deleteAllRooms(roomIds); + res.render('index', { rooms: [] }); + } catch (error) { + console.error('Error deleting all rooms:', error); + res.status(500).send('Internal Server Error ' + JSON.stringify(error)); + return; + } }; export const deleteAllRecordingsCtrl = async (_req: Request, res: Response) => { - try { - const [{ recordings }, { rooms }] = await Promise.all([ - getAllRecordings(), - getAllRooms(), - ]); - if (recordings.length === 0) { - console.log('No recordings to delete'); - res.render('index', { rooms }); - return; - } - const recordingIds = recordings.map((recording) => recording.recordingId); - await deleteAllRecordings(recordingIds); - console.log(`Deleted ${recordingIds.length} recordings`); - res.render('index', { rooms }); - } catch (error) { - console.error('Error deleting all recordings:', error); - res.status(500).send('Internal Server Error ' + JSON.stringify(error)); - return; - } + try { + const [{ recordings }, { rooms }] = await Promise.all([getAllRecordings(), getAllRooms()]); + if (recordings.length === 0) { + console.log('No recordings to delete'); + res.render('index', { rooms }); + return; + } + + const recordingIds = recordings.map((recording) => recording.recordingId); + await deleteAllRecordings(recordingIds); + console.log(`Deleted ${recordingIds.length} recordings`); + res.render('index', { rooms }); + } catch (error) { + console.error('Error deleting all recordings:', error); + res.status(500).send('Internal Server Error ' + JSON.stringify(error)); + return; + } }; /** * Converts flat form data to nested MeetRoomPreferences object */ const processFormPreferences = (body: any): any => { - const preferences = { - chatPreferences: { - enabled: body['preferences.chatPreferences.enabled'] === 'on', - }, - recordingPreferences: { - enabled: body['preferences.recordingPreferences.enabled'] === 'on', - // Only include allowAccessTo if recording is enabled - ...(body['preferences.recordingPreferences.enabled'] === 'on' && { - allowAccessTo: - body['preferences.recordingPreferences.allowAccessTo'] || - 'admin-moderator-publisher', - }), - }, - virtualBackgroundPreferences: { - enabled: - body['preferences.virtualBackgroundPreferences.enabled'] === 'on', - }, - }; + const preferences = { + chatPreferences: { + enabled: body['preferences.chatPreferences.enabled'] === 'on' + }, + recordingPreferences: { + enabled: body['preferences.recordingPreferences.enabled'] === 'on', + // Only include allowAccessTo if recording is enabled + ...(body['preferences.recordingPreferences.enabled'] === 'on' && { + allowAccessTo: body['preferences.recordingPreferences.allowAccessTo'] || 'admin-moderator-publisher' + }) + }, + virtualBackgroundPreferences: { + enabled: body['preferences.virtualBackgroundPreferences.enabled'] === 'on' + } + }; - return preferences; + return preferences; }; diff --git a/testapp/src/controllers/roomController.ts b/testapp/src/controllers/roomController.ts index aa8dc84..8105d6c 100644 --- a/testapp/src/controllers/roomController.ts +++ b/testapp/src/controllers/roomController.ts @@ -5,56 +5,55 @@ import { ParticipantRole } from '../../../typings/src/participant'; import { MeetWebhookEvent } from '../../../typings/src/webhook.model'; interface JoinRoomRequest { - participantRole: ParticipantRole; - roomUrl: string; - roomId: string; - participantName?: string; + participantRole: ParticipantRole; + roomUrl: string; + roomId: string; + participantName?: string; + showOnlyRecordings?: boolean; } export const joinRoom = (req: Request, res: Response) => { - try { - const { - participantRole, - roomUrl, - roomId, - participantName = 'User', - } = req.body as JoinRoomRequest; - if (!roomUrl) { - throw new Error('Room URL is required.'); - } - res.render('room', { - roomUrl, - participantRole, - participantName, - roomId, - isModerator: participantRole === 'moderator', - }); - } catch (error) { - console.error('Error joining room:', error); - res.status(500).send('Internal Server Error'); - return; - } + try { + const { + participantRole, + roomUrl, + roomId, + participantName = 'User', + showOnlyRecordings + } = req.body as JoinRoomRequest; + if (!roomUrl) { + throw new Error('Room URL is required.'); + } + + res.render('room', { + roomUrl, + isModerator: participantRole === 'moderator', + participantName, + roomId, + showOnlyRecordings: showOnlyRecordings || false + }); + } catch (error) { + console.error('Error joining room:', error); + res.status(500).send('Internal Server Error'); + return; + } }; -export const handleWebhook = async ( - req: Request, - res: Response, - io: IOServer -): Promise => { - try { - const webhookEvent = req.body as MeetWebhookEvent; +export const handleWebhook = async (req: Request, res: Response, io: IOServer): Promise => { + try { + const webhookEvent = req.body as MeetWebhookEvent; - // Log event details - console.info(`Webhook received: ${webhookEvent.event}`); + // Log event details + console.info(`Webhook received: ${webhookEvent.event}`); - // Broadcast to all connected clients - io.emit('webhookEvent', webhookEvent); - res.status(200).send('Webhook received'); - } catch (error) { - console.error('Error handling webhook:', error); - res.status(400).json({ - message: 'Error handling webhook', - error: (error as Error).message, - }); - } + // Broadcast to all connected clients + io.emit('webhookEvent', webhookEvent); + res.status(200).send('Webhook received'); + } catch (error) { + console.error('Error handling webhook:', error); + res.status(400).json({ + message: 'Error handling webhook', + error: (error as Error).message + }); + } }; diff --git a/testapp/src/index.ts b/testapp/src/index.ts index c620adc..a6f0e28 100644 --- a/testapp/src/index.ts +++ b/testapp/src/index.ts @@ -1,13 +1,13 @@ import express from 'express'; import http from 'http'; -import { Server as IOServer } from 'socket.io'; import path from 'path'; +import { Server as IOServer } from 'socket.io'; import { - getHome, - postCreateRoom, - deleteRoomCtrl, - deleteAllRoomsCtrl, - deleteAllRecordingsCtrl, + deleteAllRecordingsCtrl, + deleteAllRoomsCtrl, + deleteRoomCtrl, + getHome, + postCreateRoom } from './controllers/homeController'; import { handleWebhook, joinRoom } from './controllers/roomController'; import { configService } from './services/configService'; @@ -31,27 +31,24 @@ app.use(express.json()); // Routes app.get('/', getHome); -app.get('/room', joinRoom); app.post('/room', postCreateRoom); app.post('/room/delete', deleteRoomCtrl); app.post('/delete-all-rooms', deleteAllRoomsCtrl); app.post('/delete-all-recordings', deleteAllRecordingsCtrl); app.post('/join-room', joinRoom); app.post('/webhook', (req, res) => { - handleWebhook(req, res, io); + handleWebhook(req, res, io); }); const PORT = configService.serverPort; server.listen(PORT, () => { - console.log('-----------------------------------------'); - console.log(`Server running on port ${PORT}`); - console.log(`Meet API URL: ${configService.meetApiUrl}`); - console.log('-----------------------------------------'); - console.log(''); - console.log(`Visit http://localhost:${PORT}/ to access the app`); + console.log('-----------------------------------------'); + console.log(`Server running on port ${PORT}`); + console.log(`Visit http://localhost:${PORT}/ to access the app`); + console.log('-----------------------------------------'); + console.log(''); - console.log('Environment variables:'); - console.log(`OPENVIDU_MEET_URL: ${process.env.OPENVIDU_MEET_URL}`); - console.log(`MEET_API_KEY: ${process.env.MEET_API_KEY} `); - console.log(`PORT: ${process.env.PORT}`); + console.log('OpenVidu Meet Configuration:'); + console.log(`Meet API URL: ${configService.meetApiUrl}`); + console.log(`Meet API key: ${configService.meetApiKey}`); }); diff --git a/testapp/src/services/configService.ts b/testapp/src/services/configService.ts index 3a489ae..8d4ffd4 100644 --- a/testapp/src/services/configService.ts +++ b/testapp/src/services/configService.ts @@ -3,15 +3,15 @@ import dotenv from 'dotenv'; dotenv.config(); export class ConfigService { - public meetApiUrl: string; - public meetApiKey: string; - public serverPort: number; + public meetApiUrl: string; + public meetApiKey: string; + public serverPort: number; - constructor() { - this.meetApiUrl = process.env.OPENVIDU_MEET_URL!; - this.meetApiKey = process.env.MEET_API_KEY!; - this.serverPort = parseInt(process.env.PORT!, 10); - } + constructor() { + this.meetApiUrl = process.env.OPENVIDU_MEET_URL!; + this.meetApiKey = process.env.MEET_API_KEY!; + this.serverPort = parseInt(process.env.PORT!, 10); + } } export const configService = new ConfigService(); diff --git a/testapp/src/services/recordingService.ts b/testapp/src/services/recordingService.ts index c910646..7078693 100644 --- a/testapp/src/services/recordingService.ts +++ b/testapp/src/services/recordingService.ts @@ -1,41 +1,39 @@ import { del, get } from '../utils/http'; +// @ts-ignore import { MeetRecordingInfo } from '../../../typings/src/recording.model'; import { configService } from './configService'; export const getAllRecordings = async (): Promise<{ - pagination: { isTruncated: boolean; nextPageToken?: string }; - recordings: MeetRecordingInfo[]; + pagination: { isTruncated: boolean; nextPageToken?: string }; + recordings: MeetRecordingInfo[]; }> => { - const url = `${configService.meetApiUrl}/recordings`; + const url = `${configService.meetApiUrl}/recordings`; - let { pagination, recordings } = await get<{ - pagination: any; - recordings: MeetRecordingInfo[]; - }>(url, { - headers: { 'x-api-key': configService.meetApiKey }, - }); + let { pagination, recordings } = await get<{ + pagination: any; + recordings: MeetRecordingInfo[]; + }>(url, { + headers: { 'x-api-key': configService.meetApiKey } + }); - while (pagination.isTruncated) { - const nextPageUrl = `${url}?nextPageToken=${pagination.nextPageToken}`; - const nextPageResult = await get<{ - pagination: any; - recordings: MeetRecordingInfo[]; - }>(nextPageUrl, { - headers: { 'x-api-key': configService.meetApiKey }, - }); - recordings.push(...nextPageResult.recordings); - pagination = nextPageResult.pagination; - } - return { pagination, recordings }; + while (pagination.isTruncated) { + const nextPageUrl = `${url}?nextPageToken=${pagination.nextPageToken}`; + const nextPageResult = await get<{ + pagination: any; + recordings: MeetRecordingInfo[]; + }>(nextPageUrl, { + headers: { 'x-api-key': configService.meetApiKey } + }); + recordings.push(...nextPageResult.recordings); + pagination = nextPageResult.pagination; + } + + return { pagination, recordings }; }; -export const deleteAllRecordings = async ( - recordingIds: string[] -): Promise => { - const url = `${ - configService.meetApiUrl - }/recordings?recordingIds=${recordingIds.join(',')}`; - await del(url, { - headers: { 'x-api-key': configService.meetApiKey }, - }); +export const deleteAllRecordings = async (recordingIds: string[]): Promise => { + const url = `${configService.meetApiUrl}/recordings?recordingIds=${recordingIds.join(',')}`; + await del(url, { + headers: { 'x-api-key': configService.meetApiKey } + }); }; diff --git a/testapp/src/services/roomService.ts b/testapp/src/services/roomService.ts index d9160c5..769ba35 100644 --- a/testapp/src/services/roomService.ts +++ b/testapp/src/services/roomService.ts @@ -1,41 +1,45 @@ -import { get, post, del } from '../utils/http'; +import { del, get, post } from '../utils/http'; import { configService } from './configService'; // @ts-ignore import { MeetRoom, MeetRoomOptions } from '../../../typings/src/room'; export async function getAllRooms(): Promise<{ - pagination: any; - rooms: MeetRoom[]; + pagination: any; + rooms: MeetRoom[]; }> { - const url = `${configService.meetApiUrl}/rooms`; - return get<{ pagination: any; rooms: MeetRoom[] }>(url, { - headers: { 'x-api-key': configService.meetApiKey }, - }); + const url = `${configService.meetApiUrl}/rooms`; + return get<{ pagination: any; rooms: MeetRoom[] }>(url, { + headers: { 'x-api-key': configService.meetApiKey } + }); } export async function createRoom(roomData: MeetRoomOptions): Promise { - const url = `${configService.meetApiUrl}/rooms`; - // Default to 1 hour if autoDeletionDate is not provided - if (!roomData.autoDeletionDate) - roomData.autoDeletionDate = new Date(Date.now() + 60 * 61 * 1000).getTime(); - console.log('Creating room with options:', roomData); - return post(url, { - headers: { 'x-api-key': configService.meetApiKey }, - body: roomData, - }); + const url = `${configService.meetApiUrl}/rooms`; + // Default to 1 hour if autoDeletionDate is not provided + if (!roomData.autoDeletionDate) { + roomData.autoDeletionDate = new Date(Date.now() + 60 * 61 * 1000).getTime(); + } else { + // Ensure autoDeletionDate is a timestamp + roomData.autoDeletionDate = new Date(roomData.autoDeletionDate).getTime(); + } + + console.log('Creating room with options:', roomData); + return post(url, { + headers: { 'x-api-key': configService.meetApiKey }, + body: roomData + }); } export async function deleteRoom(roomId: string): Promise { - const url = `${configService.meetApiUrl}/rooms/${roomId}`; - await del(url, { - headers: { 'x-api-key': configService.meetApiKey }, - }); + const url = `${configService.meetApiUrl}/rooms/${roomId}`; + await del(url, { + headers: { 'x-api-key': configService.meetApiKey } + }); } export async function deleteAllRooms(roomIds: string[]): Promise { - const url = `${configService.meetApiUrl}/rooms?roomIds=${roomIds.join(',')}`; - - await del(url, { - headers: { 'x-api-key': configService.meetApiKey }, - }); + const url = `${configService.meetApiUrl}/rooms?roomIds=${roomIds.join(',')}`; + await del(url, { + headers: { 'x-api-key': configService.meetApiKey } + }); } diff --git a/testapp/src/utils/http.ts b/testapp/src/utils/http.ts index 8d50109..ff5fbd7 100644 --- a/testapp/src/utils/http.ts +++ b/testapp/src/utils/http.ts @@ -1,70 +1,50 @@ export interface RequestOptions { - headers?: Record; - queryParams?: Record; - body?: any; + headers?: Record; + queryParams?: Record; + body?: any; } -async function buildUrl( - url: string, - queryParams?: Record -): Promise { - if (!queryParams) return url; - const params = new URLSearchParams( - queryParams as Record - ).toString(); - return `${url}?${params}`; +async function buildUrl(url: string, queryParams?: Record): Promise { + if (!queryParams) return url; + const params = new URLSearchParams(queryParams as Record).toString(); + return `${url}?${params}`; } -async function request( - method: string, - url: string, - options: RequestOptions = {} -): Promise { - const fullUrl = await buildUrl(url, options.queryParams); - const fetchOptions: RequestInit = { - method, - headers: { 'Content-Type': 'application/json', ...(options.headers || {}) }, - body: options.body ? JSON.stringify(options.body) : undefined, - }; - const response = await fetch(fullUrl, fetchOptions); - if (!response.ok) { - const text = await response.text(); - throw new Error(`HTTP ${response.status}: ${text}`); - } +async function request(method: string, url: string, options: RequestOptions = {}): Promise { + const fullUrl = await buildUrl(url, options.queryParams); + const fetchOptions: RequestInit = { + method, + headers: { 'Content-Type': 'application/json', ...(options.headers || {}) }, + body: options.body ? JSON.stringify(options.body) : undefined + }; - // Handle empty responses (e.g., for DELETE requests) - const text = await response.text(); - if (!text) { - return {} as T; - } + const response = await fetch(fullUrl, fetchOptions); + if (!response.ok) { + const text = await response.text(); + throw new Error(`HTTP ${response.status}: ${text}`); + } - return JSON.parse(text) as T; + // Handle empty responses (e.g., for DELETE requests) + const text = await response.text(); + if (!text) { + return {} as T; + } + + return JSON.parse(text) as T; } -export function get( - url: string, - options?: Omit -): Promise { - return request('GET', url, options || {}); +export function get(url: string, options?: Omit): Promise { + return request('GET', url, options || {}); } -export function post( - url: string, - options?: Omit & { body: any } -): Promise { - return request('POST', url, options as RequestOptions); +export function post(url: string, options?: Omit & { body: any }): Promise { + return request('POST', url, options as RequestOptions); } -export function put( - url: string, - options?: Omit & { body: any } -): Promise { - return request('PUT', url, options as RequestOptions); +export function put(url: string, options?: Omit & { body: any }): Promise { + return request('PUT', url, options as RequestOptions); } -export function del( - url: string, - options?: Omit -): Promise { - return request('DELETE', url, options || {}); +export function del(url: string, options?: Omit): Promise { + return request('DELETE', url, options || {}); }