Skip to content

Instantly share code, notes, and snippets.

@sschlein
Created January 5, 2017 13:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sschlein/d82c41511d9e71963bcc5c84f9d5a508 to your computer and use it in GitHub Desktop.
Save sschlein/d82c41511d9e71963bcc5c84f9d5a508 to your computer and use it in GitHub Desktop.
<?php
namespace Mpociot\BotMan\Drivers;
use Mpociot\BotMan\Answer;
use Mpociot\BotMan\Message;
use Mpociot\BotMan\Question;
use Illuminate\Support\Collection;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ParameterBag;
use Mpociot\BotMan\Messages\Message as IncomingMessage;
class FacebookDriver extends Driver
{
/** @var Collection|ParameterBag */
protected $payload;
/** @var Collection */
protected $event;
/** @var string */
protected $signature;
/** @var string */
protected $content;
const DRIVER_NAME = 'Facebook';
/**
* @param Request $request
*/
public function buildPayload(Request $request)
{
$this->payload = new ParameterBag((array) json_decode($request->getContent(), true));
$this->event = Collection::make((array) $this->payload->get('entry')[0]);
$this->signature = $request->headers->get('X_HUB_SIGNATURE', '');
$this->content = $request->getContent();
}
/**
* 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()
{
if (! $this->config->has('facebook_app_secret')) {
return $this->event->has('messaging');
}
return $this->signature == 'sha1='.hash_hmac('sha1', $this->content, $this->config->get('facebook_app_secret'));
}
/**
* @param Message $matchingMessage
* @return void
*/
public function types(Message $matchingMessage)
{
$parameters = [
'recipient' => [
'id' => $matchingMessage->getChannel(),
],
'access_token' => $this->config->get('facebook_token'),
'sender_action' => 'typing_on',
];
return $this->http->post('https://graph.facebook.com/v2.6/me/messages', [], $parameters);
}
/**
* @param Message $message
*
* @return Answer
*/
public function getConversationAnswer(Message $message)
{
$payload = $message->getPayload();
if (isset($payload['message']['quick_reply'])) {
return Answer::create($message->getMessage())
->setInteractiveReply(true)
->setValue($payload['message']['quick_reply']['payload']);
}
return Answer::create($message->getMessage());
}
/**
* Retrieve the chat message.
*
* @return array
*/
public function getMessages()
{
$messages = Collection::make($this->event->get('messaging'));
$messages = $messages->transform(function ($msg) {
if (isset($msg['message'])) {
return new Message($msg['message']['text'], $msg['recipient']['id'], $msg['sender']['id'], $msg);
} elseif (isset($msg['postback'])) {
return new Message($msg['postback']['payload'], $msg['recipient']['id'], $msg['sender']['id'], $msg);
}
return new Message('', '', '');
})->toArray();
if (count($messages) === 0) {
return [new Message('', '', '')];
}
return $messages;
}
/**
* @return bool
*/
public function isBot()
{
// Facebook bot replies don't get returned
return false;
}
/**
* Convert a Question object into a valid Facebook
* quick reply response object.
*
* @param Question $question
* @return array
*/
private function convertQuestion(Question $question)
{
$questionData = $question->toArray();
$replies = Collection::make($question->getButtons())->map(function ($button) {
return [
'content_type' => 'text',
'title' => $button['text'],
'payload' => $button['value'],
'image_url' => $button['image_url'],
];
});
if ($questionData["text"] instanceof IncomingMessage) {
$message = $this->convertMessage($questionData["text"]);
} else {
$message = [
'text' => $questionData["text"],
];
}
$message['quick_replies'] = $replies->toArray();
return $message;
}
/**
* Convert a Message object into a valid Facebook
* message with an image or text.
*
* @param IncomingMessage $message
* @return array
*/
private function convertMessage(IncomingMessage $message)
{
if (! is_null($message->getImage())) {
return [
'attachment' => [
'type' => 'image',
'payload' => [
'url' => $message->getImage(),
],
],
];
} else {
return [
'text' => $message->getMessage(),
];
}
}
/**
* @param string|Question|IncomingMessage $message
* @param Message $matchingMessage
* @param array $additionalParameters
* @return $this
*/
public function reply($message, $matchingMessage, $additionalParameters = [])
{
$parameters = array_merge([
'recipient' => [
'id' => $matchingMessage->getChannel(),
],
'message' => [
'text' => $message,
],
], $additionalParameters);
/*
* If we send a Question with buttons, ignore
* the text and append the question.
*/
if ($message instanceof Question) {
$parameters['message'] = $this->convertQuestion($message);
} elseif ($message instanceof IncomingMessage) {
$parameters['message'] = $this->convertMessage($message);
}
$parameters['access_token'] = $this->config->get('facebook_token');
return $this->http->post('https://graph.facebook.com/v2.6/me/messages', [], $parameters);
}
/**
* @return bool
*/
public function isConfigured()
{
return ! is_null($this->config->get('facebook_token'));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment