6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

呉高専エンジニア勉強会Advent Calendar 2017

Day 1

おにぎりくんbotの誕生、繁栄、そして死

Last updated at Posted at 2017-12-01

この記事は呉高専エンジニア勉強会 Advent Calendar 2017 1日目の記事になります。

🍙🍙🍙🍙🍙🍙🍙🍙🍙🍙🍙🍙🍙🍙🍙🍙🍘🍙🍙🍙🍙

こんにちは、ちゃんゆーです。

趣味の延長で友人とローカルなコミュニティラジオをPodcastで配信しています。
準備をTrelloでタスク管理しながら進めていくなかで、TrelloのカードをLINEで通知してくれたら便利だなーと思ったので、そんなおにぎりくんbotを作って壊した話です。

何を作ったのか

Trelloでカードが移動したらLINEに通知してくれるbot。

image.png

おにぎりくんと呼ばれています。

なぜ作ったのか

そもそもなぜLINEなのか

Slack使えば一瞬で作れますというか、ノンプログラミングで設定できますが、いかんせんSlackは特に情報系に疎い学生には敷居が高いのでした。(経験談)
Notificationナニソレ? と言われてひとつづつ使い方教えるのも骨が折れるのです。

そうしてLINEでやり取りして開発やラジオの収録を行うことになったのでした。

IFTTT時代

最初はIFTTT連携してLINE Notifyが教えてくれていました。

image.png

でもラグがひどくてつらかったのです。

おにぎりくんの誕生

そこで自作bot製作に踏み切りました。

image.png

こうしてTrelloのカードが移動する度におにぎりくんが教えてくれるようになりました。

どうやって作ったのか

僕はPythonしか書けないので、PythonのDjangoでサクッと組みました。
コードはGitHubにあげています。

ざっくりこんな感じになりました。

trello/views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

import json
import requests
import os

from line.views import push_message

REPLY_ENDPOINT = 'https://api.line.me/v2/bot/message/reply'
ACCESS_TOKEN = os.getenv('LINE_ACCESS_TOKEN')
LINE_USERID = os.getenv('LINE_USERID')
LINE_GROUPID = os.getenv('LINE_GROUPID')
HEADER = {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + ACCESS_TOKEN
}

def index(request):
    return HttpResponse("Hello World")

@csrf_exempt
def callback(request):
    try:
        action = json.loads(request.body.decode('utf-8'))['action']
        from pprint import pprint
        pprint(action)
        entities = action['display']['entities']
        action_type = action['display']['translationKey']
        if action_type == 'action_create_card':
            list_name = entities['list']['text']
            card_name = entities['card']['text']
            member_name = entities['memberCreator']['text']
            body = f'カード「{card_name}」がリスト「{list_name}」に追加されました。\n追加者:{member_name}'
            push_message(LINE_GROUPID, body)
        elif action_type == 'action_move_card_from_list_to_list':
            after_list_name = entities['listAfter']['text']
            before_list_name = entities['listBefore']['text']
            card_name = entities['card']['text']
            member_name = entities['memberCreator']['text']
            body = f'カード「{card_name}」がリスト「{before_list_name}」からリスト「{after_list_name}」に移動されました。\n移動者:{member_name}'
            push_message(LINE_GROUPID, body)
    except Exception as e:
        pass
    return HttpResponse("callback")

line/views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

import json
import requests
import os

REPLY_ENDPOINT = 'https://api.line.me/v2/bot/message/reply'
PUSH_ENDPOINT = 'https://api.line.me/v2/bot/message/push'
ACCESS_TOKEN = os.getenv('LINE_ACCESS_TOKEN')
HEADER = {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + ACCESS_TOKEN
}

def index(request):
    return HttpResponse("Hello World")

@csrf_exempt
def callback(request):
    events = json.loads(request.body.decode('utf-8'))['events']
    for event in events:
        reply_token = event['replyToken']
        if event['type'] == 'message':
            if event['message']['type'] == 'text':
                if 'debug' in event['message']['text']:
                    reply = event['message']['text']
                    reply += get_line_ids(event['source'])
                    reply_message(reply_token, reply)
                elif 'おにぎり' in event['message']['text']:
                    reply = 'おにぎりくんだよ。呼んだ?'
                    reply_message(reply_token, reply)
                else:
                    pass
            else:
                 pass
        else:
            pass
    return HttpResponse("callback")

def get_line_ids(source):
    reply = ''
    if 'userId' in source:
        reply += '\nuserId:' + source['userId']
    if 'groupId' in source:
        reply += '\ngroupId:' + source['groupId']
    if 'roomId' in source:
        reply += '\nroomId:' + source['roomId']
    return reply


def reply_message(reply_token, reply):
    reply_body = {
        "replyToken":reply_token,
        "messages":[
            {
                "type": "text",
                "text": reply
            }
        ]
    }
    requests.post(REPLY_ENDPOINT, headers=HEADER, data=json.dumps(reply_body))

def push_message(to, message):
    push_body = {
        "to": to,
        "messages":[
            {
                "type": "text",
                "text": message
            }
        ]
    }
    requests.post(PUSH_ENDPOINT, headers=HEADER, data=json.dumps(push_body))
    

改良の余地が大いにあるコードたちです。

おにぎりくんの定着

コードを見ての通り、LINEのトーク内で おにぎりが含まれた発言をすると、おにぎりくんが反応してくれます。

image.png

おぎにりはダメでした。

稼働後のおにぎりくん

その後、おにぎりくんは死亡、その後蘇生することで復活し、さらにはゾンビ化した挙句、巨人に取って代わられたのでした。
詳細についてはまた書きますね。

駄文失礼いたしました。

6
1
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
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?