Quantcast
Channel: laravel5.8タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 87

Laravelの通知ライブラリでslackボタンアクション機能を実装

$
0
0

Laravel Advent Calendar 2019 - Qiita の 9 日目 の記事です。

Laravelの通知ライブラリを使ってボタン付きのslack通知を実装した記事を
下書きのままにしていたので書き上げることにしました..!

Laravelの通知ライブラリ

laravel5.8以降のslack通知機能に変化

通知クラスが外部ライブラリに変わりました!
5.8以降のslack通知(公式)

composerを使って入れないと使えなくなりました。

composer require laravel/slack-notification-channel

ちなみにv5.8以前はguzzleを入れれば使える形でした..。
5.8以前のslack通知(公式)

(実はv5.7.16以降から通知クラスは外部ライブラリ化されてますが、ドキュメントは5.8以降しか)

Nexmoの通知クラスと一緒にframwork内から削除されています。

gitの差分

slack通知のボタンアクション機能とは?

公式のgifだと以下のような表示。
ボタンが付いていて押された後、元のメッセージを変えて1人しか押せなかったり、誰が押したか表示したり色んな機能が考えられそうです..!
Example_6.gif

slack公式のボタン機能

今までのslack通知クラスでボタン機能使えなかったの?

そうなんです!
当然、slack側のAPIには用意されていたのでguzzleで直接叩いたり、Custom Channelsを使って実装することは出来ましたが、Laravelが用意してくれている通知クラスでは使えませんでした。

環境

Laravelの開発環境をdockerで作るなら、@ucan-labさんのLaravelの開発環境をDockerを使って構築するがおすすめです。常に更新されてる!

slack側の設定は以下を参考に
Slack APIを使用してメッセージを送信する

slackのボタンアクション通知の仕組みはこちらを参考にしました!
slackで単純なボタン付きメッセージを送る

通信ライブラリを使って実装

さて、通信ライブラリを使って実装してみましょう。
slack-notification-channel

通知したいチャンネルにIncoming Webhooksの設定をしてwebhookを取得します

Incoming Webhooksについてはこの記事を参考にしました。
SlackのIncoming Webhooksを使い倒す

slack通知機能をまず作ります。この時、.envに設定したwebhookをconfigに書いておき、routeNotificationForSlackメソッドで指定します。

SlackNotificationService.php
<?phpnamespaceApp\Services;useApp\Notifications\SlackButtonMessage;useApp\Notifications\SlackSend;useApp\Notifications\SlackSendQuestion;useIlluminate\Notifications\Notifiable;classSlackNotificationService{useNotifiable;/**
     * SlackチャンネルのWebhookURLを返す
     *
     * @return string
     */publicfunctionrouteNotificationForSlack(){returnconfig('services.slack.button');}/**
     * 送信メソッド
     * @param $message
     */publicfunctionsend(){// 通知$this->notify(newSlackButtonMessage());}}

上記の送信メソッドで呼ばれるslackボタン通知用のNotificationクラスを作成

SlackButtonMessage.php
<?phpnamespaceApp\Notifications;useIlluminate\Bus\Queueable;useIlluminate\Notifications\Messages\SlackMessage;useIlluminate\Notifications\Notification;/**
 * Slack通知クラス
 */classSlackButtonMessageextendsNotification{useQueueable;private$sendMessage;private$title;/**
     * Create a new notification instance.
     *
     * @return void
     */publicfunction__construct(){}/**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */publicfunctionvia($notifiable){return['slack'];}/**
     * Slack通知処理
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\SlackMessage
     */publicfunctiontoSlack($notifiable){return(newSlackMessage)->from('Test通知',':face_vomiting:')->content('これはテストです :face_vomiting:')->attachment(function($attachment){$attachment->action('googleリンク','https://www.google.com/','primary');});}}

出ました!
スクリーンショット 2019-12-09 5.24.12.png

そして積みました...。slack-notification-channelはボタン通知に対応していますが、ボタン押した際のアクションは単純なURLリンクしか設定できないようです!
SlackAttachment.phpの所定の位置を見ると確かにそうなってます。

SlackAttachment.php
/**
     * Add an action (button) under the attachment.
     *
     * @param  string  $title
     * @param  string  $url
     * @param  string  $style
     * @return $this
     */publicfunctionaction($title,$url,$style=''){$this->actions[]=['type'=>'button','text'=>$title,'url'=>$url,'style'=>$style,];return$this;}

gifのようにボタン押下後に、元のメッセージに色々アクションを実装したい場合は、無理ですね。
あくまでも通知クラスのライブラリということですね。

GuzzleでAPI実装

書いていきます!

SlackButtonService.php
<?phpnamespaceApp\Services;useGuzzleHttp\Client;classSlackButtonService{publicfunctionpostMessage($message){$client=newClient(['headers'=>['Content-Type'=>'application/json']]);$response=$client->post(config('services.slack.button'),['body'=>$message]);logger($response->getBody());$data=json_decode($response->getBody()->getContents());return$data;}}

送信メッセージ出す所

send.php
private$slack;/**
     * Create a new controller instance.
     *
     * @return void
     */publicfunction__construct(SlackButtonService$service){$this->slack=$service;}publicfunctionsend(){$message="こんにちは!";$data=array("text"=>$message);$actions=["id"=>"1","name"=>"test",'type'=>"button",'text'=>"こんにちは!","value"=>"button_1",];$data+=["attachments"=>[["callback_id"=>"test","fallback"=>"More details...",'actions'=>[$actions],]]];$payload=json_encode($data);$res=$this->slack->postMessage($payload);}

こんな感じで出ますね!
スクリーンショット 2019-12-09 7.37.30.png

slackからのレスポンス処理を設定(Interactive MessagesでここのURLを設定しておくことでPOSTされます)

web.php
Route::group(['prefix'=>'slack'],function(){Route::post('/api/response','ApiController@getSlackResponse');});

slackからのPOSTに対してcsrfトークンチェックを外す

VerifyCsrfToken.php
<?phpnamespaceApp\Http\Middleware;useIlluminate\Foundation\Http\Middleware\VerifyCsrfTokenasMiddleware;classVerifyCsrfTokenextendsMiddleware{/**
     * Indicates whether the XSRF-TOKEN cookie should be set on the response.
     *
     * @var bool
     */protected$addHttpCookie=true;/**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */protected$except=[//'/slack/api/*',];}

レスポンス処理

ApiController.php
publicfunctiongetSlackResponse(Request$request){$temp=json_decode($request['payload'],true);$temp['original_message']['text']=$temp['user']['name'].'が押しました!';returnresponse($temp['original_message']);}

こんな感じで通知が来た後に...

スクリーンショット 2019-12-09 7.37.30.png

ボタンを押すと...
スクリーンショット 2019-12-09 7.37.49.png

みたいに元のメッセージを変更したり出来ます!

slackを使っている会社では、slack連携による業務改善やエンゲージメントを高めるような施策が今後も増えてくると思います!
この記事が少しでも実装の助けになればと思います。


Viewing all articles
Browse latest Browse all 87

Trending Articles