Pular para conteúdo

GOOGLE_DOCS - Integração com Google Docs

O que é este Node?

O GOOGLE_DOCS é o node responsável por criar e manipular documentos do Google Docs, permitindo criar, ler, inserir texto e fazer atualizações em lote automaticamente.

Por que este Node existe?

Documentos precisam ser criados e editados programaticamente. O GOOGLE_DOCS existe para:

  1. Gerar documentos automaticamente: Criar contratos, propostas, relatórios
  2. Preencher templates: Inserir dados dinâmicos em modelos prontos
  3. Extrair conteúdo: Ler texto de documentos existentes
  4. Automatizar edição: Fazer alterações em massa via API
  5. Integração com workflows: Conectar documentação com processos

Como funciona internamente?

Quando o GOOGLE_DOCS é executado, o sistema:

  1. Autentica via OAuth2 com Google (access_token e refresh_token)
  2. Conecta à API do Google Docs v1
  3. Executa operação solicitada (create, get, batchUpdate, insertText)
  4. Processa estrutura do documento (parágrafos, texto, formatação)
  5. Retorna documentId, conteúdo ou confirmação
  6. Se erro: Retorna mensagem de erro detalhada

Código interno (google-executors.service.ts:480-560):

async executeGoogleDocs(data: any, variables: Record<string, any>): Promise<any> {
  try {
    this.logger.log('📄 [GOOGLE DOCS] Executing operation');

    const oauth2Client = new OAuth2Client(
      process.env.GOOGLE_CLIENT_ID,
      process.env.GOOGLE_CLIENT_SECRET,
      process.env.GOOGLE_REDIRECT_URI
    );

    oauth2Client.setCredentials({
      access_token: data.accessToken,
      refresh_token: data.refreshToken,
    });

    const docs = google.docs({ version: 'v1', auth: oauth2Client });

    switch (data.operation) {
      case 'create':
        const createResult = await docs.documents.create({
          requestBody: {
            title: data.title,
          },
        });

        return {
          success: true,
          documentId: createResult.data.documentId,
          title: createResult.data.title,
        };

      case 'get':
        const getResult = await docs.documents.get({
          documentId: data.documentId,
        });

        return {
          success: true,
          document: getResult.data,
          content: getResult.data.body?.content,
        };

      case 'batchUpdate':
        const updateResult = await docs.documents.batchUpdate({
          documentId: data.documentId,
          requestBody: {
            requests: data.requests,
          },
        });

        return {
          success: true,
          replies: updateResult.data.replies,
        };

      case 'insertText':
        const insertResult = await docs.documents.batchUpdate({
          documentId: data.documentId,
          requestBody: {
            requests: [{
              insertText: {
                location: { index: data.index || 1 },
                text: data.text,
              },
            }],
          },
        });

        return {
          success: true,
          replies: insertResult.data.replies,
        };

      default:
        throw new Error(`Unknown Google Docs operation: ${data.operation}`);
    }
  } catch (error) {
    this.logger.error('Google Docs execution error:', error);
    throw error;
  }
}

Quando você DEVE usar este Node?

Use GOOGLE_DOCS sempre que precisar criar ou editar documentos automaticamente:

Casos de uso

  1. Gerar contratos: "Criar contrato com dados do cliente"
  2. Criar propostas: "Gerar proposta comercial personalizada"
  3. Relatórios automáticos: "Gerar relatório mensal de vendas"
  4. Preencher templates: "Substituir [NOME] por dados reais"
  5. Documentação dinâmica: "Criar documentação de projeto"
  6. Extrair texto: "Ler conteúdo de documento para análise"

Quando NÃO usar GOOGLE_DOCS

  • Formatação complexa: Use templates manuais para design elaborado
  • PDFs imediatos: Docs é editável, para PDF use conversão
  • Documentos muito grandes: Considere performance da API

Parâmetros

Campo Tipo Obrigatório Descrição
operation string Sim create, get, batchUpdate, insertText
title string Condicional Título do documento (para create)
documentId string Condicional ID do documento (para get/update)
text string Condicional Texto a inserir (para insertText)
index number Não Posição de inserção (padrão: 1)
requests array Condicional Array de requests (para batchUpdate)
accessToken string Sim Token OAuth2 do Google
refreshToken string Sim Refresh token OAuth2 do Google

Operações Disponíveis

1. create - Criar documento

O que faz: Cria novo documento vazio no Google Docs.

Parâmetros obrigatórios: - title - accessToken - refreshToken

2. get - Ler documento

O que faz: Obtém conteúdo completo do documento.

Parâmetros obrigatórios: - documentId - accessToken - refreshToken

3. insertText - Inserir texto

O que faz: Insere texto em posição específica do documento.

Parâmetros obrigatórios: - documentId - text - accessToken - refreshToken

Parâmetros opcionais: - index (posição, padrão: 1 = início)

4. batchUpdate - Atualizações em lote

O que faz: Executa múltiplas operações de edição em uma chamada.

Parâmetros obrigatórios: - documentId - requests (array de operações) - accessToken - refreshToken

Exemplo 1: Criar Contrato Automático

Objetivo: Criar documento de contrato com dados do cliente.

JSON para Importar

{
  "name": "Gerar Contrato no Google Docs",
  "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": "Nome Cliente",
        "parameters": {
          "message": "Nome do cliente:",
          "variable": "cliente_nome"
        }
      }
    },
    {
      "id": "input_2",
      "type": "input",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "CPF",
        "parameters": {
          "message": "CPF do cliente:",
          "variable": "cliente_cpf"
        }
      }
    },
    {
      "id": "input_3",
      "type": "input",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Serviço",
        "parameters": {
          "message": "Descrição do serviço:",
          "variable": "servico"
        }
      }
    },
    {
      "id": "google_docs_1",
      "type": "google_docs",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Criar Documento",
        "parameters": {
          "operation": "create",
          "title": "Contrato - {{cliente_nome}}",
          "accessToken": "{{google_access_token}}",
          "refreshToken": "{{google_refresh_token}}"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Montar Texto",
        "parameters": {
          "operation": "set",
          "name": "contrato_texto",
          "value": "CONTRATO DE PRESTAÇÃO DE SERVIÇOS\n\nCONTRATANTE: {{cliente_nome}}\nCPF: {{cliente_cpf}}\n\nOBJETO: {{servico}}\n\nData: {{$now}}"
        }
      }
    },
    {
      "id": "google_docs_2",
      "type": "google_docs",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Inserir Conteúdo",
        "parameters": {
          "operation": "insertText",
          "documentId": "{{documentId}}",
          "text": "{{contrato_texto}}",
          "index": 1,
          "accessToken": "{{google_access_token}}",
          "refreshToken": "{{google_refresh_token}}"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 1500, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Contrato gerado!\n\n📄 {{title}}\n👤 Cliente: {{cliente_nome}}\n\n🔗 Abrir: https://docs.google.com/document/d/{{documentId}}/edit"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "input_2" },
    { "source": "input_2", "target": "input_3" },
    { "source": "input_3", "target": "google_docs_1" },
    { "source": "google_docs_1", "target": "variable_1" },
    { "source": "variable_1", "target": "google_docs_2" },
    { "source": "google_docs_2", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Nome do cliente:
Usuário: João Silva
Sistema: CPF do cliente:
Usuário: 123.456.789-00
Sistema: Descrição do serviço:
Usuário: Desenvolvimento de website
Sistema: ✅ Contrato gerado!

📄 Contrato - João Silva
👤 Cliente: João Silva

🔗 Abrir: https://docs.google.com/document/d/abc123.../edit

Exemplo 2: Ler Documento Existente

Objetivo: Extrair conteúdo de documento para processamento.

JSON para Importar

{
  "name": "Ler Documento do Google Docs",
  "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": "ID do Documento",
        "parameters": {
          "message": "Cole o ID do documento:",
          "variable": "doc_id"
        }
      }
    },
    {
      "id": "google_docs_1",
      "type": "google_docs",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Ler Documento",
        "parameters": {
          "operation": "get",
          "documentId": "{{doc_id}}",
          "accessToken": "{{google_access_token}}",
          "refreshToken": "{{google_refresh_token}}"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Mostrar Info",
        "parameters": {
          "message": "📄 Documento carregado!\n\nTítulo: {{document.title}}\n\nConteúdo extraído com sucesso!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "google_docs_1" },
    { "source": "google_docs_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Exemplo 3: Gerar Proposta Comercial

Objetivo: Criar proposta com valores e descrição personalizados.

JSON para Importar

{
  "name": "Gerar Proposta Comercial",
  "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": "Nome Empresa",
        "parameters": {
          "message": "Nome da empresa cliente:",
          "variable": "empresa"
        }
      }
    },
    {
      "id": "number_1",
      "type": "number",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Valor",
        "parameters": {
          "message": "Valor da proposta (R$):",
          "variable": "valor",
          "decimals": 2
        }
      }
    },
    {
      "id": "input_2",
      "type": "input",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Escopo",
        "parameters": {
          "message": "Escopo do projeto:",
          "variable": "escopo"
        }
      }
    },
    {
      "id": "google_docs_1",
      "type": "google_docs",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Criar Proposta",
        "parameters": {
          "operation": "create",
          "title": "Proposta Comercial - {{empresa}}",
          "accessToken": "{{google_access_token}}",
          "refreshToken": "{{google_refresh_token}}"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Montar Proposta",
        "parameters": {
          "operation": "set",
          "name": "proposta_texto",
          "value": "PROPOSTA COMERCIAL\n\n═══════════════════════════\n\nCLIENTE: {{empresa}}\n\nESCOPO:\n{{escopo}}\n\nVALOR TOTAL: R$ {{valor}}\n\nVALIDADE: 30 dias\n\n═══════════════════════════\n\nData: {{$now}}"
        }
      }
    },
    {
      "id": "google_docs_2",
      "type": "google_docs",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Inserir Texto",
        "parameters": {
          "operation": "insertText",
          "documentId": "{{documentId}}",
          "text": "{{proposta_texto}}",
          "accessToken": "{{google_access_token}}",
          "refreshToken": "{{google_refresh_token}}"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 1500, "y": 100 },
      "data": {
        "label": "Enviar Link",
        "parameters": {
          "message": "✅ Proposta gerada!\n\n🏢 {{empresa}}\n💰 R$ {{valor}}\n\n🔗 https://docs.google.com/document/d/{{documentId}}/edit"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "number_1" },
    { "source": "number_1", "target": "input_2" },
    { "source": "input_2", "target": "google_docs_1" },
    { "source": "google_docs_1", "target": "variable_1" },
    { "source": "variable_1", "target": "google_docs_2" },
    { "source": "google_docs_2", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Resposta do Node

Operação create

{
  "success": true,
  "documentId": "1abc123XYZ...",
  "title": "Contrato - João Silva"
}

Operação get

{
  "success": true,
  "document": {
    "documentId": "1abc123...",
    "title": "Meu Documento",
    "body": {
      "content": [
        {
          "paragraph": {
            "elements": [
              {
                "textRun": {
                  "content": "Texto do documento..."
                }
              }
            ]
          }
        }
      ]
    }
  },
  "content": [/* estrutura completa */]
}

Operação insertText

{
  "success": true,
  "replies": [
    {
      /* detalhes da operação */
    }
  ]
}

Operação batchUpdate

{
  "success": true,
  "replies": [
    /* array de respostas para cada request */
  ]
}

Como obter documentId

O documentId está na URL do Google Docs:

https://docs.google.com/document/d/1abc123XYZ.../edit
                                   ^^^^^^^^^^^
                                   documentId

Índices de Posição

O Google Docs usa índices numéricos para posições no texto:

Índice Posição
1 Início do documento
> 1 Caracteres após o início
-1 Usa localização automática

Exemplo:

index: 1 = insere no início
index: 50 = insere na posição 50

Requests do batchUpdate

O parâmetro requests permite múltiplas operações:

{
  "requests": [
    {
      "insertText": {
        "location": { "index": 1 },
        "text": "Título do Documento\n"
      }
    },
    {
      "updateTextStyle": {
        "range": {
          "startIndex": 1,
          "endIndex": 20
        },
        "textStyle": {
          "bold": true,
          "fontSize": { "magnitude": 18, "unit": "PT" }
        },
        "fields": "bold,fontSize"
      }
    }
  ]
}

Operações disponíveis: - insertText - deleteContentRange - updateTextStyle - insertPageBreak - createParagraphBullets - E muitas outras...

Estrutura de Conteúdo

Documentos do Google Docs têm estrutura hierárquica:

Document
└── Body
    └── Content []
        ├── Paragraph
        │   └── Elements []
        │       └── TextRun
        │           └── content: "texto"
        ├── Table
        └── SectionBreak

Boas Práticas

SIM:

  • Use títulos descritivos ao criar documentos
  • Salve documentId para operações futuras
  • Valide conteúdo antes de inserir
  • Use batchUpdate para múltiplas edições
  • Organize documentos em pastas do Drive

NÃO:

  • Não insira texto sem validar caracteres especiais
  • Não delete conteúdo sem backup
  • Não crie documentos duplicados sem necessidade
  • Não ignore estrutura de índices
  • Não faça edições simultâneas sem controle

Dicas

💡 Templates: Crie template base e clone para novos documentos

💡 Formatação: Use batchUpdate para aplicar estilos complexos

💡 Performance: Agrupe múltiplas operações em um batchUpdate

💡 Versionamento: Google Docs mantém histórico automático

💡 Compartilhamento: Configure permissões via Drive API após criar

Troubleshooting

Erro: "Document not found"

Causa: documentId inválido ou sem permissão

Solução: Verifique ID na URL e permissões de acesso

Erro: "Invalid index"

Causa: Posição de inserção inválida

Solução: Use index 1 para início ou obtenha tamanho do documento

Erro: "Invalid requests"

Causa: Formato incorreto em batchUpdate

Solução: Siga estrutura da documentação oficial do Google

Erro: "Quota exceeded"

Causa: Muitas requisições em pouco tempo

Solução: Implemente rate limiting ou aguarde

Conversão para PDF

Para converter documento em PDF, use Google Drive API:

  1. Crie/edite documento com Google Docs API
  2. Use Drive API export:
    GET https://www.googleapis.com/drive/v3/files/{documentId}/export?mimeType=application/pdf
    

Próximo Node

GOOGLE_SLIDES - Criar apresentações → GOOGLE_SHEETS - Trabalhar com planilhas → GOOGLE_DRIVE - Gerenciar arquivos