From eb0e7b67e54c39ed544d93d5e879f79068a961a0 Mon Sep 17 00:00:00 2001 From: arungane Date: Tue, 5 Feb 2019 13:53:39 -0500 Subject: [PATCH] fix: added locus meetings sync --- .../@webex/plugin-meetings/src/constants.js | 3 +- .../plugin-meetings/src/locus-Info/index.js | 17 +-- .../src/locus-Info/parser.js~HEAD | 111 ------------------ .../src/locus-Info/utils/info.js | 20 +++- .../plugin-meetings/src/meeting/index.js | 18 +-- .../plugin-meetings/src/meeting/util.js | 10 +- .../src/meetings/collection.js | 2 +- .../plugin-meetings/src/meetings/index.js | 29 ++++- .../plugin-meetings/src/meetings/request.js | 53 +++++++++ 9 files changed, 116 insertions(+), 147 deletions(-) delete mode 100644 packages/node_modules/@webex/plugin-meetings/src/locus-Info/parser.js~HEAD create mode 100644 packages/node_modules/@webex/plugin-meetings/src/meetings/request.js diff --git a/packages/node_modules/@webex/plugin-meetings/src/constants.js b/packages/node_modules/@webex/plugin-meetings/src/constants.js index 395ec04620e..02570540304 100644 --- a/packages/node_modules/@webex/plugin-meetings/src/constants.js +++ b/packages/node_modules/@webex/plugin-meetings/src/constants.js @@ -328,7 +328,8 @@ export const ICESTATE = { export const RESOURCE = { CLUSTERS: 'clusters', - REACHABILITY: 'reachability' + REACHABILITY: 'reachability', + LOCI: 'loci' }; export const REACHABILITY = { diff --git a/packages/node_modules/@webex/plugin-meetings/src/locus-Info/index.js b/packages/node_modules/@webex/plugin-meetings/src/locus-Info/index.js index af40e5336f3..01eb0061a9b 100644 --- a/packages/node_modules/@webex/plugin-meetings/src/locus-Info/index.js +++ b/packages/node_modules/@webex/plugin-meetings/src/locus-Info/index.js @@ -13,7 +13,7 @@ export default class LocusInfo { constructor(callback) { this.setup({}); this.updateMeeting = callback; - this.emitChanges = false; + this.emitChange = false; } /** @@ -148,6 +148,9 @@ export default class LocusInfo { this.updateSequence(locus.sequence); this.updateMemberShip(locus.membership); this.updateIdentifiers(locus.identities); + + + // update which required to compare different objects from locus } addedOrRemovedParticipant() { @@ -184,7 +187,7 @@ export default class LocusInfo { console.log('participants changed check everything'); // First time the participants are set - if (this.participants === null) { + if (this.participants === null || this.participants.length === 0) { this.participants = participants; return participants; } @@ -259,11 +262,11 @@ export default class LocusInfo { // state: "ACTIVE" // type: "CALL" - { - type: 'CALL' // For 1:1 calls the type is CALL - type: 'MEETING' // When Guest added the type is meeting - 'CALL' // When guest user leaves - } + // { + // 'CALL'; // For 1:1 calls the type is CALL + // 'MEETING'; // When Guest added the type is meeting + // 'CALL'; // When guest user leaves + // } this.fullState = fullState; console.info('LocusInfo:fullState got updated'); } diff --git a/packages/node_modules/@webex/plugin-meetings/src/locus-Info/parser.js~HEAD b/packages/node_modules/@webex/plugin-meetings/src/locus-Info/parser.js~HEAD deleted file mode 100644 index f4d983ab41f..00000000000 --- a/packages/node_modules/@webex/plugin-meetings/src/locus-Info/parser.js~HEAD +++ /dev/null @@ -1,111 +0,0 @@ -import LocusUtil from '../locus-Info/utils'; -import {DELTAEVENT, LOCUS} from '../constants'; - -const Parser = {}; - -// https://sqbu-github.cisco.com/WebExSquared/cloud-apps/wiki/Locus-Delta-Events -Parser.updateWithDeltaLocus = (deltaLocus, meeting) => { - if (!(deltaLocus.sequence && (deltaLocus.sequence.rangeStart <= deltaLocus.sequence.rangeEnd) && (deltaLocus.sequence.rangeEnd <= min(deltaLocus.sequence.entries)))) { - return null; - } - - // THIS IS A NEW MEETING OBJECT - // // If meeting has no sequence, it means just initialized and will apply whatever in locus DTO - // if (isNewMeeting || !this.locus.sequence) { - // meeting._updateWithDeltaLocus(deltaLocus, emitter); - // meeting.locusDesync = false; - // meeting.needToGetFullLocus = false; - // return DELTAEVENT.GT; - // } - - if (!deltaLocus.sequence) { - // TODO: force update - } - - // TODO: If this was the first event, the client will not have a syncURL - // in its working copy to do a GET on. In this case clients should do a GET on locusUrl contained in the DTO - - let res; - let resBase; - res = LocusUtil.compareLocus(deltaLocus.sequence, meeting.locus.sequence); - // In-coming locus is greater than working copy, need to compare with base if there - // is base sequence except the first delta locus event - if (res === DELTAEVENT.GT && deltaLocus.baseSequence && meeting.locus.syncUrl) { - resBase = LocusUtil.compareLocus(deltaLocus.baseSequence, meeting.locus.sequence); - if (resBase === DELTAEVENT.LT || resBase === DELTAEVENT.CF) { - res = DELTAEVENT.CF; - } - } - // Special case for OBTP with meeting size equal or over 5. Locus might change this later - // This is a temporary fix. I will find a better solution later. - if (!deltaLocus.baseSequence && res === DELTAEVENT.EQ && deltaLocus.fullState.state === 'INITIALIZING' - && deltaLocus.sequence.rangeStart === 0 && deltaLocus.sequence.rangeEnd === 0 - && deltaLocus.sequence.entries.length === 0) { - res = DELTAEVENT.GT; - console.log('Special case for OBTP'); - } - - console.log('RESULT :', res); - switch (res) { - case DELTAEVENT.LT: - case DELTAEVENT.EQ: - meeting.locusDesync = false; - meeting.needToGetFullLocus = false; - break; - case DELTAEVENT.CF: - LocusUtil.generateSyncDebugFlag(meeting, deltaLocus); - if (meeting.locusDesync) { - meeting.meetingRequest.getFullLocus({ - desync: true, - locusUrl: meeting.locusUrl - }).then((res) => { - meeting.locusInfo.onFullLocus(res.body); - }); - } - else { - meeting.locusDesync = true; - Parser.syncMeeting(meeting, deltaLocus); - } - break; - case DELTAEVENT.GT: - console.info('MeetingAmpstate#updateWithDeltaLocus: MeetingConstants.deltaLocusResult.GT'); - meeting.locusInfo.onDeltaLocus(deltaLocus); - // Turn off desync in case this delta locus comes from a sync request - meeting.locusDesync = false; - meeting.needToGetFullLocus = false; - break; - default: - } - return res; -}; - - -Parser.syncMeeting = (meeting, deltaLocus) => { - if (meeting - && meeting.locus - && meeting.locus.syncUrl - && meeting.locus.fullState - && meeting.locus.fullState.state !== LOCUS.STATE.INACTIVE) { - // found that the locus syncs were happening even after 4 hrs of meeting - // completion, resulting in 403 errors. This check ensures we call - // syncing only if the locus state is not INACTIVE. - meeting.meetingRequest.syncMeeting({ - syncUrl: deltaLocus.syncUrl, - desync: meeting.desync - }) - .then((res) => { - meeting.locusInfo.onDeltaLocus(res.body); - // Parser.updateMeeting(res.body, meeting); - console.log(`meeting-adapter#syncMeeting: performing sync for uri: ${meeting.locus.syncUrl} and state: ${meeting.locus.fullState.state}`); - }) - .catch((err) => { - console.error('Error syncing the locus', err); - }); - } - else if (meeting && meeting.locus && meeting.locus.syncUrl && meeting.locus.fullState) { - // TODO: remoev this later as meeting object wont be present - console.error(`meeting-adapter#syncMeeting: skip sync for url: ${meeting.locus.syncUrl} and state: ${meeting.locus.fullState.state}`); - } -}; - -export default Parser; diff --git a/packages/node_modules/@webex/plugin-meetings/src/locus-Info/utils/info.js b/packages/node_modules/@webex/plugin-meetings/src/locus-Info/utils/info.js index 22ef1f5e06a..3d58ab1d0f6 100644 --- a/packages/node_modules/@webex/plugin-meetings/src/locus-Info/utils/info.js +++ b/packages/node_modules/@webex/plugin-meetings/src/locus-Info/utils/info.js @@ -1,13 +1,17 @@ + +import {ONE_ON_ONE} from '../../constants'; + const InfoUtils = {}; InfoUtils.parse = (info) => ({ policy: InfoUtils.parsePolicy(info), - type: InfoUtils.parseMeetingType(info) + type: InfoUtils.parseMeetingType(info), + sipUri: info.sipUri }); InfoUtils.parsePolicy = (info) => { const policy = {}; // Parses the policy to show valid uses - if (info.displayHints.joined && info.displayHints.joined.length > 0) { + if (info.displayHints && info.displayHints.joined && info.displayHints.joined.length > 0) { // TODO: find a better way info.displayHints.joined.forEach((key) => { policy[key] = true; @@ -18,12 +22,18 @@ InfoUtils.parsePolicy = (info) => { InfoUtils.parseMeetingType = (info) => { let type = 'UNKNOWN'; - if (info.locusTags.indexOf('ONE_ON_ONE') >= 0) { - type = 'ONE_ON_ONE'; + // Parse all the value and get the type of meeting + // 1:1 meeting + if (info.locusTags && info.locusTags.indexOf(ONE_ON_ONE) >= 0) { + return ONE_ON_ONE; } - if (info.locusTags.indexOf('MEEING') >= 0) { + if (info.locusTags && info.locusTags.indexOf('MEEING') >= 0) { type = 'MEETING'; } + // For webex meeting claimed or unclaimed or calender meeting with webex site + if (info.webexServiceType === 'MEETING_CENTER' || info.isPmr) { + return 'WEBEX_MEETING'; + } return type; }; diff --git a/packages/node_modules/@webex/plugin-meetings/src/meeting/index.js b/packages/node_modules/@webex/plugin-meetings/src/meeting/index.js index c555170f23e..0dd0e6fd194 100644 --- a/packages/node_modules/@webex/plugin-meetings/src/meeting/index.js +++ b/packages/node_modules/@webex/plugin-meetings/src/meeting/index.js @@ -190,16 +190,19 @@ export default class Meeting extends StatelessSparkPlugin { parseLocus(locus) { if (locus) { this.locusUrl = locus.url; - if (locus.info) { - this.type = MeetingUtil.getLocusType(locus.info.locusTags); - } + // TODO: move this to parse participants module + this.setLocus(locus); + + // check if we can extract this info from partner + // Parsing of locus object must be finished at this state if (locus.participants && locus.self) { this.partner = MeetingUtil.getLocusPartner(locus.participants, locus.self); } - if (this.partner) { + + // For webex meeting the sipUrl gets updated in info parser + if (!this.sipUri && this.partner && this.type === 'ONE_ON_ONE') { this.sipUri = this.partner.person.sipUrl || this.partner.person.emailAddress || this.partner.person.email; } - this.setLocus(locus); } } @@ -236,7 +239,8 @@ export default class Meeting extends StatelessSparkPlugin { */ setLocus(locus) { const mtgLocus = locus.locus || locus; - this.locus = mtgLocus; + // LocusInfo object saves the locus object + // this.locus = mtgLocus; this.mediaConnections = locus.mediaConnections; this.locusUrl = locus.locusUrl || locus.url; this.locusId = locus.locusId; @@ -244,7 +248,7 @@ export default class Meeting extends StatelessSparkPlugin { this.mediaId = locus.mediaId; this.hostId = mtgLocus.host ? mtgLocus.host.id : this.hostId; // TODO: use this in the future - this.locusInfo.intialSetup(locus.locus); + this.locusInfo.intialSetup(mtgLocus); this.members.set(mtgLocus); } diff --git a/packages/node_modules/@webex/plugin-meetings/src/meeting/util.js b/packages/node_modules/@webex/plugin-meetings/src/meeting/util.js index 9c3c496ad83..065f207cb3c 100644 --- a/packages/node_modules/@webex/plugin-meetings/src/meeting/util.js +++ b/packages/node_modules/@webex/plugin-meetings/src/meeting/util.js @@ -1,7 +1,7 @@ import {isEmpty} from 'lodash'; import Media from '../media'; -import {ONE_ON_ONE, USER, INTENT_TO_JOIN, MODERATOR_TRUE, MODERATOR_FALSE} from '../constants'; +import {USER, INTENT_TO_JOIN, MODERATOR_TRUE, MODERATOR_FALSE} from '../constants'; const MeetingUtil = {}; @@ -23,14 +23,6 @@ MeetingUtil.parseLocusJoin = (response) => { return parsed; }; -MeetingUtil.getLocusType = (locusTags) => { - // Parse all the value and get the type of meeting - if (locusTags.find((tag) => tag === ONE_ON_ONE)) { - return ONE_ON_ONE; - } - return null; -}; - MeetingUtil.getLocusPartner = (participants, self) => participants.find((participant) => (self && participant.identity !== self.identity) && (participants.length <= 2 || (participant.type === USER && !participant.removed))) || this.partner; diff --git a/packages/node_modules/@webex/plugin-meetings/src/meetings/collection.js b/packages/node_modules/@webex/plugin-meetings/src/meetings/collection.js index b2145135118..972a9196e2e 100644 --- a/packages/node_modules/@webex/plugin-meetings/src/meetings/collection.js +++ b/packages/node_modules/@webex/plugin-meetings/src/meetings/collection.js @@ -43,7 +43,7 @@ const MeetingCollection = { * @returns {Object} returns an object map of Meeting instances * @memberof MeetingCollection */ - getAll(options) { + getAll(options = false) { if (options.active) { return pickBy(this.meetings, (value) => value.active); } diff --git a/packages/node_modules/@webex/plugin-meetings/src/meetings/index.js b/packages/node_modules/@webex/plugin-meetings/src/meetings/index.js index 4d12739d570..b5e52b6045b 100644 --- a/packages/node_modules/@webex/plugin-meetings/src/meetings/index.js +++ b/packages/node_modules/@webex/plugin-meetings/src/meetings/index.js @@ -10,6 +10,7 @@ import MeetingInfo from '../meeting-info'; import Meeting from '../meeting'; import PersonalMeetingRoom from '../personal-meeting-room'; import Reachability from '../reachability'; +import Request from '../meetings/request'; import MeetingCollection from './collection'; import MeetingsUtil from './util'; @@ -41,8 +42,12 @@ export default class Meetings extends SparkPlugin { constructor(...args) { super(...args); this.meetingInfo = new MeetingInfo({}, {parent: this.spark}); + this.request = new Request({}, {parent: this.spark}); this.personalMeetingRoom = new PersonalMeetingRoom({}, {parent: this.spark}); this.onReady(); + + // TODO: remove this added for testing + window.MeetingCollection = MeetingCollection; } handleLocusEvent(data) { @@ -66,15 +71,20 @@ export default class Meetings extends SparkPlugin { // Check the locus object and see who has joined }; - meeting = this.create(data.locus, LOCUS_ID); - // // Remove this after we determine when to show incoming notification + + // rather then locus object change to locus url + this.create(data.locus, LOCUS_ID) + .then((meeting) => { + meeting.locusInfo.parse(meeting, data); + }); + // Remove this after we determine when to show incoming notification // if (data.eventType === LOCUSEVENT.PARTICIPANT_JOIN) { // meeting = this.create(data.locus, LOCUS_ID); // } } - - - meeting.locusInfo.parse(meeting, data); + else { + meeting.locusInfo.parse(meeting, data); + } } /** @@ -106,6 +116,13 @@ export default class Meetings extends SparkPlugin { } } }); + + this.spark.internal.device('ready', () => { + console.log('READY for netwrok call'); + this.request.getActiveMeetings().then((res) => { + console.log(res); + }); + }); } /** @@ -113,7 +130,7 @@ export default class Meetings extends SparkPlugin { * @memberof Meetings */ onReady() { - this.spark.once(READY, () => { + this.spark.internal.once(READY, () => { if (this.spark.canAuthorize) { this.listenForEvents(); this.trigger(EVENT_TRIGGERS.MEETINGS_READY); diff --git a/packages/node_modules/@webex/plugin-meetings/src/meetings/request.js b/packages/node_modules/@webex/plugin-meetings/src/meetings/request.js new file mode 100644 index 00000000000..36c0e647b65 --- /dev/null +++ b/packages/node_modules/@webex/plugin-meetings/src/meetings/request.js @@ -0,0 +1,53 @@ +import {StatelessSparkPlugin} from '@ciscospark/spark-core'; + +import { + GET, + API, + RESOURCE +} from '../constants'; + +/** + * @class MeetingRequest + */ +export default class MeetingRequest extends StatelessSparkPlugin { + /** + * get all the active meetings for the user + * @returns {Array} return locus array + */ + getActiveMeetings() { + return this.request({ + api: API.LOCUS, + resource: RESOURCE.LOCI + }) + .then((res) => this.determineRedirections(res.body)) + .catch((error) => { + console.error('meeting-adapter: failed to get locus details error: ', error); + }); + } + + // locus federation, determines and populate locus if the responseBody has remote URLs to fetch locus details + + /** + * Fetches indivdual locus rather then getting all at once + * @param {object} responseBody determine the locus and fetch them if a remoteUrl is given + * @returns {Promise} returns locusObject array + */ + determineRedirections(responseBody) { + if (responseBody.remoteLocusClusterUrls && responseBody.remoteLocusClusterUrls.length) { + return Promise.all(responseBody.remoteLocusClusterUrls.map((url) => this.request({ + method: GET, + url, + runWhitelistedDomains: true // allows auth token for whitelisted domain + }) + .then((res) => { + responseBody.loci.push(...res.body.loci); + responseBody.locusUrls.push(...res.body.locusUrls); + }) + .catch((error) => { + console.error('failed to get locus details from: ', url, ' Reason: ', error); + }))) + .then(() => Promise.resolve(responseBody)); + } + return Promise.resolve(responseBody); + } +}