functions/slack_slash_command/index.php (80 lines of code) (raw):

<?php /** * Copyright 2020 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // [START functions_slack_setup] use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use GuzzleHttp\Psr7\Response; // [END functions_slack_setup] // [START functions_verify_webhook] /** * Verify that the webhook request came from Slack. */ function isValidSlackWebhook(ServerRequestInterface $request): bool { $SLACK_SECRET = getenv('SLACK_SECRET'); // Check for headers $timestamp = $request->getHeaderLine('X-Slack-Request-Timestamp'); $signature = $request->getHeaderLine('X-Slack-Signature'); if (!$timestamp || !$signature) { return false; } // Compute signature $plaintext = sprintf('v0:%s:%s', $timestamp, $request->getBody()); $hash = sprintf('v0=%s', hash_hmac('sha256', $plaintext, $SLACK_SECRET)); return $hash === $signature; } // [END functions_verify_webhook] // [START functions_slack_format] /** * Format the Knowledge Graph API response into a richly formatted Slack message. */ function formatSlackMessage(Google_Service_Kgsearch_SearchResponse $kgResponse, string $query): string { $responseJson = [ 'response_type' => 'in_channel', 'text' => 'Query: ' . $query ]; $entityList = $kgResponse['itemListElement']; // Extract the first entity from the result list, if any if (empty($entityList)) { $attachmentJson = ['text' => 'No results match your query...']; $responseJson['attachments'] = $attachmentJson; return json_encode($responseJson); } $entity = $entityList[0]['result']; // Construct Knowledge Graph response attachment $title = $entity['name']; if (isset($entity['description'])) { $title = $title . ' ' . $entity['description']; } $attachmentJson = ['title' => $title]; if (isset($entity['detailedDescription'])) { $detailedDescJson = $entity['detailedDescription']; $attachmentJson = array_merge([ 'title_link' => $detailedDescJson[ 'url'], 'text' => $detailedDescJson['articleBody'], ], $attachmentJson); } if (isset($entity['image'])) { $imageJson = $entity['image']; $attachmentJson['image_url'] = $imageJson['contentUrl']; } $responseJson['attachments'] = array($attachmentJson); return json_encode($responseJson); } // [END functions_slack_format] // [START functions_slack_request] /** * Send the user's search query to the Knowledge Graph API. */ function searchKnowledgeGraph(string $query): Google_Service_Kgsearch_SearchResponse { $API_KEY = getenv('KG_API_KEY'); $apiClient = new Google\Client(); $apiClient->setDeveloperKey($API_KEY); $service = new Google_Service_Kgsearch($apiClient); $params = ['query' => $query]; $kgResults = $service->entities->search($params); return $kgResults; } // [END functions_slack_request] // [START functions_slack_search] /** * Receive a Slash Command request from Slack. */ function receiveRequest(ServerRequestInterface $request): ResponseInterface { // Validate request if ($request->getMethod() !== 'POST') { // [] = empty headers return new Response(405); } // Parse incoming URL-encoded requests from Slack // (Slack requests use the "application/x-www-form-urlencoded" format) $bodyStr = $request->getBody(); parse_str($bodyStr, $bodyParams); if (!isset($bodyParams['text'])) { // [] = empty headers return new Response(400); } if (!isValidSlackWebhook($request, $bodyStr)) { // [] = empty headers return new Response(403); } $query = $bodyParams['text']; // Call knowledge graph API $kgResponse = searchKnowledgeGraph($query); // Format response to Slack // See https://api.slack.com/docs/message-formatting $formatted_message = formatSlackMessage($kgResponse, $query); return new Response( 200, ['Content-Type' => 'application/json'], $formatted_message ); } // [END functions_slack_search]