iT邦幫忙

2021 iThome 鐵人賽

DAY 30
0
Software Development

Laravel 新手初見 API系列 第 30

Day30-用 LINEBot、Google Calendar、Dialogflow ES 做個開會機器人當結尾!

大家好~
今天是最後一天了,
來將這幾天所學結合成一個小作品吧!

功能部分就是當使用者跟 LINEBot 說什麼時候要開會,
LINEBot 會回應一個 Google Meet 的會議連結。

功能滿簡單的,
所以我決定用 Dialogflow 這個架構。

LINEBot Channel 申請可以參考 Day12
Dialogflow 與 LINEBot Channel 連動設定可以參考 Day26
Dialogflow Intent 的訓練也可以參考 Day26
Google Calendar 會用 Oauth 的憑證,
可以參考 Day25

底下就是程式的實作啦~

Route::post('/dialogflow', [DialogflowController::class, 'intent']);

開個 Webhook 給 Dialogflow。

GoogleMeetController
use Illuminate\Http\Request;
use Google\Client;
use Google\Service\Calendar;
use Google\Service\Calendar\Event;
use Google\Service\Calendar\EventDateTime;
use Google\Service\Calendar\ConferenceData;
use Google\Service\Calendar\ConferenceSolutionKey;
use Google\Service\Calendar\CreateConferenceRequest;

class GoogleMeetController extends Controller
{
    protected $client;
    protected $calendar;
    protected $calendarId;

    public function __construct()
    {
        $this->client = new Client();
        $this->client->setAuthConfig(env('OAUTH_CLIENT_CREDENTIALS_PATH'));
        $this->client->addScope(Calendar::CALENDAR_EVENTS);
        $tokenPath = env('OAUTH_TOKEN_JSON_PATH');
        $accessToken = json_decode(file_get_contents($tokenPath), true);
        $this->client->setAccessToken($accessToken);
        $this->calendar = new Calendar($this->client);
        $this->calendarId = env('GOOGLE_CALENDAR_ID');
    }

    public function create($request)
    {
        $calendarEvent = new Event();

        $conferenceSolutionKey = new ConferenceSolutionKey();
        $conferenceSolutionKey->setType('hangoutsMeet');

        $createConferenceRequest = new CreateConferenceRequest();
        $createConferenceRequest->setRequestId(md5('ironman2021' . time()));
        $createConferenceRequest->setConferenceSolutionKey($conferenceSolutionKey);

        $conferenceData = new ConferenceData();
        $conferenceData->setCreateRequest($createConferenceRequest);
        $calendarEvent->setConferenceData($conferenceData);

        $calendarEvent->setSummary($request['summary']);

        $startTime = new EventDateTime();
        $startTime->setDateTime($request['startTime']);
        $calendarEvent->setStart($startTime);

        $endTime = new EventDateTime();
        $endTime->setDateTime($request['endTime']);
        $calendarEvent->setEnd($endTime);

        $response = $this->calendar->events->insert(
            $this->calendarId,
            $calendarEvent,
            [
                'conferenceDataVersion' => 1
            ]
        );

        return $response->getHangoutLink();
    }
}

GoogleMeetController 會在指定時間建立一個 Google Calendar Event,
然後回傳 Google Meet 連結。

env 的設定也是和 Day25 一樣喔~

DialogflowController
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\GoogleMeetController;

class DialogflowController extends Controller
{
    public function intent(Request $request)
    {
        $queryText = $request->queryResult['queryText'];

        $datetime = $request->queryResult['outputContexts'][0]['parameters']['date-time'];

        $meetData['summary'] = "開會";

        switch ($datetime) {
            case is_string($datetime):
                $meetData['startTime'] = $datetime;
                $meetData['endTime'] = Carbon::parse($datetime)->addHour()->toRfc3339String();
                break;
            case is_array($datetime):
                if (isset($datetime['date_time'])) {
                    $startTime = $datetime['date_time'];
                    $meetData['startTime'] = $startTime;
                    $meetData['endTime'] = Carbon::parse($startTime)->addHour()->toRfc3339String();
                } elseif (isset($datetime['startDateTime'])) {
                    $startTime = $datetime['startDateTime'];
                    $endTime = $datetime['endDateTime'];
                    $meetData['startTime'] = $startTime;
                    $meetData['endTime'] = $endTime;
                } else {
                    $startTime = $datetime['startTime'];
                    $endTime = $datetime['endTime'];
                    $meetData['startTime'] = $startTime;
                    $meetData['endTime'] = $endTime;
                }
                break;
            default:
                return response('400', Response::HTTP_BAD_REQUEST);
        }

        $googleMeetController = new GoogleMeetController;
        $url = $googleMeetController->create($meetData);

        $jsonResponse = [
            "fulfillmentMessages" => [
                [
                    "text" => [
                        "text" => [
                            $url
                        ]
                    ]
                ]
            ]
        ];
        return $jsonResponse;
    }
}

DialogflowController 會將 Google Meet 連結傳給 Dialogflow。

這樣就差不多完成啦~
以下開始成果預覽!

成果預覽:

測試結果#1

測試結果#2

功能測試成功!

以上程式碼僅僅只是可動而已,
還有許多的不足,
例外處理以及一些安全上的問題都還沒完善,
像是 Dialogflow 發送的 Request 沒在 Headers 加入驗證相關的訊息,
DialogflowController 也沒有對 Request 做驗證。

之後還有更多要加強的地方,
這只是個起點。

感謝30天來收看的你~

若文章有任何問題,
還請不吝賜教!
也歡迎一起討論~
謝謝大家!


上一篇
Day29-介接 API(四)Laravel 實作 Dialogflow ES 之 API interactions
系列文
Laravel 新手初見 API30

尚未有邦友留言

立即登入留言