2025-12-23 14:48:25 +01:00
|
|
|
import { Injectable } from "@angular/core";
|
|
|
|
|
import { Subject } from "rxjs";
|
2017-10-09 18:48:05 +02:00
|
|
|
|
2025-12-23 14:48:25 +01:00
|
|
|
import * as stringify from "json-stringify-safe";
|
2019-02-06 15:04:49 +01:00
|
|
|
|
2025-12-23 14:48:25 +01:00
|
|
|
import {
|
|
|
|
|
// Base classes
|
|
|
|
|
Session,
|
|
|
|
|
Stream,
|
|
|
|
|
Connection,
|
|
|
|
|
StreamManager,
|
|
|
|
|
Publisher,
|
|
|
|
|
Subscriber,
|
|
|
|
|
|
|
|
|
|
// Base Event
|
|
|
|
|
Event,
|
|
|
|
|
|
|
|
|
|
// Session Events
|
|
|
|
|
ConnectionEvent,
|
|
|
|
|
SessionDisconnectedEvent,
|
|
|
|
|
SignalEvent,
|
|
|
|
|
StreamEvent,
|
|
|
|
|
StreamPropertyChangedEvent,
|
|
|
|
|
ConnectionPropertyChangedEvent, // Missed previously
|
|
|
|
|
NetworkQualityLevelChangedEvent, // Missed previously
|
|
|
|
|
SpeechToTextEvent, // Missed previously
|
|
|
|
|
ExceptionEvent,
|
|
|
|
|
|
|
|
|
|
// StreamManager / Publisher / Subscriber Events
|
|
|
|
|
StreamManagerEvent,
|
|
|
|
|
VideoElementEvent,
|
|
|
|
|
PublisherSpeakingEvent,
|
|
|
|
|
RecordingEvent,
|
|
|
|
|
FilterEvent, // Missed previously
|
|
|
|
|
} from "openvidu-browser-v2compatibility";
|
|
|
|
|
|
|
|
|
|
const API_ALLOWLIST = new Map<any, string[]>([
|
|
|
|
|
// ===========================================================================
|
|
|
|
|
// 1. CORE ENTITIES
|
|
|
|
|
// ===========================================================================
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/Session.html
|
|
|
|
|
[Session, ["sessionId", "connection", "capabilities", "streamManagers"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/Connection.html
|
|
|
|
|
[Connection, ["connectionId", "creationTime", "data", "record", "role"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/Stream.html
|
|
|
|
|
[
|
|
|
|
|
Stream,
|
|
|
|
|
[
|
|
|
|
|
"streamId",
|
|
|
|
|
"creationTime",
|
|
|
|
|
"hasAudio",
|
|
|
|
|
"hasVideo",
|
|
|
|
|
"audioActive",
|
|
|
|
|
"videoActive",
|
|
|
|
|
"typeOfVideo",
|
|
|
|
|
"frameRate",
|
|
|
|
|
"videoDimensions",
|
|
|
|
|
"connection",
|
|
|
|
|
"filter",
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/StreamManager.html
|
|
|
|
|
[StreamManager, ["stream", "id", "remote", "videos"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/Publisher.html
|
|
|
|
|
[Publisher, ["stream", "id", "remote", "videos", "accessAllowed"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/Subscriber.html
|
|
|
|
|
[Subscriber, ["stream", "id", "remote", "videos"]],
|
|
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
|
|
|
// 2. BASE EVENT
|
|
|
|
|
// ===========================================================================
|
|
|
|
|
// These are merged into all specific events
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/Event.html
|
|
|
|
|
[Event, ["type", "cancelable", "target"]],
|
|
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
|
|
|
// 3. SPECIFIC EVENTS (Alphabetical Order)
|
|
|
|
|
// ===========================================================================
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/ConnectionEvent.html
|
|
|
|
|
[ConnectionEvent, ["connection", "reason"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/ConnectionPropertyChangedEvent.html
|
|
|
|
|
[
|
|
|
|
|
ConnectionPropertyChangedEvent,
|
|
|
|
|
["connection", "changedProperty", "oldValue", "newValue", "reason"],
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/ExceptionEvent.html
|
|
|
|
|
[ExceptionEvent, ["name", "message", "data"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/FilterEvent.html
|
|
|
|
|
[FilterEvent, ["filter", "eventType", "data"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/NetworkQualityLevelChangedEvent.html
|
|
|
|
|
[NetworkQualityLevelChangedEvent, ["connection", "newValue", "oldValue"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/PublisherSpeakingEvent.html
|
|
|
|
|
[PublisherSpeakingEvent, ["connection", "streamId", "reason"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/RecordingEvent.html
|
|
|
|
|
[RecordingEvent, ["id", "name", "reason"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/SessionDisconnectedEvent.html
|
|
|
|
|
[SessionDisconnectedEvent, ["reason"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/SignalEvent.html
|
|
|
|
|
[SignalEvent, ["type", "data", "from"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/SpeechToTextEvent.html
|
|
|
|
|
[SpeechToTextEvent, ["connection", "text", "reason", "timestamp", "raw"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/StreamEvent.html
|
|
|
|
|
[StreamEvent, ["stream", "reason"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/StreamManagerEvent.html
|
|
|
|
|
[StreamManagerEvent, ["stream", "reason"]],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/StreamPropertyChangedEvent.html
|
|
|
|
|
[
|
|
|
|
|
StreamPropertyChangedEvent,
|
|
|
|
|
["stream", "changedProperty", "oldValue", "newValue", "reason"],
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// https://docs.openvidu.io/en/2.32.0/api/openvidu-browser/classes/VideoElementEvent.html
|
|
|
|
|
[VideoElementEvent, ["element"]],
|
|
|
|
|
]);
|
2022-11-08 14:20:42 +01:00
|
|
|
|
2017-10-09 18:48:05 +02:00
|
|
|
@Injectable()
|
|
|
|
|
export class TestFeedService {
|
2025-12-23 14:48:25 +01:00
|
|
|
lastEvent: { user: number; event: Event };
|
2017-10-09 18:48:05 +02:00
|
|
|
newLastEvent$ = new Subject<any>();
|
|
|
|
|
|
2025-12-23 14:48:25 +01:00
|
|
|
constructor() {}
|
2017-10-09 18:48:05 +02:00
|
|
|
|
|
|
|
|
getLastEvent() {
|
|
|
|
|
return this.lastEvent;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-08 14:20:42 +01:00
|
|
|
pushNewEvent({ user: number, event: Event }) {
|
|
|
|
|
this.lastEvent = { user: number, event: Event };
|
2017-10-09 18:48:05 +02:00
|
|
|
this.newLastEvent$.next(this.lastEvent);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-08 14:20:42 +01:00
|
|
|
stringifyEventNoCircularDependencies(event: Event): string {
|
2025-12-23 14:48:25 +01:00
|
|
|
return this.cleanEvent(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cleanEvent(root: any): string {
|
|
|
|
|
const seen = new WeakSet();
|
|
|
|
|
|
|
|
|
|
const getAllowedKeys = (obj: any): string[] | null => {
|
|
|
|
|
for (const [ClassConstructor, keys] of API_ALLOWLIST.entries()) {
|
|
|
|
|
if (obj instanceof ClassConstructor) {
|
|
|
|
|
// If instance of specific Event, merge with base Event keys
|
|
|
|
|
if (obj instanceof Event && ClassConstructor !== Event) {
|
|
|
|
|
return [...(API_ALLOWLIST.get(Event) || []), ...keys];
|
|
|
|
|
}
|
|
|
|
|
return keys;
|
|
|
|
|
}
|
2022-11-08 14:20:42 +01:00
|
|
|
}
|
2025-12-23 14:48:25 +01:00
|
|
|
return null;
|
|
|
|
|
};
|
2022-11-23 17:14:38 +01:00
|
|
|
|
2025-12-23 14:48:25 +01:00
|
|
|
const traverse = (current: any): any => {
|
|
|
|
|
if (current === null || current === undefined) return current;
|
|
|
|
|
if (typeof current === "bigint") return current.toString();
|
|
|
|
|
if (typeof current !== "object") return current;
|
|
|
|
|
|
|
|
|
|
if (seen.has(current)) return undefined;
|
|
|
|
|
seen.add(current);
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(current)) {
|
|
|
|
|
return current.map(traverse).filter((x) => x !== undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const allowedKeys = getAllowedKeys(current);
|
|
|
|
|
const copy: any = {};
|
2022-11-08 14:20:42 +01:00
|
|
|
|
2025-12-23 14:48:25 +01:00
|
|
|
if (allowedKeys) {
|
|
|
|
|
// Known Class: Filter strictly
|
|
|
|
|
for (const key of allowedKeys) {
|
|
|
|
|
if (key in current) {
|
|
|
|
|
const val = traverse(current[key]);
|
|
|
|
|
if (val !== undefined) copy[key] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Plain Object: Copy recursive
|
|
|
|
|
for (const [key, value] of Object.entries(current)) {
|
|
|
|
|
const val = traverse(value);
|
|
|
|
|
if (val !== undefined) copy[key] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return JSON.stringify(traverse(root));
|
|
|
|
|
}
|
2017-10-09 18:48:05 +02:00
|
|
|
}
|