{
  "name": "WF03: YouTube\u767b\u9332\u8005\u6570\u66f4\u65b0",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 3 * * *"
            }
          ]
        }
      },
      "id": "schedule-trigger",
      "name": "\u6bce\u65e53\u6642\u30b9\u30b1\u30b8\u30e5\u30fc\u30eb\uff08\u4f4e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u6642\u9593\u5e2f\uff09",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        300
      ],
      "notes": "YouTube API quota\u7bc0\u7d04\u306e\u305f\u3081\u6df1\u591c3\u6642\u306b\u5b9f\u884c"
    },
    {
      "parameters": {
        "method": "GET",
        "url": "http://localhost:10004/wp-json/wp/v2/vtubers",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "per_page",
              "value": "100"
            },
            {
              "name": "status",
              "value": "publish"
            },
            {
              "name": "_fields",
              "value": "id,slug,meta"
            }
          ]
        }
      },
      "id": "wp-get-vtubers",
      "name": "WP REST API: \u5168Vtubers\u53d6\u5f97",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        460,
        300
      ],
      "notes": "TODO: \u30da\u30fc\u30b8\u30cd\u30fc\u30b7\u30e7\u30f3\u5bfe\u5fdc\uff08100\u4ef6\u8d85\u306e\u5834\u5408\uff09"
    },
    {
      "parameters": {
        "jsCode": "// YouTube\u30c1\u30e3\u30f3\u30cd\u30ebID\u3092\u62bd\u51fa\nconst items = $input.all();\nconst vtubers = items.map(item => {\n  const meta = item.json.meta || {};\n  const ytUrl = meta.vt_sns_youtube || '';\n  \n  // \u30c1\u30e3\u30f3\u30cd\u30ebID\u306e\u62bd\u51fa\u30d1\u30bf\u30fc\u30f3:\n  // https://www.youtube.com/channel/UCxxxxxxxxxxxxxxxx\n  // https://www.youtube.com/@channelname\n  let channelId = '';\n  const channelMatch = ytUrl.match(/youtube\\.com\\/channel\\/([a-zA-Z0-9_-]+)/);\n  const handleMatch = ytUrl.match(/youtube\\.com\\/@([a-zA-Z0-9_.-]+)/);\n  \n  if (channelMatch) {\n    channelId = channelMatch[1];\n  } else if (handleMatch) {\n    // @\u30cf\u30f3\u30c9\u30eb\u5f62\u5f0f\u306fYouTube API\u3067forHandle\u3092\u4f7f\u3046\n    channelId = '@' + handleMatch[1];\n  }\n  \n  return {\n    wp_post_id: item.json.id,\n    slug: item.json.slug,\n    channel_id: channelId,\n    yt_url: ytUrl,\n    is_retired: meta.vt_is_retired || false\n  };\n}).filter(v => v.channel_id && !v.is_retired); // \u5f15\u9000\u6e08\u307f\u3068\u30c1\u30e3\u30f3\u30cd\u30ebID\u672a\u8a2d\u5b9a\u3092\u9664\u5916\n\nreturn vtubers;"
      },
      "id": "extract-channel-ids",
      "name": "\u30c1\u30e3\u30f3\u30cd\u30ebID\u62bd\u51fa",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ]
    },
    {
      "parameters": {
        "batchSize": 50,
        "options": {}
      },
      "id": "split-batches",
      "name": "50\u4ef6\u305a\u3064\u30d0\u30c3\u30c1\u51e6\u7406",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        900,
        300
      ],
      "notes": "YouTube API: channels.list \u306f1\u30ea\u30af\u30a8\u30b9\u30c8\u6700\u592750\u4ef6"
    },
    {
      "parameters": {
        "jsCode": "// TODO: YouTube Data API v3 \u547c\u3073\u51fa\u3057\u5b9f\u88c5\n// \u73fe\u5728\u306f\u30b9\u30b1\u30eb\u30c8\u30f3\u5b9f\u88c5\n// \n// \u5b9f\u88c5\u624b\u9806:\n// 1. YouTube\u30c1\u30e3\u30f3\u30cd\u30ebID\u3092\u53ce\u96c6\uff08\u6700\u592750\u4ef6\uff09\n// 2. YouTube Data API v3 channels.list \u306b\u30ea\u30af\u30a8\u30b9\u30c8\n//    GET https://www.googleapis.com/youtube/v3/channels\n//    ?part=statistics\n//    &id=UC1234,UC5678,...\n//    &key={{ $env.YOUTUBE_API_KEY }}\n// 3. \u5404\u30c1\u30e3\u30f3\u30cd\u30eb\u306e subscriberCount, viewCount \u3092\u53d6\u5f97\n// 4. WP REST API \u3067 vt_subscribers_yt, vt_total_views \u3092\u66f4\u65b0\n//\n// YouTube API Quota: 1\u30e6\u30cb\u30c3\u30c8/\u30ea\u30af\u30a8\u30b9\u30c8\uff08channels.list with statistics\uff09\n// 1\u65e5\u306e\u4e0a\u9650: 10,000\u30e6\u30cb\u30c3\u30c8\n\nconst items = $input.all();\nconst channelIds = items\n  .map(i => i.json.channel_id)\n  .filter(id => id && !id.startsWith('@')) // @\u30cf\u30f3\u30c9\u30eb\u306f\u5225\u51e6\u7406\u304c\u5fc5\u8981\n  .join(',');\n\n// \u30d7\u30ec\u30fc\u30b9\u30db\u30eb\u30c0\u30fc: \u5b9f\u969b\u306eAPI\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u6a21\u5023\n// \u672c\u5b9f\u88c5\u6642\u306f\u3053\u306e\u30ce\u30fc\u30c9\u306e\u4ee3\u308f\u308a\u306bHTTP Request\u30ce\u30fc\u30c9\u3092\u4f7f\u7528\nreturn items.map(item => ({\n  ...item.json,\n  api_ready: true,\n  channel_ids_batch: channelIds,\n  note: 'TODO: YouTube API\u5b9f\u88c5\u304c\u5fc5\u8981'\n}));"
      },
      "id": "yt-api-placeholder",
      "name": "YouTube API: \u767b\u9332\u8005\u6570\u53d6\u5f97\uff08TODO\uff09",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        300
      ],
      "notes": "\u5b9f\u88c5TODO: YouTube Data API v3 channels.list \u3092\u547c\u3073\u51fa\u3059"
    },
    {
      "parameters": {
        "jsCode": "// TODO: WP REST API \u3067\u30e1\u30bf\u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u66f4\u65b0\u3059\u308b\u5b9f\u88c5\n// \n// \u5b9f\u88c5\u624b\u9806:\n// 1. YouTube API\u304b\u3089\u306e\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u53d7\u3051\u53d6\u308b\n// 2. \u5404Vtuber\u306eWP\u6295\u7a3fID\u306b\u5bfe\u3057\u3066 PATCH \u30ea\u30af\u30a8\u30b9\u30c8:\n//    PATCH http://localhost:10004/wp-json/wp/v2/vtubers/{id}\n//    Body: { meta: { vt_subscribers_yt: 12345, vt_total_views: 9876543, vt_subscribers_updated: '2026-03-18T03:00:00Z' } }\n//\n// \u73fe\u5728\u306f\u30b9\u30b1\u30eb\u30c8\u30f3\u5b9f\u88c5\u306e\u305f\u3081\u30ed\u30b0\u51fa\u529b\u306e\u307f\n\nconst items = $input.all();\nconst summary = {\n  processed: items.length,\n  timestamp: new Date().toISOString(),\n  status: 'skeleton - YouTube API\u5b9f\u88c5\u5f8c\u306b\u6709\u52b9\u5316',\n  items: items.map(i => ({\n    wp_post_id: i.json.wp_post_id,\n    slug: i.json.slug,\n    channel_id: i.json.channel_id\n  }))\n};\n\nconsole.log('WF03\u5b9f\u884c\u30b5\u30de\u30ea\u30fc:', JSON.stringify(summary, null, 2));\nreturn [{ summary }];"
      },
      "id": "wp-update-meta",
      "name": "WP REST API: \u30e1\u30bf\u66f4\u65b0\uff08TODO\uff09",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1340,
        300
      ],
      "notes": "\u5b9f\u88c5TODO: WP REST API\u3067vt_subscribers_yt\u3092\u66f4\u65b0\u3059\u308b"
    }
  ],
  "connections": {
    "\u6bce\u65e53\u6642\u30b9\u30b1\u30b8\u30e5\u30fc\u30eb\uff08\u4f4e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u6642\u9593\u5e2f\uff09": {
      "main": [
        [
          {
            "node": "WP REST API: \u5168Vtubers\u53d6\u5f97",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WP REST API: \u5168Vtubers\u53d6\u5f97": {
      "main": [
        [
          {
            "node": "\u30c1\u30e3\u30f3\u30cd\u30ebID\u62bd\u51fa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u30c1\u30e3\u30f3\u30cd\u30ebID\u62bd\u51fa": {
      "main": [
        [
          {
            "node": "50\u4ef6\u305a\u3064\u30d0\u30c3\u30c1\u51e6\u7406",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "50\u4ef6\u305a\u3064\u30d0\u30c3\u30c1\u51e6\u7406": {
      "main": [
        [
          {
            "node": "YouTube API: \u767b\u9332\u8005\u6570\u53d6\u5f97\uff08TODO\uff09",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "YouTube API: \u767b\u9332\u8005\u6570\u53d6\u5f97\uff08TODO\uff09": {
      "main": [
        [
          {
            "node": "WP REST API: \u30e1\u30bf\u66f4\u65b0\uff08TODO\uff09",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": ""
  },
  "staticData": null,
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "id": "wf03-yt-update",
  "tags": [
    {
      "id": "vtuber",
      "name": "vtuber"
    },
    {
      "id": "youtube",
      "name": "youtube"
    },
    {
      "id": "update",
      "name": "update"
    }
  ],
  "active": false,
  "versionId": "1.0.0",
  "_comment": {
    "\u8aac\u660e": "WF03: YouTube\u767b\u9332\u8005\u6570\u30fb\u518d\u751f\u6570\u306e\u5b9a\u671f\u66f4\u65b0\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\uff08\u30b9\u30b1\u30eb\u30c8\u30f3\u5b9f\u88c5\uff09",
    "\u30d5\u30ed\u30fc": "\u6bce\u65e53\u6642 \u2192 WP REST API\u3067\u5168vtubers\u53d6\u5f97 \u2192 \u30c1\u30e3\u30f3\u30cd\u30ebID\u62bd\u51fa \u2192 YouTube API channels.list\uff0850\u4ef6\u30d0\u30c3\u30c1\uff09\u2192 WP REST API\u3067\u30e1\u30bf\u66f4\u65b0",
    "\u5b9f\u88c5TODO": [
      "YouTube Data API v3 \u306e\u8a8d\u8a3c\u60c5\u5831\u8a2d\u5b9a\uff08Google API Key\uff09",
      "channels.list\u30ce\u30fc\u30c9\u306e\u5b9f\u88c5\uff08HTTP Request\u30ce\u30fc\u30c9\uff09",
      "@\u30cf\u30f3\u30c9\u30eb\u5f62\u5f0f\u306e\u30c1\u30e3\u30f3\u30cd\u30ebID\u89e3\u6c7a\uff08forHandle \u30d1\u30e9\u30e1\u30fc\u30bf\uff09",
      "WP REST API PATCH \u30ea\u30af\u30a8\u30b9\u30c8\u306e\u5b9f\u88c5",
      "API quota\u7ba1\u7406\uff081\u65e510,000\u30e6\u30cb\u30c3\u30c8\u4e0a\u9650\uff09",
      "100\u4ef6\u8d85\u306eVtubers\u5bfe\u5fdc\uff08WP\u30da\u30fc\u30b8\u30cd\u30fc\u30b7\u30e7\u30f3\uff09"
    ],
    "YouTube API quota\u6982\u7b97": {
      "channels.list with statistics": "1\u30e6\u30cb\u30c3\u30c8/\u30ea\u30af\u30a8\u30b9\u30c8",
      "50\u4ef6\u30d0\u30c3\u30c1": "200Vtuber\u30674\u30ea\u30af\u30a8\u30b9\u30c8 = 4\u30e6\u30cb\u30c3\u30c8/\u65e5",
      "\u4e0a\u9650": "10,000\u30e6\u30cb\u30c3\u30c8/\u65e5\uff08\u4f59\u88d5\u3042\u308a\uff09"
    }
  }
}