{ "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 }, "alwaysOutputData": 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": [ 6140, 170 ], "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": [ 6360, 170 ], "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": [ 6580, 170 ], "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": [ 6800, 170 ], "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": { "fallbackOutput": "extra" } } }, { "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": [ 7020, 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": [ 6600, 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": [ 5920, 720 ], "parameters": { "method": "GET", "url": "={{ 'https://www.worksapis.com/v1.0/bots/' + $('JWTクレーム組み立て(ファイルDL)').item.json.botId + '/attachments/' + $('署名検証・送信者解決').item.json.fileId }}", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Authorization", "value": "=Bearer {{ $('アクセストークン取得(ファイルDL)').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": [ 6140, 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": [ 6360, 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": [ 6580, 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": [ 6380, 950 ], "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": [ 8200, 500 ], "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify({ result: \"ok\" }) }}", "options": {} } }, { "id": "http-bot-master-get-dateerr", "name": "Botマスタ取得(日付エラー)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 5480, 600 ], "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-dateerr", "name": "JWTクレーム組み立て(日付エラー)", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 5700, 600 ], "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-dateerr", "name": "Sign JWT(日付エラー)", "type": "n8n-nodes-base.jwt", "typeVersion": 1, "position": [ 5920, 600 ], "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-dateerr", "name": "アクセストークン取得(日付エラー)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 6140, 600 ], "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": "http-bot-master-get-filemiss", "name": "Botマスタ取得(ファイル未着)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 5260, 950 ], "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-filemiss", "name": "JWTクレーム組み立て(ファイル未着)", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 5480, 950 ], "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-filemiss", "name": "Sign JWT(ファイル未着)", "type": "n8n-nodes-base.jwt", "typeVersion": 1, "position": [ 5700, 950 ], "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-filemiss", "name": "アクセストークン取得(ファイル未着)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 5920, 950 ], "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": "http-bot-master-get-filedl", "name": "Botマスタ取得(ファイルDL)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 5040, 650 ], "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-filedl", "name": "JWTクレーム組み立て(ファイルDL)", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 5260, 650 ], "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マスタ取得(ファイルDL)').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-filedl", "name": "Sign JWT(ファイルDL)", "type": "n8n-nodes-base.jwt", "typeVersion": 1, "position": [ 5480, 650 ], "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-filedl", "name": "アクセストークン取得(ファイルDL)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 5700, 650 ], "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": "if-state-exists", "name": "待機状態存在チェック", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [ 2400, 680 ], "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "loose", "version": 2 }, "conditions": [ { "id": "cond-1", "leftValue": "={{ !!($('待機状態取得').item.json.awaitInput) }}", "rightValue": true, "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} } }, { "id": "respond-error-no-state", "name": "Respond to Webhook(待機状態エラー)", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [ 2620, 800 ], "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify({ result: \"error\", message: \"待機状態が見つかりません\" }) }}", "options": {} } }, { "id": "respond-error-switch-fallback", "name": "Respond to Webhook(分岐エラー)", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [ 4820, 1150 ], "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify({ result: \"error\", message: \"未対応のawaitInput値です: \" + ($('待機状態取得').item.json.awaitInput ?? '(undefined)') }) }}", "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": "awaitInput分岐", "type": "main", "index": 0 } ] ] }, "awaitInput分岐": { "main": [ [ { "node": "テキスト照合", "type": "main", "index": 0 } ], [ { "node": "日付パース", "type": "main", "index": 0 } ], [ { "node": "ファイル判定", "type": "main", "index": 0 } ], [ { "node": "Respond to Webhook(分岐エラー)", "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": "Botマスタ取得", "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": "Botマスタ取得(日付エラー)", "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": "Botマスタ取得(ファイルDL)", "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": "Botマスタ取得(ファイル未着)", "type": "main", "index": 0 } ] ] }, "Process実行(ファイル完了)": { "main": [ [ { "node": "Respond to Webhook", "type": "main", "index": 0 } ] ] }, "ファイル未着送信": { "main": [ [ { "node": "Respond to Webhook", "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": "追加案内送信", "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": "日付エラー送信", "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": "ファイル未着送信", "type": "main", "index": 0 } ] ] }, "Botマスタ取得(ファイルDL)": { "main": [ [ { "node": "JWTクレーム組み立て(ファイルDL)", "type": "main", "index": 0 } ] ] }, "JWTクレーム組み立て(ファイルDL)": { "main": [ [ { "node": "Sign JWT(ファイルDL)", "type": "main", "index": 0 } ] ] }, "Sign JWT(ファイルDL)": { "main": [ [ { "node": "アクセストークン取得(ファイルDL)", "type": "main", "index": 0 } ] ] }, "アクセストークン取得(ファイルDL)": { "main": [ [ { "node": "LINEWORKSファイルダウンロード", "type": "main", "index": 0 } ] ] }, "待機状態存在チェック": { "main": [ [ { "node": "サイト設定取得", "type": "main", "index": 0 } ], [ { "node": "Respond to Webhook(待機状態エラー)", "type": "main", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1" } }