iranianpep/botonomous

View on GitHub
src/Botonomous/Sender.php

Summary

Maintainability
A
0 mins
Test Coverage
A
95%
<?php

namespace Botonomous;

use Botonomous\listener\EventListener;
use Botonomous\listener\SlashCommandListener;
use /* @noinspection PhpUndefinedClassInspection */
    GuzzleHttp\Psr7\Request;

class Sender extends AbstractSender
{
    const SLACK_RESPONSE_TYPE = 'slack';
    const SLASH_COMMAND_RESPONSE_TYPE = 'slashCommand';
    const JSON_RESPONSE_TYPE = 'json';

    private $slackbot;

    /**
     * Sender constructor.
     *
     * @param AbstractBot $slackbot
     */
    public function __construct(AbstractBot $slackbot)
    {
        $this->setSlackbot($slackbot);
    }

    /**
     * @return AbstractBot
     */
    public function getSlackbot(): AbstractBot
    {
        return $this->slackbot;
    }

    /**
     * @param AbstractBot $slackbot
     */
    public function setSlackbot(AbstractBot $slackbot)
    {
        $this->slackbot = $slackbot;
    }

    /**
     * Final endpoint for the response.
     *
     * @param $channel
     * @param $text
     * @param $attachments
     *
     * @throws \Exception
     *
     * @return bool
     */
    public function send($text, $channel = null, $attachments = null)
    {
        // @codeCoverageIgnoreStart
        if ($this->getSlackbot()->getListener()->isThisBot() !== false) {
            return false;
        }
        // @codeCoverageIgnoreEnd

        if (empty($channel)) {
            $channel = $this->getSlackbot()->getListener()->getChannelId();
        }

        $data = [
            'text'    => $text,
            'channel' => $channel,
        ];

        if ($attachments !== null) {
            $data['attachments'] = json_encode($attachments);
        }

        $this->getLoggerUtility()->logChat(__METHOD__, $text, $channel);

        $responseType = $this->getResponseType();
        if ($responseType === self::SLACK_RESPONSE_TYPE) {
            $this->respondToSlack($data);
        } elseif ($responseType === self::SLASH_COMMAND_RESPONSE_TYPE) {
            $this->respondToSlashCommand($text);
        } elseif ($responseType === self::JSON_RESPONSE_TYPE) {
            $this->respondAsJSON($data);
        }

        return true;
    }

    /**
     * @param $response
     */
    private function respondToSlashCommand($response)
    {
        /** @noinspection PhpUndefinedClassInspection */
        $request = new Request(
            'POST',
            $this->getSlackbot()->getRequest('response_url'),
            ['Content-Type' => 'application/json'],
            json_encode([
                'text'          => $response,
                'response_type' => 'in_channel',
            ])
        );

        /* @noinspection PhpUndefinedClassInspection */
        $this->getClient()->send($request);
    }

    /**
     * @param $data
     *
     * @throws \Exception
     */
    private function respondToSlack($data)
    {
        $this->getApiClient()->chatPostMessage($data);
    }

    /**
     * @param $data
     */
    private function respondAsJSON($data)
    {
        // headers_sent is used to avoid issue in the test
        if (!headers_sent()) {
            header('Content-type:application/json;charset=utf-8');
        }

        echo json_encode($data);
    }

    /**
     * Specify the response type
     * If response in config is set to empty, it will be considered based on listener.
     *
     * @throws \Exception
     *
     * @return mixed|string
     */
    private function getResponseType()
    {
        if ($this->getSlackbot()->getRequest('debug') === true
            || $this->getSlackbot()->getRequest('debug') === 'true') {
            return self::JSON_RESPONSE_TYPE;
        }

        // response type in the config is empty, so choose it based on listener type
        return $this->getResponseByListenerType();
    }

    /**
     * @throws \Exception
     *
     * @return string
     */
    private function getResponseByListenerType(): string
    {
        $listener = $this->getConfig()->get('listener');
        switch ($listener) {
            case SlashCommandListener::KEY:
                return self::SLASH_COMMAND_RESPONSE_TYPE;
            case EventListener::KEY:
                return self::SLACK_RESPONSE_TYPE;
            default:
                return self::SLASH_COMMAND_RESPONSE_TYPE;
        }
    }

    /**
     * Send confirmation.
     *
     * @throws BotonomousException
     */
    public function sendConfirmation()
    {
        try {
            $userId = $this->getSlackbot()->getRequest('user_id');

            $user = '';
            if (!empty($userId)) {
                $user = $this->getMessageUtility()->linkToUser($userId).' ';
            }

            $confirmMessage = $this->getSlackbot()->getDictionary()->getValueByKey(
                'generic-messages',
                'confirmReceivedMessage',
                ['user' => $user]
            );

            if (!empty($confirmMessage)) {
                $this->send($confirmMessage);
            }
        } catch (\Exception $e) {
            throw new BotonomousException('Failed to send confirmatyion: '.$e->getMessage());
        }
    }
}