初版作成 2022.3.24
最終更新 2024.04.01
2 つのことができる (1) push : 投稿する 具体的には https://api.line.me/v2/bot/message/push に 対して json 形式のデータを POST する (2) reply : 投稿されたメッセージを読み取り、応答メッセージを投稿する 具体的には、投稿されたメッセージを受信する url を用意し、 cgi プログラムを配置する。 その url に対して json 形式のデータが POST されてくる。 応答を json 形式で用意し、 https://api.line.me/v2/bot/message/reply に POST する。 必要な json の内容は若干異なるが、 https://api.line.me/v2/bot/message/push に POST しても 投稿に対応して、応答を投稿するという機能は 同じであると思われる。
チュートリアル:#_#link#https://developers.line.biz/ja/docs/messaging-api/line-bot-sdk/#https://developers.line.biz/ja/docs/messaging-api/line-bot-sdk/# - line developer へ登録する(無料) developers.line.biz/ja/ - プロバイダを新規作成 - チャンネルを新規作成 チャンネル名が Line の公式アカウントとなる チャンネルの種類は Messaging API - QR コードを使ってスマホで Line に参加する スマホで Line を起動し、 ホームの 上方の検索窓の右端の [ ] をタップして QR コードを読み取ると、友達追加の画面になり 友達追加をタップする。 その友達のトークルームが見あたらない。 もういちど、QR コードを読み取らせると、その友達のトークルームが 出現する。 - メッセージを送ったらコールされる url を設定する Message API 設定 のタブを押す Webhook URL を入力し更新する(https でないとダメ) Webhook の利用を on にする - 一番下に channel access token がある issue を押してトークンを取得する
- push に必要な情報は以下の 2 つ channel access token (Message API設定のタブの下の方) user id (チャネル基本設定のタブの下の方) push は普通のパソコンからできる。 - reply は投稿データを受信する url が必要 json データが送られてくる。その中に投稿データと replyToken が入っている 応答の投稿には来たデータの中にある replyToken と channel access token が必要
以下の 4 つが考えられる (1) Google google drive に google Apps Script を作成し、 「デプロイする」のボタンを押すと、 そのスクリプトに url が割り当てられ、 POST されたデータを受け取ることができる。 プログラムを変更した場合、デプロイし直す 必要があり、url が変わるので、開発効率が 悪い。 しかし、無料で使える環境の中では 最も優れた環境であると思われる。 (2) lolipop などのレンタルサーバ python でプログラムを書くなら、これが一番やりやすい。 月 400 円~ 700 円程度かかるが、python を使って 開発したいなら、開発効率は高い。 ただし、lolipop ではエラーログを見ることができないので、 開発効率が悪い。 (3) heroku heroku という無料で web アプリを配置できるサービスがあったが、 2022/11/27 で廃止されたらしい。heroku のしくみは以下の通り。 プログラムを手元の PC で作成し、heroku という独自コマンドと git コマンドを利用して、プログラムの作成とアップロードを行う。 この方法は flask を用いたサンプルプログラムが ネットに多数あるが、以下の欠点があり、開発効率が 絶望的に悪い。 > cme.exe において CLI (command line interface) の操作が必要 > git のシステムを理解し、コマンドを使いこなすのは敷居が高い > git でアップロードするのにある程度時間がかかる。 レンタルサーバを用いる方法だと、ssh で接続し、 プログラムを修正してセーブしたら、即実行可能である。 > flask は web サーバーを立てるモジュールである。 heroku の https (443) ポートに来たアクセスを、 ポート番号 5000 に転送し、5000 番で待っている flask サーバ が処理するという方法である。 その概念を理解するのに時間がかかる。 > flask を利用したプログラムはデコレータを利用しており、 非常に難易度が高い。 > heroku は 30 分経つとスリープ状態になるので実用的では ないらしい。 > レンタルサーバで flask で受ける場合 443 ではなく 8080 などの 番号で受けることになる。その場合、SSL のエンコードとデコードを 自力で行う必要があり、証明書の取得など難易度が高い。 (4) 自前のサーバ 自力でサーバを用意し、グローバル IP を取得し、 外部からアクセスできるようにする。 非常に敷居が高いが、スクリプトでエラーが発生したとき、 access_log, error_log を即座に確認できるので 開発効率は最も高いと思われる。
以下のようにすると開発効率が高いと思われる (Windows マシン使用) ・PC 版 Line をインストールし、Line への投稿、確認は PC で行う。 投稿は alt+Enter ではなく Enter でできるようにしておいた方が操作性がよい。 ウィンドウ左下の非常に薄い文字の「設定」をクリック ・Web ブラウザは Line Developer のサイト(投稿を受け取る url の 設定変更に必要)、投稿を受け取る url を常に開いておく。 ・プログラムは Google Apps Script で開発するならブラウザで、 レンタルサーバで python を使うなら、teraterm などで ssh 接続 してプログラミングする。
$ pip3 install line-bot-sdk $ pip3 install requests flask を使う場合、ファイル名を flask.py とすると、 import するときに自分を import しようとして エラーが出るので注意。
プログラムは最もシンプルになる import sys from linebot import LineBotApi from linebot.models import TextSendMessage token = 'トークンの値' user_id = "id の値' lines = "push line bot" messages = TextSendMessage(text=lines) print(messages) line_bot_api = LineBotApi(token) line_bot_api.push_message(user_id, messages=messages)
import requests import json token = "トークンの値" user_id = "id の値" api_url = 'https://api.line.me/v2/bot/message/push' message = "send string" token_dic = {"Content-Type": "application/json", "Authorization": "Bearer " + token} send_dic = {"to": user_id, "messages":[{"type":"text", "text":message}]} send_dic_json = json.dumps(send_dic) requests.post(api_url, headers=token_dic, data=send_dic_json)
画像を push するには、あらかじめどこかの url に 画像をアップロードしておくことが必要。 notify ならローカルの画像ファイルを送信可能 import linebot from linebot import LineBotApi from linebot.models import TextSendMessage from linebot.models import ImageSendMessage token = 'トークン' user_id = 'user id' image_url = "https://xxx.yyy.zzz/dir/fname.jpg" image_message = ImageSendMessage( original_content_url = image_url, preview_image_url = image_url) print(image_message) line_bot_api = LineBotApi(token) line_bot_api.push_message(user_id, messages=image_message)
import requests import json token = 'トークンの値' user_id = 'user id の値' api_url = 'https://api.line.me/v2/bot/message/push' image_url = 'https://xxx.yyy.zzz/dir1/fname.jpg' token_dic = {"Content-Type": "application/json", \ "Authorization": "Bearer " + token} send_dic = {"to": user_id, \ "messages": [ {"type": "image", \ "originalContentUrl": image_url, \ "previewImageUrl": image_url, \ } ] \ } send_dic_json = json.dumps(send_dic) requests.post(api_url, headers=token_dic, data=send_dic_json)
import json import sys import datetime import linebot from linebot import LineBotApi from linebot.models import TextSendMessage from linebot.models import ImageSendMessage token = 'トークン' line_bot_api = LineBotApi(token) data = json.load(sys.stdin) text = data["events"][0]["message"]["text"] replyToken = data["events"][0]["replyToken"] # ファイルに書き出して確認 f = open("json.txt","w") print(json.dumps(data), file = f) f.close() # 応答の例 if text == "t": messages = "reply by text" line_bot_api.reply_message(replyToken, TextSendMessage(text=messages)) elif text == "c": image_url = "https://aaa.bbb.jp/dir/image.jpg" image_message = ImageSendMessage( original_content_url = image_url, preview_image_url = image_url) line_bot_api.reply_message(replyToken, image_message) else: messages = "no action" line_bot_api.reply_message(replyToken, TextSendMessage(text=messages))
import requests import json import sys token = "トークンの内容" url = 'https://api.line.me/v2/bot/message/reply' data = json.load(sys.stdin) text = data["events"][0]["message"]["text"] replyToken = data["events"][0]["replyToken"] # ファイルに書き出して確認 f = open("json.txt","w") print(json.dumps(data), file = f) f.close() # 応答の例 if text == "a": message = "you input a" elif text == "b": message = "you input b" else: message = "you input other" token_dic = {"Content-Type": "application/json", \ "Authorization": "Bearer " + token} send_dic = {"replyToken": replyToken, \ "messages":[{"type":"text", "text": message}]} send_dic_json = json.dumps(send_dic) requests.post(url, headers=token_dic, data=send_dic_json)
(1) line-bot-sdk のインストール 参考サイト https://dattesar.com/lolipop-pip-flask/ - pip3 をインストールする $ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py $ python3 get-pip.py --user - path を通す ~/.bash_profile に以下を記述 PATH=$PATH:/home/users/0/xxxxxxx/.local/bin export PATH $ . ~/.bash_profile - ライブラリのインストール $ pip3 install line-bot-sdk 既にインストールされているライブラリの確認法 $ pip3 freeze - cgi を配置する chmod 755 を忘れずに cgi は www-data ではなく、自分の権限で動作する。 ディレクトリを 777 にするとエラーになるので要注意
○ JavaScript での使い方 let data = {"key1": "data1", "key2": ["a","b"]}; a = data.key1; b = data[1].key2; 配列へのアクセス ○ python での使い方 ・web 上にあるファイルからの読み込み url = 'https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json' req = urllib.request.urlopen(url) page = req.read().decode() # このサイトは decode() はなくても同じ結果 print(page) dic = json.loads(page) print(dic['reportDatetime']) # 1 つのフィールドを表示 for key in dic.keys(): # .keys() はなくてもよい print("key = " + key + " value = " + dic[key]) ・ファイルからの読み込み f = open(fname, "r") dic = json.load(f) 以下同じ
自分だけに通知するなら Line Notify を利用する方法が簡便である。 トークンだけで、投稿できる。 以下の url にアクセスする https://notify-bot.line.me/ja/ ログインして、右上の自分の名前 --- マイページ あるいは以下のページに直接アクセスする https://notify-bot.line.me/my/ 「トークンを発行する」を押す トークン名を入れ、通知を送信するトークルームを 選択する。 1:1でLINE Notifyから通知を受け取る という トークルームが先頭にある。これを選択すると LINE Notify というトークルームが新規作成され、 そのトークルームに投稿される。 「コピー」ボタンを押すと、トークンがクリップボードに コピーされる。プログラムの中に貼り付けて使用する。 それ以外のトークルームとして、 友達リストに登録されたグループ名が表示される。 この扱い方はよく分からない。
import requests url = "https://notify-api.line.me/api/notify" token = "トークン" message = "投稿したい文字列" headers = {'Authorization': f'Bearer {token}'} data = {'message': f'{message}'} response = requests.post(url, headers=headers, data=data) print(response.status_code) print(response.text)
import requests token = 'トークン' url = "https://notify-api.line.me/api/notify" message = "notifyで画像送信" fname = "./sample.jpg" image = open(fname, "rb") image_dic = {'imageFile': image} token_dic = {'Authorization': f'Bearer {token}'} send_dic = {'message': message} response = requests.post(url, headers=token_dic, data=send_dic, files=image_dic) print(response.text)