Skip to content

Commit

Permalink
Merge pull request #8 from rtckit/v0.0.4
Browse files Browse the repository at this point in the history
v0.0.4
  • Loading branch information
cdosoftei authored May 24, 2024
2 parents 2cf4944 + 8b97d64 commit 8d67e50
Show file tree
Hide file tree
Showing 18 changed files with 186 additions and 83 deletions.
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "rtckit/ficore",
"description": "FreeSWITCH Integration Core",
"version": "0.0.3",
"version": "0.0.4",
"keywords": [
"telecommunications",
"voip",
Expand All @@ -28,7 +28,7 @@
"ext-libxml": "*",
"ext-pcre": "*",
"ext-simplexml": "*",
"monolog/monolog": "^3.5",
"monolog/monolog": "^3.6",
"ramsey/uuid": "^4.7",
"react/event-loop": "^1.5",
"react/promise": "^3.1",
Expand All @@ -38,9 +38,9 @@
"wyrihaximus/react-psr-3-stdio": "^3.0"
},
"require-dev": {
"phpstan/phpstan": "^1.10",
"phpstan/phpstan": "^1.11",
"phpunit/phpunit": "^10.4",
"vimeo/psalm": "^5.16"
"vimeo/psalm": "^5.24"
},
"suggest": {
"ext-pcntl": "Enables daemonization support",
Expand Down
2 changes: 1 addition & 1 deletion etc/phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
includes:
- ../vendor/phpstan/phpstan/conf/bleedingEdge.neon
parameters:
checkGenericClassInNonGenericObjectType: false
ignoreErrors:
- identifier: missingType.generics
- '#Parameter \#1 \$onFulfilled of method React\\Promise\\PromiseInterface<mixed>::then\(\) expects \(callable\(mixed\):#'
1 change: 1 addition & 0 deletions etc/psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<TypeDoesNotContainType errorLevel="suppress" />
<PossiblyUnusedReturnValue errorLevel="suppress" />
<UnusedForeachValue errorLevel="suppress" />
<MissingClassConstType errorLevel="suppress" />

<!-- https://github.com/vimeo/psalm/issues/4823 -->
<RedundantPropertyInitializationCheck errorLevel="suppress" />
Expand Down
4 changes: 2 additions & 2 deletions src/Command/Channel/Playback/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ private function getPlayCommandsBLeg(Request $request, string $playString, strin
}
}

if (!$uuid) {
if (is_null($uuid)) {
$this->app->commandConsumer->logger->warning('No BLeg found');

return resolve([]);
Expand Down Expand Up @@ -257,7 +257,7 @@ private function getDisplaceMediaList(Core $core, string $uuid): PromiseInterfac
}
}

if (!$xml) {
if (is_null($xml) || ($xml === false)) {
$this->app->commandConsumer->logger->warning('cannot get displace_media_list: no list');

return resolve([]);
Expand Down
13 changes: 13 additions & 0 deletions src/Command/Conference/Member/ActionEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,17 @@ enum ActionEnum: string
case Undeaf = 'undeaf';
case Kick = 'kick';
case Hangup = 'hup';
case Play = 'play';
case Stop = 'stop';

case ExtHold = 'ext-hold';
case ExtUnhold = 'ext-unhold';

/* These native actions do not produce the desired results:
* https://github.com/signalwire/freeswitch/issues/796
*
* Use the extended/pseudo actions above instead.
*/
case Hold = 'hold';
case Unhold = 'unhold';
}
103 changes: 89 additions & 14 deletions src/Command/Conference/Member/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,102 @@ public function execute(RequestInterface $request): PromiseInterface
$response->successful = true;

foreach ($request->members as $member) {
$promises[] = $request->conference->core->client->api(
(new ESL\Request\Api())->setParameters("conference {$request->conference->room} {$request->action->value} {$member}")
)
->then(function (ESL\Response\ApiResponse $eslResponse) use ($request, $member, $response): PromiseInterface {
if (!$eslResponse->isSuccessful()) {
$response->successful = false;

$this->app->commandConsumer->logger->warning("`conference {$request->conference->room} {$request->action->value} {$member}` failed");
} else {
$response->members[] = $member;

$this->app->commandConsumer->logger->debug("`conference {$request->conference->room} {$request->action->value} {$member}` success");
$confCmd = "{$request->action->value} {$member}";

switch ($request->action) {
case ActionEnum::ExtHold:
$promises[] = $this->executeExtHold($request, $member);
break;

case ActionEnum::ExtUnhold:
$promises[] = $this->executeExtUnhold($request, $member);
break;

case ActionEnum::Play:
case ActionEnum::Stop:
$confCmd = "{$request->action->value}";

if (isset($request->medium)) {
$confCmd .= " {$request->medium}";
}

return resolve(null);
});
if ($member !== 'all') {
$confCmd .= " {$member}";
}

default:
$apiCmd = "conference {$request->conference->room} {$confCmd}";
$promises[] = $request->conference->core->client->api((new ESL\Request\Api())->setParameters($apiCmd))
->then(function (ESL\Response\ApiResponse $eslResponse) use ($member, $response, $apiCmd): PromiseInterface {
if (!$eslResponse->isSuccessful()) {
$response->successful = false;

$this->app->commandConsumer->logger->warning("`{$apiCmd}` failed");
} else {
$response->members[] = $member;

$this->app->commandConsumer->logger->debug("`{$apiCmd}` success");
}

return resolve(null);
});
break;
}
}

return all($promises)
->then(function () use ($response): Response {
return $response;
});
}

private function executeExtHold(Request $request, string $member): PromiseInterface
{
$deafRequest = clone $request;
$deafRequest->action = ActionEnum::Deaf;
$deafRequest->members = [$member];

$muteRequest = clone $request;
$muteRequest->action = ActionEnum::Mute;
$muteRequest->members = [$member];

$promises = [
'deaf' => $this->execute($deafRequest),
'mute' => $this->execute($muteRequest),
];

if (isset($request->medium)) {
$playRequest = clone $request;
$playRequest->action = ActionEnum::Play;
$playRequest->members = [$member];

$promises['play'] = $this->execute($playRequest);
}

return all($promises);
}

private function executeExtUnhold(Request $request, string $member): PromiseInterface
{
$unmuteRequest = clone $request;
$unmuteRequest->action = ActionEnum::Unmute;
$unmuteRequest->members = [$member];

$undeafRequest = clone $request;
$undeafRequest->action = ActionEnum::Undeaf;
$undeafRequest->members = [$member];

$stopRequest = clone $request;
$stopRequest->action = ActionEnum::Stop;
$stopRequest->members = [$member];
$stopRequest->medium = 'current';

$promises = [
'unmute' => $this->execute($unmuteRequest),
'undeaf' => $this->execute($undeafRequest),
'stop' => $this->execute($stopRequest),
];

return all($promises);
}
}
2 changes: 2 additions & 0 deletions src/Command/Conference/Member/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ class Request implements RequestInterface

/** @var list<string> */
public array $members = [];

public string $medium;
}
3 changes: 2 additions & 1 deletion src/Config/AbstractSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

class AbstractSet
{
/** @var string */
public const INBOUND_SOCKET_ADDRESS = 'inbound_socket_address';

/* General settings */
Expand Down Expand Up @@ -61,7 +62,7 @@ public static function parseSocketAddr(string $str, ?string &$ip, ?int &$port):
{
$ret = self::parseHostPort($str, $ip, $port);

if ($ret) {
if (!is_null($ret)) {
return $ret;
}

Expand Down
5 changes: 4 additions & 1 deletion src/Config/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ class Core

public bool $connected = false;

/** @var string */
public const SPEC_REGEX = '/^(?:([^\:]+)\:)?([a-z0-9]+)@([^:]+):([0-9]+)$/mi';

public static function parseSpec(string $spec): ?Core
{
if (!preg_match_all(self::SPEC_REGEX, $spec, $matches)) {
$count = preg_match_all(self::SPEC_REGEX, $spec, $matches);

if (($count === false) || ($count === 0)) {
return null;
}

Expand Down
1 change: 1 addition & 0 deletions src/Plan/AbstractElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

abstract class AbstractElement
{
/** @var bool */
public const NO_ANSWER = false;

public Channel $channel;
Expand Down
25 changes: 11 additions & 14 deletions src/Plan/CaptureSpeech/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,25 +93,22 @@ public function execute(Channel $channel, AbstractElement $element): PromiseInte
unset($element->channel->ttsVoice);
}

$promises = [];

if (isset($element->setVars[0])) {
$promises['set'] = $element->channel->client->sendMsg(
$promises = [
'set' => $element->channel->client->sendMsg(
(new ESL\Request\SendMsg())
->setHeader('call-command', 'execute')
->setHeader('execute-app-name', 'multiset')
->setHeader('execute-app-arg', implode(' ', $element->setVars))
->setHeader('event-lock', 'true')
);
}

$promises['playback'] = $element->channel->client->sendMsg(
(new ESL\Request\SendMsg())
->setHeader('call-command', 'execute')
->setHeader('execute-app-name', 'playback')
->setHeader('execute-app-arg', $playStr)
->setHeader('event-lock', 'true')
);
),
'playback' => $element->channel->client->sendMsg(
(new ESL\Request\SendMsg())
->setHeader('call-command', 'execute')
->setHeader('execute-app-name', 'playback')
->setHeader('execute-app-arg', $playStr)
->setHeader('event-lock', 'true')
),
];

return all($promises);
})
Expand Down
38 changes: 18 additions & 20 deletions src/Plan/CaptureTones/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,32 +67,30 @@ public function execute(Channel $channel, AbstractElement $element): PromiseInte

$regExp = '^(' . implode('|', $digits) . ')+';
$playStr = str_replace("'", "\\'", $playStr);
$promises = [];

if (isset($element->setVars[0])) {
$promises['set'] = $element->channel->client->sendMsg(
$promises = [
'set' => $element->channel->client->sendMsg(
(new ESL\Request\SendMsg())
->setHeader('call-command', 'execute')
->setHeader('execute-app-name', 'multiset')
->setHeader('execute-app-arg', implode(' ', $element->setVars))
->setHeader('event-lock', 'true')
);
}

$promises['pagd'] = $element->channel->client->sendMsg(
(new ESL\Request\SendMsg())
->setHeader('call-command', 'execute')
->setHeader('execute-app-name', 'play_and_get_digits')
->setHeader(
'execute-app-arg',
'1 ' . $element->maxTones . ' ' .
$element->tries . ' ' . $element->timeout . " '" .
$element->terminators . "' '" . $playStr . "' " .
$element->invalidMedium . ' pagd_input ' .
$regExp . ' ' . $digitTimeout
)
->setHeader('event-lock', 'true')
);
),
'pagd' => $element->channel->client->sendMsg(
(new ESL\Request\SendMsg())
->setHeader('call-command', 'execute')
->setHeader('execute-app-name', 'play_and_get_digits')
->setHeader(
'execute-app-arg',
'1 ' . $element->maxTones . ' ' .
$element->tries . ' ' . $element->timeout . " '" .
$element->terminators . "' '" . $playStr . "' " .
$element->invalidMedium . ' pagd_input ' .
$regExp . ' ' . $digitTimeout
)
->setHeader('event-lock', 'true')
),
];

return all($promises)
->then(function () use ($element): PromiseInterface {
Expand Down
1 change: 1 addition & 0 deletions src/Plan/Conference/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class Handler implements HandlerInterface
{
use HandlerTrait;

/** @var int */
public const EVENT_TIMEOUT = 30;

public function execute(Channel $channel, AbstractElement $element): PromiseInterface
Expand Down
Loading

0 comments on commit 8d67e50

Please sign in to comment.