LINEのBOT API Trial Account 先着10,000名様まで先行申し込み受付中、という言葉につられて登録したので試してみました。
基本的にはbotとお友達になって、botに何か話しかけたら答える、みたいな1対1の対話が想定のようで、メッセージを受信したら送信者に何かを送るという流れのようです。
なので、お友達全員にメッセージを一斉送信、ということがしたかったのですが、友達のID一覧取得、みたいのがないので、お友達になった時(operation requestを受信した時)に保存しておくようにしました。(配列をjson_encodeしてファイルに保存してます。)
LINEのChannels管理画面みたいなので自分のBOTのChannel IDとかSecretとかMIDとかを確認して、Callback URL に https://myhost.mydomain.jp:443/linebot/rcv
みたいに受信するURLを設定します。
諸事情によりCodeIgniter2で書いてます。
class Linebot extends CI_Controller {
private $_channel_id = '自分のBOTのChannel ID';
private $_channel_secret = '自分のBOTのChannel Secret';
private $_channel_mid = '自分のBOTのMID';
private $_allow_ip = 'メッセージ送信を許可するIPアドレス(自分のIPとか)';
private $_save_path;
public function __construct()
{
parent::__construct();
$this->_save_path = APPPATH . 'logs/line_friends';
}
public function rcv()
{
$input = file_get_contents('php://input');
log_message('debug', $input);
$json = json_decode($input);
if ( ! isset($json->result) OR ! is_array($json->result))
{
log_message('error', 'no result');
$this->output->set_status_header('400');
return;
}
foreach ($json->result as $result) {
if ( ! isset($result->content->opType))
{
// operation requestじゃない(メッセージとかが送られてきた)場合はスタンプをランダムで返す
$this->_send_sticker(rand(1, 17), 1, $result->content->from);
continue;
}
// operation requestの場合
switch ($result->content->opType)
{
case 4:
// added as friend
if ($this->_set_friend($result->content->params[0]) !== FALSE) {
$this->_send_text('ようこそ!', $result->content->params[0]);
}
break;
case 8:
// blocked account
$this->_del_friend($result->content->params[0]);
break;
}
}
$this->output->set_status_header('200');
}
public function snd($msg)
{
// 指定したIPからのアクセスのみ許可する
$remote_addr = $this->input->server('HTTP_X_FORWARDED_FOR');
if ($remote_addr === FALSE)
{
$remote_addr = $this->input->server('REMOTE_ADDR');
}
if (empty($remote_addr))
{
log_message('error', 'no remote address');
show_error('no remote address');
}
if ($remote_addr !== $this->_allow_ip)
{
log_message('error', 'invalid access: ' . $remote_addr);
show_error('invalid access: ' . $remote_addr);
}
$this->_send_text(urldecode($msg));
$this->output->set_status_header('200');
}
private function _get_friends()
{
if ( ! file_exists($this->_save_path))
{
return array();
}
return json_decode(file_get_contents($this->_save_path));
}
private function _set_friend($mid)
{
$friends = $this->_get_friends();
if ( ! in_array($mid, $friends))
{
$friends[] = $mid;
return file_put_contents($this->_save_path, json_encode($friends));
}
}
private function _del_friend($mid)
{
$friends = $this->_get_friends();
if (($key = array_search($mid, $friends)) !== FALSE)
{
unset($friends[$key]);
return file_put_contents($this->_save_path, json_encode(array_values($friends)));
}
}
private function _send_text($message, $mid_arr = NULL)
{
$content = array(
'contentType' => 1,
'toType' => 1,
'text' => $message
);
return $this->_send_message($content, $mid_arr);
}
private function _send_sticker($stkid, $stkpkgid, $mid_arr = NULL)
{
$content = array(
'contentType' => 8,
'toType' => 1,
'contentMetadata' => array(
'STKID' => (string)$stkid,
'STKPKGID' => (string)$stkpkgid
)
);
return $this->_send_message($content, $mid_arr);
}
private function _send_message($content, $mid_arr = NULL)
{
if (is_string($mid_arr))
{
$mid_arr = array($mid_arr);
}
elseif (is_null($mid_arr)) {
$mid_arr = $this->_get_friends();
}
if (empty($mid_arr))
{
return FALSE;
}
$url = 'https://trialbot-api.line.me/v1/events';
$headers = array(
'Content-Type: application/json; charser=UTF-8',
'X-Line-ChannelID: ' . $this->_channel_id,
'X-Line-ChannelSecret: ' . $this->_channel_secret,
'X-Line-Trusted-User-With-ACL: ' . $this->_channel_mid
);
$post = array(
'to' => $mid_arr,
'toChannel' => 1383378250,
'eventType' => '138311608800106203',
'content' => $content
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$ret = curl_exec($ch);
log_message('debug', $ret);
return $ret;
}
}
なにか話しかけられた時に何もないのも寂しいので、17種類のスタンプをランダムで返すようにしました。
(スタンプのIDとかは、API referenceにsticker listのExcelファイルがあります。)
https://myhost.mydomain.jp/linebot/snd/Hello
とかで『Hello』をBOTのお友達全員に送ることができます。
日本語とか記号はURLエンコードする必要があります。(日本語はブラウザがやってくれるかも)
toTypeが『1 = user』って書いてあって、1しか書いてないんだけど、他にも違うタイプがあるのか、これからできるようになるのか…。
グループにも送信できるといいんだけどなー。