Your IP : 216.73.217.77


Current Path : /home/users/unlimited/www/whatsjet-saas/Source/app/Yantrana/Components/BotReply/
Upload File :
Current File : /home/users/unlimited/www/whatsjet-saas/Source/app/Yantrana/Components/BotReply/BotReplyEngine.php

<?php
/**
* BotReplyEngine.php - Main component file
*
* This file is part of the BotReply component.
*-----------------------------------------------------------------------------*/

namespace App\Yantrana\Components\BotReply;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use App\Yantrana\Base\BaseEngine;
use Illuminate\Database\Query\Builder;
use App\Yantrana\Components\Media\MediaEngine;
use App\Yantrana\Components\WhatsAppService\WhatsAppServiceEngine;
use App\Yantrana\Components\BotReply\Repositories\BotFlowRepository;
use App\Yantrana\Components\BotReply\Repositories\BotReplyRepository;
use App\Yantrana\Components\BotReply\Interfaces\BotReplyEngineInterface;
use App\Yantrana\Components\Contact\Repositories\ContactCustomFieldRepository;

class BotReplyEngine extends BaseEngine implements BotReplyEngineInterface
{
    /**
     * @var  BotReplyRepository $botReplyRepository - BotReply Repository
     */
    protected $botReplyRepository;

    /**
     * @var  ContactCustomFieldRepository $contactCustomFieldRepository - ContactCustomField Repository
     */
    protected $contactCustomFieldRepository;

    /**
     * @var MediaEngine - Media Engine
     */
    protected $mediaEngine;

    /**
     * @var WhatsAppServiceEngine - WhatsApp Service Engine
     */
    protected $whatsAppServiceEngine;

    /**
     * @var  BotFlowRepository $botFlowRepository - BotFlow Repository
     */
    protected $botFlowRepository;

    /**
      * Constructor
      *
      * @param  BotReplyRepository $botReplyRepository - BotReply Repository
      * @param  ContactCustomFieldRepository $contactCustomFieldRepository - BotReply Repository
      * @param  MediaEngine $mediaEngine
      * @param  WhatsAppServiceEngine $whatsAppServiceEngine
      * @param  BotFlowRepository $botFlowRepository
      *
      * @return  void
      *-----------------------------------------------------------------------*/

    public function __construct(
        BotReplyRepository $botReplyRepository,
        ContactCustomFieldRepository $contactCustomFieldRepository,
        MediaEngine $mediaEngine,
        WhatsAppServiceEngine $whatsAppServiceEngine,
        BotFlowRepository $botFlowRepository,
    ) {
        $this->botReplyRepository = $botReplyRepository;
        $this->contactCustomFieldRepository = $contactCustomFieldRepository;
        $this->mediaEngine = $mediaEngine;
        $this->whatsAppServiceEngine = $whatsAppServiceEngine;
        $this->botFlowRepository = $botFlowRepository;
    }

    /**
     * Get contact dynamic fields and custom fields
     *
     * @return EngineResponse
     */
    public function preDataForBots()
    {
        $vendorId = getVendorId();

        $dynamicFieldsToReplace = [
            '{first_name}',
            '{last_name}',
            '{full_name}',
            '{phone_number}',
            '{email}',
            '{country}',
            '{language_code}',
        ];

        $customFields = $this->contactCustomFieldRepository->fetchItAll([
            'vendors__id' => $vendorId
        ]);

        foreach ($customFields as $customField) {
            $dynamicFieldsToReplace[] = "{{$customField->input_name}}";
        }

        return $this->engineSuccessResponse([
            'dynamicFields' => $dynamicFieldsToReplace
        ]);
    }

    /**
      * BotReply datatable source
      *
      * @return  array
      *---------------------------------------------------------------- */
    public function prepareBotReplyDataTableSource()
    {
        $botReplyCollection = $this->botReplyRepository->fetchBotReplyDataTableSource();
        $orderStatuses = configItem('status_codes');
        $botTriggerTypes = configItem('bot_reply_trigger_types');
        // required columns for DataTables
        $requireColumns = [
            '_id',
            '_uid',
            'name',
            'reply_text',
            'trigger_type',
            'trigger_type' => function ($rowData) use(&$botTriggerTypes) {
                return $botTriggerTypes[$rowData['trigger_type']]['title'] ?? '';
            },
            'reply_trigger' => function ($rowData) {
                return ($rowData['trigger_type'] != 'welcome') ? $rowData['reply_trigger'] : '';
            },
            'created_at' => function ($rowData) {
                return formatDateTime($rowData['created_at']);
            },
            'status' => function ($key) use (&$orderStatuses) {
                if($key['status'] === null) {
                    $key['status'] = 1; // active
                }
                return Arr::get($orderStatuses, $key['status']);
            },
            'bot_type' => function ($rowData) {
                $botReplyType = __tr('Simple');
                if($rowData['__data']['media_message'] ?? null) {
                    $botReplyType = __tr('Media');
                } elseif($rowData['__data']['interaction_message'] ?? null) {
                    $botReplyType = __tr('Interactive/Buttons');
                    ;
                }
                return $botReplyType;
            },
        ];
        // prepare data for the DataTables
        return $this->dataTableResponse($botReplyCollection, $requireColumns);
    }


    /**
      * BotReply delete process
      *
      * @param  mix $botReplyIdOrUid
      *
      * @return  EngineResponse
      *---------------------------------------------------------------- */

    public function processBotReplyDelete($botReplyIdOrUid)
    {
        $vendorId = getVendorId();
        // fetch the record
        $botReply = $this->botReplyRepository->fetchIt([
            '_uid' => $botReplyIdOrUid,
            'vendors__id' => $vendorId,
        ]);
        // check if the record found
        if (__isEmpty($botReply)) {
            // if not found
            return $this->engineResponse(18, [
                'botReplyUid' => $botReplyIdOrUid
            ], __tr('Bot Reply not found'));
        }

        // demo bot delete protection
        if(isDemo() and in_array($botReply->_id, explode(',', config('__misc.demo_protected_bots')))) {
            return $this->engineResponse(2, null, __tr('Your are not allowed to delete this bot in DEMO.'));
        }
        // ask to delete the record
        if ($this->botReplyRepository->deleteIt($botReply)) {
            // delete the links
            $this->botReplyRepository->updateItAll([
                'bot_replies__id' => $botReply->_id
            ], [
                'reply_trigger' => null
            ]);
            // if successful
            return $this->engineResponse(1, [
                'botReplyUid' => $botReply->_uid
            ], __tr('Bot Reply deleted successfully'));
        }
        // if failed to delete
        return $this->engineResponse(2, [
            'botReplyUid' => $botReplyIdOrUid
        ], __tr('Failed to delete BotReply'));
    }
    /**
      * BotReply duplicate process
      *
      * @param  mix $botReplyIdOrUid
      *
      * @return  EngineResponse
      *---------------------------------------------------------------- */

    public function processBotReplyDuplicate($botReplyIdOrUid)
    {
        $vendorId = getVendorId();
        // fetch the record
        $botReply = $this->botReplyRepository->fetchIt([
            '_uid' => $botReplyIdOrUid,
            'vendors__id' => $vendorId,
        ]);
        // check if the record found
        if (__isEmpty($botReply)) {
            // if not found
            return $this->engineResponse(18, [
                'botReplyUid' => $botReplyIdOrUid
            ], __tr('Bot Reply not found'));
        }
        // do not apply plan restriction if bot is getting added for bot flow
        // as there no limit for flows
        if(!$botReply->bot_flows__id) {
            // check the feature limit
            $vendorPlanDetails = vendorPlanDetails('bot_replies', $this->botReplyRepository->countIt([
                'vendors__id' => $vendorId,
                'bot_flows__id' => null,
            ]), $vendorId);
            if (!$vendorPlanDetails['is_limit_available']) {
                return $this->engineResponse(22, null, $vendorPlanDetails['message']);
            }
        }
        // ask to duplicate the record
        $newBotUid = Str::uuid();
        $newBotReply = $botReply->replicate();
        $newBotReply->name = $botReply->name . '-' . uniqid();
        $newBotReply->_uid = $newBotUid;
        $botData = $botReply->__data;
        // unset buttons
        if(isset($botData['interaction_message']['buttons'])) {
            $botData['interaction_message']['buttons'] = [];
        }
        // unset list data
        if(isset($botData['interaction_message']['list_data'])) {
            $botData['interaction_message']['list_data'] = [
                'button_text' => $botData['interaction_message']['list_data']['button_text'],
            ];
        }
        if($botReply->bot_flows__id) {
            $newBotReply->reply_trigger = null;
            $newBotReply->status = 2; // it always be inactive for bot flow
            $newBotReply->__data = $botData;
        }
        if ($newBotReply->save()) {
            if($botReply->bot_flows__id) {
                return $this->engineResponse(21, [
                    'reloadPage' => true,
                    'messageType' => 'success',
                ], __tr('Bot Reply duplicated'));
            }
            // if successful
            return $this->engineResponse(1, [
                'botReplyUid' => $newBotUid
            ], __tr('Bot Reply duplicated'));
        }
        // if failed to delete
        return $this->engineResponse(2, [
            'botReplyUid' => $botReplyIdOrUid
        ], __tr('Failed to duplicate Bot Reply'));
    }

    /**
      * BotReply create
      *
      * @param  array $inputData
      *
      * @return  array
      *---------------------------------------------------------------- */

    public function processBotReplyCreate($request)
    {
        $inputData = $request->all();
        $vendorId = getVendorId();
        $inputData['status'] = ($inputData['status'] ?? null) ? 1 : 2;
        // if bot flow
        if(isset($inputData['bot_flow_uid']) and $inputData['bot_flow_uid']) {
            $botFlow = $this->botFlowRepository->fetchIt($inputData['bot_flow_uid']);
            if (__isEmpty($botFlow)) {
                return $this->engineResponse(2, null, __tr('Invalid bot flow'));
            }
            $inputData['bot_flows__id'] = $botFlow->_id;

            $request->validate([
                'name' => [
                    "required",
                    "max:200",
                    Rule::unique('bot_replies')->where(fn (Builder $query) => $query->where([
                        'vendors__id' => $vendorId,
                        'bot_flows__id' => $botFlow->_id,
                    ]))
                ]
            ]);
            // bot flow bot always in inactive state, its state will be depend on flow status
            $inputData['status'] = 2;
        }
        $messageType = $inputData['message_type'] ?? 'simple';
        // do not apply plan restriction if bot is getting added for bot flow
        // as there no limit for flows
        if(!isset($inputData['bot_flow_uid']) or !$inputData['bot_flow_uid']) {
            // check the feature limit
            $vendorPlanDetails = vendorPlanDetails('bot_replies', $this->botReplyRepository->countIt([
                'vendors__id' => $vendorId,
                'bot_flows__id' => null,
            ]), $vendorId);
            if (!$vendorPlanDetails['is_limit_available']) {
                return $this->engineResponse(22, null, $vendorPlanDetails['message']);
            }
        }
        $inputData['vendors__id'] = $vendorId;
        if($messageType == 'interactive') {
            $interactiveType = $inputData['interactive_type'] ?? 'button';
            $mediaLink = '';
            if($inputData['header_type'] and ($inputData['header_type'] != 'text')) {
                $isProcessed = $this->mediaEngine->whatsappMediaUploadProcess(['filepond' => $inputData['uploaded_media_file_name']], 'whatsapp_' . $inputData['header_type']);
                if ($isProcessed->failed()) {
                    return $isProcessed;
                }
                $mediaLink = $isProcessed->data('path');
            }
            $ctaUrlButton = null;
            $listData = null;
            if($interactiveType == 'cta_url') {
                $ctaUrlButton = [
                    'display_text' => $inputData['button_display_text'],
                    'url' => $inputData['button_url'],
                ];
            }
            if($interactiveType == 'list') {
                $listData = [
                    'button_text' => $inputData['list_button_text'],
                    'sections' => array_filter($inputData['sections'] ?? []),
                ];
            }
            $inputData['__data'] = [
                'interaction_message' => [
                    'interactive_type' => $interactiveType,
                    'media_link' => $mediaLink,
                    'header_type' => $inputData['header_type'], // "text", "image", or "video"
                    'header_text' => $inputData['header_text'] ?? '',
                    'body_text' => $inputData['reply_text'],
                    'footer_text' => $inputData['footer_text'] ?? '',
                    'buttons' => array_filter($inputData['buttons'] ?? []),
                    'cta_url' => $ctaUrlButton,
                    'list_data' => $listData,
                ]
            ];
        } elseif($messageType == 'media') {
            $inputData['header_type'] = $inputData['media_header_type'];
            $mediaLink = '';
            $isProcessed = $this->mediaEngine->whatsappMediaUploadProcess(['filepond' => $inputData['uploaded_media_file_name']], 'whatsapp_' . $inputData['header_type']);
            if ($isProcessed->failed()) {
                return $isProcessed;
            }
            $mediaLink = $isProcessed->data('path');
            $inputData['reply_text'] = '';
            $inputData['__data'] = [
                'media_message' => [
                    'media_link' => $mediaLink,
                    'header_type' => $inputData['header_type'], // "text", "image", "audio or "video"
                    'caption' => $inputData['caption'] ?? '',
                    'file_name' => $isProcessed->data('fileName'),
                ]
            ];
        }
        // ask to add record
        $engineResponse = $this->botReplyRepository->processTransaction(function () use (&$inputData, &$vendorId) {
            if ($botReply = $this->botReplyRepository->storeBotReply($inputData)) {
                // if needs to validate message using by sending test message
                if($inputData['validate_bot_reply'] ?? null) {
                    $validateTestBotReply = $this->whatsAppServiceEngine->validateTestBotReply($botReply->_id);
                    if($validateTestBotReply->success()) {
                        return $this->botReplyRepository->transactionResponse(1, [], __tr('Bot Reply Created'));
                    }
                    // if got any errors etc
                    return $this->botReplyRepository->transactionResponse($validateTestBotReply->reaction(), [], $validateTestBotReply->message());
                }
                // success
                return $this->botReplyRepository->transactionResponse(1, [], __tr('Bot Reply Created'));
            }
            // failed for any other reason
            return $this->botReplyRepository->transactionResponse(2, [], __tr('Failed to create Bot Reply'));
        });
        // if bot flow
        if(isset($inputData['bot_flow_uid']) and $inputData['bot_flow_uid'] and ($engineResponse[0] == 1)) {
            $flowBots = $this->botReplyRepository->fetchItAll([
                'bot_flows__id' => $inputData['bot_flows__id'],
                'vendors__id' => $vendorId,
            ]);
            updateClientModels([
                'flowBots' => $flowBots,
            ]);
        }
        return $this->engineResponse($engineResponse);

    }

    /**
      * BotReply prepare update data
      *
      * @param  mix $botReplyIdOrUid
      *
      * @return  array
      *---------------------------------------------------------------- */

    public function prepareBotReplyUpdateData($botReplyIdOrUid)
    {
        $vendorId = getVendorId();
        // fetch the record
        $botReply = $this->botReplyRepository->fetchIt([
            '_uid' => $botReplyIdOrUid,
            'vendors__id' => $vendorId,
        ]);
        // Check if $botReply not exist then throw not found
        // exception
        if (__isEmpty($botReply)) {
            return $this->engineResponse(18, null, __tr('Bot Reply not found.'));
        }

        return $this->engineResponse(1, $botReply->toArray());
    }

    /**
      * BotReply process update
      *
      * @param  mixed $botReplyIdOrUid
      * @param  object $request
      *
      * @return  array
      *---------------------------------------------------------------- */

    public function processBotReplyUpdate($botReplyIdOrUid, $request)
    {
        $vendorId = getVendorId();
        // fetch the record
        $botReply = $this->botReplyRepository->fetchIt([
            '_uid' => $botReplyIdOrUid,
            'vendors__id' => $vendorId,
        ]);
        // Check if $botReply not exist then throw not found
        // exception
        if (__isEmpty($botReply)) {
            return $this->engineResponse(18, null, __tr('Bot Reply not found.'));
        }
        // demo bot edit protection
        if(isDemo() and in_array($botReply->_id, explode(',', config('__misc.demo_protected_bots')))) {
            return $this->engineResponse(2, null, __tr('Your are not allowed to edit this bot in DEMO.'));
        }
        $botFlowId = null;
        $inputData = $request->all();
        // if bot flow
        if(isset($inputData['bot_flow_uid']) and $inputData['bot_flow_uid']) {
            $botFlow = $this->botFlowRepository->fetchIt($inputData['bot_flow_uid']);
            if (__isEmpty($botFlow)) {
                return $this->engineResponse(2, null, __tr('Invalid bot flow'));
            }
            $botFlowId = $botFlow->_id;
        }
        $currentInputSectionsData = array_filter($inputData['sections'] ?? []);
        $currentInputButtonsData = array_filter($inputData['buttons'] ?? []);
        if($botFlowId) {
            // validate for uniqueness
            $request->validate([
                "name" => [
                    "required",
                    "max:200",
                    Rule::unique('bot_replies')->where(fn (Builder $query) => $query->where([
                        'vendors__id' => $vendorId,
                        'bot_flows__id'  => $botFlowId,
                    ]))->ignore($botReply->_id, '_id')
                ],
            ]);
        } else {
            $request->validate([
                "name" => [
                    "required",
                    "max:200",
                    Rule::unique('bot_replies')->where(fn (Builder $query) => $query->where([
                        'vendors__id' => $vendorId,
                        'bot_flows__id'  => null,
                    ]))->ignore($botReply->_id, '_id')
                ],
            ]);
        }

        $messageType = $inputData['message_type'] ?? 'simple';
        $updateData = [
            'name' => $inputData['name'],
            'reply_text' => $inputData['reply_text'] ?? '',
        ];
        if(!$botFlowId) {
            $updateData['trigger_type'] = $request->trigger_type;
            $updateData['reply_trigger'] = $request->reply_trigger;
            $updateData['status'] = $request->status ? 1 : 2;
        }
        // media message
        if($messageType == 'media') {
            $updateData['__data'] = [
                'media_message' => [
                    'caption' => $inputData['caption'] ?? '',
                ]
            ];
        } elseif($messageType == 'interactive') {
            $interactiveType = $inputData['interactive_type'] ?? 'button';
            $ctaUrlButton = null;
            if($interactiveType == 'cta_url') {
                $ctaUrlButton = [
                    'display_text' => $inputData['button_display_text'],
                    'url' => $inputData['button_url'],
                ];
            }
            $listData = null;
            if($interactiveType == 'list') {
                $listData = [
                    'button_text' => $inputData['list_button_text'],
                    'sections' => $currentInputSectionsData,
                ];
            }
            $updateData['__data'] = [
                'interaction_message' => [
                    'interactive_type' => $interactiveType,
                    'header_text' => $inputData['header_text'] ?? '',
                    'body_text' => $inputData['reply_text'],
                    'footer_text' => $inputData['footer_text'] ?? '',
                    'buttons' => $currentInputButtonsData,
                    'cta_url' => $ctaUrlButton,
                    'list_data' => $listData,
                ]
            ];
        }
        // update process
        $engineResponse = $this->botReplyRepository->processTransaction(function () use (&$botReply, &$updateData, &$request, &$interactiveType, &$currentInputButtonsData, &$botFlowId, &$botFlow, $currentInputSectionsData, &$inputData) {
            $isUpdated = false;
            $botFlowData = $botFlow->__data ?? [];
            $botData = $botReply->__data;
            $existingLinks = $botFlowData['flow_builder_data']['links'] ?? [];
            if($interactiveType == 'button') {
                // update links etc for bot flow
                if($botFlowId) {
                    $existingButtons = $botReply->__data['interaction_message']['buttons'] ?? [];
                    $buttonsRemoved = array_diff($existingButtons, $currentInputButtonsData);
                    $buttonsAdded = array_diff($currentInputButtonsData, $existingButtons);
                    $existingBotsForTrigger = $this->botReplyRepository->fetchItAll($existingButtons, [], 'reply_trigger', [
                        'where' => [
                            'bot_flows__id' => $botFlowId,
                            'bot_replies__id' => $botReply->_id,
                        ]
                    ]);
                    foreach ($existingBotsForTrigger as $existingBotForTrigger) {
                        $itemIndexInRemoved = array_search($existingBotForTrigger->reply_trigger, $buttonsRemoved);
                        if($itemIndexInRemoved !== false) {
                            $newReplyTrigger = $buttonsAdded[$itemIndexInRemoved] ?? null;
                            $isUpdated = $this->botReplyRepository->updateIt($existingBotForTrigger, [
                                'reply_trigger' => $newReplyTrigger
                            ]);
                            if(!$newReplyTrigger) {
                                if(!empty($existingLinks)) {
                                    $existingLinks = Arr::where($existingLinks, function ($value, $key) use (&$existingBotForTrigger) {
                                        return $value['toOperator'] != $existingBotForTrigger['_uid'];
                                    });
                                }
                            }
                        }
                    }
                    // update flow links
                    // following type of method to update JSON creates problem for mariadb 
                    //  '__data->flow_builder_data->links' => $existingLinks
                    // instead we have used it
                    Arr::set($botFlowData, 'flow_builder_data.links', $existingLinks);
                    $isUpdated = $this->botFlowRepository->updateBotFlowData($botFlowId, [
                        '__data' => json_encode($botFlowData)
                    ]);
                }
                // update buttons
                // following type of method to update JSON creates problem for mariadb 
                //  '__data->interaction_message->buttons' => $updateData['__data']['interaction_message']['buttons']
                // instead we have used it
                Arr::set($botData, 'interaction_message.buttons', $updateData['__data']['interaction_message']['buttons']);
                unset($updateData['__data']);
                if($request->has('footer_text') and !$request->footer_text) {
                    Arr::set($botData, 'interaction_message.footer_text', '');
                }
                $updateData['__data'] = json_encode($botData);
                $isUpdated = $this->botReplyRepository->updateForListAndButtonMessage($botReply->_id, $updateData);
            } elseif($interactiveType == 'list') {
                $listDataSections =  $botReply->__data['interaction_message']['list_data']['sections'] ?? [];
                $existingRowSubjects = [];
                foreach ($listDataSections as $listDataSection) {
                    foreach ($listDataSection['rows'] as $listDataSectionRow) {
                        $existingRowSubjects[] = $listDataSectionRow['title'];
                    }
                }
                $currentRowSubjects = [];
                foreach ($currentInputSectionsData as $currentInputSection) {
                    foreach ($currentInputSection['rows'] as $currentInputSectionRow) {
                        $currentRowSubjects[] = $currentInputSectionRow['title'];
                    }
                }

                $rowsRemoved = array_diff($existingRowSubjects, $currentRowSubjects);
                $rowsAdded = array_diff($currentRowSubjects, $existingRowSubjects);
                $existingBotsForTrigger = $this->botReplyRepository->fetchItAll($existingRowSubjects, [], 'reply_trigger', [
                    'where' => [
                        'bot_flows__id' => $botFlowId,
                        'bot_replies__id' => $botReply->_id,
                    ]
                ]);
                foreach ($existingBotsForTrigger as $existingBotForTrigger) {
                    $itemIndexInRemoved = array_search($existingBotForTrigger->reply_trigger, $rowsRemoved);
                    if($itemIndexInRemoved !== false) {
                        $newReplyTrigger = $rowsAdded[$itemIndexInRemoved] ?? null;
                        $isUpdated = $this->botReplyRepository->updateIt($existingBotForTrigger, [
                            'reply_trigger' => $newReplyTrigger
                        ]);
                        if(!$newReplyTrigger) {
                            if(!empty($existingLinks)) {
                                $existingLinks = Arr::where($existingLinks, function ($value, $key) use (&$existingBotForTrigger) {
                                    return $value['toOperator'] != $existingBotForTrigger['_uid'];
                                });
                            }
                        }
                    }
                }
                // update flow links
                // following type of method to update JSON creates problem for mariadb 
                //  '__data->flow_builder_data->links' => $existingLinks
                // instead we have used it
                Arr::set($botFlowData, 'flow_builder_data.links', $existingLinks);
                $isUpdated = $this->botFlowRepository->updateBotFlowData($botFlowId, [
                    '__data' => json_encode($botFlowData)
                ]);
                // following type of method to update JSON creates problem for mariadb 
                //  '__data->interaction_message->buttons' => $updateData['__data']['interaction_message']['buttons']
                // instead we have used it
                Arr::set($botData, 'interaction_message', $updateData['__data']['interaction_message']);
                unset($updateData['__data']);
                if($request->has('footer_text') and !$request->footer_text) {
                    Arr::set($botData, 'interaction_message.footer_text', '');
                }
                $updateData['__data'] = json_encode($botData);
                $isUpdated = $this->botReplyRepository->updateForListAndButtonMessage($botReply->_id, $updateData);
            } else {
                $isUpdated = $this->botReplyRepository->updateIt($botReply, $updateData);
                if($request->has('footer_text') and !$request->footer_text) {
                    $isUpdated = $this->botReplyRepository->updateForListAndButtonMessage($botReply->_id, [
                        '__data->interaction_message->footer_text' => ''
                    ]);
                }
            }
            if ($isUpdated) {
                if($request->validate_bot_reply) {
                    $validateTestBotReply = $this->whatsAppServiceEngine->validateTestBotReply($botReply->_id);
                    if($validateTestBotReply->success()) {
                        return $this->botReplyRepository->transactionResponse(1, [], __tr('Bot Reply updated.'));
                    }
                    return $this->botReplyRepository->transactionResponse($validateTestBotReply->reaction(), [], $validateTestBotReply->message());
                }
                return $this->botReplyRepository->transactionResponse(1, [], __tr('Bot Reply updated.'));
            }
            return $this->botReplyRepository->transactionResponse(2, [], __tr('Bot Reply Not updated.'));
        });
        // if bot flow
        if($botFlowId and ($engineResponse[0] == 1)) {
            // reloadPage
            return $this->engineResponse(21, [
                'reloadPage' => true
            ]);
        }
        return $this->engineResponse($engineResponse);
    }
}