#はじめに
PFでジャニーズの私物を特定して、すぐに購入できるサービスを作成したのでまとめます。
あまりにも長くなりそうなので、今回はLINE Messaging API
を使用した部分についてまとめます。
❶はこちらです。
#サービスの概要
ジャニーズファンは推しと同じものを日常生活やライブで身につけたいという心理があります。
twitte上にファンの人が私物を特定してツイートをするので、そのツイートをキャッチして、LINEで通知・購入できるサービスになっています。
#なぜこのサービスを作成したか
私物の特定のツイートがされるとすぐファンが購入し、売り切れてしまうことがよくあります。
私自身、私物特定のツイートを発見し、サイトを検索してももう売り切れてしまっていたということが何回もあります。
他のファンよりも早く購入できるサービスがあればいいなと思い、このサービスを作成しました。
##完成したサービス
Webサイトは以下になります↓
LINEのQRコードになります。
ぜひ動かしてみてください!!
サービスのイメージがしづらいと思いますがこんな流れになります
1.Twitterで私服特定ツイートがされます。
LINE友達登録後できること
1.最新の情報を確認できます。
リッチメニュー右上の最新の情報ボタン
を押す→情報を確認したいメンバーを選択
する→最新の情報
が表示される
2.情報を受け取るメンバーを選択できます。
リッチメニュー左上のメンバー設定を変更する
を選択する→設定したいメンバーを選択
する→通知を受け取る
か、受け取らない
かを選択する
もちろん、現在の通知設定についてもリッチメニュー左下のメンバー設定を確認する
から確認可能です。
##使用した機能
Twitter API
LINE Messaging API
dotenv-rails'
config gem
ransack gem
sorcery gem
kaminari gem
enum_help gem
rails-i18n gem
AWS
heroku
##画面遷移図
##LINE Messaging API
「LINE BOT」とは、メッセージアプリのLINEを使用して、ユーザーの質問に自動で返答できたり、メッセージを送信できたりするプログラムのことです。
仕組みについてはこちら↓
Messaging APIを使って、ボットサーバーとLINEプラットフォームの間でデータを交換できます。リクエストは、JSON形式でHTTPSを使って送信されます。
1.ユーザーが、LINE公式アカウントにメッセージを送信します。
2.LINEプラットフォームからボットサーバーのWebhook URLに、Webhookイベントが送信されます。
3.Webhookイベントに応じて、ボットサーバーからユーザーにLINEプラットフォームを介して応答します
###今回の目標
・LINEbotは一つで6人分の情報を送信したい
・友達登録してくれたユーザーが自分で受け取るメンバーを選択できるようにしたい
・メンバー設定等はLINE画面で、全てこなせるようにしたい
###完成系
受信するメンバー設定をLINE画面からできるようにする。
リッチメニュー左上のメンバー設定を変更する
を選択する→設定したいメンバーを選択
する→通知を受け取る
か、受け取らない
かを選択する。
###流れ
1.リッチメニューを押したときにレスポンスボディに指定するdata
を含ませる
2.data
の内容を判断させ、処理を行う
####1.リッチメニューを押したときにレスポンスボディに指定するdata
を含ませる
#####リッチメニューのメンバー設定を変更する
ボタンを押すと、data
にset_member
が含まれているようにする
以下のような形で設定しておく。ここの部分については前回の記事でまとめたので省略します。
"action": {
"type": "postback",
"data": "set_member"
}
####2.data
の内容を判断させ、処理を行う
#####data
にset_member
が含まれていた際に、指定したmessage
が返答されるようにする。ここで作成するmessage
はユーザーが選択できる形に設定し、data
にメンバーを判別できる文字を含ませておく。
ここの部分を作成しています。
def line_responce
#LINE Messaging API認証
line_client ||= Line::Bot::Client.new { |config|
config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
}
body = request.body.read
signature = request.env['HTTP_X_LINE_SIGNATURE']
unless line_client.validate_signature(body, signature)
error 400 do 'Bad Request' end
end
#request.bodyを解析する
events = line_client.parse_events_from(body)
events.each do |event|
#user_id取得
userId = event['source']['userId']
data = event['postback']['data']
if data == "start"
LineUser.start(userId)
#dataにset_memberが含まれていたら
elsif data == ("set_member")
LineUser.set_member(userId)
elsif data.include?("_info")
LineUser.settei_member(data, userId)
elsif data.include?("on_")
LineUser.on_info(data, userId,)
elsif data.include?("off_")
LineUser.off_info(data, userId)
end
end
end
head :ok
end
#メンバー別に通知を設定(メンバー指定部分)
def self.set_member(user_id)
message =
{
"type": "flex",
"altText": "メンバー設定",
"contents": {
"type": "bubble",
"body": {
"type": "box",
"layout": "vertical",
"spacing": "sm",
"contents": [
{
"type": "text",
"wrap": true,
"weight": "bold",
"size": "xl",
"text": "メンバー設定"
},
{
"type": "text",
"text": "通知を受け取るメンバーを設定します。",
"color": "#aaaaaa",
"size": "sm",
"flex": 12
},
{
"type": "text",
"text": "設定したいメンバーを選択してください。",
"color": "#aaaaaa",
"size": "sm",
"flex": 12
}
]
},
"footer": {
"type": "box",
"layout": "vertical",
"spacing": "sm",
"contents": [
{
"type": "button",
"style": "link",
"height": "sm",
"action": {
"type": "postback",
"label": "高地優吾さん",
"displayText": "高地優吾さんの情報について設定する",
"data": "yugo_info"
}
},
{
"type": "button",
"style": "link",
"height": "sm",
"action": {
"type": "postback",
"label": "京本大我さん",
"displayText": "京本大我さんの情報について設定する",
"data": "taiga_info"
}
},
#長いので省略
]
}
}
}
client.push_message(user_id, message)
end
"data": "yugo_info"
や"data": "taiga_info"
をそれぞれ設定する。
#####上で返信したmessage
をユーザーがタッチすると、またdata
がレスポンスボディとして戻ってくるので、data
の内容を判断し、どのメンバーを設定するのか判断する。
今回返信するmessage
はユーザーが通知を受け取る
か受け取らないか
を選択できる形に設定し、on
とoff
を判別できる文字を含ませておく。
data": "メンバー名_info
の形で作成しているので、以下のように判断させる。
def line_responce
#省略
events = line_client.parse_events_from(body)
events.each do |event|
#省略
#今回はここの部分
#dataに_infoが含まれていたら
elsif data.include?("_info")
LineUser.settei_member(data, userId)
end
end
head :ok
end
dataの部分も引数で受け取り、名前を判断しています。
def self.settei_member(data, user_id)
data_member_check(data)
#dateのメンバー名の部分のみ抜き出し
data.slice!(-5,5)
message =
{
"type": "flex",
"altText": "メンバー別通知設定",
"contents": {
"type": "bubble",
"body": {
"type": "box",
"layout": "vertical",
"spacing": "sm",
"contents": [
{
"type": "text",
"wrap": true,
"weight": "bold",
"size": "xl",
"text": "通知設定"
},
{
"type": "text",
"text": "#{@name}さんの通知について設定します。",
"color": "#aaaaaa",
"size": "sm",
"flex": 12
},
{
"type": "text",
"text": "複数のメンバーの通知を受け取る場合、",
"color": "#aaaaaa",
"size": "sm",
"flex": 12
},
{
"type": "text",
"text": "それぞれ設定してください。",
"color": "#aaaaaa",
"size": "sm",
"flex": 12
},
{
"type": "text",
"text": "いつでも変更可能です。",
"color": "#aaaaaa",
"size": "sm",
"flex": 12
}
]
},
"footer": {
"type": "box",
"layout": "vertical",
"spacing": "sm",
"contents": [
{
"type": "button",
"style": "link",
"height": "sm",
"action": {
"type": "postback",
"label": "通知を受け取る",
"displayText": "#{@name}さんの情報を受け取る",
"data": "on_#{data}"
}
},
{
"type": "button",
"style": "link",
"height": "sm",
"action": {
"type": "postback",
"label": "通知を受け取らない",
"displayText": "#{@name}さんの情報を受け取らない",
"data": "off_#{data}"
}
}
]
}
}
}
client.push_message(user_id, message)
end
#dataでユーザーを判定する
def self.data_member_check(data)
@name = '高地優吾' if data.include?('yugo')
@name = '京本大我' if data.include?('taiga')
@name = '田中樹' if data.include?('juri')
@name = '松村北斗' if data.include?('hokuto')
@name = 'ジェシー' if data.include?('jess')
@name = '森本慎太郎' if data.include?('shintarou')
end
#####はユーザーが通知を受け取る
か受け取らないか
についてのdata
がレスポンスとして戻ってくるので、処理を行う
def line_responce
#省略
events = line_client.parse_events_from(body)
events.each do |event|
#user_id取得
userId = event['source']['userId']
data = event['postback']['data']
#省略
#今回はここの部分
elsif data.include?("on_")
LineUser.on_info(data, userId,)
elsif data.include?("off_")
LineUser.off_info(data, userId)
end
end
head :ok
end
def self.on_info(data, user_id)
data_member_check(data)
@user = LineUser.find_by(line_user_id: user_id)
if data.include?('yugo')
@user.yugo_on!
elsif data.include?('taiga')
@user.taiga_on!
elsif data.include?('juri')
@user.juri_on!
elsif data.include?('hokuto')
@user.hokuto_on!
elsif data.include?('jess')
@user.jess_on!
elsif data.include?('shintarou')
@user.shintarou_on!
end
message =
{
"type": "flex",
"altText": "メンバー別通知設定",
"contents": {
"type": "bubble",
"body": {
"type": "box",
"layout": "vertical",
"spacing": "sm",
"contents": [
{
"type": "text",
"wrap": true,
"weight": "bold",
"size": "xl",
"text": "通知設定完了"
},
{
"type": "text",
"text": "#{@name}さんの情報について",
"size": "md",
"flex": 12
},
{
"type": "text",
"text": "通知をお送りします。",
"size": "md",
"flex": 12
}
]
}
}
}
client.push_message(user_id, message)
end
offの方は省略します。
以上の流れで実装しました。