{
  "nodes": [
    {
      "id": "b002f21b-0426-4a0d-ae4b-456b353d1b9a",
      "name": "Update JSON Catalog",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2864,
        128
      ],
      "parameters": {
        "color": 3,
        "width": 2056,
        "height": 328,
        "content": "## Update JSON Catalog"
      },
      "typeVersion": 1
    },
    {
      "id": "f4d4700e-e055-4581-8aa4-9319bceb2d2d",
      "name": "Process Videos",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2864,
        512
      ],
      "parameters": {
        "color": 7,
        "width": 2056,
        "height": 296,
        "content": "## Process Videos"
      },
      "typeVersion": 1
    },
    {
      "id": "ff58825b-0663-4acc-a28e-48358b03d0ce",
      "name": "Fetch & Filter",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1248,
        528
      ],
      "parameters": {
        "color": 6,
        "width": 1076,
        "height": 296,
        "content": "## Fetch & Filter"
      },
      "typeVersion": 1
    },
    {
      "id": "19f3bae2-2df1-47d2-b1b8-39604eb3ceec",
      "name": "Setup Instructions",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 860,
        "height": 900,
        "content": "## Instagram Video Backup to Google Drive\n\nAutomatically backs up Instagram videos (VIDEO and REELS) to Google Drive with searchable JSON metadata catalog.\n\n## Setup Instructions\n\n### 1. Create Google Drive Folder\n   - Create a dedicated folder in Google Drive\n   - Copy the folder ID from the URL\n   - Example: `https://drive.google.com/drive/folders/1tsSr_Ky0...` \u2192 ID is `1tsSr_Ky0...`\n\n###  2. Create Data Table: \"Instagram Video Backups\"\n   Required fields:\n   - `postId` (string, primary key)\n   - `accountId` (string)\n   - `title` (string)\n   - `description` (string)\n   - `descriptionFull` (string)\n   - `tagList` (string)\n\n### 3. Add Credentials\n   - Instagram: HTTP Bearer Auth with access token\n   - Google Drive: OAuth2 account\n\n### 4. Configure Workflow\n   - Update Configuration node with your Google Drive folder ID\n   - Adjust `maxVideosPerRun` if needed (default: 100)\n\n### 5. Test\n   - Run with Manual Trigger first\n   - Check Google Drive for uploaded videos\n   - Verify metadata JSON file is created\n\n### Schedule:\n   -Daily at midnight (customizable)"
      },
      "typeVersion": 1
    },
    {
      "id": "89183b88-0910-40cd-b666-5b4ae3307130",
      "name": "Upload New Metadata File",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        3376,
        240
      ],
      "parameters": {
        "name": "={{ $('Build Metadata from Data Table').item.json.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Configuration').first().json.googleDriveFolderId }}"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "inputsOverride": {
        "main": [
          {
            "sourcePath": "$('Build Metadata from Data Table')"
          }
        ]
      }
    },
    {
      "id": "e3f0c373-5228-4531-9e72-d0eedefdf55f",
      "name": "List All Metadata Files",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3600,
        240
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/drive/v3/files",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "=name='{{ $('Configuration').first().json.metadataFileName }}' and '{{ $('Configuration').first().json.googleDriveFolderId }}' in parents and trashed=false"
            },
            {
              "name": "fields",
              "value": "files(id,name,createdTime)"
            },
            {
              "name": "orderBy",
              "value": "createdTime"
            }
          ]
        },
        "nodeCredentialType": "googleDriveOAuth2Api"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "cff11e7f-8989-432e-9a2f-4fa1ba0a3139",
      "name": "Find Old Metadata Files",
      "type": "n8n-nodes-base.code",
      "position": [
        3824,
        240
      ],
      "parameters": {
        "jsCode": "// Get all metadata files from Google Drive API response\nconst response = $input.item.json;\nconst allFiles = response.files || [];\n\nconsole.log('Total metadata files found:', allFiles.length);\n\n// If only 1 or no files, don't delete anything\nif (allFiles.length <= 1) {\n  console.log('Only one or no metadata files - nothing to delete');\n  return [];\n}\n\n// Sort by creation time to ensure newest is last\nallFiles.sort((a, b) => {\n  const dateA = new Date(a.createdTime);\n  const dateB = new Date(b.createdTime);\n  return dateA - dateB;\n});\n\n// Keep only the newest file (last in array), delete all others\nconst newestFile = allFiles[allFiles.length - 1];\nconst filesToDelete = allFiles.slice(0, -1); // All files except the last one\n\nconsole.log('Newest file (keeping):', newestFile.name, 'created:', newestFile.createdTime);\nconsole.log('Files to delete:', filesToDelete.length);\n\n// Return array of files to delete\nreturn filesToDelete.map(file => ({\n  fileId: file.id,\n  fileName: file.name,\n  createdTime: file.createdTime\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "de67c9e1-5c0e-441e-866d-7a5214432074",
      "name": "Loop Over Old Files",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        4048,
        240
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "07435d9d-e2e5-4855-a9a0-e459da841cda",
      "name": "Delete Old Metadata File",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        4272,
        304
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.fileId }}"
        },
        "options": {},
        "operation": "deleteFile"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "18827ae0-05c3-444b-8220-eecc28317637",
      "name": "End Cleanup Loop",
      "type": "n8n-nodes-base.noOp",
      "position": [
        4272,
        176
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "826f7257-5442-479e-a023-050a67fe7539",
      "name": "Build Metadata from Data Table",
      "type": "n8n-nodes-base.code",
      "position": [
        3152,
        240
      ],
      "parameters": {
        "jsCode": "// Export n8n Data Table to JSON\n\n// Get all records from Data Table\nconst tableRecords = $('Get All Data Table Records').all();\nconst videos = tableRecords.map(item => item.json);\n\n// Build metadata structure from Data Table\nconst newMetadata = {\n  lastUpdated: new Date().toISOString(),\n  totalVideos: videos.length,\n  videos: videos\n};\n\nconsole.log('Built metadata from Data Table with', videos.length, 'videos');\n\n// Get file ID from search results\nlet existingFileId = null;\ntry {\n  const searchResult = $('Search for Metadata File').item;\n  if (searchResult && searchResult.json && searchResult.json.id) {\n    existingFileId = searchResult.json.id;\n    console.log('Found existing metadata file with ID:', existingFileId);\n  } else {\n    console.log('No existing metadata file found');\n  }\n} catch (error) {\n  console.log('No existing metadata file found');\n}\n\n// Convert to binary data for Google Drive upload\nconst jsonContent = JSON.stringify(newMetadata, null, 2);\nconst binaryData = Buffer.from(jsonContent, 'utf-8');\n\nreturn {\n  json: {\n    fileName: $('Configuration').item.json.metadataFileName,\n    existingFileId: existingFileId\n  },\n  binary: {\n    data: {\n      data: binaryData,\n      mimeType: 'application/json',\n      fileName: $('Configuration').item.json.metadataFileName\n    }\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "6b72580f-48f3-4bc5-ac86-0319799f8173",
      "name": "Get All Data Table Records",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        2928,
        240
      ],
      "parameters": {
        "operation": "get",
        "returnAll": true,
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "aNByykkM3ZxYjt5K",
          "cachedResultUrl": "/projects/vZdjtqHcrLoO32Ib/datatables/aNByykkM3ZxYjt5K",
          "cachedResultName": "Instagram Video Backups"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "038b0927-d467-4bad-8c9f-ceb4466bcb39",
      "name": "End Loop",
      "type": "n8n-nodes-base.noOp",
      "position": [
        4752,
        704
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "a875008d-2339-478b-a517-a728f1fda30e",
      "name": "Save Backup Record",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        4496,
        560
      ],
      "parameters": {
        "columns": {
          "value": {
            "title": "={{ $json.title }}",
            "postId": "={{ $json.postId }}",
            "tagList": "={{ $json.description }}",
            "accountId": "={{ $json.accountId }}",
            "description": "={{ $json.description }}",
            "descriptionFull": "={{ $json.descriptionFull }}"
          },
          "schema": [
            {
              "id": "postId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "postId",
              "defaultMatch": false
            },
            {
              "id": "accountId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "accountId",
              "defaultMatch": false
            },
            {
              "id": "tagList",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "tagList",
              "defaultMatch": false
            },
            {
              "id": "description",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "description",
              "defaultMatch": false
            },
            {
              "id": "title",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "title",
              "defaultMatch": false
            },
            {
              "id": "descriptionFull",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "descriptionFull",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "aNByykkM3ZxYjt5K",
          "cachedResultUrl": "/projects/vZdjtqHcrLoO32Ib/datatables/aNByykkM3ZxYjt5K",
          "cachedResultName": "Instagram Video Backups"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6787f380-7e93-48f8-b813-126e1c1689aa",
      "name": "Extract Metadata",
      "type": "n8n-nodes-base.set",
      "position": [
        4272,
        560
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "account-id",
              "name": "accountId",
              "type": "string",
              "value": "={{ $('Configuration').item.json.accountId }}"
            },
            {
              "id": "post-id",
              "name": "postId",
              "type": "string",
              "value": "={{ $('Filter Videos Only').item.json.id }}"
            },
            {
              "id": "drive-file-id",
              "name": "googleDriveFileId",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "drive-file-name",
              "name": "googleDriveFileName",
              "type": "string",
              "value": "={{ $json.name }}"
            },
            {
              "id": "permalink",
              "name": "permalink",
              "type": "string",
              "value": "={{ $('Filter Videos Only').item.json.permalink }}"
            },
            {
              "id": "title",
              "name": "title",
              "type": "string",
              "value": "={{ $('Parse Caption').item.json.title }}"
            },
            {
              "id": "description",
              "name": "description",
              "type": "string",
              "value": "={{ $('Parse Caption').item.json.description }}"
            },
            {
              "id": "tag-list",
              "name": "tagList",
              "type": "array",
              "value": "={{ $('Parse Caption').item.json.tagList }}"
            },
            {
              "id": "description-full",
              "name": "descriptionFull",
              "type": "string",
              "value": "={{ $('Parse Caption').item.json.descriptionFull }}"
            },
            {
              "id": "timestamp",
              "name": "instagramTimestamp",
              "type": "string",
              "value": "={{ $('Filter Videos Only').item.json.timestamp }}"
            },
            {
              "id": "media-type",
              "name": "mediaType",
              "type": "string",
              "value": "={{ $('Filter Videos Only').item.json.media_type }}"
            },
            {
              "id": "backed-up-at",
              "name": "backedUpAt",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "3d50a9d3-0cf2-486e-8fcd-f325d0698762",
      "name": "Upload to Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        4048,
        560
      ],
      "parameters": {
        "name": "={{ $json.title }}-{{ $('Loop Over Videos').item.json.id }}.mp4",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Configuration').item.json.googleDriveFolderId }}"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "1a1d1d80-9a54-4135-bf71-3118caa7527d",
      "name": "Download Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3824,
        560
      ],
      "parameters": {
        "url": "={{ $('Filter Videos Only').item.json.media_url }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "efab7150-5f13-4bd4-aa8a-14a7dc32bd2a",
      "name": "Parse Caption",
      "type": "n8n-nodes-base.code",
      "position": [
        3600,
        560
      ],
      "parameters": {
        "jsCode": "// Parse Instagram caption into structured fields\nconst caption = $('Filter Videos Only').item.json.caption || '';\n\n// Find first hashtag position\nconst hashtagMatch = caption.match(/#/);\nconst firstHashtagIndex = hashtagMatch ? caption.indexOf('#') : -1;\n\nlet title = '';\nlet description = '';\nconst tagList = [];\n\nif (firstHashtagIndex === -1) {\n  // No hashtags - entire caption is title\n  title = caption.trim();\n  description = '';\n} else {\n  // Split at first hashtag\n  title = caption.substring(0, firstHashtagIndex).trim();\n  description = caption.substring(firstHashtagIndex).trim();\n}\n\n// Extract all hashtags\nconst hashtagMatches = caption.match(/#\\w+/g);\nif (hashtagMatches) {\n  tagList.push(...hashtagMatches.map(tag => tag.substring(1)));\n}\n\nreturn {\n  title: title,\n  description: description,\n  tagList: tagList,\n  descriptionFull: caption\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "b7ea7693-b851-460c-aac4-2365e3887880",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        3376,
        560
      ],
      "parameters": {
        "amount": "={{ $('Configuration').item.json.waitBetweenDownloads }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "fe280ca2-a8c9-44cf-ac03-cbf3eef364f3",
      "name": "IF Not Already Backed Up",
      "type": "n8n-nodes-base.if",
      "position": [
        3152,
        624
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "not-exists",
              "operator": {
                "type": "object",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $('Check If Already Backed Up').first().json }}",
              "rightValue": "postId"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "18bb4f99-2744-43ca-9d8e-25e88db383bd",
      "name": "Check If Already Backed Up",
      "type": "n8n-nodes-base.dataTable",
      "onError": "continueRegularOutput",
      "position": [
        2928,
        624
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "postId",
              "keyValue": "={{ $json.id }}"
            }
          ]
        },
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "aNByykkM3ZxYjt5K",
          "cachedResultUrl": "/projects/vZdjtqHcrLoO32Ib/datatables/aNByykkM3ZxYjt5K",
          "cachedResultName": "Instagram Video Backups"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "7efb911b-b3e3-4672-b980-2d0d38744e8b",
      "name": "Loop Over Videos",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2624,
        624
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "93c781b7-066d-4147-af35-6c541cd9df33",
      "name": "Filter Videos Only",
      "type": "n8n-nodes-base.if",
      "position": [
        2416,
        640
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "filter-video",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.media_type }}",
              "rightValue": "VIDEO"
            },
            {
              "id": "filter-reels",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.media_type }}",
              "rightValue": "REELS"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "94dbe269-01c1-4e80-b1d3-075c6b39dd75",
      "name": "Sort Earliest to Latest",
      "type": "n8n-nodes-base.code",
      "position": [
        1968,
        640
      ],
      "parameters": {
        "jsCode": "// Sort media items from earliest to latest by timestamp\nconst response = $input.item.json;\nconst mediaItems = response.data || [];\n\nconsole.log('Total media items fetched:', mediaItems.length);\n\n// Sort by timestamp - earliest first (ascending order)\nmediaItems.sort((a, b) => {\n  const dateA = new Date(a.timestamp);\n  const dateB = new Date(b.timestamp);\n  return dateA - dateB;\n});\n\nif (mediaItems.length > 0) {\n  console.log('Earliest:', mediaItems[0].timestamp);\n  console.log('Latest:', mediaItems[mediaItems.length - 1].timestamp);\n}\n\nreturn {\n  json: {\n    data: mediaItems,\n    paging: response.paging\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "bebb7d7f-0259-40e5-af93-1d23623b547f",
      "name": "Split Out Media Items",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        2192,
        640
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "082f5c57-cdb5-4aff-9621-6811514779d2",
      "name": "Fetch Instagram Media",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1744,
        640
      ],
      "parameters": {
        "url": "=https://graph.instagram.com/me/media?fields=id,media_type,media_url,permalink,caption,timestamp,thumbnail_url&limit={{ $('Configuration').item.json.maxVideosPerRun }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ca45ba9e-41d7-4d4d-990d-1dded3212ce3",
      "name": "Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        1520,
        640
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "account-id",
              "name": "accountId",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "account-username",
              "name": "accountUsername",
              "type": "string",
              "value": "={{ $json.username }}"
            },
            {
              "id": "google-drive-folder",
              "name": "googleDriveFolderId",
              "type": "string",
              "value": "YOUR_GOOGLE_DRIVE_ID"
            },
            {
              "id": "max-videos",
              "name": "maxVideosPerRun",
              "type": "number",
              "value": 100
            },
            {
              "id": "wait-seconds",
              "name": "waitBetweenDownloads",
              "type": "number",
              "value": 5
            },
            {
              "id": "metadata-filename",
              "name": "metadataFileName",
              "type": "string",
              "value": "instagram-backup-metadata.json"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4c2cd070-686f-474d-ab4e-6f2feb31c9b6",
      "name": "Get Instagram Account Info",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1296,
        640
      ],
      "parameters": {
        "url": "=https://graph.instagram.com/me?fields=id,username",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "5ad4a85b-dceb-425d-ba06-c1e4dec516e5",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        1072,
        544
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "a162785e-9490-4394-861e-59ac8b1ca3a1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1072,
        736
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 0 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    }
  ],
  "connections": {
    "Wait": {
      "main": [
        [
          {
            "node": "Parse Caption",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "End Loop": {
      "main": [
        [
          {
            "node": "Loop Over Videos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configuration": {
      "main": [
        [
          {
            "node": "Fetch Instagram Media",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Caption": {
      "main": [
        [
          {
            "node": "Download Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Video": {
      "main": [
        [
          {
            "node": "Upload to Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Get Instagram Account Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Metadata": {
      "main": [
        [
          {
            "node": "Save Backup Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Videos": {
      "main": [
        [
          {
            "node": "Get All Data Table Records",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check If Already Backed Up",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get Instagram Account Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Videos Only": {
      "main": [
        [
          {
            "node": "Loop Over Videos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Backup Record": {
      "main": [
        [
          {
            "node": "End Loop",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Old Files": {
      "main": [
        [
          {
            "node": "End Cleanup Loop",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Delete Old Metadata File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Instagram Media": {
      "main": [
        [
          {
            "node": "Sort Earliest to Latest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out Media Items": {
      "main": [
        [
          {
            "node": "Filter Videos Only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to Google Drive": {
      "main": [
        [
          {
            "node": "Extract Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Old Metadata Files": {
      "main": [
        [
          {
            "node": "Loop Over Old Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List All Metadata Files": {
      "main": [
        [
          {
            "node": "Find Old Metadata Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sort Earliest to Latest": {
      "main": [
        [
          {
            "node": "Split Out Media Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delete Old Metadata File": {
      "main": [
        [
          {
            "node": "Loop Over Old Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Not Already Backed Up": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "End Loop",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload New Metadata File": {
      "main": [
        [
          {
            "node": "List All Metadata Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Already Backed Up": {
      "main": [
        [
          {
            "node": "IF Not Already Backed Up",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get All Data Table Records": {
      "main": [
        [
          {
            "node": "Build Metadata from Data Table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Instagram Account Info": {
      "main": [
        [
          {
            "node": "Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Metadata from Data Table": {
      "main": [
        [
          {
            "node": "Upload New Metadata File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}