この記事は Lancers(ランサーズ) Advent Calendar 2020 3日目のエントリーです。
ランサーズ新卒エンジニアの太田有紀(@ifuriito09R)です。
今回の記事では、GASとRoboticCrowd APIを使って、業務を効率化したことについて書いていきます。
RoboticCrowdとは?
クラウド型のRPAツールです。
各サービスのAPI公開有無に関係なく、ブラウザ上の作業を自動化が出来ます。
様々なプロジェクト、ワークフローをつくることができる業務自動化プラットフォームを通じて、もっとクリエイティブなことに集中できることを実現します。
RoboticCrowdのワークフローで具体的に何が出来るのか?
RoboticCrowdのワークフローは、労務や法務などのバックオフィス業務やマーケティング業務の効率化に役立てられています。
具体的には、指定した文言で検索した結果として出力された画面のスクリーンショット、PDFを作成、スプレッドシートに記録、メールやSlackにて通知、プラットフォームに自動ログインなどブラウザ上で出来ることはほとんど自動化することが出来ます。
このような機能を使って、ジョブカンから交通費の実費を計算するワークフロー、KARTEからセグメントを作成するワークフローなどを運用しています。
機能の組み合わせの一例として、「反社チェック」という特定の組織が反社会勢力ではないかを確認する業務の効率化施策を紹介します。
こちらはGoogleスプレッドシートに企業名を入力すると、約10秒から20秒で指定したブラウザ、ツールで検索、検知して、エビデンスとなるPDF資料を作成してくれるワークフローです。
このようにランサーズでは、RoboticCrowdが活用されています。
今回の実装内容と背景
実装内容
Slackで/rpa 動作させるワークフローIDというコマンドを打つと、実行者が指定したワークフローの実行権限を持つユーザーであることを判定して、それを突破するとワークフローを実行されて、コマンド実行者や実行日時などのログを取得して、専用のスプレッドシートに記載する実装です。
実装背景
実行のたびに直接RoboticCrowdさんの画面にアクセスして、ワークフローを手動で実行しなければならないことやRoboticCrowd画面から直接アクセスして手動で実行できる人数が決まっていました。
そういった背景があって、適切な権限の管理やログ(実行者、実行日時、実行ワークフローIDなど)が取得できるなど、内部統制上に問題なく、適切な人がSlackから簡単に実行できることを目指して、今回の実装に至りました。
実装手順
下記のステップを一つずつクリアしていきましょう!
ステップ1:シェル上でRoboticCrowdのワークフローの実行が出来ること
ステップ2:GASでRoboticCrowdのワークフローを実行が出来ること
ステップ3:GASのスクリプトをデプロイして、/rpa ワークフローID コマンドを打つと、指定したワークフローIDが実行されること
ステップ4:連想配列にワークフローID、実行可能ユーザー、プロジェクトJWTトークンを格納して、そのデータをもとに処理が正しく分岐して、実行されること
ステップ5:実行ログ(実行者、実行日時、実行ワークフローIDなど)を取得して、実行ログがスプレッドシートにて保存されること
では、一つずつ丁寧に説明していきます。
ステップ1
まず外部から実行するためには、プロジェクトごとにJWTトークンが必要です。
JWT は、3つの部分、すなわちヘッダー、ペイロード、および署名からなる、エンコードされたJSONオブジェクトです。
curlコマンドを実行すると、JWTトークンが発行されます。
curl --location --request POST "https://api.roboticcrowd.com/v1/token" \ --header "content-type: application/json" \ --data "{ \"access_key_id\": \"AccessKeyをここに貼る\", \"secret_access_key\": \"SecreteKeyをここに貼る\", \"expires\": 36000` }"
expiresは、トークンの有効期限を設定するところです。分単位で値が入ります。(今回の例だと36000 = 10時間です。)
下記のような形式のJWTトークンが発行されます。
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxx
API の認証は、JWT を設定することで可能になります。
では実際にcurlでRoboticsCrowd APIを叩いて、ワークフローを実行してみます。
curl –location –request POST “https://api.roboticcrowd.com/v1/session_queues” \
–header “Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxx” \
–header “content-type: application/json” \
–data “{
\”workflow_id\”: ワークフローID
}”
successとなり、実行することができました。
ステップ2
次のステップとして、curlでRoboticsCrowd APIを叩いて、ワークフローを実行したステップ1をGASのスクリプトで、実行できるようにします。
function actRpaApi(){ var url = "https://api.roboticcrowd.com/v1/session_queues"; var headers = { "Content-type": "application/json", "Authorization": "Bearer JWTのトークンが入ります" } var data = { "workflow_id":ワークフローIDが入ります } var options = { "method": "post", "payload": JSON.stringify(data), "headers": headers }; UrlFetchApp.fetch(url, options); }
こちらで実行することができます。
ステップ3
次はSlackのSlashコマンドからワークフローIDを受け取って、指定されたワークフローを実行します。
/rpa 22222とSlackに打つと、動作確認用ワークフローが実行される処理が出来ます。
以下が具体例です。
自分にしか見えないメッセージで、動作されたことを確認するためのメッセージを表示されます。
以下の画像のようにRPAの動作確認ワークフローが実行されると、https://www.lancers.jp/ でスクショした画像が指定したチャンネルに投稿されます。
このような実装をGASのスクリプトを書くことで実現させます。
ステップ2と違う部分としましては、doPost関数の引数に「e」を用いています。doPost関数の引数である「e」は、SlackのSlashコマンドを打ったタイミングで取得される値です。「e」の中には、実行者のSlackID、動作させるワークフローID、実行日時などが入っています。
function doPost(e) { var actWorkflowId = e.parameter.text; function actRpaApi(){ var url = "https://api.roboticcrowd.com/v1/session_queues"; var headers = { "Content-type": "application/json", "Authorization": "Bearer JWTのトークンが入ります" } var data = { "workflow_id":actWorkflowId } var options = { "method": "post", "payload": JSON.stringify(data), "headers": headers }; UrlFetchApp.fetch(url, options); } }
スクリプトを実行して、ワークフローが動作することが確認できたら、次のステップへいきます。
ステップ4
このステップでは、連想配列にワークフローID、実行可能ユーザー、プロジェクトJWTトークンを格納して、そのデータをもとに処理が正しく分岐して、実行される処理をつくっていきたいと思います。
まず連想配列であるworkflowsを定義します。このworkflowsの中には、ワークフローIDなどの数字に紐付いて、実行権限のあるユーザーのSlackIDやJWTトークンが格納されています。
var workflows = { // 11111: [CP]反社チェックフロー(Google検索) 実行権限ユーザー: 太田(有) 11111:{"slackMemberId":['XXXXXXXX','XXXXXXXX','XXXXXXXX','XXXXXXXX'], "JwtAuthorization":"Bearer XXXXXXXXXXXXXXXX"}, // 22222: [共通]RPA確認フロー 実行権限ユーザー: ランサーズグループ全員 22222:{"slackMemberId":[], "JwtAuthorization":"Bearer XXXXXXXXXXXXXXXXXXXXX"} }
SlackIDは、変数actSlackUserId。ワークフローIDは、変数selectedWorkflowId。ユーザー名は、変数actSlackUserNameに格納します。
var actSlackUserId = e.parameter.user_id; var selectedWorkflowId = e.parameter.text; var actSlackUserName = e.parameter.user_name;
次に下記のコードでSlackからPostされた値を活用します。
はじめのif文でSlackで指定したワークフローIDが存在するワークフローかどうかを確かめます。
存在しない場合は、「指定されたワークフローIDは、コマンド実行可能なワークフローとして許可されていません。」がSlackのメッセージとして返ります。
存在する場合は、連想配列であるworkflowsからslackMemberIdとJwtAuthorizationを受け取って、次の処理で実行権限があるかどうかを確認します。
これを突破したら、ステップ2で作成したactRpaApi関数の引数にselectedWorkflowIdとnewJwtAuthorizationを渡して、関数を実行します。
function doPost(e) { var actSlackUserId = e.parameter.user_id; var selectedWorkflowId = e.parameter.text; var actSlackUserName = e.parameter.user_name; var workflows = { // 11111: [CP]反社チェックフロー(Google検索) 実行権限ユーザー: 太田(有) 11111:{"slackMemberId":['XXXXXXXX','XXXXXXXX','XXXXXXXX','XXXXXXXX'], "JwtAuthorization":"Bearer XXXXXXXXXXXXXXXX"}, // 22222: [共通]RPA確認フロー 実行権限ユーザー: ランサーズグループ全員 22222:{"slackMemberId":[], "JwtAuthorization":"Bearer XXXXXXXXXXXXXXXXXXXXX"} } if (workflows[selectedWorkflowId]) { // 存在する時の処理(実行権限確認など) var permissionList = workflows[selectedWorkflowId]["slackMemberId"]; var newJwtAuthorization = workflows[selectedWorkflowId]["JwtAuthorization"]; if (permissionList.indexOf(actSlackUserId) == -1) { var response = { text: "実行権限はありません" }; } if (permissionList.indexOf(actSlackUserId) >= 0 || permissionList == "") { var responseTextRpa = actRpaApi(selectedWorkflowId, newJwtAuthorization); var response = returnValueChecker(responseTextRpa); } return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); } var response = { text: "指定されたワークフローIDは、コマンド実行可能なワークフローとして許可されていません。" }; return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); }
ステップ5
最後に実行ログ(実行者、実行日時、実行ワークフローIDなど)を取得して、実行ログがスプレッドシートにて保存する処理を実行します。
var actSlackUserId = e.parameter.user_id; var selectedWorkflowId = e.parameter.text; var actSlackUserName = e.parameter.user_name; var actDate = Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy-MM-dd HH:mm");   // 指定したスプレッドシートへ記録 var spreadsheet = SpreadsheetApp.openById('XXXXXXXXXXXXXXXXXXXXXXXX'); var sheet = spreadsheet.getSheets()[0]; var lastRow = sheet.getLastRow(); sheet.getRange(lastRow + 1, 1).setValue(actSlackUserId); sheet.getRange(lastRow + 1, 2).setValue(actSlackUserName); sheet.getRange(lastRow + 1, 3).setValue(actDate); sheet.getRange(lastRow + 1, 4).setValue(selectedWorkflowId);
Googleスプレッドシート関連の処理は、GASとの相性がとても良いです。
以上で今回の目的の「Slackで/rpa 動作させるワークフローIDというコマンドを打つと、実行者が指定したワークフローの実行権限を持つユーザーであることを判定して、それを突破するとワークフローが実行されて、コマンド実行者や実行日時などのログを取得して、専用のスプレッドシートに記載する実装」が出来ました。
さいごに
最後まで読んでいただきましてありがとうございます。
今回は、GASとRoboticCrowd APIで業務効率化したお話をさせていただきました。
ツールを実装する過程で業務フローに対する理解が進み、その業務に関係する人々への感謝の気持ちが大きくなりました。
普段支えてくださっている人々への感謝の気持ちを忘れずに、技術力を高めて、たくさん感謝されるエンジニアになろうと強く思いました!
明日は、平野さんです!ぜひお楽しみに。