From 52a0302dc24b9ee8befc6a03d14b1b1970e4b32f Mon Sep 17 00:00:00 2001
From: osaajani <>
Date: Tue, 23 Mar 2021 04:31:13 +0100
Subject: [PATCH] start adding call support
---
controllers/internals/Received.php | 4 +-
controllers/internals/Sended.php | 4 +-
controllers/internals/Webhook.php | 16 +--
controllers/publics/Call.php | 81 +++++++++++++
controllers/publics/Callback.php | 110 ++++++++++++++++++
.../20210322193953_update_webhook_types.php | 16 +++
db/migrations/20210322223812_create_call.php | 47 ++++++++
models/Call.php | 29 +++++
models/Webhook.php | 5 +-
routes.php | 1 +
templates/webhook/add.php | 1 +
templates/webhook/list.php | 2 +
12 files changed, 298 insertions(+), 18 deletions(-)
create mode 100644 controllers/publics/Call.php
create mode 100644 db/migrations/20210322193953_update_webhook_types.php
create mode 100644 db/migrations/20210322223812_create_call.php
create mode 100644 models/Call.php
diff --git a/controllers/internals/Received.php b/controllers/internals/Received.php
index 0f0388a..c685adb 100644
--- a/controllers/internals/Received.php
+++ b/controllers/internals/Received.php
@@ -287,11 +287,11 @@ namespace controllers\internals;
'origin' => $origin,
'command' => $is_command,
'mms' => $mms,
- 'medias' => $media_ids,
+ 'medias' => $this->get_model()->gets_in_for_user($id_user, $media_ids),
];
$internal_webhook = new Webhook($this->bdd);
- $internal_webhook->trigger($id_user, \models\Webhook::TYPE_RECEIVE, $received);
+ $internal_webhook->trigger($id_user, \models\Webhook::TYPE_RECEIVE_SMS, $received);
$internal_user = new User($this->bdd);
$internal_user->transfer_received($id_user, $received);
diff --git a/controllers/internals/Sended.php b/controllers/internals/Sended.php
index dfac195..ee3ea04 100644
--- a/controllers/internals/Sended.php
+++ b/controllers/internals/Sended.php
@@ -236,10 +236,12 @@ namespace controllers\internals;
'text' => $text,
'destination' => $destination,
'origin' => $id_phone,
+ 'mms' => $mms,
+ 'medias' => $medias,
];
$internal_webhook = new Webhook($this->bdd);
- $internal_webhook->trigger($id_user, \models\Webhook::TYPE_SEND, $sended);
+ $internal_webhook->trigger($id_user, \models\Webhook::TYPE_SEND_SMS, $sended);
return $return;
}
diff --git a/controllers/internals/Webhook.php b/controllers/internals/Webhook.php
index 8d25108..3cbaff0 100644
--- a/controllers/internals/Webhook.php
+++ b/controllers/internals/Webhook.php
@@ -94,17 +94,11 @@ class Webhook extends StandardController
*
* @param int $id_user : User to trigger the webhook for
* @param string $type : Type of webhook to trigger
- * @param array $sms : The sms [
- * int 'id' => SMS id,
- * string 'at' => SMS date,
- * string 'text' => sms body,
- * string 'origin' => sms origin (number or phone id)
- * string 'destination' => sms destination (number or phone id)
- * ]
+ * @param array $body : The body, an array depending on webhook type
*
* @return bool : False if no trigger, true else
*/
- public function trigger(int $id_user, string $type, array $sms)
+ public function trigger(int $id_user, string $type, array $body)
{
$internal_setting = new Setting($this->bdd);
$internal_user = new User($this->bdd);
@@ -137,11 +131,7 @@ class Webhook extends StandardController
'webhook_type' => $webhook['type'],
'webhook_random_id' => $webhook_random_id,
'webhook_signature' => $webhook_signature,
- 'id' => $sms['id'],
- 'at' => $sms['at'],
- 'text' => $sms['text'],
- 'origin' => $sms['origin'],
- 'destination' => $sms['destination'],
+ 'body' => json_encode($body),
],
];
diff --git a/controllers/publics/Call.php b/controllers/publics/Call.php
new file mode 100644
index 0000000..55acbb2
--- /dev/null
+++ b/controllers/publics/Call.php
@@ -0,0 +1,81 @@
+
+ *
+ * This source file is subject to the GPL-3.0 license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace controllers\internals;
+
+ class Call extends StandardController
+ {
+ protected $model;
+
+ /**
+ * Create a media.
+ *
+ * @param int $id_user : Id of the user
+ * @param int $id_phone : Id of the phone that emitted (outbound) or received (inbound) the call
+ * @param string $uid : Uid of the phone call
+ * @param string $direction : Direction of the call, \models\Call::DIRECTION_INBOUND | \models\Call::DIRECTION_OUTBOUND
+ * @param string $start : Date of the call beginning
+ * @param ?string $end : Date of the call end
+ * @param ?string $origin : Origin of the call or null if outbound
+ * @param ?string $destination : Destination of the call or null if inbound
+ *
+ * @return mixed bool|int : false on error, new call id else
+ */
+ public function create(int $id_user, int $id_phone, string $uid, string $direction, string $start, ?string $end = null, ?string $origin = null, ?string $destination = null)
+ {
+ $call = [
+ 'id_user' => $id_user,
+ 'id_phone' => $id_phone,
+ 'uid' => $uid,
+ 'start' => $start,
+ 'end' => $end,
+ 'direction' => $direction,
+ 'origin' => $origin,
+ 'destination' => $destination,
+ ];
+
+ if (!$origin && !$destination)
+ {
+ return false;
+ }
+
+ switch ($direction)
+ {
+ case \models\Call::DIRECTION_OUTBOUND :
+ null === $destination ?: return false;
+ break;
+
+ case \models\Call::DIRECTION_INBOUND :
+ null === $origin ?: return false;
+ break;
+
+ default :
+ return false;
+ }
+
+ if (!\controllers\internals\Tool::validate_date($start, 'Y-m-d H:i:s'))
+ {
+ return false;
+ }
+
+ if (null !== $end && !\controllers\internals\Tool::validate_date($end, 'Y-m-d H:i:s'))
+ {
+ return false;
+ }
+
+ if (null !== $end && new \DateTime($end) < new \DateTime($start))
+ {
+ return false;
+ }
+
+ return $this->get_model()->insert($call);
+ }
+ }
diff --git a/controllers/publics/Callback.php b/controllers/publics/Callback.php
index 1a4c951..5c6e32e 100644
--- a/controllers/publics/Callback.php
+++ b/controllers/publics/Callback.php
@@ -26,6 +26,7 @@ use Monolog\Logger;
private $internal_received;
private $internal_adapter;
private $internal_media;
+ private $internal_phone;
public function __construct()
{
@@ -36,6 +37,7 @@ use Monolog\Logger;
$this->internal_received = new \controllers\internals\Received($bdd);
$this->internal_media = new \controllers\internals\Media($bdd);
$this->internal_adapter = new \controllers\internals\Adapter();
+ $this->internal_phone = new \controllers\internals\Phone();
//Logger
$this->logger = new Logger('Callback ' . uniqid());
@@ -242,4 +244,112 @@ use Monolog\Logger;
return true;
}
+
+
+ /**
+ * Function call on call reception notification
+ * We return nothing, and we let the adapter do his things.
+ *
+ * @param int $id_phone : Phone id
+ *
+ * @return bool : true on success, false on error
+ */
+ public function inbound_call(int $id_phone)
+ {
+ $this->logger->info('Callback reception call with phone : ' . $id_phone);
+ $phone = $this->internal_phone->get_for_user($this->user['id'], $id_phone);
+
+ if (!$phone)
+ {
+ $this->logger->error('Callback inbound_call use non existing phone : ' . $id_phone);
+
+ return false;
+ }
+
+ if (!class_exists($phone['adapter']))
+ {
+ $this->logger->error('Callback inbound_call use non existing adapter : ' . $phone['adapter']);
+
+ return false;
+ }
+
+ if (!$phone['adapter']::meta_support_inbound_call_callback())
+ {
+ $this->logger->error('Callback inbound_call use adapter ' . $phone['adapter'] . ' which does not support inbound_call callback.');
+
+ return false;
+ }
+
+ $response = $phone['adapter']::inbound_call_callback();
+ if ($response['error'])
+ {
+ $this->logger->error('Callback reception with adapter ' . $adapter_uid . ' failed : ' . $response['error_message']);
+
+ return false;
+ }
+
+ $sms = $response['sms'];
+ $mms = !empty($sms['mms']);
+ $medias = empty($sms['medias']) ? [] : $sms['medias'];
+ $media_ids = [];
+
+ //We create medias to link to the sms
+ if ($mms)
+ {
+ foreach ($medias as $media)
+ {
+ try
+ {
+ $media['mimetype'] = empty($media['mimetype']) ? mime_content_type($media['filepath']) : $media['mimetype'];
+
+ $mimey = new \Mimey\MimeTypes;
+ $extension = empty($media['extension']) ? $mimey->getExtension($media['mimetype']) : $media['extension'];
+
+ $new_filename = \controllers\internals\Tool::random_uuid() . '.' . $extension;
+ $new_filedir = PWD_DATA . '/medias/' . $this->user['id'];
+ $new_filerelpath = 'medias/' . $this->user['id'] . '/' . $new_filename;
+ $new_filepath = $new_filedir . '/' . $new_filename;
+
+ //Create user dir if not exists
+ if (!file_exists($new_filedir))
+ {
+ if (!mkdir($new_filedir, fileperms(PWD_DATA), true))
+ {
+ throw new \Exception('Cannot create dir ' . $new_filedir . ' to copy media : ' . json_encode($media));
+ }
+ }
+
+ if (!rename($media['filepath'], $new_filepath))
+ {
+ throw new \Exception('Cannot copy media : ' . json_encode($media) . ' to ' . $new_filepath);
+ }
+
+ $new_media_id = $this->internal_media->create($this->user['id'], $new_filerelpath);
+ if (!$new_media_id)
+ {
+ throw new \Exception('Cannot save into db media : ' . json_encode($media));
+ }
+
+ $media_ids[] = $new_media_id;
+ }
+ catch (\Throwable $t)
+ {
+ $this->logger->error($t->getMessage());
+ continue;
+ }
+ }
+ }
+
+ $response = $this->internal_received->receive($this->user['id'], $id_phone, $sms['text'], $sms['origin'], $sms['at'], \models\Received::STATUS_UNREAD, $mms, $media_ids);
+ if ($response['error'])
+ {
+ $this->logger->error('Failed receive message : ' . json_encode($sms) . ' with error : ' . $response['error_message']);
+
+ return false;
+ }
+
+ $this->logger->info('Callback reception successfully received message : ' . json_encode($sms));
+
+ return true;
+ }
}
diff --git a/db/migrations/20210322193953_update_webhook_types.php b/db/migrations/20210322193953_update_webhook_types.php
new file mode 100644
index 0000000..80f2392
--- /dev/null
+++ b/db/migrations/20210322193953_update_webhook_types.php
@@ -0,0 +1,16 @@
+execute('ALTER TABLE `webhook` MODIFY `type` ENUM(\'send_sms\', \'receive_sms\', \'inbound_call\')');
+ }
+
+ public function down()
+ {
+ $this->execute('ALTER TABLE `webhook` MODIFY `type` ENUM(\'send_sms\', \'receive_sms\')');
+ }
+}
diff --git a/db/migrations/20210322223812_create_call.php b/db/migrations/20210322223812_create_call.php
new file mode 100644
index 0000000..dda93d0
--- /dev/null
+++ b/db/migrations/20210322223812_create_call.php
@@ -0,0 +1,47 @@
+table('call');
+ $table->addColumn('id_user', 'integer')
+ ->addColumn('id_phone', 'integer', ['null' => true])
+ ->addColumn('uid', 'string', ['limit' => 500])
+ ->addColumn('start', 'datetime')
+ ->addColumn('end', 'datetime', ['null' => true])
+ ->addColumn('direction', 'enum', ['values' => ['inbound', 'outbound']])
+ ->addColumn('origin', 'string', ['limit' => 20, 'null' => true])
+ ->addColumn('destination', 'string', ['limit' => 20, 'null' => true])
+ ->addForeignKey('id_user', 'user', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
+ ->addForeignKey('id_phone', 'user', 'id', ['delete' => 'SET_NULL', 'update' => 'CASCADE'])
+ ->create();
+ }
+}
diff --git a/models/Call.php b/models/Call.php
new file mode 100644
index 0000000..fee82b3
--- /dev/null
+++ b/models/Call.php
@@ -0,0 +1,29 @@
+
+ *
+ * This source file is subject to the GPL-3.0 license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+namespace models;
+
+ /**
+ * Manage bdd operations for calls
+ */
+ class Call extends StandardModel
+ {
+ const DIRECTION_INBOUND = 'inbound';
+ const DIRECTION_OUTBOUND = 'outbound';
+
+ /**
+ * Return table name.
+ */
+ protected function get_table_name(): string
+ {
+ return 'call';
+ }
+ }
diff --git a/models/Webhook.php b/models/Webhook.php
index 945cd82..48d4998 100644
--- a/models/Webhook.php
+++ b/models/Webhook.php
@@ -13,8 +13,9 @@ namespace models;
class Webhook extends StandardModel
{
- const TYPE_SEND = 'send_sms';
- const TYPE_RECEIVE = 'receive_sms';
+ const TYPE_SEND_SMS = 'send_sms';
+ const TYPE_RECEIVE_SMS = 'receive_sms';
+ const TYPE_INBOUND_CALL = 'inbound_call';
/**
* Find all webhooks for a user and for a type of webhook.
diff --git a/routes.php b/routes.php
index 121d4ba..bf66579 100644
--- a/routes.php
+++ b/routes.php
@@ -168,6 +168,7 @@
'Callback' => [
'update_sended_status' => '/callback/status/{adapter_uid}/',
'reception' => '/callback/reception/{adapter_uid}/{id_phone}/',
+ 'inbound_call' => '/callback/inbound_call/{id_phone}/',
],
'Api' => [
diff --git a/templates/webhook/add.php b/templates/webhook/add.php
index 3fc35b9..6e53c43 100644
--- a/templates/webhook/add.php
+++ b/templates/webhook/add.php
@@ -47,6 +47,7 @@
Annuler
diff --git a/templates/webhook/list.php b/templates/webhook/list.php
index 0b306dc..20a99b9 100644
--- a/templates/webhook/list.php
+++ b/templates/webhook/list.php
@@ -92,6 +92,8 @@ jQuery(document).ready(function ()
return 'Envoi de SMS';
case 'receive_sms':
return 'Réception de SMS';
+ case 'inbound_call':
+ return 'Réception d\'un appel téléphonique';
default:
return 'Inconnu';
}