LINE Bot + Clova スキル開発 Python Django チュートリアル(Clova スキル 開発編)

# LINE Bot + Clova スキルを Python Django で作って動かす！

準備はこちら
**[LINE Bot + Clova スキル開発 Python Django チュートリアル(準備編)](https://qiita.com/TakeshiSaito/items/7d6874363427e5deb609)**

Bot 開発はこちら
**[LINE Bot + Clova スキル開発 Python Django チュートリアル(LINE Bot 開発編)](https://qiita.com/TakeshiSaito/items/7b55aaf963f9228d6945)**

続きです。

一つ前の記事で LINE Bot の動作確認まで行いました。
いよいよ、いよいよ、スキル の開発を行います。

前々回、前回の記事は読んでいただけている体で書いていきます。
ここだけ読みたかった方、お手数をおかけしますが少し遡って記事を見ていただけるとありがたいです。

## LINE Devlopers にアクセスして スキル の設定
Bot 作成の時と同様です。

### スキル の設定
[Line Developers](https://developers.line.me/ja/)

上のリンクにアクセスするとこんな感じになっています。Clova をクリックしてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/e96f8f4d-0e6d-6b58-a54a-3b5c5b37c296.png)

スキルを開発する をクリック

![line_dev_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/7d4daec7-bcc2-3e28-344c-c2497769f7e4.jpeg)

LINE Developersでスキルチャネルを新規作成 をクリック

![line_dev_2.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/ce76eee9-0b88-ef3d-fedd-b09a74b5cc82.jpeg)

こんな画面になるので、作成済みのプロバイダーを選んで 次のページ をクリック

![line_dev_3.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/f573a2b2-768b-ee55-c806-0de5940828bd.jpeg)

チャネル名は Bot と混同しないように サンプル占い Clova スキル にしました。
入力したら 入力内容を確認する をクリック！

![line_dev_4.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/b1d3e606-b2bb-725f-9899-e5e01a7d70f4.jpeg)

作成して Clova Developer Centerに移動 をクリック

![line_dev_5.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/55b7a3c9-8c05-4464-506b-b94d696ef1ab.jpeg)

ハァハァ・・・あと少し。で前半終了

こんな画面になったと思います。

![screencapture-clova-developers-line-me-cek-2018-09-19-19_32_12.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/0a795b40-36a6-c0c6-42f5-8280a1f669b2.jpeg)


|項目|入力|
|---|---|
|タイプ|カスタム|
|Extension ID|リバースドメイン形式で。ハンズオン資料では、com.[あなたの氏名].uranai みたいな指示があった気がします。考えるの面倒ならそうしておいて大丈夫。なはず|
|スキル名|サンプル占い Clova スキル|
|スキル名(メイン)|サンプル占い|
|スキル名(サブ)|さんぷる占い<br />サンプル占いを<br />さんぷる占いを|
|提供者について|よき感じに入力してください。ただし、Extensionと連携するLINEのアカウント には [前回](https://qiita.com/TakeshiSaito/items/7b55aaf963f9228d6945) 作成した サンプル占い Bot ちゃんを指定で！|

**スキル名(メイン、サブ)は実際に Clova にスキルの起動を依頼するためのキーワードです。**
**いくつかパターンを登録しているのは環境によって聞き取った文章が違ったりするのである程度のユレを吸収するためのものになっています。**
**動作確認時に影響するので上記の通りに設定してください。**

下２つの規約に同意したらチェック入れて 作成 をクリック

サーバー設定は後回しにするので、ここで画面上の スキル設定 をクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/306e7c1c-f00b-b78a-f31e-f8ad18af3abb.png)

そうすると出来立てほやほやのスキルが表示されているので 対話モデル 列の 修正 をクリック

![line_dev_6.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/fddabe6b-93f1-ca74-0722-01c115502101.jpeg)

### 対話モデルを作る
こんな画面が別ウィンドウで表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/362af7ec-bf38-527f-e3b2-37f88273dc13.png)

ここでは対話モデルっちゅうものの設定を行います。
大きく分けてインテント、スロット、スロットタイプで構成されていて、これらをこれから定義していきます。
それぞれの説明も書こうかと思いましたが日本語がうまくなかったのでやめておきます。

インテント > スロット > スロットタイプ という感じなので枝葉の スロットタイプ から作っていきましょう。

カスタムスロットタイプ の右の + をクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/2bd0b90b-4b3b-72ab-a3d5-72a2232534f5.png)

スロットタイプのタイトル はお馴染みの `zodiac_signs` です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/9e455378-a851-1f35-87a8-3ac8445cd3cd.png)

最初にハンズオンで見たときから星座って意味なんやろなぁ。と思っていたのですが
Google 翻訳すると 十二支のサイン ってでてきますね。
十二支って世界共通で 子丑虎・・・ のあれなんですかね。

作成 をクリックしてください。

どんどん代表後を登録しましょう。

> zodiac_signs(星座) って言うけどさ。Clova 何て聞こえたら 星座だ！って思えばいいわけ？

という Clova ちゃんからの至極まっとうな疑問に答える設定です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/fa7420c6-8bae-28f0-0737-540b441d240b.png)

同義語を設定しておくと、"双子座" と聞こえたら zodiac_signs = 双子座、"ふたご座" と聞こえても zodiac_signs = 双子座
みたいになります。同じ意味の単語なら同じ値でプログラム側は受け取りたいですもんね。

入力したら右上の 保存 をクリックするのを忘れずに

スロットタイプの登録が終わったら カスタム インテント 右の + をクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/5b4fd57d-ebc6-7b36-cbe6-40867267833b.png)

インテント名もお馴染みの `FortuneIntent` です。
フォーチューンは jojo で見た気がする。運勢って意味でしょう。疑う余地はありません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/18bdc5df-ba1c-fb07-218b-e7e6d5f45846.png)

入力したら 作成 をクリック

まずは、スロットを登録しましょう。下の部分です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/c0977d90-b84d-af48-f486-fdd6b4986229.png)

スロット名は `zodiac_signs` スロットタイプ には先ほど作った `zodiac_signs` を指定します。

少し上に戻ってサンプル発話を登録します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/56994c36-1e96-a02a-b007-b66e8488c0ff.png)

こんな感じ。そしたら 星座 の部分を選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/18425444-3665-a12a-9c2f-c48447e45e1b.png)

すると、こんな感じ。この文章の中でこの部分が星座に該当するよ。って印をつけます。
選択後はこんな感じ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/f6566247-5dc7-dc45-573d-12fbf6a628eb.png)

発話リストもどんどん登録するべし

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/459efcea-aac2-9b3b-827c-b7262902f03d.png)

> いや、星座が何なのかは大体わかったけどさ。そもそも運勢知りたい時 Clova に何て話しかけるの？

という Clova ちゃんの質問に解をあげましょう。

> そんな感じなんだ。ちなみに、この文章の中で星座ってどこのことなの？

にも答えを教えてあげます。

OK ここまで来たら、忘れずに右上の 保存 をクリック、立て続けに左上の ビルド もクリック
そうするとグルグルとお勉強が始まります。

## Python でスキルのプログラムを作る
次はプログラムの作成になるので PyCharm に戻ります。

uranai プロジェクトを [前々回](https://qiita.com/TakeshiSaito/items/7d6874363427e5deb609) 作ったんでした。
さらに
[前回](https://qiita.com/TakeshiSaito/items/7b55aaf963f9228d6945) Bot 作ったんでした。

最終的にこんな構成になってましたね

![pycharm_16.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/ce3567ae-a255-59bb-f96a-3f1bf863695a.jpeg)

では、同じような感じで clova packeage を作って `urls.py` と `views.py` もその下に作りましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/4e774ef5-e0bb-fc6e-e965-1deca1f92ad9.png)

こんな構成になっていれば大丈夫、で中身は下の通り、はっつけてください。

```python:clova\urls.py
from django.conf.urls import url
from clova import views

urlpatterns = [
    url(r'^webhook$', views.webhook, name='webhook'),
]

```

```python:clova\views.py
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

import json

from cek import (Clova, SpeechBuilder, ResponseBuilder,)

from linebot import LineBotApi, WebhookHandler
from linebot.models import TextSendMessage

clova = Clova(application_id='Extension ID', default_language='ja')

line_bot_api = LineBotApi(
    'Bot アクセストークン(ロングターム)'
)


@csrf_exempt
def webhook(request):
    request.META['SIGNATURECEK'] = request.META['HTTP_SIGNATURECEK']

    body_dict = clova.route(body=request.body, header=request.META)

    response = HttpResponse(json.dumps(body_dict), content_type='application/json; charset=UTF-8', status=200)

    return response


@clova.handle.launch
def launch_request_handler(clova_request):
    return clova.response('サンプル占いスキルを起動します。')


@clova.handle.default
def default_handler(clova_request):
    return clova.response('もう一度お願いします')


@clova.handle.intent('FortuneIntent')
def fortune_intent_handler(clova_request):
    zodiac_signs = clova_request.slot_value('zodiac_signs')

    if zodiac_signs is not None:
        if zodiac_signs == '双子座':
            response = clova.response('双子座の運勢は１２位です')
            line_bot_api.push_message(clova_request.user_id, TextSendMessage('双子座の運勢は１２位です'))
        elif zodiac_signs == '牡牛座':
            response = clova.response('牡牛座の運勢は１１位です')
            line_bot_api.push_message(clova_request.user_id, TextSendMessage('牡牛座の運勢は１１位です'))
        elif zodiac_signs == '牡羊座':
            response = clova.response('牡羊座の運勢は１０位です')
            line_bot_api.push_message(clova_request.user_id, TextSendMessage('牡羊座の運勢は１０位です'))
        else:
            response = clova.response('その星座は対応してないです')
    else:
        response = clova.response('星座がわかりませんでした。もう一度お願いします')

    return response


if __name__ == '__main__':
    pass
```

そしたら書き換えるところあるので修正していきましょう。

> clova の URL を追加
> 
> ```python:config\urls.py
> from django.contrib import admin
> # , include を追加
> from django.urls import path, include
> 
> urlpatterns = [
>     path('admin/', admin.site.urls),
>     path('bot/', include(('bot.urls', 'bot'),)),
>     # 追加
>     path('clova/', include(('clova.urls', 'clova'), )),
> ]
> ```

> Extension ID と アクセストークン を変更、前者は Clova Developer Center で設定したやつ、後者は LINE Developers の サンプル占いにあったやつ
> 
> ```python:clova\views.py
> 
> # ... 略
> 
> clova = Clova(application_id='Extension ID', default_language='ja')
> speech_builder = SpeechBuilder(default_language='ja')
> response_builder = ResponseBuilder(default_language='ja')
> 
> line_bot_api = LineBotApi(
>     'アクセストークン(ロングターム)'
> )
> 
> # ... 略
> 
> ```
>
> これ
> ![line_dev_7.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/41045f0a-3a24-f36f-2f70-d6589b39a082.jpeg)
> と、これ
> ![line_dev_5.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/903f1403-f1e4-bebe-bab8-9766b7499e98.jpeg)

### ExtensionサーバーのURL の設定
Clova Developer Center サンプル占い Clova スキル で サーバー設定 を開きここを更新しましょう。
URL は `ngrok の URL/clova/webhook` です

![line_dev_8.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/c85db6bf-e9bb-a529-0387-0fbe68a78fa3.jpeg)

config\urls.py と clova\urls.py に定義したやつですね。
入力したら画面下の 保存 をクリック

### Django を起動
Django の起動はこんな感じにするんでした。

> 右上で uranai が選択されていればいい感じ。
> ついでに一度 起動してみましょう。
> uranai の右側にある再生(三角)をクリック
> 
> ![pycharm_14.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/d61c1d09-607e-c1bc-7b0e-0e7ecb547bf1.jpeg)

## いざ動作確認
- Extension ID、アクセストークン は `clova\views.py` に設定しましたか？
- ExtensionサーバーのURL は サンプル占い Clova スキル に設定しましたか？
- ngrok は起動していますか？
- Django は起動していますか？
- Bot と別日に作った場合、ngrok は再起動していませんか？ngrok を再起動すると URL が変わるので、[前回](https://qiita.com/TakeshiSaito/items/7b55aaf963f9228d6945) の **Webhook URL の設定** を見直す必要があります。

では、Clova に話しかけてみましょう。

私)クローバ
Clova)ポンッ
私)サンプル占いを起動して
Clova)サンプル占いスキルを起動します
私)双子座の運勢を教えて
Clova)双子座の運勢は１２位です

ってなればイケテル！

で、スマホを見ると

![WIN_20180919_21_59_16_Pro.jpg](https://qiita-image-store.s3.amazonaws.com/0/276015/9061aa9f-e7a2-1a88-981b-ceb2426e3e0c.jpeg)

って感じで占いの結果を文字でもお知らせ。そういう寸法

# お疲れさまでした
これで、Python Django の環境で LINE Bot Clova スキルを作成し、その２つを連携することに成功しました。

この記事はチュートリアルとして進めてきたのですが、実は若干の問題提起も含んでいます。

それは
![owari.png](https://qiita-image-store.s3.amazonaws.com/0/276015/13c75956-f824-7c15-c417-4da6420e3bc8.png)
ここだよ！

clova-cek-sdk の中で META、ようは Header 情報から 'signaturecek' というキーで何らかの値を取り出してるんです。
signature って書いてあるから予想はつくけど。

なんですが Django には
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276015/d08b940a-587e-9e9d-f8fa-ab88130513ed.png)
[Django ドキュメント](https://docs.djangoproject.com/en/2.1/ref/request-response/)
こんな仕様がございまして clova-cek-sdk が 'signaturecek' ナイからエラーな！って言ってきます。

いやはやまさしくそのキーはナイので正常な動きだし
Web フレームワークはすごい多くて全部の違いを完全に吸収するのは無理だよ。
っていうのは分かる。本当に分かる。
でも、Header 書き換えたくないので何とか SDK 側で 'signaturecek' or 'http_signaturecek' から
値をとるようにしてもらえないだろうか。という話し。

どこにこの相談をするかは検討中、いったんまとめたから現状の話しはこれでできるはず。

# 2018/9/26 追記
上記の課題について LINE developers community に質問を投稿しました。
回答をいただけたら内容を追記する予定です。

準備はこちら
**[LINE Bot + Clova スキル開発 Python Django チュートリアル(準備編)](https://qiita.com/TakeshiSaito/items/7d6874363427e5deb609)**

Bot 開発はこちら
**[LINE Bot + Clova スキル開発 Python Django チュートリアル(LINE Bot 開発編)](https://qiita.com/TakeshiSaito/items/7b55aaf963f9228d6945)**