Edited at

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

More than 1 year has passed since last update.

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

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

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

趣味の延長で友人とローカルなコミュニティラジオをPodcastで配信しています。

準備をTrelloでタスク管理しながら進めていくなかで、TrelloのカードをLINEで通知してくれたら便利だなーと思ったので、そんなおにぎりくんbotを作って壊した話です。


何を作ったのか

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

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


なぜ作ったのか


そもそもなぜLINEなのか

Slack使えば一瞬で作れますというか、ノンプログラミングで設定できますが、いかんせんSlackは特に情報系に疎い学生には敷居が高いのでした。(経験談)

Notificationナニソレ? と言われてひとつづつ使い方教えるのも骨が折れるのです。

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


IFTTT時代

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

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


おにぎりくんの誕生

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

こうして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のトーク内で おにぎりが含まれた発言をすると、おにぎりくんが反応してくれます。

おぎにりはダメでした。


稼働後のおにぎりくん

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

詳細についてはまた書きますね。

駄文失礼いたしました。