{
  "name": "Capslane: Google Sheets URL to saved transcript (HTTP)",
  "nodes": [
    {
      "id": "new-url-row",
      "name": "New URL row",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "typeVersion": 1,
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "event": "rowAdded",
        "options": {}
      },
      "position": [
        0,
        0
      ]
    },
    {
      "id": "validate-input",
      "name": "Validate input",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "if (!String($input.item.json.id ?? '').trim()) throw new Error('Each input row needs a unique non-empty id.');\nconst row = $input.item.json;\nconst value = String(row.url ?? '').trim();\nconst short = value.match(/^https:\\/\\/youtu\\.be\\/([A-Za-z0-9_-]{11})(?:[/?#].*)?$/);\nconst shorts = value.match(/^https:\\/\\/(?:www\\.|m\\.)?youtube\\.com\\/shorts\\/([A-Za-z0-9_-]{11})(?:[/?#].*)?$/);\nconst watch = value.match(/^https:\\/\\/(?:www\\.|m\\.)?youtube\\.com\\/watch\\?([^#]*)/);\nconst videoId = /^[A-Za-z0-9_-]{11}$/.test(value) ? value : short?.[1] ?? shorts?.[1] ?? watch?.[1].match(/(?:^|&)v=([A-Za-z0-9_-]{11})(?:&|$)/)?.[1];\nif (!videoId) throw new Error('Provide a public YouTube URL or an 11-character video ID in url.');\nreturn { json: { ...row, videoId, url: 'https://www.youtube.com/watch?v=' + videoId } };"
      },
      "position": [
        240,
        0
      ]
    },
    {
      "id": "get-native-transcript",
      "name": "Get native transcript",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "parameters": {
        "url": "https://capslane.com/v1/transcript",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json.videoId }}"
            },
            {
              "name": "mode",
              "value": "native"
            },
            {
              "name": "text",
              "value": "false"
            },
            {
              "name": "chunkSize",
              "value": "1000"
            }
          ]
        },
        "options": {
          "timeout": 45000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          },
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          }
        }
      },
      "position": [
        480,
        0
      ]
    },
    {
      "id": "prepare-row",
      "name": "Prepare row",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const response = $input.item.json;\nconst row = $('Validate input').item.json;\nif (!String(row.id ?? '').trim()) throw new Error('Each input row needs a unique non-empty id.');\nif (!Array.isArray(response.content)) throw new Error('No complete transcript returned. Check the execution error; do not write a job ID as a transcript.');\nconst text = response.content.map(segment => segment.text).join(' ');\nif (!text.trim()) throw new Error('The returned transcript is empty.');\nif (text.length > 45000) throw new Error('Transcript exceeds this template\\'s 45,000-character cell budget. Use the Markdown workflow to keep the complete text.');\nreturn { json: { id: String(row.id), url: row.url, transcript: text, language: response.lang, status: 'done' } };"
      },
      "position": [
        720,
        0
      ]
    },
    {
      "id": "save-transcript",
      "name": "Save transcript",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "parameters": {
        "resource": "sheet",
        "operation": "update",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "id": "={{ $json.id }}",
            "url": "={{ $json.url }}",
            "transcript": "={{ $json.transcript }}",
            "language": "={{ $json.language }}",
            "status": "={{ $json.status }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "displayName": "url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "transcript",
              "displayName": "transcript",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "language",
              "displayName": "language",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "displayName": "status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ]
        },
        "options": {
          "cellFormat": "RAW"
        }
      },
      "position": [
        960,
        0
      ]
    }
  ],
  "connections": {
    "New URL row": {
      "main": [
        [
          {
            "node": "Validate input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate input": {
      "main": [
        [
          {
            "node": "Get native transcript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get native transcript": {
      "main": [
        [
          {
            "node": "Prepare row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare row": {
      "main": [
        [
          {
            "node": "Save transcript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}
