まぁ、つまらないものですが

エンジニニャーの気ままな技術ブログ、日々のログを残してゆきます。

slackでプロ生ちゃんに進捗どうですかって聞かれたい!

この記事はプロ生ちゃん Advent Calendar 2015 17日めの記事です!
qiita.com

ホントは13日だったのですがゴタゴタしてて今日になってしまいました…
スミマセン…

最近slackを始めたので作業と締め切りを言ったらその直前で「進捗どうですか?」って聞いてくるプロ生ちゃんをうちのサークルのSlackに招待したいなと思います。
Hubotではないです。

f:id:gakusei200709:20151216095824p:plain
製作中のプロ生ちゃんの様子

今回使うもの

  • PHP
  • PHPが動くサーバ
  • Incoming WebHooks Slackの外からURL指定で特定のチャンネルとかに書き込めるサービス
  • Outgoing WebHooks 特定の単語が書かれると指定しておいたURLに書き込まれた情報がPOSTで送られる

今回は特定のチャンネルで「プロ生ちゃん いつまでとに タスク名」とつぶやくと締め切り前にプロ生ちゃんこと暮井慧ちゃんが「タスク名の進捗大丈夫?」と聞いてくれるまでを目標にします!

f:id:gakusei200709:20151216105229j:plain
だいたいこんなイメージ

「プロ生ちゃんに反応してもらう」

App Directory | Slack
ここで「Outgoing WebHooks」を検索して自分のチームに追加します。
f:id:gakusei200709:20151216112306p:plain
設定で

  • 反応するチャンネル
  • 反応するキーワード
  • その時にPOSTを飛ばすURL

を設定します。
Outgoing WebHooksはJSONを返すと表示してくれるそうなので反応先のPHPは投稿者の名前とコメントを格納したJSONを返すプログラムとします。

<?php

//送られてきたPOSTデータ
$post_msg['text'] = $_POST['text'];                //本文
$post_msg['chanel'] = $_POST['chanel'];            //投稿されたチャンネル名
$post_msg['user_name'] = $_POST['user_name'];    //投稿したユーザー名
$payload = array(
	'username' => '暮井 慧',                                    //投稿するユーザー名
	'icon_url' => 'http://アイコン画像のURL/kurei.png',            // 投稿者のアイコン画像のリンク
	'text'     => "{$post_msg['user_name']}プログラミング楽しい!"    //投稿本文
);
// JSON化して表示
echo json_encode($payload); 

f:id:gakusei200709:20151216122207p:plain
動いた!

「プロ生ちゃんに自由につぶやいてもらう」

App Directory | Slack
今度は「Incoming WebHooks」を追加します。
そうすると今度はつぶやくチャンネル名を選択する欄とWebhook URLが生成されるのでそれを控えます。
今度はこちら側からそのURLにパラメータをJSON化したPOST送ると指定したチャンネルに書き込まれるようになります。
関数を一つ追加して実装してみます。

<?php
$hook_url = "生成されたWEBhookURL";
//送られてきたPOSTデータ
$post_msg['text'] = $_POST['text'];                //本文
$post_msg['chanel'] = $_POST['chanel'];            //投稿されたチャンネル名
$post_msg['user_name'] = $_POST['user_name'];    //投稿したユーザー名
$payload = array(
	'username' => '暮井 慧',                                    //投稿するユーザー名
	'icon_url' => 'http://アイコンデータ/kurei.png',            // 投稿者のアイコン画像のリンク
	'chanel'   => $post_msg['chanel']                                //投稿先チャンネル
);
//自由に何回も呟けるかテスト
for($i=0;$i<3;$i++){
	$payload['text']="{$i}回目";
	postRequest($hook_url,$payload);
}

//送信するcurl処理用関数
function postRequest($url, $params, $headers = array())
{
	$json = array('payload'=>json_encode($params));
	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_POST, true);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
	$result = curl_exec($ch);
	curl_close($ch);

	return $result;
}

f:id:gakusei200709:20151216125523p:plain
何回も呟けた!

締め切りの処理とか諸々設定する

メッセージを処理の流れは

  • スペースごとに配列に格納
  • ふたつ目の「いつまで」の部分を正規化で抽出
  • 現在から何秒後かを計算
  • 「タスク名 進捗どう?」とつぶやく

という風にしたいと思います。
(ほんとはwait()とかじゃなくてクーロンとかシステム化するべきだろうけど今回は時間がないので勘弁)

<?php
date_default_timezone_set('Asia/Tokyo');
$hook_url = "WEB_hookURL";
//送られてきたPOSTデータ
$post_msg['text'] = $_POST['text'];                //本文
$post_msg['chanel'] = $_POST['chanel'];            //投稿されたチャンネル名
$post_msg['user_name'] = $_POST['user_name'];    //投稿したユーザー名
$payload = array(
	'username' => '暮井 慧',                                    //投稿するユーザー名
	'icon_url' => 'http://アイコンURL/kurei.png',            // 投稿者のアイコン画像のリンク
	'chanel'   => $post_msg['chanel']                                //投稿先チャンネル
);

$msg = explode(" ",$post_msg['text']);
$wait_time = text_analysis($msg[1]);
if($wait_time == false){
	$payload['text'] = 'ごめんその日はいないんだ…';
	postRequest($hook_url,$payload);
	exit;
}else{
	$payload['text'] = "了解!{$wait_time}後に連絡するね!";
	postRequest($hook_url,$payload);
}
sleep($wait_time);
$payload['text'] = "そろそろ締め切りだけど{$msg[2]}の進捗大丈夫?";
postRequest($hook_url,$payload);

function text_analysis($text)
{
	$str_time = "";
	//何日後か取得
	if ( preg_match('/(\d)日後/', $text,$date)) {
		$str_time .= " +{$date[1]}day";
	} elseif (preg_match('/明日/', $text)) {
		$str_time .= " +1day";
	}
	if (preg_match('/(\d{1,2}):(\d{1,2})/', $text,$date )) {
		$now_date = strtotime(date("H:i:00 Y-m-d"));
		$target_date = strtotime("{$date[0]} ".date("Y-m-d") . " {$str_time}");
		//もし過去を指定しているならFalseを返す
		if ($now_date > $target_date) {
			return false;
		}
		return $target_date - $now_date;
	}

}

function postRequest($url, $params, $headers = array())
{
	$json = array('payload' => json_encode($params));
	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_POST, true);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
	$result = curl_exec($ch);
	curl_close($ch);

	return $result;
}

というわけでこんな風になりました。
まだまだおかしな点があるけど今後改良で…
f:id:gakusei200709:20151216142940p:plain
無事プロ生ちゃんが進捗を聞いてくれるようになったので今回の目標は達成出来たかな。
そのうちHubotで作ってみようと思います。

今回はこちらのサイトを参考に作りました。
Slack APIを使ってプッシュ通知を受け取ろう | 株式会社バニーホップ
ここよりももっとわかりやすいです。

相互リンク

  • 技術ブログ:ヤモト.tvp
  • 友人氏の技術ブログ 数学ガチ勢がエンジニアになっていく奮闘記