You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AVModeration.ts 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import { getLogger } from '@jitsi/logger';
  2. import { $msg } from 'strophe.js';
  3. import { MediaType } from '../../service/RTC/MediaType';
  4. import { XMPPEvents } from '../../service/xmpp/XMPPEvents';
  5. import ChatRoom from './ChatRoom';
  6. import XMPP from './xmpp';
  7. const logger = getLogger('modules/xmpp/AVModeration');
  8. export interface IModerationEnabledByType {
  9. audio: boolean;
  10. video: boolean;
  11. }
  12. export interface IMessageObject {
  13. actor: string;
  14. approved: boolean;
  15. enabled: boolean;
  16. mediaType: MediaType;
  17. removed: boolean;
  18. whitelists: { audio: string[]; video: string[]; };
  19. }
  20. /**
  21. * The AVModeration logic.
  22. */
  23. export default class AVModeration {
  24. /**
  25. * Constructs AV moderation room.
  26. *
  27. * @param {ChatRoom} room the main room.
  28. */
  29. private _xmpp: XMPP;
  30. private _mainRoom: ChatRoom;
  31. private _moderationEnabledByType: IModerationEnabledByType;
  32. private _whitelistAudio: string[];
  33. private _whitelistVideo: string[];
  34. constructor(room: ChatRoom) {
  35. this._xmpp = room.xmpp;
  36. this._mainRoom = room;
  37. this._moderationEnabledByType = {
  38. [MediaType.AUDIO]: false,
  39. [MediaType.VIDEO]: false
  40. };
  41. this._whitelistAudio = [];
  42. this._whitelistVideo = [];
  43. this._onMessage = this._onMessage.bind(this);
  44. this._xmpp.addListener(XMPPEvents.AV_MODERATION_RECEIVED, this._onMessage);
  45. }
  46. /**
  47. * Stops listening for events.
  48. */
  49. dispose() {
  50. this._xmpp.removeListener(XMPPEvents.AV_MODERATION_RECEIVED, this._onMessage);
  51. }
  52. /**
  53. * Whether AV moderation is supported on backend.
  54. *
  55. * @returns {boolean} whether AV moderation is supported on backend.
  56. */
  57. isSupported() {
  58. return Boolean(this._xmpp.avModerationComponentAddress);
  59. }
  60. /**
  61. * Enables or disables AV Moderation by sending a msg with command to the component.
  62. */
  63. enable(state: string, mediaType: MediaType) {
  64. if (!this.isSupported() || !this._mainRoom.isModerator()) {
  65. logger.error(`Cannot enable:${state} AV moderation supported:${this.isSupported()},
  66. moderator:${this._mainRoom.isModerator()}`);
  67. return;
  68. }
  69. if (state === this._moderationEnabledByType[mediaType]) {
  70. logger.warn(`Moderation already in state:${state} for mediaType:${mediaType}`);
  71. return;
  72. }
  73. // send the enable/disable message
  74. const msg = $msg({ to: this._xmpp.avModerationComponentAddress });
  75. msg.c('av_moderation', {
  76. enable: state,
  77. mediaType
  78. }).up();
  79. this._xmpp.connection.send(msg);
  80. }
  81. /**
  82. * Approves that a participant can unmute by sending a msg with its jid to the component.
  83. */
  84. approve(mediaType: MediaType, jid: string) {
  85. if (!this.isSupported() || !this._mainRoom.isModerator()) {
  86. logger.error(`Cannot approve in AV moderation supported:${this.isSupported()},
  87. moderator:${this._mainRoom.isModerator()}`);
  88. return;
  89. }
  90. // send a message to whitelist the jid and approve it to unmute
  91. const msg = $msg({ to: this._xmpp.avModerationComponentAddress });
  92. msg.c('av_moderation', {
  93. mediaType,
  94. jidToWhitelist: jid }).up();
  95. this._xmpp.connection.send(msg);
  96. }
  97. /**
  98. * Rejects that a participant can unmute by sending a msg with its jid to the component.
  99. */
  100. reject(mediaType: MediaType, jid: string) {
  101. if (!this.isSupported() || !this._mainRoom.isModerator()) {
  102. logger.error(`Cannot reject in AV moderation supported:${this.isSupported()},
  103. moderator:${this._mainRoom.isModerator()}`);
  104. return;
  105. }
  106. // send a message to remove from whitelist the jid and reject it to unmute
  107. const msg = $msg({ to: this._xmpp.avModerationComponentAddress });
  108. msg.c('av_moderation', {
  109. mediaType,
  110. jidToBlacklist: jid
  111. }).up();
  112. this._xmpp.connection.send(msg);
  113. }
  114. /**
  115. * Receives av_moderation parsed messages as json.
  116. * @param obj the parsed json content of the message to process.
  117. * @private
  118. */
  119. _onMessage(obj: IMessageObject) {
  120. const { removed, mediaType: media, enabled, approved, actor, whitelists: newWhitelists } = obj;
  121. if (newWhitelists) {
  122. const oldList = media === MediaType.AUDIO
  123. ? this._whitelistAudio
  124. : this._whitelistVideo;
  125. const newList = Array.isArray(newWhitelists[media]) ? newWhitelists[media] : [];
  126. if (removed) {
  127. oldList.filter(x => !newList.includes(x))
  128. .forEach(jid => this._xmpp.eventEmitter
  129. .emit(XMPPEvents.AV_MODERATION_PARTICIPANT_REJECTED, media, jid));
  130. } else {
  131. newList.filter(x => !oldList.includes(x))
  132. .forEach(jid => this._xmpp.eventEmitter
  133. .emit(XMPPEvents.AV_MODERATION_PARTICIPANT_APPROVED, media, jid));
  134. }
  135. if (media === MediaType.AUDIO) {
  136. this._whitelistAudio = newList;
  137. } else {
  138. this._whitelistVideo = newList;
  139. }
  140. } else if (enabled !== undefined && this._moderationEnabledByType[media] !== enabled) {
  141. this._moderationEnabledByType[media] = enabled;
  142. this._xmpp.eventEmitter.emit(XMPPEvents.AV_MODERATION_CHANGED, enabled, media, actor);
  143. } else if (removed) {
  144. this._xmpp.eventEmitter.emit(XMPPEvents.AV_MODERATION_REJECTED, media);
  145. } else if (approved) {
  146. this._xmpp.eventEmitter.emit(XMPPEvents.AV_MODERATION_APPROVED, media);
  147. }
  148. }
  149. }