From bf7ece8f1791932180df4785eb26ffdc62ad0882 Mon Sep 17 00:00:00 2001 From: xquanluu <110280845+xquanluu@users.noreply.github.com> Date: Tue, 13 Sep 2022 13:46:16 +0700 Subject: [PATCH] feat: play verb support seekOffset and actionHook (#160) * feat: play verb support seekOffset and actionHook * add testcase * fix: testcase --- lib/tasks/play.js | 9 ++++++++- lib/tasks/specs.json | 5 ++++- package-lock.json | 14 +++++++------- package.json | 2 +- test/play-tests.js | 40 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+), 10 deletions(-) diff --git a/lib/tasks/play.js b/lib/tasks/play.js index 7ac98eae..07b8f48e 100644 --- a/lib/tasks/play.js +++ b/lib/tasks/play.js @@ -7,6 +7,8 @@ class TaskPlay extends Task { this.preconditions = TaskPreconditions.Endpoint; this.url = this.data.url; + this.seekOffset = this.data.seekOffset || -1; + this.timeoutSecs = this.data.timeoutSecs || -1; this.loop = this.data.loop || 1; this.earlyMedia = this.data.earlyMedia === true; } @@ -31,8 +33,13 @@ class TaskPlay extends Task { } else { await this.playToConfMember(this.ep, memberId, confName, confUuid, this.url); } + } else { + const file = (this.timeoutSecs >= 0 || this.seekOffset >= 0) ? + {file: this.url, seekOffset: this.seekOffset, timeoutSecs: this.timeoutSecs} : this.url; + const result = await ep.play(file); + await this.performAction(Object.assign(result, {reason: 'playCompleted'}), + !(this.parentTask || cs.isConfirmCallSession)); } - else await ep.play(this.url); } } catch (err) { this.logger.info(err, `TaskPlay:exec - error playing ${this.url}`); diff --git a/lib/tasks/specs.json b/lib/tasks/specs.json index 0c0df844..0ecc4972 100644 --- a/lib/tasks/specs.json +++ b/lib/tasks/specs.json @@ -98,7 +98,10 @@ "properties": { "url": "string|array", "loop": "number|string", - "earlyMedia": "boolean" + "earlyMedia": "boolean", + "seekOffset": "number|string", + "timeoutSecs": "number|string", + "actionHook": "object|string" }, "required": [ "url" diff --git a/package-lock.json b/package-lock.json index afb78278..9c2dedcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "bent": "^7.3.12", "debug": "^4.3.4", "deepcopy": "^2.1.0", - "drachtio-fsmrf": "^3.0.2", + "drachtio-fsmrf": "^3.0.3", "drachtio-srf": "^4.5.1", "express": "^4.18.1", "helmet": "^5.1.0", @@ -1992,9 +1992,9 @@ } }, "node_modules/drachtio-fsmrf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/drachtio-fsmrf/-/drachtio-fsmrf-3.0.2.tgz", - "integrity": "sha512-Daub8hXFVNr8OTc7HnkdusNFjpgBavLYr+0TVTu9q5eemum7lgmnrCY3qKfSnPDEb24TpLbZarFa4NWPFYoqNQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/drachtio-fsmrf/-/drachtio-fsmrf-3.0.3.tgz", + "integrity": "sha512-RJpGS+lX3Cmqd725zJGf1KvONH38/9YDHkPxXevmiVBp+iD/EbRps/ze5wpE0MKbjEA93DOmiXGTWqsOChWttw==", "dependencies": { "camel-case": "^4.1.2", "debug": "^2.6.9", @@ -7791,9 +7791,9 @@ } }, "drachtio-fsmrf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/drachtio-fsmrf/-/drachtio-fsmrf-3.0.2.tgz", - "integrity": "sha512-Daub8hXFVNr8OTc7HnkdusNFjpgBavLYr+0TVTu9q5eemum7lgmnrCY3qKfSnPDEb24TpLbZarFa4NWPFYoqNQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/drachtio-fsmrf/-/drachtio-fsmrf-3.0.3.tgz", + "integrity": "sha512-RJpGS+lX3Cmqd725zJGf1KvONH38/9YDHkPxXevmiVBp+iD/EbRps/ze5wpE0MKbjEA93DOmiXGTWqsOChWttw==", "requires": { "camel-case": "^4.1.2", "debug": "^2.6.9", diff --git a/package.json b/package.json index e2721bb4..de71a8c3 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "bent": "^7.3.12", "debug": "^4.3.4", "deepcopy": "^2.1.0", - "drachtio-fsmrf": "^3.0.2", + "drachtio-fsmrf": "^3.0.3", "drachtio-srf": "^4.5.1", "express": "^4.18.1", "helmet": "^5.1.0", diff --git a/test/play-tests.js b/test/play-tests.js index 3968e8cd..5f200ead 100644 --- a/test/play-tests.js +++ b/test/play-tests.js @@ -156,3 +156,43 @@ test('\'play\' tests multi links in array in conference', async(t) => { t.error(err); } }); + +test('\'play\' tests with seekOffset and actionHook', async(t) => { + clearModule.all(); + const {srf, disconnect} = require('../app'); + + try { + await connect(srf); + + // GIVEN + const verbs = [ + { + verb: 'play', + url: 'silence_stream://5000', + seekOffset: 8000, + timeoutSecs: 2, + actionHook: '/customHook' + } + ]; + + const waitHookVerbs = []; + + const from = 'play_action_hook'; + provisionCallHook(from, verbs) + provisionCustomHook(from, waitHookVerbs) + + // THEN + await sippUac('uac-success-received-bye.xml', '172.38.0.10', from); + t.pass('play: succeeds'); + const obj = await getJSON(`http:127.0.0.1:3100/lastRequest/${from}_customHook`) + t.ok(obj.body.reason === "playCompleted", "play: actionHook success received") + t.ok(obj.body.playback_seconds === "2", "playback_seconds: actionHook success received") + t.ok(obj.body.playback_milliseconds === "2048", "playback_milliseconds: actionHook success received") + t.ok(obj.body.playback_last_offset_pos === "16000", "playback_last_offset_pos: actionHook success received") + disconnect(); + } catch (err) { + console.log(`error received: ${err}`); + disconnect(); + t.error(err); + } +});