お知らせ

ただいま、シンタックスハイライターの設定を見直しております。
プログラムが見にくくなっているページがありますが、ご容赦ください。

LINE Messaging APIを使ってみる

プログラミング

こんにちは。今回もAPIを使ってみます。今回はLINE Messaging APIを取り上げます。

LINE Messaging APIを使ってみた動機

今回は、このサイトの記事のためではなく、ある行事で多くの人が撮影した写真を手軽な方法で集める必要性が生じました。以前は、専用のメールアドレスを作って送信してもらっていたのですが、添付ファイルを一つ一つダウンロードする手間がかかり、もう少し手軽な方法がないかを考えました。

ほとんどの人がアカウントを持っていて操作に慣れているアプリということで、LINEを候補に考えました。

しかし、LINEで受け取った写真を、行事の記録として残したり報告を書いたりする必要があり、写真を整理しながらダウンロードする必要があります。そこで、Messaging APIを使って受け取った写真のファイル名を規則的に付けながら1つのフォルダにまとめていくことができるようにしようと考えて、APIを使ってみることにしました。

LINE Messaging APIについて

LINE Messaging APIについての詳細な説明は公式サイトに任せてしまおうと思います。

今回の内容と関係することをかいつまんでまとめます。APIにはプッシュメッセージ(Push messages)と応答メッセージ(Reply messages)の2種類あります。プッシュメッセージは、サービス側から任意のタイミングでメッセージを発信することができます。それに対して、応答メッセージは、ユーザからのメッセージに対して応答するメッセージを送ることができます。

料金については、次のリンクを参照してください。今回は写真を受け取る部分と受け取った旨の返信についてAPIを利用するだけなので、Message APIのフリープランを使います。

必要になるものは

  • LINEアカウント
  • メッセージを受け取った後の処理をするサーバ

です。メッセージを受け取った後の処理を行うサーバとして、ネット上で見つけた多くの記事ではHerokuを使っているようでした。私は、さくらレンタルサーバを借りているので、そこで動かすようにしました。

LINE Botを作る

はじめにチャンネルを作ります。操作については公式サイトを参照してください。

次に、作ったチャンネルでBotが使えるように設定します。こちらについても公式サイトのリンクを貼っておきます。この中の、「コンソールでボットを設定する」の「チャンネルアクセストークンを設定する」と「Webhook URLを設定する」を設定します。Webhook URLという言葉に慣れていないとわかりにくいのですが、LINE Botがメッセージを受け取るなどのトリガー(引き金)に対して、メッセージを受け取るなど何らかの処理をするプログラムはどこにあるかを示すURLになります。

特に関係する部分のスクリーンショットは次になります。

次に、Webhook URLに設定したプログラムを作ります。今回はPHPで書いています。(さくらインターネットでPython3を使えるようにしていなかったので・・・(-_-;))

<?php

$accessToken = 'Your Access Token';

//ユーザーからのメッセージ取得
$json_string = file_get_contents( 'php://input' );
$jsonObj = json_decode( $json_string );
 
$type = $jsonObj->{"events"}[0]->{"message"}->{"type"};

//メッセージ取得
$text = $jsonObj->{"events"}[0]->{"message"}->{"text"};

//LINE ID取得
$user_id = $jsonObj->{"events"}[0]->{"source"}->{"userId"};

//message ID取得
$message_id = $jsonObj->{"events"}[0]->{"message"}->{"id"};

//ReplyToken取得
$replyToken = $jsonObj->{"events"}[0]->{"replyToken"};
 

if( $type == "text" ){
  $file = 'groupdata.txt';

  // ファイルをオープンして既存のコンテンツを取得します
  $current = file_get_contents( $file );

  // 新しい人物をファイルに追加します
  $current .= $user_id.",".$text.",\n";
  // 結果をファイルに書き出します
  file_put_contents( $file, $current );

  $response_format_text = [
    "type" => "text",
    "text" =>  $text."に登録しました"
  ];
} else if( $type == "image" ){
  $file = fopen( './groupdata.txt', 'r' );
  $group = '';
  if( $file ){
    while ( $line = fgets( $file ) ) {
      if( strpos( $line, $user_id ) !== false ){
        $words = explode( ",", $line );
        $group = $words[1];
      }
    }
  }
  fclose( $file );

  if( $group == '' ){
    $response_format_text = [
      "type" => "text",
      "text" => "写真を送る前にグループ番号を送ってください。"
    ];
  } else {

    $file = fopen( './photodata.txt', 'r' );
    $count = 1;
    if( $file ){
      while ( $line = fgets( $file ) ) {
        if( strpos( $line, $group ) !== false ){
          $count += 1;
        }
      }
    }
    fclose( $file );


    $file = 'photodata.txt';

    // ファイルをオープンして既存のコンテンツを取得します
    $current = file_get_contents( $file );

    // グループの写真の枚数がわかるようにファイルに追加します
    $current .= $group.",\n";
    // 結果をファイルに書き出します
    file_put_contents( $file, $current );


    $ch = curl_init( "https://api.line.me/v2/bot/message/".$message_id."/content" );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );

    curl_setopt( $ch, CURLOPT_HTTPHEADER, array(
      'Content-Type: application/json; charser=UTF-8',
      'Authorization: Bearer ' . $accessToken
    ) );
    $result = curl_exec( $ch );
    curl_close( $ch );

    // ファイルの作成
    $fileInfo = "group".sprintf( '%02d', $group )."photo".sprintf( '%04d', $count ).".jpg";
    $fp = fopen( $fileInfo, 'wb' );
    if ( $fp ){
      if ( flock( $fp, LOCK_EX ) ){
        if ( fwrite( $fp, $result ) === FALSE ){
          // エラー処理
        }
        flock( $fp, LOCK_UN );
      }else{
        // エラー処理
      }
    }
    fclose( $fp );


    $response_format_text = [
      "type" => "text",
      "text" => $group."グループの".$count."枚目の画像を受け取りました。\n送信してくれてありがとう。"
    ];
  }
} else {
  exit;
}


$post_data = [
  "replyToken" => $replyToken,
  "messages" => [$response_format_text]
];

 
$ch = curl_init( "https://api.line.me/v2/bot/message/reply" );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'POST' );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $post_data ) );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array(
  'Content-Type: application/json; charser=UTF-8',
  'Authorization: Bearer ' . $accessToken
));
$result = curl_exec( $ch );
curl_close( $ch );

う~ん、間に合わせで書いているからぐちゃぐちゃなプログラムだな・・・すみません。一応ざっと説明します。

9~21行目で受け取ったデータから必要なものを取り出しています。

24~38行目は文字を受け取ったときの処理です。送信者に事前にグループを区別するための番号を送信してもらうことになっていて、その数値と送信者のIDとをテキストファイルに追加しています。面倒だったので、何回でも送信可として、最新のものを使うことにしています。また、返信メッセージもここで用意しています。

39~112行目は画像(写真)が送られたときの処理です。

40~50行目は、送信者のグループ番号を取得する処理が書かれています。

51~56行目では、グループ番号を事前に送っていない人に対して、先にグループ番号を送信してもらうように応答する処理をしています。

59~68行目は、送信されたグループの何枚目の写真かをテキストファイルを用いて数えています。ここはもう少し綺麗な処理ができそう。

71~79行目は、グループごとの写真の枚数がわかるように、テキストファイルにデータを記録しています。

82~105行目は、画像をサーバに複製している操作です。

108~112行目は、返信メッセージを作っています。

113~115行目では、他の形式の場合には何も処理をしないで終了するようにしています。

118行目以降では、APIを用いてメッセージを返信しています。

今回はこれでおしまいにします。それではまた。

この記事を書いた人
春日井 優

高校で情報科という教科を担当しています。以前は数学科も担当していました。(今でも数学科の教員免許状は有効です。)プログラムを覚えたのは、「ゲームセンターあらし」という漫画のキャラクターがBASICを解説する「こんにちはマイコン」を読んだことがきっかけでした。

Posted by kasugai