4
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 3 years have passed since last update.

【Rails】Twitter APIとLINE APIでジャニーズの私物を特定して、すぐに購入できるサービスを作ってみた!!! PF [LINE API部分❷]

Last updated at Posted at 2021-12-19

#はじめに
PFでジャニーズの私物を特定して、すぐに購入できるサービスを作成したのでまとめます。
あまりにも長くなりそうなので、今回はLINE Messaging APIを使用した部分についてまとめます。
❶はこちらです。

#サービスの概要

ジャニーズファンは推しと同じものを日常生活やライブで身につけたいという心理があります。
twitte上にファンの人が私物を特定してツイートをするので、そのツイートをキャッチして、LINEで通知・購入できるサービスになっています。

#なぜこのサービスを作成したか
私物の特定のツイートがされるとすぐファンが購入し、売り切れてしまうことがよくあります。
私自身、私物特定のツイートを発見し、サイトを検索してももう売り切れてしまっていたということが何回もあります。
他のファンよりも早く購入できるサービスがあればいいなと思い、このサービスを作成しました。

##完成したサービス
Webサイトは以下になります↓

LINEのQRコードになります。
ぜひ動かしてみてください!!
a163e5fa2b2098ef30926fb607faa8ff.png

サービスのイメージがしづらいと思いますがこんな流れになります
1.Twitterで私服特定ツイートがされます。
S__37232668.jpg

2.LINEにこのような通知が届きます。
S__37232670.jpg

3.商品検索ボタンから検索可能です。
S__37232676.jpg

4.To tweetボタンからソース元に遷移可能です。
S__37232678aaa.jpg

LINE友達登録後できること
1.最新の情報を確認できます。
リッチメニュー右上の最新の情報ボタンを押す→情報を確認したいメンバーを選択する→最新の情報が表示される
S__37232679ss.jpg

S__37232680ss.jpg

2.情報を受け取るメンバーを選択できます。
リッチメニュー左上のメンバー設定を変更するを選択する→設定したいメンバーを選択する→通知を受け取るか、受け取らないかを選択する

S__37232682b.jpg S__37232683b.jpg

もちろん、現在の通知設定についてもリッチメニュー左下のメンバー設定を確認する から確認可能です。

S__37232681b.jpg

##使用した機能
Twitter API
LINE Messaging API
dotenv-rails'
config gem
ransack gem
sorcery gem
kaminari gem
enum_help gem
rails-i18n gem
AWS
heroku

##ER図
3917056f5181a1ce73694684e344b358.png

##画面遷移図

d657ee3591bde2b85796fbee48567573.png

##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画面からできるようにする。
リッチメニュー左上のメンバー設定を変更するを選択する→設定したいメンバーを選択する→通知を受け取るか、受け取らないかを選択する。

S__37232682b.jpg S__37232683b.jpg

###流れ
1.リッチメニューを押したときにレスポンスボディに指定するdataを含ませる
2.dataの内容を判断させ、処理を行う

####1.リッチメニューを押したときにレスポンスボディに指定するdataを含ませる

#####リッチメニューのメンバー設定を変更するボタンを押すと、dataset_memberが含まれているようにする

以下のような形で設定しておく。ここの部分については前回の記事でまとめたので省略します。

"action": {
        "type": "postback",
        "data": "set_member"
     }

####2.dataの内容を判断させ、処理を行う

#####dataset_memberが含まれていた際に、指定したmessageが返答されるようにする。ここで作成するmessageはユーザーが選択できる形に設定し、dataにメンバーを判別できる文字を含ませておく。
ここの部分を作成しています。

S__37232682b.jpg
line_users_conrtoller.rb
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
LineUser.rb
#メンバー別に通知を設定(メンバー指定部分)
  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はユーザーが通知を受け取る受け取らないかを選択できる形に設定し、onoffを判別できる文字を含ませておく。

ここの部分を作成しています。
S__37232682b.jpg

data": "メンバー名_infoの形で作成しているので、以下のように判断させる。

line_users_conrtoller.rb
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の部分も引数で受け取り、名前を判断しています。

LineUser.rb
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がレスポンスとして戻ってくるので、処理を行う

ここの部分を作成しています。
S__37232683b.jpg

line_users_conrtoller.rb
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
LineUser.rb
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の方は省略します。

以上の流れで実装しました。

4
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
4
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?