Last active
September 21, 2022 08:30
-
-
Save easterapps/c7b3b0b665e3402a83e14a388cc31ca9 to your computer and use it in GitHub Desktop.
Simple PHP Webhook for Dialogflow v2 - Actions on Google
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Webhook { | |
public $decodedWebhook = null; | |
public $googleUserId = false; | |
// Other | |
public $hasResponded = false; | |
private $platforms = array('PLATFORM_UNSPECIFIED'); | |
// Response To Dialogflow | |
public $expectUserResponse = true; // Default, expect a user's response | |
private $items = array(); | |
private $suggestions = array(); | |
public $conversationToken = "{\"state\":null,\"data\":{}}"; | |
public $speech = 'Sorry, that action is not available on this platform.'; | |
public $displayText = 'Sorry, that action is not available on this platform.'; | |
// Constructor ---------------------------------------------------------------------------------------------------------------- | |
public function __construct($projectId) { | |
// Get the type of request this is | |
$requestType = $this->getTypeOfRequest($projectId); | |
if ($requestType == 'webhook') { | |
$this->processWebHook(); | |
return; | |
} | |
return; // Otherwise, return nothing | |
} | |
// Other Methods --------------------------------------------------------------------------------------------------------------- | |
// Determines the type of request this is @return STRING: webhook | other | |
private function getTypeOfRequest($projectId) { | |
// If this is a POST request, likely it's Google, but let's check to confirm | |
if ($_SERVER['REQUEST_METHOD'] === 'POST') { | |
try { | |
$json = file_get_contents('php://input'); | |
$action = json_decode($json, true); | |
if ($action == '' or $action == null) { | |
return 'other'; | |
} | |
// Confirm that this request matches the projectID | |
$this->decodedWebhook = $action; // Make the webhook JSON available to the class | |
return 'webhook'; | |
} | |
catch (Exception $e) { | |
return 'other'; | |
} | |
} | |
return 'other'; // Else, just return something else | |
} | |
// Processes the webhook from google for the user to access @return void | |
private function processWebHook() { | |
// If there is a user ID, add it to the global scope for access | |
if ( isset($this->decodedWebhook['originalRequest']['data']['user']['userId']) ) { | |
$this->googleUserId = $this->decodedWebhook['originalRequest']['data']['user']['userId']; | |
} | |
} | |
// Respond to DialogFlow ---------------------------------------------------------------------------------------------------- | |
// Builds an item for the carousel | |
public function build_carouselItem($title, $description, $imageUrl, $imageAlt, $dialogKey = '', $dialogSynonyms = '' ) { | |
return array( | |
'info' => array( | |
'key' => $dialogKey, | |
'synonyms' => $dialogSynonyms, | |
), | |
'title' => $title, | |
'description' => $description, | |
'image' => array( | |
'imageUri' => $imageUrl, | |
'accessibilityText' => $imageAlt, | |
), | |
); | |
} | |
public function build_carousel($simpleResponseText, $items) { | |
// There must be a simple response before a carousel, so create one now | |
$this->build_simpleResponse($simpleResponseText, $simpleResponseText); | |
$carousel = array( | |
'carouselSelect' => array( | |
'items' => $items | |
) | |
); | |
$this->items[] = $carousel; | |
} | |
// Builds a BasicCard Object | |
public function build_basicCard( | |
$simpleResponseText, | |
$title, | |
$subtitle, | |
$formattedText, | |
$imageObject, | |
$buttonObject, | |
$imageDisplayOptions = 'DEFAULT' | |
) { | |
// There must be a simple response before a card, so create one now | |
$this->build_simpleResponse($simpleResponseText, $simpleResponseText); | |
// Construct the basic card JSON | |
$basicCard = array( | |
'basicCard' => array( | |
'title' => $title, | |
'subtitle' => $subtitle, | |
'formattedText' => $formattedText, | |
'image' => $imageObject, | |
'buttons' => array($buttonObject), | |
'imageDisplayOptions' => $imageDisplayOptions, | |
) | |
); | |
$this->items[] = $basicCard; | |
} | |
// Builds the image attribute for a structure like the basic card | |
public function build_image($url, $accessibilityText, $height = null, $width = null) { | |
$image = array( | |
'url' => $url, | |
'accessibilityText' => $accessibilityText, | |
'height' => $height, | |
'width' => $width, | |
); | |
return $image; | |
} | |
// needs 1 simpleResponse before and suggestions or marked as final response | |
public function build_media($url, $name, $description = "null", $imageUrl) { | |
$objects = array(); | |
$mediaObject = array( | |
'name' => $name, | |
'description' => $description, | |
"largeImage"=> array( | |
'url'=> $imageUrl | |
) , | |
'contentUrl' => $url); | |
$objects[] = $mediaObject; | |
$file = array( | |
'mediaResponse' => array( | |
'mediaType' => "AUDIO", | |
'mediaObjects' => $objects | |
) | |
); | |
$this->items[] = $file; | |
} | |
// Builds the button attribute for a structure | |
public function build_button($title, $url) { | |
return array( | |
'title' => $title, | |
'openUrlAction' => array( | |
'url' => $url, | |
) | |
); | |
} | |
// Builds a simple response item | |
public function build_simpleResponse($textToSpeech, $displayText) { | |
$response = array( | |
'simpleResponse' => array( | |
'textToSpeech' => $textToSpeech, | |
'displayText' => $displayText | |
) | |
); | |
$this->items[] = $response; | |
} | |
// Build a suggestion item | |
public function build_suggestions($displayText) { | |
$this->suggestions[] = array('title' => $displayText); | |
} | |
// Builds a SSML response item | |
public function build_ssmlResponse($ssml, $displayText) { | |
$response = array( | |
'simpleResponse' => array( | |
'ssml' => $ssml, | |
'displayText' => $displayText | |
) | |
); | |
$this->items[] = $response; | |
} | |
// Builds an audio response item (just a SSML with audio) | |
public function build_audioResponse($url, $displayText) { | |
// Loop through the URLs if they are an array and build the ssml as necessary | |
$ssml = ' <speak> '; | |
if ( is_array($url) ) { | |
foreach($url as $u) { | |
$ssml .= "<audio src = '" . $u . "' /> "; | |
} | |
} | |
else { | |
$ssml .= "<audio src = '" . $url . "' /> "; | |
} | |
$ssml .= '</speak>'; | |
$response = array( | |
'simpleResponse' => array( | |
'ssml' => $ssml, | |
'displayText' => $displayText | |
) | |
); | |
$this->items[] = $response; | |
} | |
// Responds immediately with an array of the user's choosing, printed as JSON | |
public function respond_fullJson($jsonString) { | |
// Prevent duplicate responses | |
if ($this->hasResponded) return; | |
$this->hasResponded = true; | |
header("Content-type:application/json"); | |
echo $json; | |
} | |
// Responds immediately with a simple text/string message | |
public function respond_simpleMessage($textToSpeak, $stringToDisplay = '') { | |
// Prevent duplicate responses | |
if ($this->hasResponded) return; | |
$this->hasResponded = true; | |
// If this hasn't been defined, set it to the same text as the speech (accessibility) | |
if ($stringToDisplay == '') { | |
$stringToDisplay = $textToSpeak; | |
} | |
header("Content-type:application/json"); | |
echo json_encode(array( | |
"speech" => $textToSpeak, | |
"displayText" => $stringToDisplay, | |
)); | |
} | |
// Sends the response to Dialogflow | |
public function respond() { | |
// Prevent duplicate responses | |
if ($this->hasResponded) return; | |
$this->hasResponded = true; | |
// Set google as default for now | |
$integrations = array( | |
'google' => array( | |
'richResponse' => array( | |
'items' => $this->items, | |
"suggestions" => $this->suggestions | |
), | |
'expectUserResponse' => $this->expectUserResponse | |
) | |
); | |
$fulfillmentMessages = array(); | |
$response = array( | |
'fulfillmentText' => $this->speech, | |
'payload' => $integrations | |
); | |
header("Content-type:application/json"); | |
echo json_encode($response); | |
} | |
// Redefine fallback / default text for speech (in case a user doesn't have a google device) | |
public function setFallbackText($text) { | |
$this->speech = $text; | |
} | |
// DialogFlow Data Retrieval -------------------------------------------------------------------------------------------------------- | |
// Returns the full decoded webhook array for the user | |
public function getDecodedWebhook() { | |
return $this->decodedWebhook; | |
} | |
// Returns the raw input for the user (if it's from dialogflow: it's a json string) | |
public function getRawInput() { | |
return file_get_contents('php://input'); | |
} | |
// Gets the intent passed with the webhook | |
public function get_intent() { | |
return $this->decodedWebhook['queryResult']['action']; | |
} | |
// Returns the language | |
public function get_language() { | |
return $this->decodedWebhook['queryResult']['languageCode']; | |
} | |
// Returns the timestamp | |
public function get_timestamp() { | |
return $this->decodedWebhook['timestamp']; | |
} | |
// Returns the user's query | |
public function get_query() { | |
return $this->decodedWebhook['queryResult']['queryText']; | |
} | |
// Returns a full array of the parameters passed with the webhook | |
public function get_parameters() { | |
return $this->decodedWebhook['queryResult']['parameters']; | |
} | |
// Returns a specific parameter, or false if no parameter exists | |
public function get_parameter($parameter) { | |
if (isset($this->decodedWebhook['queryResult']['parameters'][$parameter])) { | |
return $this->decodedWebhook['queryResult']['parameters'][$parameter]; | |
} | |
return false; | |
} | |
// Ends the conversation by not expecting a response from the user | |
public function endConversation() { | |
$this->expectUserResponse = false; | |
} | |
// Adds FACEBOOK, SLACK, TELEGRAM, KIK, SKYPE, LINE, VIBER, ACTIONS_ON_GOOGLE, for rich messages | |
public function addPlatform($platformEnum) { | |
#$this-platform[] = $platforms; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment