Skip to content

Instantly share code, notes, and snippets.

@christophrumpel
Created February 15, 2017 13:16
Show Gist options
  • Save christophrumpel/ebfad7af0d470614491c4669f507064d to your computer and use it in GitHub Desktop.
Save christophrumpel/ebfad7af0d470614491c4669f507064d to your computer and use it in GitHub Desktop.
BotMan ApiDriver Draft
<?php
namespace App\Chatbot\Conversations;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Mpociot\BotMan\Answer;
use Mpociot\BotMan\Drivers\Driver;
use Mpociot\BotMan\Facebook\ButtonTemplate;
use Mpociot\BotMan\Facebook\GenericTemplate;
use Mpociot\BotMan\Facebook\ListTemplate;
use Mpociot\BotMan\Facebook\ReceiptTemplate;
use Mpociot\BotMan\Interfaces\UserInterface;
use Mpociot\BotMan\Message;
use Mpociot\BotMan\Question;
use Illuminate\Support\Collection;
use Mpociot\BotMan\User;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ParameterBag;
use Mpociot\BotMan\Messages\Message as IncomingMessage;
class ApiDriver extends Driver
{
/** @var Collection|ParameterBag */
protected $payload;
/** @var Collection */
protected $event;
/** @var array */
protected $templates = [
ButtonTemplate::class,
GenericTemplate::class,
ListTemplate::class,
ReceiptTemplate::class,
];
const DRIVER_NAME = 'Api';
/**
* @param Request $request
*/
public function buildPayload(Request $request)
{
$this->payload = $request->request->all();
$this->event = Collection::make($this->payload);
}
/**
* Return the driver name.
* @return string
*/
public function getName()
{
return self::DRIVER_NAME;
}
/**
* Determine if the request is for this driver.
* @return bool
*/
public function matchesRequest()
{
return $this->event->get('driver') === 'api';
}
/**
* @param Message $message
* @return Answer
*/
public function getConversationAnswer(Message $message)
{
return Answer::create($message->getMessage());
}
/**
* Retrieve the chat message.
* @return array
*/
public function getMessages()
{
$message = $this->event->get('message');
$userId = $this->event->get('userId');
return [new Message($message, $userId, $userId, $this->payload)];
}
/**
* @return bool
*/
public function isBot()
{
return false;
}
/**
* @param string|Question|IncomingMessage $message
* @param Message $matchingMessage
* @param array $additionalParameters
* @return $this|void
*/
public function reply($message, $matchingMessage, $additionalParameters = [])
{
$cachedReplies = $this->getCachedMessages($message);
if ($this->isLastReply($message)) {
Cache::forget($this->event->get('userId'));
$messages = $this->buildReply($cachedReplies);
$replyData = [
'status' => 200,
'messages' => $messages
];
Response::create(json_encode($replyData), 200, [
'Content-Type' => 'application/json',
'Access-Control-Allow-Credentials' => true,
'Access-Control-Allow-Origin' => '*'
])->send();
}
}
/**
* @return bool
*/
public function isConfigured()
{
return true;
}
/**
* Retrieve User information.
* @param Message $matchingMessage
* @return UserInterface
*/
public function getUser(Message $matchingMessage)
{
return new User($matchingMessage->getChannel());
}
/**
* Build API reply
* @param $messages
* @return array
*/
private function buildReply($messages)
{
$replyData = collect($messages)->transform(function ($message) {
if ($message instanceof Question) {
$reply = $this->buildQuestionPayload($message);
} elseif (is_object($message) && in_array(get_class($message), $this->templates)) {
$reply = $this->buildTemplatePayload($message);
} else {
$reply = [
'type' => 'text',
'text' => str_replace('##end##', '', $message)
];
}
return $reply;
})->toArray();
return $replyData;
}
/**
* Check if this is the last reply of multiple ones
* @param $message
* @return bool|mixed
*/
public function isLastReply($message)
{
if ($message instanceof Question) {
$message = $message->toArray()['text'];
} elseif (is_object($message) && in_array(get_class($message), $this->templates)) {
$message = Arr::get($message->toArray(), 'attachment.payload.text');
}
return strpos($message, '##end##') !== false;
}
/**
* Pull cached replies
* @param $message
* @return array
*/
private function getCachedMessages($message)
{
$userId = $this->event->get('userId');
$cachedReplies = Cache::pull($userId);
$cachedReplies[] = $message;
Cache::put($userId, $cachedReplies, 100);
return $cachedReplies;
}
/**
* Build reply payload for a Question object
* @param Question $message
* @return array
*/
private function buildQuestionPayload(Question $message)
{
$questionsData = $message->toArray();
$reply = [
'type' => 'text',
'text' => str_replace('##end##', '', $questionsData['text'])
];
if ( ! empty($message->getButtons())) {
$reply['type'] = 'buttons';
$reply['buttons'] = Collection::make($message->getButtons())->map(function ($button) {
return [
'text' => $button['text'],
'keyword' => $button['value'],
'imageUrl' => $button['image_url']
];
})->toArray();
}
return $reply;
}
private function buildTemplatePayload($message)
{
$reply = [];
if ($message instanceof ButtonTemplate) {
$reply['type'] = 'buttonlist';
$reply['text'] = str_replace('##end##', '', Arr::get($message->toArray(), 'attachment.payload.text'));
$reply['buttons'] = Collection::make(Arr::get($message->toArray(),
'attachment.payload.buttons'))->map(function ($button) {
$returnArray = [
'type' => $button['type'] === 'web_url' ? 'url' : 'postback',
'text' => $button['title'],
'keyword' => $button['payload'] ?? null
];
if (isset($button['url'])) {
$returnArray['url'] = $button['url'];
}
return $returnArray;
});
} else {
$reply = [
'status' => 500,
'message' => 'unknown tempalte'
];
}
return $reply;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment