6
2

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.

ApexLegendsの戦績をLINEで検索したい

Last updated at Posted at 2021-02-27

したいこと

大人気のバトルロワイヤルfps、「ApexLegends」の戦績を気軽に検索したいのでLINEで教えてもらえるようにしたい.

できたこと

公式アカウントにコマンドを送るとほしい情報を返信してくれる.
よかったら追加して試してみてください(無料会員なので仮に月1000回送信しちゃったら多分止まります)
https://lin.ee/corhpIr
line.png

#追記
2021/04-05に追記しました。

コマンドの紹介(v1.2現在)

基本は "!"から始める.
! [プラットフォーム(origin or psn or xbl)] [プレイヤーネーム] [コマンド]

この時プラットフォームはそれぞれ、[o][p][x]と省略することができるようになりました。

それぞれの間は半角空白
使えるコマンド

  • kill :キル数
  • rank :ランク(ダイヤとか)
  • rankscore :ランクのスコア
  • id :ID(ほとんどはそのままだけどsteam とかで変えてるときはoriginのID?)
  • level :レベル.ゲーム内では500までしか表示されないけどそれ以上でも表示される
  • s[n]k: Season[n]の時のキル数
  • s[n]w: Season[n]の時の勝利数

実装するために

大まかですが利用したサービス、方法を紹介します.
Heroku:ここにコードをデプロイして自動化させていただいてます.
LINE Developper:公式アカウントの設立やWebhookの設定など

実際の動作

利用者:コマンド送信 ----> えーぺっくすとらっかー:コマンド受信
LINEのWebhook:受け取ったテキストを送信 -----> Heroku:テキストを受信してプログラム実行
Heroku:実行結果をLINEに送信 ----> LINE:受け取ったテキストを利用者に返信

大体のイメージに過ぎないですがこんな感じで動いてると思います.

LINE Developper

これで公式ラインの作成設定をしました.
やり方などは多くの方が記事にしているのでそちらをご覧ください.

Heroku

これも同様に僕よりもっとわかりやすく解説してある記事があるのでそちらをどうぞ

ここで僕なりの注意点ですが、後述するオウム返しするコードだけコピペしてからHerokuにデプロイやアプリ作成をしたほうが無難です.
私はコードができる前にいろいろといじったた何回デプロイしても動かなくなってしまいました.(たぶん余計なファイルもデプロイしてしまった.)

#オウム返ししよう
では実際に書いてみましょう.とはいっても僕もすべて理解しているわけではありません.というかほとんど理解してないです.

必要なライブラリのインストール

このプログラムでは以下のライブラリが必要になります.pipでインストールしましょう.

pip install flask
pip install line-bot-sdk

main.pyをつくろう

main.py
from flask import Flask, request, abort
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)
import os

app = Flask(__name__)

#herokuの環境変数に設定された、LINE DevelopersのアクセストークンとChannelSecretを
#取得するコード
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]
line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)

@app.route("/callback", methods=['POST'])
def callback():
    # リクエストヘッダーから署名検証のための値を取得
    signature = request.headers['X-Line-Signature']

    # リクエストボディを取得
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # 署名を検証し、問題なければhandleに定義されている関数を呼ぶ
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'


#以下でWebhookから送られてきたイベントをどのように処理するかを記述する
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))

# ポート番号の設定
if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)

Herokuの設定

ここからはHerokuというサービスを利用するためのあれこれをします.
まずはHeroku CLIをDLしましょう.
Heroku
ここでアカウント作成もしておきます.

さらにgitも必要です
git-download
それぞれのインストールはそのまま進めばオッケーです

ここまで長かったですが次からHerokuでの作業です

Herokuでの作業

Herokuは簡単に言うとサーバーみたいな感じです.情報を受け取ったり送信したりしてくれます.そのために自分のアプリを開設したり、書いたコードを実装したりします.
まずはログインです.

gitbash
heroku login

ブラウザが開いてログインする?みたいな確認が出るのでそのまま進めましょう.出来たらgit bashに戻ります.

Herokuでのアプリを作成します.[app]はお好きに

heroku create [app]

初期化します(必ず開発してるディレクトリに移動してから行ってください)

git init

Herokuのアプリとgitを紐付けます

heroku git:remote -a [app]

herokuの環境変数にLINE Developperのトークンとapiを登録します

heroku config:set YOUR_CHANNEL_ACCESS_TOKEN="チャネルアクセストークンの文字列" -a [app]

heroku config:set YOUR_CHANNEL_SECRET="チャネルシークレットの文字列" -a [app]

herokuに登録できたか確認

heroku config

Herokuに自分のアプリを登録する際、必要になる Procfie(拡張子は無し)runtime.txt requirements.txt を作成

Procfile
web: python main.py
runtime.txt
python-3.8.0

requirements.txtはターミナルでこれを実行する.

pip freeze > requirements.txt

Herokuへデプロイ

デプロイの流れです.

  • gitの初期化
  • 紐づけ
  • ファイルのadd
  • commit
  • push
git init
heroku git:remote -a testlinebot0319
git add .
git commit -m'[コメント]'
git push heroku master

LINE DeveloperへのWebhook登録

LINE DeveloperのサイトでWebhookの欄をこのように設定します.
https://[app].herokuapp.com/callback

image.png

ちゃんと動く?

ここまで来たらデバッグです.作ったラインアカウントを追加して何か送ってみましょう.オウム返ししてくれたら成功です.

オウム返しから進化しよう

オウム返しできましたかね?
ではここでオウム返し以外もしゃべらせましょう.オウム返しの部分は

line_bot_api.reply_message(event.reply_token,TextSendMessage(text=event.message.text))

というコードの

TextSendMessage(text=event.message.text)

のevent.message.textです.この変数に送信したテキストが格納されているんですね.

これが理解できればあとはこれを利用して作業するだけです.

ApexLegendsの戦績をもってこよう

ここではApexTrackerのAPIを利用します.apiのキーを環境変数で持ってくるのでこうしましょう
image.png
さらに、urlで直接データを持ってくるのでそのurlを作成します.
image.png

このApexのデータを見るコードを貼っておきます.
image.png

Track_Apex.py
import requests, json, os
from pprint import pprint

api = ""
url = "https://public-api.tracker.gg/v2/apex/standard/profile/psn/Hayaa6211"
header = {"TRN-Api-Key":api}

res = requests.get(url, headers=header).json()
pprint(res)

これはjsonでリターンされます.

情報を扱う

正直ApexのAPIは自分で遊ぶのが一番です.
先ほどのresはjsonなので慣れてる方はそのままです.

コマンドの解釈

最初のほうで見せた通りこの公式ラインにコマンドを送ることにより返信してくれます.どうやってそのコマンドを理解してるんですかね
例えば今回は "! origin KNR_ShibuyaHal kill" というコマンドを例にしてみます(渋谷ハルさんごめんなさい)

それぞれの間は半角空白があります.

ということは.split()するとリストになるんですね.わーお
ここまで来たらこっちの勝ちです.

text = [!,"origin","KNR_ShibuyaHal","kill"]

というリストになりました.あとはここからそれぞれの条件式を書いていけばよいわけです.(数学ヤクザ風)

ではそのコードです

Track()
def Track(text):
    # テキストからリストに
    text = text.split()
    # 引数が足りないとき、エラーになるのでそのためのtry
    try:
        platform = text[1]
        user = text[2]
        what = text[3]
    except:
        return "そのコマンドおかしいで"

    user_url = f"{url}/{platform}/{user}"
    res = requests.get(user_url, headers=head).json()

    if what == "rank":
        res_result = res["data"]["segments"][0]["stats"]["rankScore"]["metadata"]["rankName"]
        return res_result
    elif what == "rankscore":
        res_result = res["data"]["segments"][0]["stats"]["rankScore"]["displayValue"]
        return res_result
    elif what == "id":
        res_result = res["data"]["platformInfo"]["platformUserId"]
        return res_result
    elif what == "level":
        res_result = res["data"]["segments"][0]["stats"]["level"]["displayValue"]
        return res_result
    elif what == "kill":
        res_result = res["data"]["segments"][0]["stats"]["kills"]["displayValue"]
        return res_result
    else:
        res_result = "そんなコマンドないんだよね"
        return res_result

ここは自分の能力不足をひしひしと感じるのですがifの無限は汚いですね.dictとかにしたいんですけど動かなくて絶賛なえてます.

おわり

終わりです.Herokuにデプロイして終わらせましょう.最後にコード全部載せておきますね.

コード全体

main.py
import os
import sys
import json
import requests
from argparse import ArgumentParser

from flask import Flask, request, abort
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

app = Flask(__name__)

Tracker_api = os.getenv('Tracker_API',None)
channel_secret = os.getenv('LINE_CHANNEL_SECRET', None)
channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None)
if channel_secret is None:
    print('Specify LINE_CHANNEL_SECRET as environment variable.')
    sys.exit(1)
if channel_access_token is None:
    print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
    sys.exit(1)


url = "https://public-api.tracker.gg/v2/apex/standard/profile"
line_bot_api = LineBotApi(channel_access_token)
handler = WebhookHandler(channel_secret)
head = {"TRN-Api-Key":Tracker_api}


@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=TextMessage)
def message_text(event):
    if event.message.text[:1] == "!":
        res_result = Track(event.message.text)
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text=res_result))
    elif event.message.text[:1] == "?":
        res_result = Neta(event.message.text)
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text=res_result))
    else:
        pass

def Track(text):
    text = text.split()
    try:
        platform = text[1]
        user = text[2]
        what = text[3]
    except:
        return "そのコマンドおかしいで"

    user_url = f"{url}/{platform}/{user}"
    res = requests.get(user_url, headers=head).json()
    #変更するところ

    if what == "rank":
        res_result = res["data"]["segments"][0]["stats"]["rankScore"]["metadata"]["rankName"]
    elif what == "rankscore":
        res_result = res["data"]["segments"][0]["stats"]["rankScore"]["displayValue"]
    elif what == "id":
        res_result = res["data"]["platformInfo"]["platformUserId"]
    elif what == "level":
        res_result = res["data"]["segments"][0]["stats"]["level"]["displayValue"]
    elif what == "kill":
        res_result = res["data"]["segments"][0]["stats"]["kills"]["displayValue"]
    else:
        res_result = "そんなコマンドないんだよね"
    return res_result
    
def Neta(text):
    text = text.split()
    what = text[1]

    if what == "help":
        res_result = "! [platform(psn or origin or xbl)] [playerName] [コマンド] です.\nコマンドは現在[rank],[rankScore],[id],[level],[kill],です"
    elif what == "fuck":
        res_result = "ごめんね by黒木ほの香"
    elif what == "ban":
        res_result = "ばいばーい"
    elif what == "ramen":
        res_result = "https://tabelog.com/tokyo/A1303/A130301/13069220/"
    return res_result



if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)

GitHub

絶賛改良中で日々変わってるので新しいこととか追加したときはこっちのコードが最新です.
頑張ってQiitaも更新しますが忘れてる可能性大です.
GitHub-Hayaa6211

あとがき

僕にとって二つ目の作品となったこれ.実力とセンスがなさ過ぎて何回見ても汚いし修正しにくいコードですね....うーん
これからはこのbotの修正、改良をしつつコーディング力の向上を目指したいと思います.
ここまでご視聴いただきありがとうございました.ノシノシ

参考にさせていただいた記事(というかまんまパクリ)

https://qiita.com/kaonashikun/items/8004dfc9deea6c25754b
https://qiita.com/hayapo/items/2ade5e149f98ec19afc1

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?