Преглед изворни кода

Handles private messages received by speakerstats component.

Updates speakers stats with values received by the spealerstats component, all the logic is activate only in case we discover speakerstats component address from disco-info and the incoming message is coming from that component.
dev1
damencho пре 7 година
родитељ
комит
7f52a2cc60

+ 1
- 1
JitsiConference.js Прегледај датотеку

@@ -33,7 +33,7 @@ import GlobalOnErrorHandler from './modules/util/GlobalOnErrorHandler';
33 33
 import ComponentsVersions from './modules/version/ComponentsVersions';
34 34
 import VideoSIPGW from './modules/videosipgw/VideoSIPGW';
35 35
 import * as VideoSIPGWConstants from './modules/videosipgw/VideoSIPGWConstants';
36
-import { JITSI_MEET_MUC_TYPE } from './modules/xmpp/ChatRoom';
36
+import { JITSI_MEET_MUC_TYPE } from './modules/xmpp/xmpp';
37 37
 import * as MediaType from './service/RTC/MediaType';
38 38
 import * as RTCEvents from './service/RTC/RTCEvents';
39 39
 import VideoType from './service/RTC/VideoType';

+ 33
- 0
modules/statistics/SpeakerStatsCollector.js Прегледај датотеку

@@ -1,5 +1,6 @@
1 1
 import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
2 2
 import SpeakerStats from './SpeakerStats';
3
+import XMPPEvents from '../../service/xmpp/XMPPEvents';
3 4
 
4 5
 /**
5 6
  * A collection for tracking speaker stats. Attaches listeners
@@ -38,6 +39,9 @@ export default class SpeakerStatsCollector {
38 39
         conference.addEventListener(
39 40
             JitsiConferenceEvents.DISPLAY_NAME_CHANGED,
40 41
             this._onDisplayNameChange.bind(this));
42
+        conference.xmpp.addListener(
43
+            XMPPEvents.SPEAKER_STATS_RECEIVED,
44
+            this._updateStats.bind(this));
41 45
     }
42 46
 
43 47
     /**
@@ -118,4 +122,33 @@ export default class SpeakerStatsCollector {
118 122
     getStats() {
119 123
         return this.stats.users;
120 124
     }
125
+
126
+    /**
127
+     * Updates of the current stats is requested, passing the new values.
128
+     *
129
+     * @param {Object} newStats - The new values used to update current one.
130
+     * @private
131
+     */
132
+    _updateStats(newStats) {
133
+        for (const userId in newStats) { // eslint-disable-line guard-for-in
134
+            let speakerStatsToUpdate;
135
+
136
+            if (this.stats.users[userId]) {
137
+                speakerStatsToUpdate = this.stats.users[userId];
138
+
139
+                if (!speakerStatsToUpdate.getDisplayName()) {
140
+                    speakerStatsToUpdate
141
+                        .setDisplayName(newStats[userId].displayName);
142
+                }
143
+            } else {
144
+                speakerStatsToUpdate = new SpeakerStats(
145
+                    userId, newStats[userId].displayName);
146
+                this.stats.users[userId] = speakerStatsToUpdate;
147
+                speakerStatsToUpdate.markAsHasLeft();
148
+            }
149
+
150
+            speakerStatsToUpdate.totalDominantSpeakerTime
151
+                = newStats[userId].totalDominantSpeakerTime;
152
+        }
153
+    }
121 154
 }

+ 1
- 47
modules/xmpp/ChatRoom.js Прегледај датотеку

@@ -76,52 +76,6 @@ function filterNodeFromPresenceJSON(pres, nodeName) {
76 76
     return res;
77 77
 }
78 78
 
79
-/**
80
- * The name of the field used to recognize a chat message as carrying a JSON
81
- * payload from another endpoint.
82
- * If the json-message of a chat message contains a valid JSON object, and the
83
- * JSON has this key, then it is a valid json-message to be sent.
84
- */
85
-export const JITSI_MEET_MUC_TYPE = 'type';
86
-
87
-/**
88
- * Check if the given argument is a valid JSON ENDPOINT_MESSAGE string by
89
- * parsing it and checking if it has a field called 'type'.
90
- *
91
- * @param {string} jsonString check if this string is a valid json string
92
- * and contains the special structure.
93
- * @returns {boolean, object} if given object is a valid JSON string, return
94
- * the json object. Otherwise, returns false.
95
- */
96
-function tryParseJSONAndVerify(jsonString) {
97
-    try {
98
-        const json = JSON.parse(jsonString);
99
-
100
-        // Handle non-exception-throwing cases:
101
-        // Neither JSON.parse(false) or JSON.parse(1234) throw errors,
102
-        // hence the type-checking,
103
-        // but... JSON.parse(null) returns null, and
104
-        // typeof null === "object",
105
-        // so we must check for that, too.
106
-        // Thankfully, null is falsey, so this suffices:
107
-        if (json && typeof json === 'object') {
108
-            const type = json[JITSI_MEET_MUC_TYPE];
109
-
110
-            if (typeof type !== 'undefined') {
111
-                return json;
112
-            }
113
-
114
-            logger.debug('parsing valid json but does not have correct '
115
-                + 'structure', 'topic: ', type);
116
-        }
117
-    } catch (e) {
118
-
119
-        return false;
120
-    }
121
-
122
-    return false;
123
-}
124
-
125 79
 // XXX As ChatRoom constructs XMPP stanzas and Strophe is build around the idea
126 80
 // of chaining function calls, allow long function call chains.
127 81
 /* eslint-disable newline-per-chained-call */
@@ -925,7 +879,7 @@ export default class ChatRoom extends Listenable {
925 879
             this.discoRoomInfo();
926 880
         }
927 881
         const jsonMessage = $(msg).find('>json-message').text();
928
-        const parsedJson = tryParseJSONAndVerify(jsonMessage);
882
+        const parsedJson = this.xmpp.tryParseJSONAndVerify(jsonMessage);
929 883
 
930 884
         // We emit this event if the message is a valid json, and is not
931 885
         // delivered after a delay, i.e. stamp is undefined.

+ 79
- 0
modules/xmpp/xmpp.js Прегледај датотеку

@@ -17,6 +17,7 @@ import initStropheLogger from './strophe.logger';
17 17
 import Listenable from '../util/Listenable';
18 18
 import Caps from './Caps';
19 19
 import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
20
+import XMPPEvents from '../../service/xmpp/XMPPEvents';
20 21
 
21 22
 const logger = getLogger(__filename);
22 23
 
@@ -40,6 +41,14 @@ function createConnection(token, bosh = '/http-bind') {
40 41
     return conn;
41 42
 }
42 43
 
44
+/**
45
+ * The name of the field used to recognize a chat message as carrying a JSON
46
+ * payload from another endpoint.
47
+ * If the json-message of a chat message contains a valid JSON object, and
48
+ * the JSON has this key, then it is a valid json-message to be sent.
49
+ */
50
+export const JITSI_MEET_MUC_TYPE = 'type';
51
+
43 52
 /**
44 53
  *
45 54
  */
@@ -167,6 +176,10 @@ export default class XMPP extends Listenable {
167 176
                     identities.forEach(identity => {
168 177
                         if (identity.type === 'speakerstats') {
169 178
                             this.speakerStatsComponentAddress = identity.name;
179
+
180
+                            this.connection.addHandler(
181
+                                this._onPrivateMessage.bind(this), null,
182
+                                'message', null, null);
170 183
                         }
171 184
                     });
172 185
                 })
@@ -588,4 +601,70 @@ export default class XMPP extends Listenable {
588 601
 
589 602
         this.connection.send(msg);
590 603
     }
604
+
605
+    /**
606
+     * Check if the given argument is a valid JSON ENDPOINT_MESSAGE string by
607
+     * parsing it and checking if it has a field called 'type'.
608
+     *
609
+     * @param {string} jsonString check if this string is a valid json string
610
+     * and contains the special structure.
611
+     * @returns {boolean, object} if given object is a valid JSON string, return
612
+     * the json object. Otherwise, returns false.
613
+     */
614
+    tryParseJSONAndVerify(jsonString) {
615
+        try {
616
+            const json = JSON.parse(jsonString);
617
+
618
+            // Handle non-exception-throwing cases:
619
+            // Neither JSON.parse(false) or JSON.parse(1234) throw errors,
620
+            // hence the type-checking,
621
+            // but... JSON.parse(null) returns null, and
622
+            // typeof null === "object",
623
+            // so we must check for that, too.
624
+            // Thankfully, null is falsey, so this suffices:
625
+            if (json && typeof json === 'object') {
626
+                const type = json[JITSI_MEET_MUC_TYPE];
627
+
628
+                if (typeof type !== 'undefined') {
629
+                    return json;
630
+                }
631
+
632
+                logger.debug('parsing valid json but does not have correct '
633
+                    + 'structure', 'topic: ', type);
634
+            }
635
+        } catch (e) {
636
+            return false;
637
+        }
638
+
639
+        return false;
640
+    }
641
+
642
+    /**
643
+     * A private message is received, message that is not addressed to the muc.
644
+     * We expect private message coming from speaker stats component if it is
645
+     * enabled and running.
646
+     *
647
+     * @param {string} msg - The message.
648
+     */
649
+    _onPrivateMessage(msg) {
650
+        const from = msg.getAttribute('from');
651
+
652
+        if (!this.speakerStatsComponentAddress
653
+            || from !== this.speakerStatsComponentAddress) {
654
+            return;
655
+        }
656
+
657
+        const jsonMessage = $(msg).find('>json-message')
658
+            .text();
659
+        const parsedJson = this.tryParseJSONAndVerify(jsonMessage);
660
+
661
+        if (parsedJson
662
+            && parsedJson[JITSI_MEET_MUC_TYPE] === 'speakerstats'
663
+            && parsedJson.users) {
664
+            this.eventEmitter.emit(
665
+                XMPPEvents.SPEAKER_STATS_RECEIVED, parsedJson.users);
666
+        }
667
+
668
+        return true;
669
+    }
591 670
 }

+ 5
- 0
service/xmpp/XMPPEvents.js Прегледај датотеку

@@ -199,6 +199,11 @@ const XMPPEvents = {
199 199
      */
200 200
     SESSION_ACCEPT_TIMEOUT: 'xmpp.session_accept_timeout',
201 201
 
202
+    /**
203
+     * Event fired when speaker stats update message is received.
204
+     */
205
+    SPEAKER_STATS_RECEIVED: 'xmpp.speaker_stats_received',
206
+
202 207
     // Designates an event indicating that we should join the conference with
203 208
     // audio and/or video muted.
204 209
     START_MUTED_FROM_FOCUS: 'xmpp.start_muted_from_focus',

Loading…
Откажи
Сачувај