LINE WORKSからの応答を受ける唯一のWebhook受信口(45ノード)をローカルJSONとして作成。 awaitInput(none/date/file)3分岐のSwitchで、既存プロセス選択・日付入力・ファイル添付の 各応答パターンをHC-SUB(Task 9)へ橋渡しする。秘密値はすべてworkflow_config_values経由の Data Table参照。デプロイ・activateはコントローラー側で別途実施(本コミットはローカル定義のみ)。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1718 lines
51 KiB
JSON
1718 lines
51 KiB
JSON
{
|
||
"name": "HC-WA: LINEWORKS応答受信",
|
||
"nodes": [
|
||
{
|
||
"id": "webhook-lineworks-response",
|
||
"name": "Webhook",
|
||
"type": "n8n-nodes-base.webhook",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
200,
|
||
500
|
||
],
|
||
"webhookId": "healthcheck-lineworks-response",
|
||
"parameters": {
|
||
"httpMethod": "POST",
|
||
"path": "healthcheck-lineworks-response",
|
||
"responseMode": "responseNode",
|
||
"options": {
|
||
"rawBody": true
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-lineworks_bot_secret",
|
||
"name": "LINEWORKS_BOT_SECRET取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
420,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "bNkadTyDgDepYx2p"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "configKey",
|
||
"keyValue": "LINEWORKS_BOT_SECRET"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "code-verify-signature",
|
||
"name": "署名検証・送信者解決",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
640,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"jsCode": "// Codeノード「署名検証・送信者解決」の中身\nconst crypto = require(\"crypto\");\nfunction normalizeSignature(value) {\n return String(value || \"\").trim().replace(/^sha256=/i, \"\");\n}\nfunction safeEqual(a, b) {\n const ab = Buffer.from(String(a), \"utf8\");\n const bb = Buffer.from(String(b), \"utf8\");\n if (ab.length !== bb.length) return false;\n return crypto.timingSafeEqual(ab, bb);\n}\nfunction verifySignature(rawBody, headerSignature, botSecret) {\n const headerSig = normalizeSignature(headerSignature);\n if (!headerSig || !botSecret) return false;\n const payload = Buffer.isBuffer(rawBody) ? rawBody : Buffer.from(String(rawBody), \"utf8\");\n const expected = crypto.createHmac(\"sha256\", botSecret).update(payload).digest(\"base64\");\n return safeEqual(headerSig, expected);\n}\n\nconst LINEWORKS_BOT_SECRET = $('LINEWORKS_BOT_SECRET取得').item.json.configValue;\n\nconst item = $input.first();\nconst headers = item.json.headers || {};\nconst rawBody = item.binary && item.binary.data\n ? Buffer.from(item.binary.data.data, \"base64\")\n : Buffer.from(JSON.stringify(item.json.body || {}), \"utf8\");\n\nif (!verifySignature(rawBody, headers[\"x-works-signature\"], LINEWORKS_BOT_SECRET)) {\n throw new Error(\"Unauthorized: signature mismatch\");\n}\n\nconst body = item.json.body || {};\nconst source = body.source || {};\nconst content = body.content || {};\n\nreturn [{\n json: {\n targetEmail: source.userId,\n contentType: content.type,\n text: content.type === \"text\" ? content.text : null,\n fileId: content.type === \"file\" ? content.fileId : null,\n },\n}];"
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-pleasanter_base_url_prod",
|
||
"name": "PLEASANTER_BASE_URL取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
860,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "bNkadTyDgDepYx2p"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "configKey",
|
||
"keyValue": "PLEASANTER_BASE_URL_PROD"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-pleasanter_api_key_prod",
|
||
"name": "PLEASANTER_API_KEY取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
1080,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "bNkadTyDgDepYx2p"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "configKey",
|
||
"keyValue": "PLEASANTER_API_KEY_PROD"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-healthcheck_site_id",
|
||
"name": "HEALTHCHECK_SITE_ID取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
1300,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "bNkadTyDgDepYx2p"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "configKey",
|
||
"keyValue": "HEALTHCHECK_SITE_ID"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "http-target-userid-resolve",
|
||
"name": "対象者UserId解決",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
1520,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('PLEASANTER_BASE_URL取得').item.json.configValue }}api/users/get",
|
||
"sendBody": true,
|
||
"specifyBody": "json",
|
||
"jsonBody": "={{ JSON.stringify({ ApiVersion: 1.1, ApiKey: $('PLEASANTER_API_KEY取得').item.json.configValue, View: { ApiGetMailAddresses: true } }) }}",
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-identify-user",
|
||
"name": "対象者UserId特定",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
1740,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"jsCode": "function extractMailAddresses(user) {\n if (!user) return [];\n if (user.MailAddress) return [user.MailAddress];\n if (Array.isArray(user.MailAddresses)) return user.MailAddresses;\n return [];\n}\n\nconst targetEmail = $('署名検証・送信者解決').item.json.targetEmail;\nconst responseData = $('対象者UserId解決').item.json.Response.Data;\n// 実機未検証: /api/users/get をWhere無しで呼んだ場合のレスポンス形状(配列直下 / .Value配下 / 単一オブジェクト)を防御的に吸収する\nconst candidates = Array.isArray(responseData)\n ? responseData\n : (responseData && Array.isArray(responseData.Value) ? responseData.Value : [responseData]);\n\nconst matchedUser = candidates.find((u) => extractMailAddresses(u).includes(targetEmail));\nif (!matchedUser) {\n throw new Error(\"Pleasanterユーザーが見つかりません: \" + targetEmail);\n}\n\nreturn [{\n json: {\n ...$('署名検証・送信者解決').item.json,\n pleasanterUserId: matchedUser.UserId,\n },\n}];"
|
||
}
|
||
},
|
||
{
|
||
"id": "http-target-record-search",
|
||
"name": "対象レコード検索",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
1960,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('PLEASANTER_BASE_URL取得').item.json.configValue }}api/items/{{ $('HEALTHCHECK_SITE_ID取得').item.json.configValue }}/get",
|
||
"sendBody": true,
|
||
"specifyBody": "json",
|
||
"jsonBody": "={{ JSON.stringify({ ApiVersion: 1.1, ApiKey: $('PLEASANTER_API_KEY取得').item.json.configValue, View: { ColumnFilterHash: { ClassC: String($('対象者UserId特定').item.json.pleasanterUserId) }, ColumnFilterSearchTypes: { ClassC: 'ExactMatch' } } }) }}",
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-pick-record",
|
||
"name": "対象レコード選定",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
2180,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"jsCode": "const responseData = $('対象レコード検索').item.json.Response.Data;\n// 実機未検証: SiteIdでの/get呼び出しレスポンスは.Value配下に配列が入る想定(公式マニュアルのサイト一覧系レスポンス形状)。単一オブジェクトの場合も防御的に吸収する\nconst records = Array.isArray(responseData)\n ? responseData\n : (responseData && Array.isArray(responseData.Value) ? responseData.Value : []);\n\nconst filtered = records.filter((r) => r.Status !== 900 && r.Status !== 910);\nconst sorted = filtered.slice().sort((a, b) => new Date(b.UpdatedTime) - new Date(a.UpdatedTime));\n\nif (sorted.length !== 1) {\n throw new Error(\"対象レコードが一意に定まりません(候補\" + sorted.length + \"件)。手動確認が必要です。\");\n}\n\nconst record = sorted[0];\n\nreturn [{\n json: {\n ...$('対象者UserId特定').item.json,\n resultId: record.ResultId,\n currentStatus: record.Status,\n },\n}];"
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-bot-state",
|
||
"name": "待機状態取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
2400,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "jqMDa2YZTI4f0iQ7"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "resultId",
|
||
"keyValue": "={{ String($('対象レコード選定').item.json.resultId) }}"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "http-site-settings-get",
|
||
"name": "サイト設定取得",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
2620,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('PLEASANTER_BASE_URL取得').item.json.configValue }}api/items/{{ $('HEALTHCHECK_SITE_ID取得').item.json.configValue }}/getsite",
|
||
"sendBody": true,
|
||
"specifyBody": "json",
|
||
"jsonBody": "={{ JSON.stringify({ ApiVersion: 1.1, ApiKey: $('PLEASANTER_API_KEY取得').item.json.configValue }) }}",
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-lw_bot_client_id",
|
||
"name": "LW_BOT_CLIENT_ID取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
2840,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "bNkadTyDgDepYx2p"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "configKey",
|
||
"keyValue": "LW_BOT_CLIENT_ID"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-lw_bot_client_secret",
|
||
"name": "LW_BOT_CLIENT_SECRET取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
3060,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "bNkadTyDgDepYx2p"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "configKey",
|
||
"keyValue": "LW_BOT_CLIENT_SECRET"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-lw_bot_service_account",
|
||
"name": "LW_BOT_SERVICE_ACCOUNT取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
3280,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "bNkadTyDgDepYx2p"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "configKey",
|
||
"keyValue": "LW_BOT_SERVICE_ACCOUNT"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-get-lineworks_bot_master_site_id",
|
||
"name": "LINEWORKS_BOT_MASTER_SITE_ID取得",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
3500,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "get",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "bNkadTyDgDepYx2p"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "configKey",
|
||
"keyValue": "LINEWORKS_BOT_MASTER_SITE_ID"
|
||
}
|
||
]
|
||
},
|
||
"returnAll": true
|
||
}
|
||
},
|
||
{
|
||
"id": "http-bot-master-get",
|
||
"name": "Botマスタ取得",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
3720,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('PLEASANTER_BASE_URL取得').item.json.configValue }}api/items/{{ $('LINEWORKS_BOT_MASTER_SITE_ID取得').item.json.configValue }}/getsite",
|
||
"sendBody": true,
|
||
"specifyBody": "json",
|
||
"jsonBody": "={{ JSON.stringify({ ApiVersion: 1.1, ApiKey: $('PLEASANTER_API_KEY取得').item.json.configValue }) }}",
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-jwt-claims",
|
||
"name": "JWTクレーム組み立て",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
3940,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"jsCode": "const now = Math.floor(Date.now() / 1000);\nconst jwtClaims = JSON.stringify({\n iss: $('LW_BOT_CLIENT_ID取得').item.json.configValue,\n sub: $('LW_BOT_SERVICE_ACCOUNT取得').item.json.configValue,\n iat: now,\n exp: now + 3600,\n aud: 'https://auth.worksmobile.com/oauth2/v2.0/token',\n});\n\n// --- Bot ID解決 ---\n// TODO(Task 12): 484184(LINEWORKS_BOT_MASTER_SITE_ID)の実データ構造は未調査。Task 9(HC-SUB)と同じ暫定実装を踏襲する。\nconst botMasterSiteSettings = $('Botマスタ取得').item.json.Response.Data.SiteSettings;\nconst candidateBotIds = botMasterSiteSettings.BotIds\n || (botMasterSiteSettings.Processes || []).map((p) => p.BotId).filter(Boolean);\nconst botId = candidateBotIds && candidateBotIds[0];\nif (!botId) {\n throw new Error('BotIdを484184(LINEWORKS_BOT_MASTER_SITE_ID)から解決できませんでした。Task 12でBot選択ロジックを実装してください。');\n}\n\nconst targetEmail = $('署名検証・送信者解決').item.json.targetEmail;\nconst apiUrl = 'https://www.worksapis.com/v1.0/bots/' + botId + '/users/' + targetEmail + '/messages';\n\nreturn [{\n json: {\n jwtClaims,\n apiUrl,\n botId,\n targetEmail,\n },\n}];"
|
||
}
|
||
},
|
||
{
|
||
"id": "jwt-sign",
|
||
"name": "Sign JWT",
|
||
"type": "n8n-nodes-base.jwt",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
4160,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"operation": "sign",
|
||
"useJson": true,
|
||
"claimsJson": "={{ $json.jwtClaims }}",
|
||
"options": {
|
||
"algorithm": "RS256"
|
||
}
|
||
},
|
||
"credentials": {
|
||
"jwtAuth": {
|
||
"id": "Hw0qlEaGfLPnQWp1",
|
||
"name": "LINEWORKS Bot Private Key (v4)"
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "http-access-token",
|
||
"name": "アクセストークン取得",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
4380,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "https://auth.worksmobile.com/oauth2/v2.0/token",
|
||
"sendBody": true,
|
||
"contentType": "form-urlencoded",
|
||
"bodyParameters": {
|
||
"parameters": [
|
||
{
|
||
"name": "assertion",
|
||
"value": "={{ $json.token }}"
|
||
},
|
||
{
|
||
"name": "grant_type",
|
||
"value": "urn:ietf:params:oauth:grant-type:jwt-bearer"
|
||
},
|
||
{
|
||
"name": "client_id",
|
||
"value": "={{ $('LW_BOT_CLIENT_ID取得').item.json.configValue }}"
|
||
},
|
||
{
|
||
"name": "client_secret",
|
||
"value": "={{ $('LW_BOT_CLIENT_SECRET取得').item.json.configValue }}"
|
||
},
|
||
{
|
||
"name": "scope",
|
||
"value": "bot"
|
||
}
|
||
]
|
||
},
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "switch-await-input",
|
||
"name": "awaitInput分岐",
|
||
"type": "n8n-nodes-base.switch",
|
||
"typeVersion": 3,
|
||
"position": [
|
||
4600,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"rules": {
|
||
"values": [
|
||
{
|
||
"conditions": {
|
||
"conditions": [
|
||
{
|
||
"leftValue": "={{ $('待機状態取得').item.json.awaitInput }}",
|
||
"rightValue": "none",
|
||
"operator": {
|
||
"type": "string",
|
||
"operation": "equals"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"outputKey": "none"
|
||
},
|
||
{
|
||
"conditions": {
|
||
"conditions": [
|
||
{
|
||
"leftValue": "={{ $('待機状態取得').item.json.awaitInput }}",
|
||
"rightValue": "date",
|
||
"operator": {
|
||
"type": "string",
|
||
"operation": "equals"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"outputKey": "date"
|
||
},
|
||
{
|
||
"conditions": {
|
||
"conditions": [
|
||
{
|
||
"leftValue": "={{ $('待機状態取得').item.json.awaitInput }}",
|
||
"rightValue": "file",
|
||
"operator": {
|
||
"type": "string",
|
||
"operation": "equals"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"outputKey": "file"
|
||
}
|
||
]
|
||
},
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-match-text",
|
||
"name": "テキスト照合",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
4820,
|
||
200
|
||
],
|
||
"parameters": {
|
||
"jsCode": "const stateItem = $('待機状態取得').item.json;\nconst text = $('署名検証・送信者解決').item.json.text;\nlet pendingProcesses = [];\ntry {\n pendingProcesses = JSON.parse(stateItem.pendingProcesses || '[]');\n} catch (e) {\n pendingProcesses = [];\n}\n\nconst trimmed = String(text ?? '').trim();\n// Task 5 matchProcessByLabel相当(pendingProcessesの保存形状に合わせ p.label で照合)\nconst matched = pendingProcesses.find((p) => p.label === trimmed) || null;\n\nreturn [{\n json: {\n resultId: stateItem.resultId,\n matched,\n },\n}];"
|
||
}
|
||
},
|
||
{
|
||
"id": "if-text-matched",
|
||
"name": "テキスト一致判定",
|
||
"type": "n8n-nodes-base.if",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
5040,
|
||
200
|
||
],
|
||
"parameters": {
|
||
"conditions": {
|
||
"options": {
|
||
"caseSensitive": true,
|
||
"leftValue": "",
|
||
"typeValidation": "loose",
|
||
"version": 2
|
||
},
|
||
"conditions": [
|
||
{
|
||
"id": "cond-1",
|
||
"leftValue": "={{ !!$('テキスト照合').item.json.matched }}",
|
||
"rightValue": true,
|
||
"operator": {
|
||
"type": "boolean",
|
||
"operation": "true",
|
||
"singleValue": true
|
||
}
|
||
}
|
||
],
|
||
"combinator": "and"
|
||
},
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-classify-await-input",
|
||
"name": "入力待ち種別判定",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
5260,
|
||
100
|
||
],
|
||
"parameters": {
|
||
"jsCode": "function getValidationColumnNames(process) {\n if (!Array.isArray(process.ValidateInputs)) return [];\n return process.ValidateInputs.map((v) => v.ColumnName).filter(Boolean);\n}\nfunction classifyAwaitInput(process) {\n const columnNames = getValidationColumnNames(process);\n if (columnNames.length === 0) {\n return { awaitInput: \"none\", column: null };\n }\n const column = columnNames[0];\n if (column.startsWith(\"Date\")) {\n return { awaitInput: \"date\", column };\n }\n if (column.startsWith(\"Attachments\")) {\n return { awaitInput: \"file\", column };\n }\n return { awaitInput: \"none\", column: null };\n}\n\nconst matched = $('テキスト照合').item.json.matched;\nconst resultId = $('テキスト照合').item.json.resultId;\n\n// 注意: HC-SUBの「選択肢組み立て」がData Tableに保存するpendingProcessesは\n// {processId, label, tooltip}のみでValidateInputsを持たないため、ここではサイト設定を\n// 再取得してProcessId一致でValidateInputsを引き直す(Task9側の保存形状を変更しない前提の対応)\nconst siteSettings = $('サイト設定取得').item.json.Response.Data.SiteSettings;\nconst processes = siteSettings.Processes || [];\nconst fullProcess = processes.find((p) => p.Id === matched.processId);\nif (!fullProcess) {\n throw new Error('ProcessId ' + matched.processId + ' がサイト設定内に見つかりません');\n}\n\nconst classification = classifyAwaitInput(fullProcess);\n\nreturn [{\n json: {\n resultId,\n processId: matched.processId,\n awaitInput: classification.awaitInput,\n awaitColumn: classification.column,\n },\n}];"
|
||
}
|
||
},
|
||
{
|
||
"id": "if-immediate-run",
|
||
"name": "即時実行判定",
|
||
"type": "n8n-nodes-base.if",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
5480,
|
||
100
|
||
],
|
||
"parameters": {
|
||
"conditions": {
|
||
"options": {
|
||
"caseSensitive": true,
|
||
"leftValue": "",
|
||
"typeValidation": "loose",
|
||
"version": 2
|
||
},
|
||
"conditions": [
|
||
{
|
||
"id": "cond-1",
|
||
"leftValue": "={{ $('入力待ち種別判定').item.json.awaitInput === 'none' }}",
|
||
"rightValue": true,
|
||
"operator": {
|
||
"type": "boolean",
|
||
"operation": "true",
|
||
"singleValue": true
|
||
}
|
||
}
|
||
],
|
||
"combinator": "and"
|
||
},
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "exec-hc-sub-immediate",
|
||
"name": "Process実行(即時)",
|
||
"type": "n8n-nodes-base.executeWorkflow",
|
||
"typeVersion": 1.2,
|
||
"position": [
|
||
5700,
|
||
30
|
||
],
|
||
"parameters": {
|
||
"workflowId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "XRqcykbG2LuAjGG2"
|
||
},
|
||
"workflowInputs": {
|
||
"mappingMode": "defineBelow",
|
||
"value": {
|
||
"resultId": "={{ $('入力待ち種別判定').item.json.resultId }}",
|
||
"processId": "={{ $('入力待ち種別判定').item.json.processId }}"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-update-state-await",
|
||
"name": "待機状態保存(入力待ち)",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
5700,
|
||
170
|
||
],
|
||
"parameters": {
|
||
"operation": "update",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "jqMDa2YZTI4f0iQ7"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "resultId",
|
||
"keyValue": "={{ String($('入力待ち種別判定').item.json.resultId) }}"
|
||
}
|
||
]
|
||
},
|
||
"columns": {
|
||
"mappingMode": "defineBelow",
|
||
"value": {
|
||
"awaitInput": "={{ $('入力待ち種別判定').item.json.awaitInput }}",
|
||
"awaitProcessId": "={{ String($('入力待ち種別判定').item.json.processId) }}",
|
||
"awaitColumn": "={{ $('入力待ち種別判定').item.json.awaitColumn }}"
|
||
},
|
||
"schema": [
|
||
{
|
||
"id": "awaitInput",
|
||
"displayName": "awaitInput",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
},
|
||
{
|
||
"id": "awaitProcessId",
|
||
"displayName": "awaitProcessId",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
},
|
||
{
|
||
"id": "awaitColumn",
|
||
"displayName": "awaitColumn",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-prompt-message",
|
||
"name": "追加案内メッセージ組み立て",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
5920,
|
||
170
|
||
],
|
||
"parameters": {
|
||
"jsCode": "const awaitInput = $('入力待ち種別判定').item.json.awaitInput;\nconst text = awaitInput === 'date'\n ? '日付を入力してください(例: 2026-03-01 や 令和6年3月1日)'\n : 'ファイルを送信してください';\n\nreturn [{ json: { messageContent: { type: 'text', text } } }];"
|
||
}
|
||
},
|
||
{
|
||
"id": "http-prompt-send",
|
||
"name": "追加案内送信",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
6140,
|
||
170
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('JWTクレーム組み立て').item.json.apiUrl }}",
|
||
"sendHeaders": true,
|
||
"headerParameters": {
|
||
"parameters": [
|
||
{
|
||
"name": "Authorization",
|
||
"value": "=Bearer {{ $('アクセストークン取得').item.json.access_token }}"
|
||
},
|
||
{
|
||
"name": "Content-Type",
|
||
"value": "application/json;charset=UTF-8"
|
||
}
|
||
]
|
||
},
|
||
"sendBody": true,
|
||
"specifyBody": "json",
|
||
"jsonBody": "={{ JSON.stringify({ content: $('追加案内メッセージ組み立て').item.json.messageContent }) }}",
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "exec-hc-sub-fallback",
|
||
"name": "Process実行(フォールバック)",
|
||
"type": "n8n-nodes-base.executeWorkflow",
|
||
"typeVersion": 1.2,
|
||
"position": [
|
||
5480,
|
||
350
|
||
],
|
||
"parameters": {
|
||
"workflowId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "XRqcykbG2LuAjGG2"
|
||
},
|
||
"workflowInputs": {
|
||
"mappingMode": "defineBelow",
|
||
"value": {
|
||
"resultId": "={{ $('テキスト照合').item.json.resultId }}",
|
||
"processId": ""
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-date-parse",
|
||
"name": "日付パース",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
4820,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"jsCode": "const ERA_INFO = {\n \"令和\": 2018,\n \"平成\": 1988,\n \"昭和\": 1925,\n \"大正\": 1911,\n};\n\nconst ERA_ALIASES = { R: \"令和\", H: \"平成\", S: \"昭和\", T: \"大正\" };\n\nfunction pad2(value) {\n return String(value).padStart(2, \"0\");\n}\n\nfunction finalizeDateParts(year, month, day) {\n if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) {\n throw new Error(\"日付形式で回答してください(例: 2026-03-01)\");\n }\n const date = new Date(year, month - 1, day);\n if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {\n throw new Error(\"存在しない日付です\");\n }\n return `${year}-${pad2(month)}-${pad2(day)}`;\n}\n\nfunction tryParseEraDate(compact) {\n const match = compact.match(/^(令和|平成|昭和|大正|R|H|S|T)(.+)$/i);\n if (!match) return null;\n\n let era = match[1];\n if (/^[RHST]$/i.test(era)) {\n era = ERA_ALIASES[era.toUpperCase()] || era;\n }\n if (!ERA_INFO[era]) return null;\n\n const normalized = match[2]\n .replace(/年/g, \"-\")\n .replace(/月/g, \"-\")\n .replace(/日/g, \"\")\n .replace(/[.\\/]/g, \"-\");\n const parts = normalized.split(\"-\").filter((part) => part.length > 0);\n if (parts.length < 3) {\n throw new Error(\"月と日まで入力してください(例: 令和6年3月1日)\");\n }\n\n const eraYear = Number(parts[0]);\n const month = Number(parts[1]);\n const day = Number(parts[2]);\n if (!Number.isFinite(eraYear) || !Number.isFinite(month) || !Number.isFinite(day)) {\n throw new Error(\"日付形式で回答してください(例: 令和6年3月1日)\");\n }\n\n return finalizeDateParts(ERA_INFO[era] + eraYear, month, day);\n}\n\nfunction tryParseMonthDay(compact) {\n const match = compact.match(/^(\\d{1,2})(?:月|\\/|-|\\.)(\\d{1,2})(?:日)?$/);\n if (!match) return null;\n const currentYear = new Date().getFullYear();\n return finalizeDateParts(currentYear, Number(match[1]), Number(match[2]));\n}\n\nfunction parseDateInput(value) {\n const trimmed = String(value ?? \"\").trim();\n if (!trimmed) {\n throw new Error(\"日付が空です\");\n }\n const compact = trimmed.replace(/\\s+/g, \"\");\n\n const eraResult = tryParseEraDate(compact);\n if (eraResult) return eraResult;\n\n const monthDayResult = tryParseMonthDay(compact);\n if (monthDayResult) return monthDayResult;\n\n const normalized = compact\n .replace(/年/g, \"-\")\n .replace(/月/g, \"-\")\n .replace(/日/g, \"\")\n .replace(/[.\\/]/g, \"-\");\n const isoParts = normalized.split(\"-\").filter((part) => part.length > 0);\n if (isoParts.length === 3 && isoParts[0].length >= 4) {\n return finalizeDateParts(Number(isoParts[0]), Number(isoParts[1]), Number(isoParts[2]));\n }\n\n const parsed = new Date(trimmed);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(\"日付形式で回答してください(例: 2026-03-01 や 令和6年3月1日)\");\n }\n return finalizeDateParts(parsed.getFullYear(), parsed.getMonth() + 1, parsed.getDate());\n}\n\nconst text = $('署名検証・送信者解決').item.json.text;\nconst stateItem = $('待機状態取得').item.json;\nlet result;\ntry {\n result = { success: true, parsedDate: parseDateInput(text) };\n} catch (err) {\n result = { success: false, errorMessage: err.message };\n}\n\nreturn [{\n json: {\n resultId: stateItem.resultId,\n awaitProcessId: stateItem.awaitProcessId,\n awaitColumn: stateItem.awaitColumn,\n ...result,\n },\n}];"
|
||
}
|
||
},
|
||
{
|
||
"id": "if-date-parse-ok",
|
||
"name": "日付パース成否判定",
|
||
"type": "n8n-nodes-base.if",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
5040,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"conditions": {
|
||
"options": {
|
||
"caseSensitive": true,
|
||
"leftValue": "",
|
||
"typeValidation": "loose",
|
||
"version": 2
|
||
},
|
||
"conditions": [
|
||
{
|
||
"id": "cond-1",
|
||
"leftValue": "={{ $('日付パース').item.json.success }}",
|
||
"rightValue": true,
|
||
"operator": {
|
||
"type": "boolean",
|
||
"operation": "true",
|
||
"singleValue": true
|
||
}
|
||
}
|
||
],
|
||
"combinator": "and"
|
||
},
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "http-date-column-update",
|
||
"name": "該当列update",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
5260,
|
||
420
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('PLEASANTER_BASE_URL取得').item.json.configValue }}api/items/{{ $('日付パース').item.json.resultId }}/update",
|
||
"sendBody": true,
|
||
"specifyBody": "json",
|
||
"jsonBody": "={{ JSON.stringify({ ApiVersion: 1.1, ApiKey: $('PLEASANTER_API_KEY取得').item.json.configValue, DateHash: { [$('日付パース').item.json.awaitColumn]: $('日付パース').item.json.parsedDate } }) }}",
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-update-state-reset-date",
|
||
"name": "待機状態リセット(日付)",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
5480,
|
||
420
|
||
],
|
||
"parameters": {
|
||
"operation": "update",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "jqMDa2YZTI4f0iQ7"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "resultId",
|
||
"keyValue": "={{ String($('日付パース').item.json.resultId) }}"
|
||
}
|
||
]
|
||
},
|
||
"columns": {
|
||
"mappingMode": "defineBelow",
|
||
"value": {
|
||
"awaitInput": "none",
|
||
"awaitProcessId": "",
|
||
"awaitColumn": ""
|
||
},
|
||
"schema": [
|
||
{
|
||
"id": "awaitInput",
|
||
"displayName": "awaitInput",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
},
|
||
{
|
||
"id": "awaitProcessId",
|
||
"displayName": "awaitProcessId",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
},
|
||
{
|
||
"id": "awaitColumn",
|
||
"displayName": "awaitColumn",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "exec-hc-sub-date-done",
|
||
"name": "Process実行(日付完了)",
|
||
"type": "n8n-nodes-base.executeWorkflow",
|
||
"typeVersion": 1.2,
|
||
"position": [
|
||
5700,
|
||
420
|
||
],
|
||
"parameters": {
|
||
"workflowId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "XRqcykbG2LuAjGG2"
|
||
},
|
||
"workflowInputs": {
|
||
"mappingMode": "defineBelow",
|
||
"value": {
|
||
"resultId": "={{ $('日付パース').item.json.resultId }}",
|
||
"processId": "={{ $('日付パース').item.json.awaitProcessId }}"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-date-error-message",
|
||
"name": "日付エラーメッセージ組み立て",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
5260,
|
||
600
|
||
],
|
||
"parameters": {
|
||
"jsCode": "const errorMessage = $('日付パース').item.json.errorMessage;\nreturn [{ json: { messageContent: { type: 'text', text: errorMessage } } }];"
|
||
}
|
||
},
|
||
{
|
||
"id": "http-date-error-send",
|
||
"name": "日付エラー送信",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
5480,
|
||
600
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('JWTクレーム組み立て').item.json.apiUrl }}",
|
||
"sendHeaders": true,
|
||
"headerParameters": {
|
||
"parameters": [
|
||
{
|
||
"name": "Authorization",
|
||
"value": "=Bearer {{ $('アクセストークン取得').item.json.access_token }}"
|
||
},
|
||
{
|
||
"name": "Content-Type",
|
||
"value": "application/json;charset=UTF-8"
|
||
}
|
||
]
|
||
},
|
||
"sendBody": true,
|
||
"specifyBody": "json",
|
||
"jsonBody": "={{ JSON.stringify({ content: $('日付エラーメッセージ組み立て').item.json.messageContent }) }}",
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "if-content-is-file",
|
||
"name": "ファイル判定",
|
||
"type": "n8n-nodes-base.if",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
4820,
|
||
800
|
||
],
|
||
"parameters": {
|
||
"conditions": {
|
||
"options": {
|
||
"caseSensitive": true,
|
||
"leftValue": "",
|
||
"typeValidation": "loose",
|
||
"version": 2
|
||
},
|
||
"conditions": [
|
||
{
|
||
"id": "cond-1",
|
||
"leftValue": "={{ $('署名検証・送信者解決').item.json.contentType === 'file' }}",
|
||
"rightValue": true,
|
||
"operator": {
|
||
"type": "boolean",
|
||
"operation": "true",
|
||
"singleValue": true
|
||
}
|
||
}
|
||
],
|
||
"combinator": "and"
|
||
},
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "http-lineworks-file-download",
|
||
"name": "LINEWORKSファイルダウンロード",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
5040,
|
||
720
|
||
],
|
||
"parameters": {
|
||
"method": "GET",
|
||
"url": "={{ 'https://www.worksapis.com/v1.0/bots/' + $('JWTクレーム組み立て').item.json.botId + '/attachments/' + $('署名検証・送信者解決').item.json.fileId }}",
|
||
"sendHeaders": true,
|
||
"headerParameters": {
|
||
"parameters": [
|
||
{
|
||
"name": "Authorization",
|
||
"value": "=Bearer {{ $('アクセストークン取得').item.json.access_token }}"
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"response": {
|
||
"response": {
|
||
"responseFormat": "file"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "http-pleasanter-attachment-upload",
|
||
"name": "Pleasanter添付アップロード",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
5260,
|
||
720
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('PLEASANTER_BASE_URL取得').item.json.configValue }}api/binaries/upload",
|
||
"sendBody": true,
|
||
"contentType": "multipart-form-data",
|
||
"bodyParameters": {
|
||
"parameters": [
|
||
{
|
||
"parameterType": "formData",
|
||
"name": "ApiKey",
|
||
"value": "={{ $('PLEASANTER_API_KEY取得').item.json.configValue }}"
|
||
},
|
||
{
|
||
"parameterType": "formBinaryData",
|
||
"name": "file",
|
||
"inputDataFieldName": "data"
|
||
}
|
||
]
|
||
},
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "dt-update-state-reset-file",
|
||
"name": "待機状態リセット(ファイル)",
|
||
"type": "n8n-nodes-base.dataTable",
|
||
"typeVersion": 1,
|
||
"position": [
|
||
5480,
|
||
720
|
||
],
|
||
"parameters": {
|
||
"operation": "update",
|
||
"dataTableId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "jqMDa2YZTI4f0iQ7"
|
||
},
|
||
"filters": {
|
||
"conditions": [
|
||
{
|
||
"keyName": "resultId",
|
||
"keyValue": "={{ String($('待機状態取得').item.json.resultId) }}"
|
||
}
|
||
]
|
||
},
|
||
"columns": {
|
||
"mappingMode": "defineBelow",
|
||
"value": {
|
||
"awaitInput": "none",
|
||
"awaitProcessId": "",
|
||
"awaitColumn": ""
|
||
},
|
||
"schema": [
|
||
{
|
||
"id": "awaitInput",
|
||
"displayName": "awaitInput",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
},
|
||
{
|
||
"id": "awaitProcessId",
|
||
"displayName": "awaitProcessId",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
},
|
||
{
|
||
"id": "awaitColumn",
|
||
"displayName": "awaitColumn",
|
||
"required": false,
|
||
"type": "string",
|
||
"canBeUsedToMatch": true
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "exec-hc-sub-file-done",
|
||
"name": "Process実行(ファイル完了)",
|
||
"type": "n8n-nodes-base.executeWorkflow",
|
||
"typeVersion": 1.2,
|
||
"position": [
|
||
5700,
|
||
720
|
||
],
|
||
"parameters": {
|
||
"workflowId": {
|
||
"__rl": true,
|
||
"mode": "id",
|
||
"value": "XRqcykbG2LuAjGG2"
|
||
},
|
||
"workflowInputs": {
|
||
"mappingMode": "defineBelow",
|
||
"value": {
|
||
"resultId": "={{ $('待機状態取得').item.json.resultId }}",
|
||
"processId": "={{ $('待機状態取得').item.json.awaitProcessId }}"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "code-file-missing-message",
|
||
"name": "ファイル未着メッセージ組み立て",
|
||
"type": "n8n-nodes-base.code",
|
||
"typeVersion": 2,
|
||
"position": [
|
||
5040,
|
||
900
|
||
],
|
||
"parameters": {
|
||
"jsCode": "return [{ json: { messageContent: { type: 'text', text: 'ファイルを送信してください(テキストではなくファイルを添付して送信してください)' } } }];"
|
||
}
|
||
},
|
||
{
|
||
"id": "http-file-missing-send",
|
||
"name": "ファイル未着送信",
|
||
"type": "n8n-nodes-base.httpRequest",
|
||
"typeVersion": 4.2,
|
||
"position": [
|
||
5260,
|
||
900
|
||
],
|
||
"parameters": {
|
||
"method": "POST",
|
||
"url": "={{ $('JWTクレーム組み立て').item.json.apiUrl }}",
|
||
"sendHeaders": true,
|
||
"headerParameters": {
|
||
"parameters": [
|
||
{
|
||
"name": "Authorization",
|
||
"value": "=Bearer {{ $('アクセストークン取得').item.json.access_token }}"
|
||
},
|
||
{
|
||
"name": "Content-Type",
|
||
"value": "application/json;charset=UTF-8"
|
||
}
|
||
]
|
||
},
|
||
"sendBody": true,
|
||
"specifyBody": "json",
|
||
"jsonBody": "={{ JSON.stringify({ content: $('ファイル未着メッセージ組み立て').item.json.messageContent }) }}",
|
||
"options": {}
|
||
}
|
||
},
|
||
{
|
||
"id": "respond-ok",
|
||
"name": "Respond to Webhook",
|
||
"type": "n8n-nodes-base.respondToWebhook",
|
||
"typeVersion": 1.1,
|
||
"position": [
|
||
6360,
|
||
500
|
||
],
|
||
"parameters": {
|
||
"respondWith": "json",
|
||
"responseBody": "={{ JSON.stringify({ result: \"ok\" }) }}",
|
||
"options": {}
|
||
}
|
||
}
|
||
],
|
||
"connections": {
|
||
"Webhook": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "LINEWORKS_BOT_SECRET取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"LINEWORKS_BOT_SECRET取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "署名検証・送信者解決",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"署名検証・送信者解決": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "PLEASANTER_BASE_URL取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"PLEASANTER_BASE_URL取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "PLEASANTER_API_KEY取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"PLEASANTER_API_KEY取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "HEALTHCHECK_SITE_ID取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"HEALTHCHECK_SITE_ID取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "対象者UserId解決",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"対象者UserId解決": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "対象者UserId特定",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"対象者UserId特定": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "対象レコード検索",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"対象レコード検索": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "対象レコード選定",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"対象レコード選定": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "待機状態取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"待機状態取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "サイト設定取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"サイト設定取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "LW_BOT_CLIENT_ID取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"LW_BOT_CLIENT_ID取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "LW_BOT_CLIENT_SECRET取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"LW_BOT_CLIENT_SECRET取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "LW_BOT_SERVICE_ACCOUNT取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"LW_BOT_SERVICE_ACCOUNT取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "LINEWORKS_BOT_MASTER_SITE_ID取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"LINEWORKS_BOT_MASTER_SITE_ID取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Botマスタ取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"Botマスタ取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "JWTクレーム組み立て",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"JWTクレーム組み立て": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Sign JWT",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"Sign JWT": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "アクセストークン取得",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"アクセストークン取得": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "awaitInput分岐",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"awaitInput分岐": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "テキスト照合",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
],
|
||
[
|
||
{
|
||
"node": "日付パース",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
],
|
||
[
|
||
{
|
||
"node": "ファイル判定",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"テキスト照合": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "テキスト一致判定",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"テキスト一致判定": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "入力待ち種別判定",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
],
|
||
[
|
||
{
|
||
"node": "Process実行(フォールバック)",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"入力待ち種別判定": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "即時実行判定",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"即時実行判定": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Process実行(即時)",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
],
|
||
[
|
||
{
|
||
"node": "待機状態保存(入力待ち)",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"待機状態保存(入力待ち)": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "追加案内メッセージ組み立て",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"追加案内メッセージ組み立て": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "追加案内送信",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"Process実行(即時)": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Respond to Webhook",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"追加案内送信": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Respond to Webhook",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"Process実行(フォールバック)": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Respond to Webhook",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"日付パース": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "日付パース成否判定",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"日付パース成否判定": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "該当列update",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
],
|
||
[
|
||
{
|
||
"node": "日付エラーメッセージ組み立て",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"該当列update": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "待機状態リセット(日付)",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"待機状態リセット(日付)": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Process実行(日付完了)",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"日付エラーメッセージ組み立て": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "日付エラー送信",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"Process実行(日付完了)": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Respond to Webhook",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"日付エラー送信": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Respond to Webhook",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"ファイル判定": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "LINEWORKSファイルダウンロード",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
],
|
||
[
|
||
{
|
||
"node": "ファイル未着メッセージ組み立て",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"LINEWORKSファイルダウンロード": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Pleasanter添付アップロード",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"Pleasanter添付アップロード": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "待機状態リセット(ファイル)",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"待機状態リセット(ファイル)": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Process実行(ファイル完了)",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"ファイル未着メッセージ組み立て": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "ファイル未着送信",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"Process実行(ファイル完了)": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Respond to Webhook",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
},
|
||
"ファイル未着送信": {
|
||
"main": [
|
||
[
|
||
{
|
||
"node": "Respond to Webhook",
|
||
"type": "main",
|
||
"index": 0
|
||
}
|
||
]
|
||
]
|
||
}
|
||
},
|
||
"settings": {
|
||
"executionOrder": "v1"
|
||
}
|
||
}
|