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:
- Gerar documentos automaticamente: Criar contratos, propostas, relatórios
- Preencher templates: Inserir dados dinâmicos em modelos prontos
- Extrair conteúdo: Ler texto de documentos existentes
- Automatizar edição: Fazer alterações em massa via API
- Integração com workflows: Conectar documentação com processos
Como funciona internamente?
Quando o GOOGLE_DOCS é executado, o sistema:
- Autentica via OAuth2 com Google (access_token e refresh_token)
- Conecta à API do Google Docs v1
- Executa operação solicitada (create, get, batchUpdate, insertText)
- Processa estrutura do documento (parágrafos, texto, formatação)
- Retorna documentId, conteúdo ou confirmação
- 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
- Gerar contratos: "Criar contrato com dados do cliente"
- Criar propostas: "Gerar proposta comercial personalizada"
- Relatórios automáticos: "Gerar relatório mensal de vendas"
- Preencher templates: "Substituir [NOME] por dados reais"
- Documentação dinâmica: "Criar documentação de projeto"
- 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:
- Crie/edite documento com Google Docs API
- 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