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.js 5.1KB

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