LoginSignup
38
37

More than 5 years have passed since last update.

LineBotで愛犬「もなかBot」を作ってみた

Last updated at Posted at 2016-04-08

Screenshot_20160408-151644.png

LineBotやってみました。
お金が惜しいのでGAEで構築しました。
JavaはしんどいのでPython/Flask使いました。

GCPでプロジェクト生成

はじめての方は、ぐぐると出てきます。

app.yamlの準備

ソースはこんな感じ。

app.yaml
runtime: python27
api_version: 1
threadsafe: yes

- url: .*  # This regex directs all routes to main.app
  script: main.app

libraries:
- name: ssl
  version: latest

最初、sslのライブラリを追加してなくて嵌まりました。

callbackの実装

ユーザーがBotに対して喋ったりすると、callbackで指定したAPIが呼ばれます。
callbackの中でLineのAPI呼んでテキストや写真を送る感じです。
callbackの設定などはマニュアルや他のqiitaをご参照ください。

ソースはこんな感じ。

main.py
# -*- coding: utf-8 -*-

import logging, random
import requests

from flask import Flask, request,Response

app = Flask(__name__)
app.config.from_object(__name__)
app.logger.setLevel(logging.DEBUG)

LINE_ENDPOINT = "https://trialbot-api.line.me"
HEADERS = {
    "X-Line-ChannelID": "<BasincInformation参照>",
    "X-Line-ChannelSecret": "<BasincInformation参照>",
    "X-Line-Trusted-User-With-ACL": "<BasincInformation参照>"
}

# 固定で返すメッセージ群
TALKS = [
    "わんわん!ごはんよこせ!!",
    "うんこ・・・したい・・・・",
    "しっこ!しっこ!",
    "飼い主どこ行ったのかな",
    "しのとも〜〜〜",
    "んぐ〜んぐ〜〜",
    "へっへっへっへっへっへっ",
    "Uo・ェ・oU",
    "ペロペロペロペロ",
    "かいぬしの手をペロペロしたいなぁ",
    "ごはん落ちてないかな",
    "すやすやすやすや",
    "おらおらー!",
    "ダンス!ダンスダンス!!"
]

# 画像群
IMAGES = [
    {"origin": "https://storage.googleapis.com/linebot-1275.appspot.com/monaka1.jpg",
     "thumb": "https://storage.googleapis.com/linebot-1275.appspot.com/monaka1thum.jpg"}
]


@app.route("/")
def hello():
    return "line bot api"


@app.route("/callback", methods=["POST"])
def callback():
    # TODO Signature validation

    app.logger.info(request.json)
    app.logger.info(request.headers)
    req = request.json["result"][0]

    if req["eventType"] == "138311609100106403":
        """
        友だち申請の受信はここに来る。
        申請されたらすぐお礼メッセージを送る。
        TODO 未検証
        """

        send_text([req["from"]], u"もなかだよ。友だち申請ありがとわん。")

    elif req["eventType"] == "138311609000106303":
        """
        会話メッセージを受信したらここに来る。
        「もなか」と声をかけると写真とメッセージを返す。
        それ以外は準備したテキストをランダムで返す。
        """

        to = [req["content"]["from"]]
        if req["content"]["text"] == u"もなか":
            # 写真送付
            i = random.randint(0, len(IMAGES) - 1)
            send_picture(to, IMAGES[i])
            send_text(to, "よんだー?")
        else:
            # メッセージ送信
            i = random.randint(0, len(TALKS) - 1)
            send_text(to, TALKS[i])

    # 戻り値は200固定
    return Response(status=200)


def send_text(to, text):
    """
    toに対してテキストを送る
    """
    content = {
        "contentType": 1,
        "toType": 1,
        "text": text
    }
    events(to, content)


def send_picture(to, img):
    """
    toに対して画像を送る
    """
    content = {
        "contentType": 2,
        "toType": 1,
        "originalContentUrl": img["origin"],
        "previewImageUrl": img["thumb"]
    }
    events(to, content)


def events(to, content):
    """
    toに対してデータ(テキスト・画像・動画)を送る
    """
    app.logger.info(content)
    data = {
        "to": to,
        "toChannel": "1383378250",
        "eventType": "138311608800106203",
        "content": content
    }
    r = requests.post(LINE_ENDPOINT + "/v1/events", json=data, headers=HEADERS)
    app.logger.info(r.text)

staticIPAddressの設定

サーバーがホワイトリスト制になっているので、IPAddressを設定しないとLineのサーバーはエラーを返します。しかしGAEなので固定IPAddressはありません。
試しにアクセスしたら 403 エラーになり、以下のメッセージが表示されました。

{"statusCode":"427","statusMessage":"Your ip address [107.178.194.118] is not allowed to access this API."}

というわけで、このIPAddressを追加して動かすと

{"statusCode":"427","statusMessage":"Your ip address [107.178.194.122, 10.128.141.149] is not allowed to access this API."}

次は内部IPAddressらしきものも設定しろよと出てきたので素直に設定します。

これで動きました。いつかIPAddressが変わって動かなくなる可能性が高いです。解決方法は未来の僕に委ねたいと思います。

フレンド申請する

QRコードから出来るようです。(分からなくてずっと苦しんだ)
今回の僕の愛犬「もなかBot」は

rjs9046g.png

から追加できます。

38
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
37