Pular para conteúdo

DRIVE_UPLOAD - Upload de Arquivos no Google Drive

O que é este Node?

O DRIVE_UPLOAD é o node responsável por fazer upload de arquivos para o Google Drive permitindo que seus flows automatizem o armazenamento de documentos, imagens, PDFs e qualquer tipo de arquivo na nuvem do Google.

Por que este Node existe?

Enviar arquivos manualmente para o Google Drive é um processo repetitivo que consome tempo valioso. O DRIVE_UPLOAD existe para:

  1. Backup Automatizado: Salvar automaticamente documentos recebidos via WhatsApp
  2. Gestão Documental: Organizar arquivos de clientes em pastas específicas
  3. Armazenamento Centralizado: Manter todos os arquivos importantes em um único lugar
  4. Compartilhamento Facilitado: Gerar links de compartilhamento automaticamente

Como funciona internamente?

Quando o DRIVE_UPLOAD é executado, o sistema:

  1. Autentica: Valida o OAuth2 token do Google (accessToken e refreshToken)
  2. Prepara o arquivo: Converte o conteúdo base64 para Buffer
  3. Define metadados: Nome do arquivo, pasta de destino (parents) e mimeType
  4. Faz upload: Envia o arquivo via Google Drive API v3
  5. Retorna resultado: FileId, fileName, webViewLink e webContentLink
  6. Se erro: Lança exceção com detalhes do erro de autenticação ou upload

Código interno (google-executors.service.ts:583-602):

case 'upload':
  const uploadResult = await drive.files.create({
    requestBody: {
      name: data.fileName,
      parents: data.folderId ? [data.folderId] : undefined,
    },
    media: {
      mimeType: data.mimeType,
      body: Buffer.from(data.content, 'base64'),
    },
    fields: 'id,name,webViewLink,webContentLink',
  });

  return {
    success: true,
    fileId: uploadResult.data.id,
    fileName: uploadResult.data.name,
    webViewLink: uploadResult.data.webViewLink,
    webContentLink: uploadResult.data.webContentLink,
  };

Quando você DEVE usar este Node?

Use DRIVE_UPLOAD sempre que precisar de armazenar arquivos automaticamente no Google Drive:

Casos de uso

  1. Backup de documentos: "Quando cliente enviar PDF do contrato, salvar no Drive"
  2. Gestão de comprovantes: "Armazenar todos os comprovantes de pagamento em pasta específica"
  3. Arquivar conversas: "Salvar transcrições de atendimento em formato TXT no Drive"

Quando NÃO usar DRIVE_UPLOAD

  • Arquivo temporário: Use armazenamento local se for usar apenas no flow
  • Sem autenticação: Precisa ter OAuth configurado (veja seção Setup)
  • Arquivo muito grande: Google Drive tem limites (750GB/dia por usuário)

Setup OAuth Google Drive

1. Criar Projeto no Google Cloud Console

  1. Acesse: https://console.cloud.google.com/
  2. Crie um novo projeto: "Lumina Flow Builder"
  3. Ative a API: Google Drive API

2. Configurar OAuth 2.0

  1. Vá em: APIs & Services > Credentials
  2. Criar credenciais > OAuth 2.0 Client ID
  3. Tipo: Web application
  4. Redirect URIs: https://seu-dominio.com/auth/google/callback

3. Configurar variáveis de ambiente

GOOGLE_CLIENT_ID=seu_client_id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=seu_client_secret
GOOGLE_REDIRECT_URI=https://seu-dominio.com/auth/google/callback

4. Obter tokens do usuário

Implemente fluxo OAuth para obter accessToken e refreshToken do usuário.

File IDs e Folder IDs

File ID

Identificador único de cada arquivo no Drive: - Exemplo: 1a2b3c4d5e6f7g8h9i0j - Obtido após upload ou via busca

Folder ID

Identificador de pastas no Drive: - Pasta raiz: root ou não informar - Pasta específica: 1aBcDeFgHiJkLmNoPqRsTuV - Múltiplos parents: arquivo pode estar em várias pastas

Como obter IDs

URL do arquivo: https://drive.google.com/file/d/1a2b3c4d5e6f7g8h9i0j/view
File ID: 1a2b3c4d5e6f7g8h9i0j

URL da pasta: https://drive.google.com/drive/folders/1aBcDeFgHiJkLmNoPqRsTuV
Folder ID: 1aBcDeFgHiJkLmNoPqRsTuV

Mime Types

Principais tipos suportados:

Tipo MimeType
PDF application/pdf
Word application/vnd.openxmlformats-officedocument.wordprocessingml.document
Excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Imagem JPEG image/jpeg
Imagem PNG image/png
Texto text/plain
JSON application/json
ZIP application/zip

Parâmetros Detalhados

accessToken (string, obrigatório)

O que é: Token de acesso OAuth2 do Google para autenticar a requisição.

Como obter: Através do fluxo OAuth2 com os escopos https://www.googleapis.com/auth/drive.file ou https://www.googleapis.com/auth/drive.

Flow completo para testar:

{
  "name": "Teste Drive Upload - AccessToken",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Definir Tokens",
        "parameters": {
          "variableName": "googleTokens",
          "value": {
            "accessToken": "ya29.a0AfH6SMB...",
            "refreshToken": "1//0g..."
          }
        }
      }
    },
    {
      "id": "drive_upload_1",
      "type": "google_drive",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Upload Arquivo",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{googleTokens.accessToken}}",
          "refreshToken": "{{googleTokens.refreshToken}}",
          "fileName": "teste.txt",
          "content": "VGVzdGUgZGUgY29udGXDumRv",
          "mimeType": "text/plain"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "Arquivo enviado!\nID: {{drive_upload_1.fileId}}\nLink: {{drive_upload_1.webViewLink}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "variable_1" },
    { "source": "variable_1", "target": "drive_upload_1" },
    { "source": "drive_upload_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Substitua os tokens por tokens reais do seu OAuth 2. Execute o flow 3. Espera: Mensagem com link do arquivo no Drive

refreshToken (string, obrigatório)

O que é: Token de atualização OAuth2 usado para renovar o accessToken quando ele expira.

Validade: Não expira (a menos que revogado pelo usuário)

Flow completo para testar:

{
  "name": "Teste Drive Upload - RefreshToken",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "drive_upload_1",
      "type": "google_drive",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Upload com Refresh",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{user.googleAccessToken}}",
          "refreshToken": "{{user.googleRefreshToken}}",
          "fileName": "documento.pdf",
          "content": "{{pdfBase64}}",
          "mimeType": "application/pdf"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Sucesso",
        "parameters": {
          "message": "PDF salvo no Drive!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "drive_upload_1" },
    { "source": "drive_upload_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Tokens devem estar salvos em variáveis do usuário 2. Sistema renova accessToken automaticamente se expirado

fileName (string, obrigatório)

O que é: Nome que o arquivo terá no Google Drive (incluindo extensão).

Exemplos: "contrato.pdf", "relatorio_2025.xlsx", "foto_produto.jpg"

Flow completo para testar:

{
  "name": "Teste Drive Upload - FileName Dinâmico",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Pedir Nome",
        "parameters": {
          "message": "Qual nome deseja dar ao arquivo?",
          "variableName": "nomeArquivo"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Adicionar Timestamp",
        "parameters": {
          "variableName": "nomeCompleto",
          "value": "{{nomeArquivo}}_{{timestamp}}.txt"
        }
      }
    },
    {
      "id": "drive_upload_1",
      "type": "google_drive",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Upload",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{tokens.access}}",
          "refreshToken": "{{tokens.refresh}}",
          "fileName": "{{nomeCompleto}}",
          "content": "Q29udGXDumRvIGRvIGFycXVpdm8=",
          "mimeType": "text/plain"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "Arquivo '{{drive_upload_1.fileName}}' enviado com sucesso!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1100, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "variable_1" },
    { "source": "variable_1", "target": "drive_upload_1" },
    { "source": "drive_upload_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Digite: "relatorio" 2. Sistema adiciona timestamp: "relatorio_1736950800000.txt" 3. Arquivo é salvo com nome único

content (string base64, obrigatório)

O que é: Conteúdo do arquivo codificado em base64.

Como converter: - Texto: Buffer.from("texto").toString('base64') - Arquivo local: Ler arquivo e converter para base64

Flow completo para testar:

{
  "name": "Teste Drive Upload - Content Base64",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Pedir Texto",
        "parameters": {
          "message": "Digite o conteúdo do arquivo:",
          "variableName": "textoUsuario"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Converter Base64",
        "parameters": {
          "variableName": "contentBase64",
          "value": "{{base64(textoUsuario)}}"
        }
      }
    },
    {
      "id": "drive_upload_1",
      "type": "google_drive",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Upload",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{tokens.access}}",
          "refreshToken": "{{tokens.refresh}}",
          "fileName": "nota.txt",
          "content": "{{contentBase64}}",
          "mimeType": "text/plain"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Sucesso",
        "parameters": {
          "message": "Sua nota foi salva no Drive!\n{{drive_upload_1.webViewLink}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1100, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "variable_1" },
    { "source": "variable_1", "target": "drive_upload_1" },
    { "source": "drive_upload_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Digite: "Reunião amanhã às 14h" 2. Sistema converte para base64 3. Arquivo texto é salvo no Drive

mimeType (string, obrigatório)

O que é: Tipo MIME do arquivo para o Google Drive processar corretamente.

Padrão: Se não informado, Google tenta detectar automaticamente.

Flow completo para testar:

{
  "name": "Teste Drive Upload - MimeTypes Diferentes",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "drive_upload_1",
      "type": "google_drive",
      "position": { "x": 300, "y": 50 },
      "data": {
        "label": "Upload TXT",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{tokens.access}}",
          "refreshToken": "{{tokens.refresh}}",
          "fileName": "dados.txt",
          "content": "VGV4dG8gc2ltcGxlcw==",
          "mimeType": "text/plain"
        }
      }
    },
    {
      "id": "drive_upload_2",
      "type": "google_drive",
      "position": { "x": 300, "y": 150 },
      "data": {
        "label": "Upload JSON",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{tokens.access}}",
          "refreshToken": "{{tokens.refresh}}",
          "fileName": "dados.json",
          "content": "eyJub21lIjoiSm9zw6kiLCJpZGFkZSI6MzB9",
          "mimeType": "application/json"
        }
      }
    },
    {
      "id": "drive_upload_3",
      "type": "google_drive",
      "position": { "x": 300, "y": 250 },
      "data": {
        "label": "Upload PDF",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{tokens.access}}",
          "refreshToken": "{{tokens.refresh}}",
          "fileName": "contrato.pdf",
          "content": "{{pdfBase64}}",
          "mimeType": "application/pdf"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 150 },
      "data": {
        "label": "Resultado",
        "parameters": {
          "message": "3 arquivos enviados:\n- TXT: {{drive_upload_1.fileName}}\n- JSON: {{drive_upload_2.fileName}}\n- PDF: {{drive_upload_3.fileName}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 150 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "drive_upload_1" },
    { "source": "start_1", "target": "drive_upload_2" },
    { "source": "start_1", "target": "drive_upload_3" },
    { "source": "drive_upload_1", "target": "message_1" },
    { "source": "drive_upload_2", "target": "message_1" },
    { "source": "drive_upload_3", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Flow envia 3 arquivos simultaneamente 2. Cada um com mimeType específico 3. Google Drive mostra ícone correto para cada tipo

folderId (string, opcional)

O que é: ID da pasta do Google Drive onde o arquivo será salvo.

Padrão: root (pasta raiz do My Drive)

Flow completo para testar:

{
  "name": "Teste Drive Upload - Com Pasta",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "switch_1",
      "type": "switch",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Tipo Cliente",
        "parameters": {
          "variable": "{{cliente.tipo}}",
          "cases": [
            { "value": "vip", "target": "drive_upload_vip" },
            { "value": "regular", "target": "drive_upload_regular" }
          ],
          "default": "drive_upload_default"
        }
      }
    },
    {
      "id": "drive_upload_vip",
      "type": "google_drive",
      "position": { "x": 500, "y": 50 },
      "data": {
        "label": "Salvar em VIP",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{tokens.access}}",
          "refreshToken": "{{tokens.refresh}}",
          "fileName": "contrato_{{cliente.id}}.pdf",
          "content": "{{contratoBase64}}",
          "mimeType": "application/pdf",
          "folderId": "1aB2cD3eF4gH5iJ6kL7mN8oP9qR"
        }
      }
    },
    {
      "id": "drive_upload_regular",
      "type": "google_drive",
      "position": { "x": 500, "y": 150 },
      "data": {
        "label": "Salvar em Regular",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{tokens.access}}",
          "refreshToken": "{{tokens.refresh}}",
          "fileName": "contrato_{{cliente.id}}.pdf",
          "content": "{{contratoBase64}}",
          "mimeType": "application/pdf",
          "folderId": "9qR8oP7mN6kL5iJ4gH3eF2cD1aB"
        }
      }
    },
    {
      "id": "drive_upload_default",
      "type": "google_drive",
      "position": { "x": 500, "y": 250 },
      "data": {
        "label": "Salvar em Raiz",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{tokens.access}}",
          "refreshToken": "{{tokens.refresh}}",
          "fileName": "contrato_{{cliente.id}}.pdf",
          "content": "{{contratoBase64}}",
          "mimeType": "application/pdf"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 150 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "Contrato salvo no Drive!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 150 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "switch_1" },
    { "source": "switch_1", "target": "drive_upload_vip", "label": "vip" },
    { "source": "switch_1", "target": "drive_upload_regular", "label": "regular" },
    { "source": "switch_1", "target": "drive_upload_default", "label": "default" },
    { "source": "drive_upload_vip", "target": "message_1" },
    { "source": "drive_upload_regular", "target": "message_1" },
    { "source": "drive_upload_default", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: 1. Cliente VIP: arquivo vai para pasta "Clientes VIP" 2. Cliente regular: arquivo vai para pasta "Clientes" 3. Outros: arquivo vai para raiz do Drive

Parâmetros

Campo Tipo Obrigatório Descrição
operation string Sim Deve ser "upload"
accessToken string Sim Token OAuth2 do Google
refreshToken string Sim Token para renovar acesso
fileName string Sim Nome do arquivo no Drive
content string Sim Conteúdo em base64
mimeType string Sim Tipo MIME do arquivo
folderId string Não ID da pasta (padrão: root)

Exemplo 1: Backup Automático de Documentos

Objetivo: Salvar automaticamente documentos PDF enviados por clientes no WhatsApp.

JSON para Importar

{
  "name": "Backup Automático de PDFs",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Solicitar Documento",
        "parameters": {
          "message": "Por favor, envie o documento em PDF que deseja arquivar."
        }
      }
    },
    {
      "id": "media_1",
      "type": "media",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Receber PDF",
        "parameters": {
          "variableName": "documentoPdf",
          "allowedTypes": ["document"],
          "timeout": 300000
        }
      }
    },
    {
      "id": "condition_1",
      "type": "condition",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Verificar se é PDF",
        "parameters": {
          "variable": "{{documentoPdf.mimeType}}",
          "operator": "equals",
          "value": "application/pdf"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 900, "y": 50 },
      "data": {
        "label": "Gerar Nome Único",
        "parameters": {
          "variableName": "nomeArquivo",
          "value": "doc_{{contact.name}}_{{timestamp}}.pdf"
        }
      }
    },
    {
      "id": "drive_upload_1",
      "type": "google_drive",
      "position": { "x": 1100, "y": 50 },
      "data": {
        "label": "Salvar no Drive",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{user.googleAccessToken}}",
          "refreshToken": "{{user.googleRefreshToken}}",
          "fileName": "{{nomeArquivo}}",
          "content": "{{documentoPdf.contentBase64}}",
          "mimeType": "application/pdf",
          "folderId": "1aBcDeFgHiJkLmNoPqRsTuVwXyZ"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1300, "y": 50 },
      "data": {
        "label": "Confirmar Sucesso",
        "parameters": {
          "message": "✅ Documento arquivado com sucesso!\n\nNome: {{drive_upload_1.fileName}}\n\nVocê pode acessá-lo em:\n{{drive_upload_1.webViewLink}}"
        }
      }
    },
    {
      "id": "message_3",
      "type": "message",
      "position": { "x": 900, "y": 150 },
      "data": {
        "label": "Erro - Não é PDF",
        "parameters": {
          "message": "❌ Por favor, envie apenas arquivos em formato PDF."
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "media_1" },
    { "source": "media_1", "target": "condition_1" },
    { "source": "condition_1", "target": "variable_1", "label": "true" },
    { "source": "condition_1", "target": "message_3", "label": "false" },
    { "source": "variable_1", "target": "drive_upload_1" },
    { "source": "drive_upload_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" },
    { "source": "message_3", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Por favor, envie o documento em PDF que deseja arquivar.
Usuário: [Envia arquivo contrato.pdf]
Sistema: ✅ Documento arquivado com sucesso!

Nome: doc_Jose_Roberto_1736950800000.pdf

Você pode acessá-lo em:
https://drive.google.com/file/d/1a2b3c4d5e6f7g8h9i0j/view

Exemplo 2: Gestão Documental por Departamento

Objetivo: Organizar documentos em pastas específicas baseado no departamento do colaborador.

JSON para Importar

{
  "name": "Gestão Documental por Departamento",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Bem-vindo",
        "parameters": {
          "message": "Sistema de Arquivamento de Documentos\n\nSelecione seu departamento:\n1️⃣ Financeiro\n2️⃣ RH\n3️⃣ Vendas\n4️⃣ TI"
        }
      }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Escolher Depto",
        "parameters": {
          "message": "Digite o número do seu departamento:",
          "variableName": "departamento",
          "timeout": 60000
        }
      }
    },
    {
      "id": "switch_1",
      "type": "switch",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Definir Pasta",
        "parameters": {
          "variable": "{{departamento}}",
          "cases": [
            { "value": "1", "target": "variable_financeiro" },
            { "value": "2", "target": "variable_rh" },
            { "value": "3", "target": "variable_vendas" },
            { "value": "4", "target": "variable_ti" }
          ],
          "default": "message_erro"
        }
      }
    },
    {
      "id": "variable_financeiro",
      "type": "variable",
      "position": { "x": 900, "y": 0 },
      "data": {
        "label": "Config Financeiro",
        "parameters": {
          "variableName": "config",
          "value": {
            "folderId": "1FinanceiroFolderID123",
            "nomeDepto": "Financeiro"
          }
        }
      }
    },
    {
      "id": "variable_rh",
      "type": "variable",
      "position": { "x": 900, "y": 80 },
      "data": {
        "label": "Config RH",
        "parameters": {
          "variableName": "config",
          "value": {
            "folderId": "1RHFolderID456",
            "nomeDepto": "RH"
          }
        }
      }
    },
    {
      "id": "variable_vendas",
      "type": "variable",
      "position": { "x": 900, "y": 160 },
      "data": {
        "label": "Config Vendas",
        "parameters": {
          "variableName": "config",
          "value": {
            "folderId": "1VendasFolderID789",
            "nomeDepto": "Vendas"
          }
        }
      }
    },
    {
      "id": "variable_ti",
      "type": "variable",
      "position": { "x": 900, "y": 240 },
      "data": {
        "label": "Config TI",
        "parameters": {
          "variableName": "config",
          "value": {
            "folderId": "1TIFolderID012",
            "nomeDepto": "TI"
          }
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1100, "y": 120 },
      "data": {
        "label": "Solicitar Arquivo",
        "parameters": {
          "message": "Departamento: {{config.nomeDepto}}\n\nEnvie o documento que deseja arquivar:"
        }
      }
    },
    {
      "id": "media_1",
      "type": "media",
      "position": { "x": 1300, "y": 120 },
      "data": {
        "label": "Receber Documento",
        "parameters": {
          "variableName": "documento",
          "allowedTypes": ["document", "image"],
          "timeout": 300000
        }
      }
    },
    {
      "id": "drive_upload_1",
      "type": "google_drive",
      "position": { "x": 1500, "y": 120 },
      "data": {
        "label": "Upload para Pasta",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{system.googleAccessToken}}",
          "refreshToken": "{{system.googleRefreshToken}}",
          "fileName": "{{config.nomeDepto}}_{{contact.name}}_{{timestamp}}.{{documento.extension}}",
          "content": "{{documento.contentBase64}}",
          "mimeType": "{{documento.mimeType}}",
          "folderId": "{{config.folderId}}"
        }
      }
    },
    {
      "id": "message_3",
      "type": "message",
      "position": { "x": 1700, "y": 120 },
      "data": {
        "label": "Sucesso",
        "parameters": {
          "message": "✅ Documento arquivado!\n\nDepartamento: {{config.nomeDepto}}\nArquivo: {{drive_upload_1.fileName}}\n\nID do arquivo: {{drive_upload_1.fileId}}"
        }
      }
    },
    {
      "id": "message_erro",
      "type": "message",
      "position": { "x": 900, "y": 320 },
      "data": {
        "label": "Opção Inválida",
        "parameters": {
          "message": "❌ Opção inválida. Por favor, escolha entre 1 e 4."
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1900, "y": 200 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "input_1" },
    { "source": "input_1", "target": "switch_1" },
    { "source": "switch_1", "target": "variable_financeiro", "label": "1" },
    { "source": "switch_1", "target": "variable_rh", "label": "2" },
    { "source": "switch_1", "target": "variable_vendas", "label": "3" },
    { "source": "switch_1", "target": "variable_ti", "label": "4" },
    { "source": "switch_1", "target": "message_erro", "label": "default" },
    { "source": "variable_financeiro", "target": "message_2" },
    { "source": "variable_rh", "target": "message_2" },
    { "source": "variable_vendas", "target": "message_2" },
    { "source": "variable_ti", "target": "message_2" },
    { "source": "message_2", "target": "media_1" },
    { "source": "media_1", "target": "drive_upload_1" },
    { "source": "drive_upload_1", "target": "message_3" },
    { "source": "message_3", "target": "end_1" },
    { "source": "message_erro", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Sistema de Arquivamento de Documentos

Selecione seu departamento:
1️⃣ Financeiro
2️⃣ RH
3️⃣ Vendas
4️⃣ TI

Sistema: Digite o número do seu departamento:
Usuário: 1

Sistema: Departamento: Financeiro

Envie o documento que deseja arquivar:
Usuário: [Envia nota_fiscal.pdf]

Sistema: ✅ Documento arquivado!

Departamento: Financeiro
Arquivo: Financeiro_Jose_Roberto_1736950800000.pdf

ID do arquivo: 1a2b3c4d5e6f7g8h9i0j

Exemplo 3: Backup Diário de Relatórios

Objetivo: Gerar e salvar relatório diário automaticamente no Google Drive.

JSON para Importar

{
  "name": "Backup Diário de Relatórios",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "schedule_1",
      "type": "schedule",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Agendar 6h da manhã",
        "parameters": {
          "cron": "0 6 * * *",
          "timezone": "America/Sao_Paulo"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Buscar Dados",
        "parameters": {
          "variableName": "relatorio",
          "value": {
            "vendas": "{{database.vendasOntem}}",
            "atendimentos": "{{database.atendimentosOntem}}",
            "satisfacao": "{{database.satisfacaoOntem}}"
          }
        }
      }
    },
    {
      "id": "variable_2",
      "type": "variable",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Gerar JSON",
        "parameters": {
          "variableName": "jsonRelatorio",
          "value": "{{json(relatorio)}}"
        }
      }
    },
    {
      "id": "variable_3",
      "type": "variable",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Converter Base64",
        "parameters": {
          "variableName": "contentBase64",
          "value": "{{base64(jsonRelatorio)}}"
        }
      }
    },
    {
      "id": "variable_4",
      "type": "variable",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Nome do Arquivo",
        "parameters": {
          "variableName": "nomeArquivo",
          "value": "relatorio_{{date('YYYY-MM-DD')}}.json"
        }
      }
    },
    {
      "id": "drive_upload_1",
      "type": "google_drive",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Salvar Relatório",
        "parameters": {
          "operation": "upload",
          "accessToken": "{{system.googleAccessToken}}",
          "refreshToken": "{{system.googleRefreshToken}}",
          "fileName": "{{nomeArquivo}}",
          "content": "{{contentBase64}}",
          "mimeType": "application/json",
          "folderId": "1RelatoriosDiariosFolderID"
        }
      }
    },
    {
      "id": "condition_1",
      "type": "condition",
      "position": { "x": 1500, "y": 100 },
      "data": {
        "label": "Verificar Sucesso",
        "parameters": {
          "variable": "{{drive_upload_1.success}}",
          "operator": "equals",
          "value": true
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 1700, "y": 50 },
      "data": {
        "label": "Notificar Admin",
        "parameters": {
          "message": "✅ Relatório diário gerado!\n\nData: {{date('DD/MM/YYYY')}}\nArquivo: {{drive_upload_1.fileName}}\n\nDados:\n- Vendas: {{relatorio.vendas}}\n- Atendimentos: {{relatorio.atendimentos}}\n- Satisfação: {{relatorio.satisfacao}}%",
          "to": "{{admin.phone}}"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1700, "y": 150 },
      "data": {
        "label": "Alerta Erro",
        "parameters": {
          "message": "❌ ERRO ao gerar relatório diário!\n\nVerifique o sistema.",
          "to": "{{admin.phone}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "schedule_1" },
    { "source": "schedule_1", "target": "variable_1" },
    { "source": "variable_1", "target": "variable_2" },
    { "source": "variable_2", "target": "variable_3" },
    { "source": "variable_3", "target": "variable_4" },
    { "source": "variable_4", "target": "drive_upload_1" },
    { "source": "drive_upload_1", "target": "condition_1" },
    { "source": "condition_1", "target": "message_1", "label": "true" },
    { "source": "condition_1", "target": "message_2", "label": "false" },
    { "source": "message_1", "target": "end_1" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

[Execução automática às 6h da manhã]

Sistema: [WhatsApp para admin]
✅ Relatório diário gerado!

Data: 15/01/2025
Arquivo: relatorio_2025-01-15.json

Dados:
- Vendas: 142
- Atendimentos: 389
- Satisfação: 94%

Resposta do Node

{
  "success": true,
  "fileId": "1a2b3c4d5e6f7g8h9i0j",
  "fileName": "documento.pdf",
  "webViewLink": "https://drive.google.com/file/d/1a2b3c4d5e6f7g8h9i0j/view",
  "webContentLink": "https://drive.google.com/uc?id=1a2b3c4d5e6f7g8h9i0j&export=download"
}

Campos retornados:

  • success: true se upload foi bem-sucedido
  • fileId: ID único do arquivo no Drive
  • fileName: Nome do arquivo salvo
  • webViewLink: URL para visualizar arquivo no navegador
  • webContentLink: URL para download direto

Boas Práticas

SIM:

  • Use nomes de arquivo descritivos e únicos (adicione timestamp)
  • Organize arquivos em pastas por departamento/categoria
  • Verifique mimeType antes de fazer upload
  • Armazene tokens OAuth de forma segura (nunca em variáveis expostas)
  • Use folderId para manter organização
  • Implemente retry em caso de falha de rede
  • Valide tamanho do arquivo antes do upload

NÃO:

  • Não faça upload de arquivos sensíveis sem criptografia
  • Não use nomes de arquivo genéricos ("arquivo.pdf")
  • Não exponha accessToken em logs ou mensagens
  • Não faça upload de arquivos muito grandes (>5GB) sem controle
  • Não ignore erros de autenticação
  • Não salve tudo na raiz do Drive (use pastas)

Dicas

💡 Dica 1: Para organizar por data, crie pastas no formato "YYYY/MM/" e use folderId dinâmico baseado no mês atual.

💡 Dica 2: Armazene o fileId retornado no seu banco de dados para poder buscar/deletar o arquivo depois.

💡 Dica 3: Use webViewLink para compartilhar arquivos com clientes (mais bonito que webContentLink).

💡 Dica 4: Para evitar duplicatas, busque primeiro se arquivo já existe usando drive_search antes do upload.

💡 Dica 5: Tokens OAuth expiram! O refreshToken renova automaticamente o accessToken quando necessário.

Próximo Node

DRIVE_DOWNLOAD - Baixar arquivos do Google Drive → DRIVE_LIST - Listar arquivos e pastas → DRIVE_DELETE - Deletar arquivos