sidekick-1.0.x-dev/src/SidekickService.php

src/SidekickService.php
<?php

namespace Drupal\sidekick;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\Renderer;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\BadResponseException;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\TransferException;
use GuzzleHttp\RequestOptions;

/**
 * Service for HTTP request.
 */
class SidekickService {

  /**
   * The HTTP client.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $httpClient;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * The sidekick config.
   *
   * @var \Drupal\Core\Config\Config
   */
  protected $configFactory;

  /**
   * Language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Renderer.
   *
   * @var \Drupal\Core\Render\Renderer
   */
  protected $renderer;

  /**
   * Renderer.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $loggerFactory;

  /**
   * CacheFactory.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cacheFactory;

  /**
   * The time service.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected $time;

  /**
   * Messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * Status of the API Key.
   *
   * @var string
   */
  protected $keyStatusApi;

  /**
   * Account API URL.
   *
   * @var string
   */
  protected $accountApi;

  /**
   * Module API URL.
   *
   * @var string
   */
  protected $accountUsageApi;

  /**
   * Account Usage API URL.
   *
   * @var string
   */
  protected $modulesListApi;

  /**
   * Language API URl.
   *
   * @var string
   */
  protected $languagesListApi;

  /**
   * Writing style API URL.
   *
   * @var string
   */
  protected $writingStyleListApi;

  /**
   * Chat API URL.
   *
   * @var string
   */
  protected $chatApi;

  /**
   * API Key value.
   *
   * @var string
   */
  protected $key;

  /**
   * Constructor.
   *
   * @param \GuzzleHttp\ClientInterface $httpClient
   *   Guzzle Http client for requests.
   * @param \Drupal\Core\Session\AccountInterface $currentUser
   *   Logged in User object.
   * @param \Drupal\Core\Config\ConfigFactory $configFactory
   *   The factory for configuration objects.
   * @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
   *   The language manager service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Render\Renderer $renderer
   *   The renderer service.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $factory
   *   The LoggerChannelFactoryInterface object.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cacheFactory
   *   Cache backend instance to use.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger service.
   */
  public function __construct(
    ClientInterface $httpClient,
    AccountInterface $currentUser,
    ConfigFactory $configFactory,
    LanguageManagerInterface $languageManager,
    EntityTypeManagerInterface $entity_type_manager,
    Renderer $renderer,
    LoggerChannelFactoryInterface $factory,
    CacheBackendInterface $cacheFactory,
    TimeInterface $time,
    MessengerInterface $messenger,
  ) {
    $this->httpClient = $httpClient;
    $this->currentUser = $currentUser;
    $this->configFactory = $configFactory;
    $this->languageManager = $languageManager;
    $this->entityTypeManager = $entity_type_manager;
    $this->renderer = $renderer;
    $this->loggerFactory = $factory;
    $this->cacheFactory = $cacheFactory;
    $this->keyStatusApi = 'https://assistant.ai-sidekick.app/api/v1/apikey-status';
    $this->accountApi = 'https://assistant.ai-sidekick.app/api/v1/accounts/current';
    $this->accountUsageApi = 'https://assistant.ai-sidekick.app/api/v1/accounts/usage';
    $this->modulesListApi = 'https://assistant.ai-sidekick.app/api/v1/modules';
    $this->languagesListApi = 'https://assistant.ai-sidekick.app/api/v1/languages';
    $this->writingStyleListApi = 'https://assistant.ai-sidekick.app/api/v1/writing-styles';
    $this->chatApi = 'https://assistant.ai-sidekick.app/api/v1/chat';
    $this->key = $this->configFactory->get('sidekick.settings')->get(
      'api_key'
    );
    $this->time = $time;
    $this->messenger = $messenger;
  }

  /**
   * To Check status of Key.
   *
   * @param string $language_code
   *   Language code for key.
   * @param string|null $key
   *   Key whose status need to check.
   * @param bool|null $reset_cache
   *   Need to reset cache. Yes or No.
   *
   * @return array|mixed
   *   Returns of data or exception.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   *   Throws Exception.
   */
  public function checkKeyStatus($language_code, ?string $key = '', ?bool $reset_cache = FALSE) {
    if (empty($key)) {
      $key = $this->key;
    }
    if (empty($key)) {
      $build_message['message'] = [
        '#type' => 'html_tag',
        '#tag' => 'span',
        '#value' => t(
          'You have not added your Sidekick api key. Please add it.'
        ),
      ];
      $build_message['link'] = [
        '#type' => 'link',
        '#title' => t('here'),
        '#url' => Url::fromRoute('sidekick.settings_form'),
      ];
      $message = $this->renderer->render($build_message);
      $this->messenger->addWarning($message);
      return [];
    }

    $data = $this->cacheFactory->get('key_status');
    if (!$reset_cache && $data) {
      $keyStatus = $data->data;
    }
    else {
      try {
        $response = $this->httpClient->post(
          $this->keyStatusApi, [
            'headers' => [
              'Content-Type' => 'application/json',
            ],
            'body' => json_encode(
              [
                'token' => $key,
                'language' => $language_code,
              ]
            ),
          ]
        );
        $keyStatus = [
          'status' => $response->getStatusCode(),
          'message' => json_decode($response->getBody()),
        ];

        $this->cacheFactory->set(
          'key_status',
          $keyStatus,
          $this->time->getRequestTime() + 86400
        // Set Cache for day.
        );
      }
      catch (ClientException $e) {
        $keyStatus = [
          'status' => $e->getCode(),
          'message' => json_decode(
            $e->getResponse()
              ->getBody()
              ->getContents()
          )->message,
        ];
      }
    }
    return $keyStatus;
  }

  /**
   * Get possible modules from AI.
   *
   * @param string $language_code
   *   Language code in which Modules are needed.
   *
   * @return array|mixed
   *   Returns of data or exception.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   *   Throws Exception.
   */
  public function getModules($language_code) {
    $data = $this->cacheFactory->get('module_list');
    if ($data) {
      $modules = $data->data;
    }
    else {
      try {
        $response = $this->httpClient->get(
          $this->modulesListApi, [
            'headers' => [
              'Content-Type' => 'application/json',
              'Authorization' => 'Bearer ' . $this->key,
            ],
            'body' => json_encode(
              [
                'language' => $language_code,
              ]
            ),
          ]
        );
        $modules = [
          'status' => $response->getStatusCode(),
          'message' => json_decode($response->getBody()),
        ];

        $this->cacheFactory->set(
          'module_list',
          $modules,
          $this->time->getRequestTime() + 86400
        // Set Cache for day.
        );
      }
      catch (ClientException $e) {
        $modules = [
          'status' => $e->getCode(),
          'message' => json_decode(
            $e->getResponse()
              ->getBody()
              ->getContents()
          )->message,
        ];
      }
    }
    return $modules;
  }

  /**
   * Get possible language options from AI.
   *
   * @param string $language_code
   *   Language code.
   *
   * @return array|mixed
   *   Returns of data or exception.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   *   Throws Exception.
   */
  public function getLanguages($language_code) {
    try {
      if ($cache = $this->cacheFactory->get('language_list')) {
        return $cache->data;
      }
      else {
        $response = $this->httpClient->get(
          $this->languagesListApi, [
            'headers' => [
              'Content-Type' => 'application/json',
              'Authorization' => 'Bearer ' . $this->key,
            ],
            'body' => json_encode(
              [
                'language' => $language_code,
              ]
            ),
          ]
        );

        $data = [
          'status' => $response->getStatusCode(),
          'message' => json_decode($response->getBody()),
        ];

        $this->cacheFactory->set(
          'language_list',
          $data,
          $this->time->getRequestTime() + 86400
        // Set Cache for day.
        );

        return $data;
      }
    }
    catch (ClientException | RequestException | TransferException | BadResponseException $exception) {
      $this->loggerFactory->get('sidekick')->error($exception);

      return (object) [
        'message' => $exception->getMessage(),
      ];
    }
  }

  /**
   * Get Writing Style from AI source.
   *
   * @param string $language_code
   *   The Language code in which Writing Style needed.
   *
   * @return array|mixed
   *   Returns of data or exception.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   *   Throws Exception.
   */
  public function getWritingStyles($language_code) {
    try {
      if ($cache = $this->cacheFactory->get('writing_style')) {
        return $cache->data;
      }
      else {
        $response = $this->httpClient->get(
          $this->writingStyleListApi,
          [
            'headers' => [
              'Content-Type' => 'application/json',
              'Authorization' => 'Bearer ' . $this->key,
            ],
            'body' => json_encode(
              [
                'language' => $language_code,
              ]
            ),
          ]
        );

        $data = [
          'status' => $response->getStatusCode(),
          'message' => json_decode($response->getBody()),
        ];

        $this->cacheFactory->set(
          'writing_style',
          $data,
          $this->time->getRequestTime() + 86400
        // Set Cache for day.
        );

        return $data;
      }
    }
    catch (ClientException | RequestException | TransferException | BadResponseException $exception) {
      $this->loggerFactory->get('sidekick')->error($exception);

      return (object) [
        'message' => $exception->getMessage(),
      ];
    }
  }

  /**
   * Get Data from AI.
   *
   * @param string $sidekick_module
   *   The module type of which we are requesting data.
   * @param string $language_code
   *   The Language code for AI.
   * @param string $writing_style
   *   The writing style in which data need to fetch.
   * @param string $salutation
   *   The Type of salutation.
   * @param string $user_input
   *   User input in JSON format.
   *
   * @return array|mixed
   *   Returns of data or exception.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   *   Throws Exception.
   */
  public function getChat(
    $sidekick_module,
    $language_code,
    $writing_style,
    $salutation,
    $user_input,
  ) {
    try {
      $response = $this->httpClient->post(
        $this->chatApi, [
          'headers' => [
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer ' . $this->key,
          ],
          'query' => ['language' => $language_code],
          'body' => json_encode(
            [
              'module' => $sidekick_module ?? 'page_title_writer',
              'writing_style' => $writing_style,
              'salutation' => $salutation,
              'user_input' => $user_input,
            ]
          ),
        ]
      );

      return [
        'status' => $response->getStatusCode(),
        'message' => json_decode($response->getBody()),
      ];
    }
    catch (ClientException | RequestException | TransferException | BadResponseException $exception) {
      $this->loggerFactory->get('sidekick')->error($exception);

      return [
        'status' => $exception->getCode(),
        'message' => $exception->getMessage(),
      ];
    }
  }

  /**
   * Fetch the Context of Account from AI source.
   *
   * @param string $key
   *   API key for AI requests.
   *
   * @return array|mixed
   *   Returns array.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   *   Throws Exception.
   */
  public function getAccountContext($key) {
    try {
      $response = $this->httpClient->get(
        $this->accountApi, [
          'headers' => [
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer ' . $key,
          ],
        ]
      );

      return [
        'status' => $response->getStatusCode(),
        'message' => Json::decode($response->getBody()),
      ];
    }
    catch (ClientException | RequestException | TransferException | BadResponseException $exception) {
      $this->loggerFactory->get('sidekick')->error($exception);

      return (object) [
        'message' => $exception->getMessage(),
      ];
    }
  }

  /**
   * Fetch the Account Usages data from AI source.
   *
   * @param string $key
   *   API key for AI requests.
   *
   * @return array|mixed
   *   Returns array.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   *   Throws Exception.
   */
  public function getAccountUsage($key) {
    try {
      $response = $this->httpClient->get(
        $this->accountUsageApi, [
          'headers' => [
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer ' . $key,
          ],
        ]
      );

      return [
        'status' => $response->getStatusCode(),
        'message' => Json::decode($response->getBody()),
      ];
    }
    catch (ClientException | RequestException | TransferException | BadResponseException $exception) {
      $this->loggerFactory->get('sidekick')->error($exception);

      return (object) [
        'message' => $exception->getMessage(),
      ];
    }
  }

  /**
   * Set the Account context to AI source.
   *
   * @param string $key
   *   API key for AI request.
   * @param string $page_briefing
   *   Briefing data for AI request.
   * @param string $target_audience
   *   Target Audience for AI request.
   *
   * @return array|mixed
   *   Returns array.
   *
   * @throws \GuzzleHttp\Exception\GuzzleException
   *   Throws Exception.
   */
  public function setAccountContext($key, $page_briefing, $target_audience) {
    try {
      $request_options = [];
      $request_options[RequestOptions::HEADERS] = [
        'Content-Type' => 'application/json',
        'Authorization' => 'Bearer ' . $key,
      ];
      $request_options[RequestOptions::BODY] = Json::encode(
        [
          'context' => $page_briefing,
          'target_audience' => $target_audience,
          "process_web_page_context" => TRUE,
        ]
      );
      $response = $this->httpClient->request(
        'put',
        $this->accountApi,
        $request_options
      );

      return [
        'status' => $response->getStatusCode(),
        'message' => Json::decode($response->getBody()),
      ];
    }
    catch (ClientException | RequestException | TransferException | BadResponseException $exception) {
      $this->loggerFactory->get('sidekick')->error($exception);

      return (object) [
        'message' => $exception->getMessage(),
      ];
    }
  }

  /**
   * To Prepare and return the Data of Node.
   *
   * @param object $node
   *   Node Object.
   * @param \Drupal\Core\Form\FormStateInterface|null $form_state
   *   FormState object.
   *
   * @return false|string
   *   Return either Form or JSON String
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getSideKickMessagingApiData($node, $form_state) {
    $nodeUrl = Url::fromRoute(
      'entity.node.canonical',
      ['node' => $node->id()],
      ['absolute' => TRUE]
    )->toString();

    $entity_type = $form_state->getFormObject()->getEntity()
      ->getEntityTypeId();
    $node = $this->entityTypeManager->getStorage($entity_type)
      ->load($node->id());
    $builder = $this->entityTypeManager->getViewBuilder($entity_type);
    $build = $builder->view($node, 'default');
    $output = $this->renderer->render($build);

    $form_fields = $form_state->getFormObject()->getEntity()
      ->getFields();
    $structuredContent = '';
    foreach ($form_fields as $key => $field) {
      if ($form_state->getFormObject()->getEntity()->get($key)->entity
      ) {
        $structuredContent[$key] = $form_state->getFormObject()
          ->getEntity()->get($key)->entity;
      }
      else {
        $structuredContent[$key] = $form_state->getFormObject()
          ->getEntity()->get($key)->value;
      }
    }

    $sideKickMessagingApiData = [
      'version' => '1.0',
      'eventName' => 'page-changed',
      'data' => [
        'url' => $nodeUrl,
        'title' => $node->getTitle(),
        'content' => $output,
        'structuredContent' => $structuredContent,
        'targetAudience' => 'Tech-savvy people',
        'pageBriefing' => '',
      ],
    ];
    return json_encode($sideKickMessagingApiData);
  }

  /**
   * Converts Query parameters in to array.
   *
   * @param string $language_code
   *   The Language Code.
   *
   * @return array
   *   Query Parameters in Array.
   */
  public function getQueryParameter($language_code) {
    $domain = Url::fromRoute(
      '<front>',
      [],
      ['absolute' => TRUE]
    )->toString();

    return [
      'contentLanguage' => $language_code,
      'interfaceLanguage' => $language_code,
      'language' => $language_code,
      'userId' => $this->currentUser->getDisplayName(),
      'domain' => $domain,
      'apikey' => $this->configFactory->get('sidekick.settings')->get(
        'api_key'
      ),
      'platform' => 'Drupal',
      'hide_account_context' => TRUE,
      'referral' => 'Acolono',
    ];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc