عملی: یک اقدام راهنمای تلویزیونی برای دستیار Google با Dialogflow و Actions on Google ایجاد کنید

۱. مقدمه

شما در حال تماشای تلویزیون هستید، اما نمی‌توانید کنترل را پیدا کنید، یا شاید نمی‌خواهید تک تک کانال‌های تلویزیونی را ببینید تا ببینید آیا چیز جالبی روی تلویزیون هست یا نه؟ بیایید از دستیار گوگل بپرسیم که چه برنامه‌ای روی تلویزیون است! در این آزمایش شما یک اکشن ساده با استفاده از Dialogflow خواهید ساخت و یاد خواهید گرفت که چگونه آن را با دستیار گوگل ادغام کنید.

این تمرین‌ها به گونه‌ای مرتب شده‌اند که منعکس‌کننده‌ی یک تجربه‌ی رایج توسعه‌دهنده‌ی فضای ابری باشند:

  1. یک عامل Dialogflow v2 ایجاد کنید
  2. ایجاد یک موجودیت سفارشی
  3. ایجاد اهداف
  4. راه‌اندازی یک وب‌هوک با توابع فایربیس
  5. چت‌بات را آزمایش کنید
  6. فعال کردن ادغام دستیار گوگل

آنچه خواهید ساخت

ما یک ربات چت راهنمای تلویزیون تعاملی برای دستیار گوگل خواهیم ساخت. می‌توانید از راهنمای تلویزیون بپرسید که در حال حاضر چه برنامه‌هایی از یک کانال خاص پخش می‌شود. برای مثال: «MTV چه برنامه‌هایی دارد؟» راهنمای تلویزیون به شما می‌گوید که در حال حاضر چه برنامه‌هایی در حال پخش است و چه برنامه‌هایی در آینده پخش خواهد شد.

آنچه یاد خواهید گرفت

  • نحوه ایجاد چت‌بات با Dialogflow نسخه ۲
  • نحوه ایجاد موجودیت‌های سفارشی با Dialogflow
  • نحوه ایجاد مکالمه خطی با Dialogflow
  • نحوه تنظیم webhook performances با توابع Dialogflow و Firebase
  • چگونه با استفاده از Actions on Google، برنامه خود را به دستیار گوگل بیاورید

پیش‌نیازها

  • برای ایجاد یک عامل Dialogflow به یک آدرس Google Identity / gmail نیاز دارید.
  • دانش پایه جاوا اسکریپت لازم نیست، اما در صورتی که بخواهید کد تکمیل وب‌هوک را تغییر دهید، می‌تواند مفید باشد.

۲. راه‌اندازی

فعال کردن فعالیت وب در مرورگر

  1. کلیک کنید: http://myaccount.google.com/activitycontrols

  1. مطمئن شوید که فعالیت وب و برنامه فعال است:

bf8d16b828d6f79a.png

یک عامل Dialogflow ایجاد کنید

  1. باز کنید: https://console.dialogflow.com

  1. در نوار سمت چپ، درست زیر لوگو، « ایجاد نماینده جدید » را انتخاب کنید. در صورتی که از قبل نماینده دارید، ابتدا روی منوی کشویی کلیک کنید.

۱d7c2b56a1ab95b8.png

  1. نام نماینده را مشخص کنید: your-name-tvguide (از نام خودتان استفاده کنید)

۳۵۲۳۷b5c5c539ecc.png

  1. به عنوان زبان پیش‌فرض انتخاب کنید: انگلیسی - انگلیسی
  2. به عنوان منطقه زمانی پیش‌فرض، منطقه زمانی نزدیک به خودتان را انتخاب کنید.
  3. روی ایجاد کلیک کنید

پیکربندی دیالوگ فلو

  1. روی نماد چرخ دنده ، در منوی سمت چپ، کنار نام پروژه خود کلیک کنید.

۱d7c2b56a1ab95b8.png

  1. توضیحات نماینده زیر را وارد کنید: راهنمای تلویزیون من

۲۶f۲۶۲d۳۵۹c۴۹۰۷۵.png

  1. به پایین اسکرول کنید تا به تنظیمات گزارش (Log Settings) برسید و هر دو سوئیچ را به حالت گزارش تعاملات Dialogflow و گزارش تمام تعاملات در Google Cloud Stackdriver تغییر دهید. بعداً، در صورتی که بخواهیم عملکرد خود را اشکال‌زدایی کنیم، به این موارد نیاز خواهیم داشت.

e80c17acc3cce993.png

  1. روی ذخیره کلیک کنید

پیکربندی اقدامات در گوگل

  1. روی لینک دستیار گوگل در بخش «نحوه کارکرد آن در دستیار گوگل» در پنل سمت راست کلیک کنید.

5a4940338fc351e3.png

این باز خواهد شد: http://console.actions.google.com

وقتی با «اقدامات در گوگل» تازه‌کار هستید، ابتدا باید این فرم را مطالعه کنید:

3fd4e594fa169072.png

  1. با کلیک روی نام پروژه، سعی کنید اکشن خود را در شبیه‌ساز** باز کنید.**
  2. در نوار منو، گزینه تست را انتخاب کنید

6adb83ffb7adeb78.png

  1. مطمئن شوید که شبیه‌ساز روی انگلیسی تنظیم شده است و روی «با برنامه آزمایشی من صحبت کن» کلیک کنید.

اکشن با همان نیت پیش‌فرض اولیه‌ی Dialogflow به شما خوشامد می‌گوید. این یعنی تنظیمات ادغام با اکشن در گوگل درست بوده است!

۳. موجودیت‌های سفارشی

موجودیت‌ها اشیایی هستند که برنامه یا دستگاه شما روی آنها اقداماتی انجام می‌دهد. آنها را به عنوان پارامتر/متغیر در نظر بگیرید. در راهنمای تلویزیون ما می‌پرسیم: "چه برنامه‌ای در MTV پخش می‌شود". MTV موجودیت و متغیر است. من می‌توانم کانال‌های دیگری را نیز درخواست کنم، مانند: "National Geographic" یا "Comedy Central". موجودیت جمع‌آوری‌شده به عنوان پارامتر در درخواست من به سرویس وب TV Guide API استفاده خواهد شد.

در اینجا اطلاعات بیشتری در مورد موجودیت‌های Dialogflow آمده است .

ایجاد موجودیت کانال

  1. در کنسول Dialogflow روی آیتم منو کلیک کنید: Entities
  2. روی ایجاد نهاد کلیک کنید
  3. نام موجودیت: channel (مطمئن شوید که همه حروف کوچک هستند)
  4. نام کانال را وارد کنید. (بعضی از کانال‌ها به یک مترادف نیاز دارند تا در صورتی که دستیار گوگل چیز دیگری را متوجه شود، بتواند آن را بخواند). می‌توانید هنگام تایپ از کلیدهای Tab و Enter استفاده کنید. شماره کانال را به عنوان مقدار مرجع وارد کنید. و نام کانال‌ها را به عنوان مترادف، مانند:
  • 1 - 1, Net 1, Net Station 1

ee4e4955aa77232d.png

۵**.** با کلیک روی دکمه منو کنار دکمه آبی ذخیره، به حالت **ویرایش خام** بروید.

e294b49b123e034f.png

  1. سایر موجودیت‌ها را با فرمت CSV کپی و جای‌گذاری کنید:
"2","2","Net 2, Net Station 2"
"3","3","Net 3, Net Station 3"
"4","4","RTL 4"
"5","5","Movie Channel"
"6","6","Sports Channel"
"7","7","Comedy Central"
"8","8","Cartoon Network"
"9","9","National Geographic"
"10","10","MTV"

ed78514afd5badef.png

  1. ذخیره را بزنید

۴. اهداف

دیالوگ‌فلو از اینتنت‌ها برای دسته‌بندی نیات کاربر استفاده می‌کند. اینتنت‌ها دارای عبارات آموزشی هستند که نمونه‌هایی از آنچه کاربر ممکن است به عامل شما بگوید، می‌باشند. برای مثال، کاربری که می‌خواهد بداند تلویزیون چه برنامه‌ای دارد، ممکن است بپرسد: «امروز چه برنامه‌ای از تلویزیون پخش می‌شود؟»، «در حال حاضر چه برنامه‌ای در حال پخش است؟» یا به سادگی بگوید «tvguide».

وقتی کاربری چیزی می‌نویسد یا می‌گوید، که به آن عبارت کاربر گفته می‌شود، Dialogflow عبارت کاربر را با بهترین هدف در عامل شما مطابقت می‌دهد. تطبیق یک هدف همچنین به عنوان طبقه‌بندی هدف شناخته می‌شود.

در اینجا اطلاعات بیشتری در مورد اهداف Dialogflow آمده است .

تغییر هدف پیش‌فرض خوشامدگویی

وقتی یک عامل Dialogflow جدید ایجاد می‌کنید، دو هدف پیش‌فرض به طور خودکار ایجاد می‌شوند. هدف خوشامدگویی پیش‌فرض ، اولین جریانی است که هنگام شروع مکالمه با عامل با آن مواجه می‌شوید. هدف جایگزین پیش‌فرض ، جریانی است که پس از اینکه عامل نتواند منظور شما را بفهمد یا نتواند یک هدف را با آنچه شما گفته‌اید مطابقت دهد، دریافت خواهید کرد.

  1. روی هدف خوشامدگویی پیش‌فرض کلیک کنید

در مورد دستیار گوگل، این دستیار به طور خودکار با هدف خوشامدگویی پیش‌فرض شروع به کار می‌کند. دلیل این امر این است که Dialogflow در حال گوش دادن به رویداد خوشامدگویی است. با این حال، می‌توانید با گفتن یکی از عبارات آموزشی وارد شده، این هدف را نیز فراخوانی کنید.

6beee64e8910b85d.png

پیام خوشامدگویی برای هدف خوشامدگویی پیش‌فرض به صورت زیر است:

کاربر

عامل

«خب گوگل، با راهنمای تلویزیون خودت صحبت کن.»

«خوش آمدید، من نماینده‌ی راهنمای تلویزیون هستم. می‌توانم به شما بگویم که در حال حاضر چه برنامه‌هایی از یک کانال تلویزیونی پخش می‌شود. برای مثال، شما می‌توانید از من بپرسید: چه برنامه‌هایی از MTV پخش می‌شود.»

  1. به پایین اسکرول کنید تا به پاسخ‌ها برسید .
  2. تمام پاسخ‌های متنی را پاک کنید.
  3. یک پاسخ متنی جدید ایجاد کنید که شامل خوشامدگویی زیر باشد:

Welcome, I am the TV Guide agent. I can tell you what's currently playing on a TV channel. For example, you can ask me: What's on MTV?

84a1110a7f7edba2.png

  1. روی ذخیره کلیک کنید

یک هدف آزمایشی موقت ایجاد کنید

برای اهداف آزمایشی، ما یک Test Intent موقت ایجاد خواهیم کرد تا بتوانیم وب‌هوک را بعداً آزمایش کنیم.

  1. دوباره روی آیتم منوی Intents کلیک کنید.
  2. روی ایجاد هدف کلیک کنید
  3. نام Intent را وارد کنید: Test Intent (مطمئن شوید که از T بزرگ و I بزرگ استفاده می‌کنید. - اگر intent را طور دیگری بنویسید، سرویس back-end کار نخواهد کرد!)

۹۲۵e۰۲caa۴de۶b۹۹.png

  1. روی افزودن عبارات آموزشی کلیک کنید
  • Test my agent
  • Test intent

2e44ddb2fae3c841.png

  1. روی تکمیل سفارش > فعال کردن تکمیل سفارش کلیک کنید

7eb73ba04d76140e.png

این بار ما پاسخ را به صورت کدنویسی شده ارائه نمی‌کنیم. پاسخ از یک تابع ابری خواهد آمد!

  1. برای این intent، دکمه‌ی Enable Webhook را برعکس کنید.

748a82d9b4d7d253.png

  1. ذخیره را بزنید

هدف کانال را ایجاد کنید

هدف کانال شامل این بخش از مکالمه خواهد بود:

کاربر

عامل

«در کمدی سنترال چه خبر است؟»

««در حال حاضر از ساعت ۶ بعد از ظهر، سریال سیمپسون‌ها از شبکه کمدی سنترال پخش می‌شود. بعد از آن، ساعت ۷ بعد از ظهر، سریال فمیلی گای شروع خواهد شد.»»

  1. دوباره روی آیتم منوی Intents کلیک کنید.
  2. روی ایجاد هدف کلیک کنید
  3. نام Intent را وارد کنید: Channel Intent (مطمئن شوید که از T بزرگ و I بزرگ استفاده می‌کنید. - اگر intent را به طور متفاوتی هجی کنید، سرویس back-end کار نخواهد کرد!)
  4. روی افزودن عبارات آموزشی کلیک کنید و موارد زیر را اضافه کنید:
  • What's on MTV?
  • What's playing on Comedy Central?
  • What show will start at 8 PM on National Geographic?
  • What is currently on TV?
  • What is airing now.
  • Anything airing on Net Station 1 right now?
  • What can I watch at 7 PM?
  • What's on channel MTV?
  • What's on TV?
  • Please give me the tv guide.
  • Tell me what is on television.
  • What's on Comedy Central from 10 AM?
  • What will be on tv at noon?
  • Anything on National Geographic?
  • TV Guide

6eee02db02831397.png

  1. به پایین اسکرول کنید تا به اکشن و پارامترها برسید.

b7e917026760218a.png

به موجودیت‌های @channel و @sys.time که برای Dialogflow شناخته شده‌اند توجه کنید. بعداً در وب‌هوک شما، نام پارامتر و مقدار پارامتر به وب سرویس شما ارسال خواهد شد. برای مثال:

channel=8

time=2020-01-29T19:00:00+01:00

  1. علامت گذاری کانال در صورت نیاز

وقتی با نماینده TV Guide مکالمه می‌کنید، همیشه باید جای خالی پارامتر نام کانال را پر کنید. اگر نام کانال در ابتدای مکالمه ذکر نشده باشد، Dialogflow بیشتر می‌پرسد تا اینکه تمام جای خالی‌های پارامتر را پر کند. 6f36973fd789c182.png

به عنوان یک اعلان، وارد کنید:

  • For which TV channel do you want to hear the tv guide information?
  • In which TV channel are you interested?

cdb5601ead9423f8.png

  1. پارامتر زمان را آنطور که لازم است تنظیم نکنید .

زمان اختیاری خواهد بود. وقتی هیچ زمانی مشخص نشده باشد، سرویس وب زمان فعلی را برمی‌گرداند.

  1. کلیک کنید

این بار ما پاسخ را به صورت کدنویسی شده ارائه نمی‌کنیم. پاسخ از تابع cloud خواهد آمد! بنابراین، برای این intent، دکمه‌ی Enable Webhook را برعکس کنید.

  1. ذخیره را بزنید

۵. تکمیل سفارش از طریق وب‌هوک

اگر عامل شما به چیزی بیش از پاسخ‌های ایستا نیاز دارد، باید از تکمیل درخواست برای اتصال وب سرویس خود به عامل خود استفاده کنید. اتصال وب سرویس به شما این امکان را می‌دهد که بر اساس عبارات کاربر اقداماتی انجام دهید و پاسخ‌های پویا را به کاربر ارسال کنید. به عنوان مثال، اگر کاربری بخواهد برنامه تلویزیونی MTV را دریافت کند، وب سرویس شما می‌تواند پایگاه داده شما را بررسی کرده و به کاربر، برنامه MTV، پاسخ دهد.

  1. در منوی اصلی روی تکمیل سفارش کلیک کنید
  2. فعال کردن سوئیچ ویرایشگر درون‌خطی

cc84351f0d03ab6f.png

برای آزمایش و پیاده‌سازی ساده‌ی وب‌هوک، می‌توانید از ویرایشگر درون‌خطی استفاده کنید. این ویرایشگر از توابع ابری بدون سرور برای فایربیس استفاده می‌کند.

  1. روی تب index.js در ویرایشگر کلیک کنید و این قطعه کد جاوا اسکریپت برای Node.js را کپی و پیست کنید:
'use strict';

process.env.DEBUG = 'dialogflow:debug';

const {
  dialogflow,
  BasicCard,
  Button,
  Image,
  List
 } = require('actions-on-google');

const functions = require('firebase-functions');
const moment = require('moment');
const TVGUIDE_WEBSERVICE = 'https://tvguide-e4s5ds5dsa-ew.a.run.app/channel';
const { WebhookClient } = require('dialogflow-fulfillment');
var spokenText = '';
var results = null;


/* When the Test Intent gets invoked. */
function testHandler(agent) {
    let spokenText = 'This is a test message, when you see this, it means your webhook fulfillment worked!';

    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
        let conv = agent.conv();
        conv.ask(spokenText);
        conv.ask(new BasicCard({
            title: `Test Message`,
            subTitle: `Dialogflow Test`,
            image: new Image({
                url: 'https://dummyimage.com/600x400/000/fff',
                alt: 'Image alternate text',
            }),
            text: spokenText,
            buttons: new Button({
                title: 'This is a button',
                url: 'https://assistant.google.com/',
            }),
        }));
        // Add Actions on Google library responses to your agent's response
        agent.add(conv);
    } else {
        agent.add(spokenText);
    }
}

/* When the Channel Intent gets invoked. */
function channelHandler(agent) {
    var jsonResponse = `{"ID":10,"Listings":[{"Title":"Catfish Marathon","Date":"2018-07-13","Time":"11:00:00"},{"Title":"Videoclips","Date":"2018-07-13","Time":"12:00:00"},{"Title":"Pimp my ride","Date":"2018-07-13","Time":"12:30:00"},{"Title":"Jersey Shore","Date":"2018-07-13","Time":"13:00:00"},{"Title":"Jersey Shore","Date":"2018-07-13","Time":"13:30:00"},{"Title":"Daria","Date":"2018-07-13","Time":"13:45:00"},{"Title":"The Real World","Date":"2018-07-13","Time":"14:00:00"},{"Title":"The Osbournes","Date":"2018-07-13","Time":"15:00:00"},{"Title":"Teenwolf","Date":"2018-07-13","Time":"16:00:00"},{"Title":"MTV Unplugged","Date":"2018-07-13","Time":"16:30:00"},{"Title":"Rupauls Drag Race","Date":"2018-07-13","Time":"17:30:00"},{"Title":"Ridiculousness","Date":"2018-07-13","Time":"18:00:00"},{"Title":"Punk'd","Date":"2018-07-13","Time":"19:00:00"},{"Title":"Jersey Shore","Date":"2018-07-13","Time":"20:00:00"},{"Title":"MTV Awards","Date":"2018-07-13","Time":"20:30:00"},{"Title":"Beavis & Butthead","Date":"2018-07-13","Time":"22:00:00"}],"Name":"MTV"}`;
    var results = JSON.parse(jsonResponse);
    var listItems = {};
    spokenText = getSpeech(results);

    for (var i = 0; i < results['Listings'].length; i++) {
        listItems[`SELECT_${i}`] = {
            title: `${getSpokenTime(results['Listings'][i]['Time'])} - ${results['Listings'][i]['Title']}`,
            description: `Channel: ${results['Name']}`
        }
    }
    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
        let conv = agent.conv();
        conv.ask(spokenText);
        conv.ask(new List({
            title: 'TV Guide',
            items: listItems
        }));
        // Add Actions on Google library responses to your agent's response
        agent.add(conv);
    } else {
        agent.add(spokenText);
    }
}

/**
 * Return a text string to be spoken out by the Google Assistant
 * @param {object} JSON tv results
 */
var getSpeech = function(tvresults) {
    let s = "";
    if(tvresults['Listings'][0]) {
        let channelName = tvresults['Name'];
        let currentlyPlayingTime = getSpokenTime(tvresults['Listings'][0]['Time']);
        let laterPlayingTime = getSpokenTime(tvresults['Listings'][1]['Time']);
        s = `On ${channelName} from ${currentlyPlayingTime}, ${tvresults['Listings'][0]['Title']} is playing.
        Afterwards at ${laterPlayingTime}, ${tvresults['Listings'][1]['Title']} will start.`
    }

    return s;
}

/**
 * Return a natural spoken time
 * @param {string} time in 'HH:mm:ss' format
 * @returns {string} spoken time (like 8 30 pm i.s.o. 20:00:00)
 */
var getSpokenTime = function(time){
    let datetime = moment(time, 'HH:mm:ss');
    let min = moment(datetime).format('m');
    let hour = moment(datetime).format('h');
    let partOfTheDay = moment(datetime).format('a');

    if (min == '0') {
        min = '';
    }

    return `${hour} ${min} ${partOfTheDay}`;
};

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
    var agent = new WebhookClient({ request, response });

    console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
    console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
   
    let channelInput = request.body.queryResult.parameters.channel;
    let requestedTime = request.body.queryResult.parameters.time;
    let url = `${TVGUIDE_WEBSERVICE}/${channelInput}`;

    var intentMap = new Map();
    intentMap.set('Test Intent', testHandler);
    intentMap.set('Channel Intent', channelHandler);
    agent.handleRequest(intentMap);
});

cc84351f0d03ab6f.png

  1. روی تب package.json در ویرایشگر کلیک کنید و این قطعه کد JSON را که تمام کتابخانه‌های Node.js Package Manager (NPM) را وارد می‌کند، کپی و پیست کنید:
{
  "name": "tvGuideFulfillment",
  "description": "Requesting TV Guide information from a web service.",
  "version": "1.0.0",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "Google Inc.",
  "engines": {
    "node": "8"
  },
  "scripts": {
    "start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
    "deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
  },
  "dependencies": {
    "actions-on-google": "^2.2.0",
    "firebase-admin": "^5.13.1",
    "firebase-functions": "^2.0.2",
    "request": "^2.85.0",
    "request-promise": "^4.2.5",
    "moment" : "^2.24.0",
    "dialogflow-fulfillment": "^0.6.1"
  }
}

af01460c2a023e68.png

  1. روی دکمه‌ی Deploy کلیک کنید. کمی طول می‌کشد، زیرا در حال پیاده‌سازی تابع بدون سرور شماست. در پایین صفحه، یک پنجره‌ی پاپ‌آپ نمایش داده می‌شود که وضعیت شما را نشان می‌دهد.
  2. بیایید وب‌هوک را آزمایش کنیم تا ببینیم کد کار می‌کند یا خیر. در شبیه‌ساز سمت راست، تایپ کنید:

Test my agent.

وقتی همه چیز درست باشد، باید عبارت "این یک پیام آزمایشی است" را ببینید.

  1. بیایید قصد کانال را آزمایش کنیم، حالا این سوال را بپرسیم:

What's on MTV?

وقتی همه چیز درست باشد، باید ببینید:

«از ساعت ۴:۳۰ بعد از ظهر، برنامه‌ی MTV Unplugged پخش می‌شود. بعد از آن، ساعت ۵:۳۰ بعد از ظهر، مسابقه‌ی درگ روپاولز شروع خواهد شد.»

مراحل اختیاری - فایربیس

وقتی این را با یک کانال دیگر آزمایش می‌کنید، متوجه خواهید شد که نتایج تلویزیون یکسان است. دلیل این امر این است که تابع ابری هنوز از یک وب سرور واقعی دریافت نمی‌کند.

برای انجام این کار، باید یک اتصال شبکه خروجی ایجاد کنیم.

در صورتی که می‌خواهید این برنامه را با یک سرویس وب آزمایش کنید، طرح Firebase خود را به Blaze ارتقا دهید. توجه: این مراحل اختیاری هستند. همچنین می‌توانید به مراحل بعدی این آزمایشگاه بروید تا آزمایش برنامه خود را در Actions on Google ادامه دهید.

  1. به کنسول فایربیس بروید: https://console.firebase.google.com

  1. در پایین صفحه، دکمه ارتقا (Upgrade ) را فشار دهید

ad38bc6d07462abf.png

طرح Blaze را در پنجره بازشو انتخاب کنید.

  1. حالا که می‌دانیم وب‌هوک کار می‌کند، می‌توانیم ادامه دهیم و کد index.js را با کد زیر جایگزین کنیم. این کار تضمین می‌کند که می‌توانید اطلاعات راهنمای تلویزیون را از سرویس وب درخواست کنید:
'use strict';

process.env.DEBUG = 'dialogflow:debug';

const {
  dialogflow,
  BasicCard,
  Button,
  Image,
  List
 } = require('actions-on-google');

const functions = require('firebase-functions');
const moment = require('moment');
const { WebhookClient } = require('dialogflow-fulfillment');
const rp = require('request-promise');

const TVGUIDE_WEBSERVICE = 'https://tvguide-e4s5ds5dsa-ew.a.run.app/channel';
var spokenText = '';
var results = null;


/* When the Test Intent gets invoked. */
function testHandler(agent) {
    let spokenText = 'This is a test message, when you see this, it means your webhook fulfillment worked!';

    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
        let conv = agent.conv();
        conv.ask(spokenText);
        conv.ask(new BasicCard({
            title: `Test Message`,
            subTitle: `Dialogflow Test`,
            image: new Image({
                url: 'https://dummyimage.com/600x400/000/fff',
                alt: 'Image alternate text',
            }),
            text: spokenText,
            buttons: new Button({
                title: 'This is a button',
                url: 'https://assistant.google.com/',
            }),
        }));
        // Add Actions on Google library responses to your agent's response
        agent.add(conv);
    } else {
        agent.add(spokenText);
    }
}

/* When the Channel Intent gets invoked. */
function channelHandler(agent) {
    var listItems = {};
    spokenText = getSpeech(results);

    for (var i = 0; i < results['Listings'].length; i++) {
        listItems[`SELECT_${i}`] = {
            title: `${getSpokenTime(results['Listings'][i]['Time'])} - ${results['Listings'][i]['Title']}`,
            description: `Channel: ${results['Name']}`

        }
    }
    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
        let conv = agent.conv();
        conv.ask(spokenText);
        conv.ask(new List({
            title: 'TV Guide',
            items: listItems
        }));
        // Add Actions on Google library responses to your agent's response
        agent.add(conv);
    } else {
        agent.add(spokenText);
    }
}

/**
 * Return a text string to be spoken out by the Google Assistant
 * @param {object} JSON tv results
 */
var getSpeech = function(tvresults) {
    let s = "";
    if(tvresults && tvresults['Listings'][0]) {
        let channelName = tvresults['Name'];
        let currentlyPlayingTime = getSpokenTime(tvresults['Listings'][0]['Time']);
        let laterPlayingTime = getSpokenTime(tvresults['Listings'][1]['Time']);
        s = `On ${channelName} from ${currentlyPlayingTime}, ${tvresults['Listings'][0]['Title']} is playing.
        Afterwards at ${laterPlayingTime}, ${tvresults['Listings'][1]['Title']} will start.`
    }

    return s;
}

/**
 * Return a natural spoken time
 * @param {string} time in 'HH:mm:ss' format
 * @returns {string} spoken time (like 8 30 pm i.s.o. 20:00:00)
 */
var getSpokenTime = function(time){
    let datetime = moment(time, 'HH:mm:ss');
    let min = moment(datetime).format('m');
    let hour = moment(datetime).format('h');
    let partOfTheDay = moment(datetime).format('a');

    if (min == '0') {
        min = '';
    }

    return `${hour} ${min} ${partOfTheDay}`;
};

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
    var agent = new WebhookClient({ request, response });

    console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
    console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
   
    let channelInput = request.body.queryResult.parameters.channel;
    let requestedTime = request.body.queryResult.parameters.time;
    let url = `${TVGUIDE_WEBSERVICE}/${channelInput}`;

    if (requestedTime) {
        console.log(requestedTime);
        let offsetMin = moment().utcOffset(requestedTime)._offset;
        console.log(offsetMin);
        let time = moment(requestedTime).utc().add(offsetMin,'m').format('HH:mm:ss');
        url = `${TVGUIDE_WEBSERVICE}/${channelInput}/${time}`;
      }
    
      console.log(url);
  
      var options = {
          uri: encodeURI(url),
          json: true
      };
       
      // request promise calls an URL and returns the JSON response.
      rp(options)
        .then(function(tvresults) {
            console.log(tvresults);
            // the JSON response, will need to be formatted in 'spoken' text strings.
            spokenText = getSpeech(tvresults);
            results = tvresults;
        })
        .catch(function (err) {
            console.error(err);
        })
        .finally(function(){
            // kick start the Dialogflow app
            // based on an intent match, execute
            var intentMap = new Map();
            intentMap.set('Test Intent', testHandler);
            intentMap.set('Channel Intent', channelHandler);
            agent.handleRequest(intentMap);
        });
});

۶. اقدامات در گوگل

اکشنز آن گوگل (Actions on Google) یک پلتفرم توسعه برای دستیار گوگل (Google Assistant) است. این پلتفرم امکان توسعه «اکشن‌ها» (Actions) - اپلت‌هایی برای دستیار گوگل که قابلیت‌های گسترده‌تری را ارائه می‌دهند - را برای اشخاص ثالث فراهم می‌کند.

شما باید با درخواست از گوگل برای باز کردن یا ارتباط با یک برنامه، یک اقدام گوگل (Google Action) را فراخوانی کنید.

این کار اکشن شما را باز می‌کند، صدا را تغییر می‌دهد و شما از محدوده «بومی» دستیار گوگل خارج می‌شوید. این یعنی از این به بعد هر چیزی که از عامل خود می‌پرسید باید توسط شما ایجاد شود. اگر می‌خواهید نمی‌توانید ناگهان از دستیار گوگل اطلاعات آب و هوای گوگل را بخواهید؛ ابتدا باید محدوده اکشن خود (برنامه‌تان) را ببندید (ترک کنید).

آزمایش عملکرد خود در شبیه‌ساز دستیار گوگل

بیایید مکالمه زیر را آزمایش کنیم:

کاربر

دستیار گوگل

«هی گوگل، با راهنمای تلویزیونِ به نام خودت صحبت کن.»

«حتماً. بذار راهنمای تلویزیونیِ «اسمت» رو برات بیارم.»

کاربر

نماینده راهنمای تلویزیون با نام شما

-

«خوش آمدید، من راهنمای تلویزیون هستم...»

عامل من را آزمایش کنید

«این یک پیام آزمایشی است، وقتی این را می‌بینید، به این معنی است که تکمیل وب‌هوک شما با موفقیت انجام شده است!»

چه برنامه‌ای از ام‌تی‌وی پخش می‌شود؟

از ساعت ۴:۳۰ بعد از ظهر، برنامه MTV Unplugged در شبکه MTV پخش می‌شود. پس از آن، ساعت ۵:۳۰ بعد از ظهر، مسابقه درگ روپاولز آغاز خواهد شد.

  1. به شبیه‌ساز دستیار گوگل برگردید

باز کنید: https://console.actions.google.com

  1. روی آیکون میکروفون کلیک کنید و موارد زیر را بپرسید:

c3b200803c7ba95e.png

  • Talk to my test agent
  • Test my agent

دستیار گوگل باید با این موارد پاسخ دهد:

5d93c6d037c8c8eb.png

  1. حالا بپرسیم:
  • What's on Comedy Central?

این باید برگردد:

در حال حاضر از ساعت ۶ بعد از ظهر در کمدی سنترال، سریال سیمپسون‌ها پخش می‌شود. پس از آن، ساعت ۷ بعد از ظهر، سریال فمیلی گای شروع خواهد شد.

۷. تبریک

شما اولین اقدام دستیار گوگل خود را با Dialogflow ایجاد کردید، آفرین!

همانطور که ممکن است متوجه شده باشید، عملکرد شما در حالت آزمایشی اجرا می‌شد که به حساب گوگل شما متصل است. اگر با همان حساب کاربری در دستگاه Nest یا برنامه Google Assistant در تلفن iOS یا Android خود وارد سیستم شوید، می‌توانید عملکرد خود را نیز آزمایش کنید.

این یک نسخه آزمایشی کارگاه است. اما وقتی واقعاً در حال ساخت برنامه‌هایی برای دستیار گوگل هستید، می‌توانید اقدام خود را برای تأیید ارسال کنید. برای اطلاعات بیشتر این راهنما را بخوانید.

آنچه ما پوشش داده‌ایم

  • نحوه ایجاد چت‌بات با Dialogflow نسخه ۲
  • نحوه ایجاد موجودیت‌های سفارشی با Dialogflow
  • نحوه ایجاد مکالمه خطی با Dialogflow
  • نحوه تنظیم webhook performances با توابع Dialogflow و Firebase
  • چگونه با استفاده از Actions on Google، برنامه خود را به دستیار گوگل بیاورید

بعدش چی؟

از این آزمایشگاه کد لذت بردید؟ نگاهی به این آزمایشگاه‌های عالی بیندازید!

این آزمایشگاه کد را با ادغام آن برای Google Chat ادامه دهید:

با G Suite و Dialogflow یک راهنمای تلویزیونی در گوگل چت ایجاد کنید