こんにちは、俊介です!
Workato触っていますでしょうか?
今回は久々にリアク字1発シリーズのシステムをWorkatoで実装しましたので書いていきます。
今回作ったものは?
会社宛に来た電話番号を1発でブロックリストに追加する動きです。
これは需要がある会社は少ないかもですが、こういう事も出来るんだとWorkatoの可能性の広さを感じて頂ければ幸いです!
▼今までの運用フローはこちら

▼Workatoを入れると

わざわざZoomのブラウザ開いて、管理画面を開いて等ブロックリストの登録画面までにユーザー操作をいくつか踏まなくていいんです。
Workatoを入れた時の流れ
- ブロックリストに追加したい番号が記載されてる特定メッセージにリアクションを追加。後続のステップはWorkatoが動いてくれます。

- テキストメッセージを取得
- 発信者
- 電話番号
- Zoomのブロックリストに追加

- リアクションを追加した特定のメッセージのスレッドとチャンネルに実行結果をレスポンス
- 登録した番号
- ブロックリストに存在する合計件数

レシピの作り方
※作る前に改めて注意事項※
このシステムを作るにはConnectionを自作しないといけません。
現在Workatoは標準では用意していない為、Custom Connector SDKでコードを書いて作成します。
下記に今回作成したConnectionを記載しますので、参考にしてください。
<div class="wp-block-urvanov-syntax-highlighter-code-block"><pre class="height-set:true height:400 lang:js decode:true " title="Zoom Phone コネクター">{
title: "ZoomPhoneAPI",
connection: {
fields: [
{
name: 'api_key',
label: 'API Key',
optional: false,
hint: "Zoom Developで作成したAppのAPI Key"
},
{
name: 'api_secret',
label: 'API Secret',
optional: false,
hint: "Zoom Developで作成したAppのAPI Secret"
}
],
authorization: {
type: 'custom_auth',
acquire: lambda do |connection|
header = '{"alg":"HS256","typ":"JWT"}'
expTime = 90.minutes.from_now.to_i
payload = '{"iss": '+'"'+connection['api_key']+'"'+',"exp":'+expTime.to_s+"}"
headerpay = header.encode_urlsafe_base64 + '.' + payload.encode_urlsafe_base64
signature = headerpay.hmac_sha256(connection['api_secret'])
{
jwt_token: header.encode_urlsafe_base64 + '.' + payload.encode_urlsafe_base64+'.'+ signature.encode_urlsafe_base64
}
end,
refresh_on: 401,
apply: lambda do |connection|
headers('Authorization': "Bearer #{connection['jwt_token']}")
end
},
base_uri: lambda do
"https://api.zoom.us"
end
},
test: lambda do |_connection|
get("/v2/users?status=active")
end,
object_definitions: {
number: {
fields: lambda do |_connection, object_definitions|
[
{
control_type: "text",
label: "Next page token",
type: "string",
name: "next_page_token"
},
{
control_type: "number",
label: "Page size",
parse_output: "float_conversion",
type: "number",
name: "page_size"
},
{
control_type: "number",
label: "Total records",
parse_output: "float_conversion",
type: "number",
name: "total_records"
},
{
name: "blocked_list",
type: "array",
of: "object",
label: "Blocked list",
properties: [
{
control_type: "text",
label: "ID",
type: "string",
name: "id"
},
{
control_type: "text",
label: "Match type",
type: "string",
name: "match_type"
},
{
control_type: "text",
label: "Phone number",
type: "string",
name: "phone_number"
},
{
control_type: "text",
label: "Block type",
type: "string",
name: "block_type"
},
{
control_type: "text",
label: "Comment",
type: "string",
name: "comment"
},
{
control_type: "text",
label: "Status",
type: "string",
name: "status"
}
]
}
]
end
},
user: {
fields: lambda do |_connection, object_definitions|
[
{
control_type: "text",
label: "Created at",
render_input: "date_time_conversion",
parse_output: "date_time_conversion",
type: "date_time",
name: "created_at"
},
{
name: "custom_attributes",
type: "array",
of: "object",
label: "Custom attributes",
properties: [
{
control_type: "text",
label: "Key",
type: "string",
name: "key"
},
{
control_type: "text",
label: "Name",
type: "string",
name: "name"
},
{
control_type: "text",
label: "Value",
type: "string",
name: "value"
}
]
},
{
control_type: "text",
label: "ID",
type: "string",
name: "id"
},
{
control_type: "text",
label: "First name",
type: "string",
name: "first_name"
},
{
control_type: "text",
label: "Last name",
type: "string",
name: "last_name"
},
{
control_type: "text",
label: "Email",
type: "string",
name: "email"
},
{
control_type: "number",
label: "Type",
parse_output: "float_conversion",
type: "number",
name: "type"
},
{
control_type: "text",
label: "Role name",
type: "string",
name: "role_name"
},
{
control_type: "number",
label: "Pmi",
parse_output: "float_conversion",
type: "number",
name: "pmi"
},
{
control_type: "text",
label: "Use pmi",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Use pmi",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "use_pmi"
},
type: "boolean",
name: "use_pmi"
},
{
control_type: "text",
label: "Personal meeting URL",
type: "string",
name: "personal_meeting_url"
},
{
control_type: "text",
label: "Timezone",
type: "string",
name: "timezone"
},
{
control_type: "number",
label: "Verified",
parse_output: "float_conversion",
type: "number",
name: "verified"
},
{
control_type: "text",
label: "Dept",
type: "string",
name: "dept"
},
{
control_type: "text",
label: "Last login time",
render_input: "date_time_conversion",
parse_output: "date_time_conversion",
type: "date_time",
name: "last_login_time"
},
{
control_type: "text",
label: "Last client version",
type: "string",
name: "last_client_version"
},
{
control_type: "text",
label: "Pic URL",
type: "string",
name: "pic_url"
},
{
control_type: "text",
label: "Host key",
type: "string",
name: "host_key"
},
{
control_type: "text",
label: "Jid",
type: "string",
name: "jid"
},
{
name: "im_group_ids",
type: "array",
of: "string",
control_type: "text",
label: "Im group ids"
},
{
control_type: "text",
label: "Account ID",
type: "string",
name: "account_id"
},
{
control_type: "text",
label: "Language",
type: "string",
name: "language"
},
{
control_type: "text",
label: "Phone country",
type: "string",
name: "phone_country"
},
{
control_type: "text",
label: "Phone number",
type: "string",
name: "phone_number"
},
{
control_type: "text",
label: "Status",
type: "string",
name: "status"
},
{
control_type: "text",
label: "Role ID",
type: "string",
name: "role_id"
},
{
control_type: "text",
label: "Employee unique ID",
type: "string",
name: "employee_unique_id"
},
{
control_type: "number",
label: "Account number",
parse_output: "float_conversion",
type: "number",
name: "account_number"
},
{
control_type: "text",
label: "Manager",
type: "string",
name: "manager"
}
]
end
},
blocked_id: {
fields: lambda do |_connection, object_definitions|
[
{
control_type: "text",
label: "ID",
type: "string",
name: "id"
}
]
end,
},
user_profile: {
fields: lambda do |_connection, object_definitions|
[
{
control_type: "text",
label: "ID",
type: "string",
name: "id"
},
{
control_type: "text",
label: "Phone user ID",
type: "string",
name: "phone_user_id"
},
{
control_type: "text",
label: "Email",
type: "string",
name: "email"
},
{
control_type: "text",
label: "Extension ID",
type: "string",
name: "extension_id"
},
{
control_type: "number",
label: "Extension number",
parse_output: "float_conversion",
type: "number",
name: "extension_number"
},
{
name: "calling_plans",
type: "array",
of: "object",
label: "Calling plans",
properties: [
{
control_type: "number",
label: "Type",
parse_output: "float_conversion",
type: "number",
name: "type"
}
]
},
{
name: "phone_numbers",
type: "array",
of: "object",
label: "Phone numbers",
properties: [
{
control_type: "text",
label: "ID",
type: "string",
name: "id"
},
{
control_type: "text",
label: "Number",
type: "string",
name: "number"
}
]
},
{
control_type: "text",
label: "Site ID",
type: "string",
name: "site_id"
},
{
control_type: "text",
label: "Status",
type: "string",
name: "status"
},
{
properties: [
{
control_type: "text",
label: "International calling",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "International calling",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "international_calling"
},
type: "boolean",
name: "international_calling"
},
{
properties: [
{
control_type: "text",
label: "Enable",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Enable",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "enable"
},
type: "boolean",
name: "enable"
},
{
control_type: "text",
label: "Locked",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Locked",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "locked"
},
type: "boolean",
name: "locked"
},
{
control_type: "text",
label: "Locked by",
type: "string",
name: "locked_by"
}
],
label: "Select outbound caller ID",
type: "object",
name: "select_outbound_caller_id"
},
{
control_type: "text",
label: "Emergency calls to psap",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Emergency calls to psap",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "emergency_calls_to_psap"
},
type: "boolean",
name: "emergency_calls_to_psap"
},
{
properties: [
{
control_type: "text",
label: "Enable",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Enable",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "enable"
},
type: "boolean",
name: "enable"
},
{
control_type: "text",
label: "Locked",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Locked",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "locked"
},
type: "boolean",
name: "locked"
},
{
control_type: "text",
label: "Locked by",
type: "string",
name: "locked_by"
}
],
label: "Hand off to room",
type: "object",
name: "hand_off_to_room"
},
{
properties: [
{
control_type: "text",
label: "Enable",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Enable",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "enable"
},
type: "boolean",
name: "enable"
},
{
control_type: "text",
label: "Locked",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Locked",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "locked"
},
type: "boolean",
name: "locked"
},
{
control_type: "text",
label: "Locked by",
type: "string",
name: "locked_by"
}
],
label: "Mobile switch to carrier",
type: "object",
name: "mobile_switch_to_carrier"
},
{
control_type: "text",
label: "Forwarding to external numbers",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Forwarding to external numbers",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "forwarding_to_external_numbers"
},
type: "boolean",
name: "forwarding_to_external_numbers"
},
{
control_type: "text",
label: "Elevate to meeting",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Elevate to meeting",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "elevate_to_meeting"
},
type: "boolean",
name: "elevate_to_meeting"
},
{
control_type: "text",
label: "Delegation",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Delegation",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "delegation"
},
type: "boolean",
name: "delegation"
},
{
properties: [
{
control_type: "text",
label: "Enable",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Enable",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "enable"
},
type: "boolean",
name: "enable"
},
{
control_type: "text",
label: "Allow transcription",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Allow transcription",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "allow_transcription"
},
type: "boolean",
name: "allow_transcription"
}
],
label: "Voicemail",
type: "object",
name: "voicemail"
},
{
properties: [
{
control_type: "text",
label: "Enable",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Enable",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "enable"
},
type: "boolean",
name: "enable"
},
{
control_type: "text",
label: "International sms",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "International sms",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "international_sms"
},
type: "boolean",
name: "international_sms"
}
],
label: "Sms",
type: "object",
name: "sms"
},
{
properties: [
{
control_type: "text",
label: "Enable",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Enable",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "enable"
},
type: "boolean",
name: "enable"
},
{
control_type: "text",
label: "Recording calls",
type: "string",
name: "recording_calls"
},
{
control_type: "text",
label: "Recording transcription",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Recording transcription",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "recording_transcription"
},
type: "boolean",
name: "recording_transcription"
},
{
control_type: "text",
label: "Recording start prompt",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Recording start prompt",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "recording_start_prompt"
},
type: "boolean",
name: "recording_start_prompt"
},
{
control_type: "text",
label: "Recording explicit consent",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Recording explicit consent",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "recording_explicit_consent"
},
type: "boolean",
name: "recording_explicit_consent"
},
{
control_type: "text",
label: "Allow stop resume recording",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Allow stop resume recording",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "allow_stop_resume_recording"
},
type: "boolean",
name: "allow_stop_resume_recording"
},
{
control_type: "text",
label: "Disconnect on recording failure",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Disconnect on recording failure",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "disconnect_on_recording_failure"
},
type: "boolean",
name: "disconnect_on_recording_failure"
},
{
control_type: "text",
label: "Locked",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Locked",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "locked"
},
type: "boolean",
name: "locked"
},
{
control_type: "text",
label: "Locked by",
type: "string",
name: "locked_by"
}
],
label: "Auto call recording",
type: "object",
name: "auto_call_recording"
},
{
properties: [
{
control_type: "text",
label: "Enable",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Enable",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "enable"
},
type: "boolean",
name: "enable"
},
{
control_type: "text",
label: "Recording start prompt",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Recording start prompt",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "recording_start_prompt"
},
type: "boolean",
name: "recording_start_prompt"
},
{
control_type: "text",
label: "Recording transcription",
render_input: {},
parse_output: {},
toggle_hint: "Select from option list",
toggle_field: {
label: "Recording transcription",
control_type: "text",
toggle_hint: "Use custom value",
type: "boolean",
name: "recording_transcription"
},
type: "boolean",
name: "recording_transcription"
}
],
label: "Ad hoc call recording",
type: "object",
name: "ad_hoc_call_recording"
}
],
label: "Policy",
type: "object",
name: "policy"
}
]
end,
}
},
actions: {
blocked_list: {
title: "ブロックリストの取得",
input_fields: lambda do |connection, object_definitions|
[{name: "page_size", type: "integer", optional: false, label: "ページサイズ", hint: "1ページ何件表示するか設定"}]
end,
execute: lambda do |connection, input|
get("v2/phone/blocked_list")
end,
output_fields: lambda do |object_definitions|
object_definitions["number"]
end,
},
get_user: {
title: "ユーザー情報取得",
input_fields: lambda do |connection, object_definitions|
[{name: "userId", type: "string", optional: true, label: "ユーザーID", hint: "ZoomのアカウントIDまたはメールアドレスを設定"}]
end,
execute: lambda do |connection, input|
get("/v2/users/#{input["userId"]}")
end,
output_fields: lambda do |object_definitions|
object_definitions["user"]
end,
},
update_blocked_list: {
title: "ブロックリスト番号を追加",
input_fields: lambda do |connection|
[
{name: "match_type", type: "string", optional: true, label: "タイプ", hint: "ブロックリストの一致タイプを設定"},
{name: "phone_number", type: "string", optional: true, label: "番号", hint: "ブロックリストに追加したい番号を設定"},
{name: "block_type", type: "string", optional: true, label: "ブロックタイプ", hint: "ブロックタイプをインバウンドかアウトバウンドか設定"},
{name: "status", type: "string", optional: true, label: "状態", hint: "ブロッキングを有効か無効か設定"},
{name: "comment", type: "string", optional: true, label: "コメント", hint: "会社名と電話かけた人を設定"},
]
end,
execute: lambda do |connection, input|
post("/v2/phone/blocked_list", input)
end,
output_fields: lambda do |object_definitions|
object_definitions["blocked_id"]
end,
}
}
}</pre></div>
レシピの全体像

トリガー設定
使うトリガーはWorkbot for Slackの「New Event」を選択
下記の様に設定する

アクション設定
Step2:まずはテキストメッセージの中身を抽出
使うアクションはWorkbot for Slackの「Custom action」を使う

それぞれ設定を行う
今回使うAPI methodはconversations.replies

Request parameter

Typical success response
{
"messages": [
{
"type": "message",
"user": "U061F7AUR",
"text": "island",
"thread_ts": "1482960137.003543",
"reply_count": 3,
"subscribed": true,
"last_read": "1484678597.521003",
"unread_count": 0,
"ts": "1482960137.003543"
}
],
"has_more": true,
"ok": true,
"response_metadata": {
"next_cursor": "bmV4dF90czoxNDg0Njc4MjkwNTE3MDkx"
}
}
上記のデータをResponse bodyに入れる

Step3:IF分岐を1個挟む
抽出したStep2のテキストに「電話番号:」含むならYes
弊社は決まった雛形でメッセージが送られてこないのでIF分岐のアクションを追加しました。

Step6:Step4、Step5で必要な情報を取得したのでブロックリストに追加
ポイントは番号の登録です。
- 国内の番号は「81」が先頭に必要
- 登録番号の最初は不要(例:090--→90–)

Step7:登録後のリストを取得
1ページに取れる件数は100件なので、今回は100と設定しています。

Step8:チャンネルに実行結果を投稿
使うアクションはWorkbot for Slackの「Posrt message」を使う
投稿したいチャンネルは「Reply channel」で設定する
投稿内容は「Notification text」で設定する

Step9:対象メッセージのスレッドにも実行結果を投稿
アクションはStep8と同じやつです。
ポイントは「Advanced」の「Thred ID」に対象メッセージのTsを設定する

最後に
今回は会社宛に来た電話番号を簡単にブロックリストに追加する動きを作ってみました。
実装レベルはちょっと高いと思いますが、Zoom PhoneのConnectionさえ手に入れればレシピ作成はそこまで難しくありません!
もし、Connection作成がめんどくさい、そんな力と時間ありません等ありましたらお問い合わせください!
では、また何か作りましたら書きたいと思います。

