cosmolocal-website/n8n-workflows/05-webhook-events.json

348 lines
10 KiB
JSON

{
"name": "Webhook Events — Gitea/GitHub to CRM",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "git-events",
"options": {}
},
"id": "webhook-git",
"name": "Webhook — Git Events",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [240, 300],
"webhookId": "git-events"
},
{
"parameters": {
"jsCode": "const body = $input.first().json.body;\nconst headers = $input.first().json.headers;\n\n// Detect source (Gitea vs GitHub)\nconst isGitea = headers['x-gitea-event'] !== undefined;\nconst isGitHub = headers['x-github-event'] !== undefined;\n\nconst eventType = isGitea \n ? headers['x-gitea-event'] \n : headers['x-github-event'] || 'unknown';\n\nlet result = {\n source: isGitea ? 'gitea' : isGitHub ? 'github' : 'unknown',\n eventType,\n repo: body.repository?.full_name || body.repository?.name || 'unknown',\n action: body.action || 'push',\n sender: body.sender?.login || body.pusher?.name || 'unknown',\n senderEmail: body.sender?.email || body.pusher?.email || '',\n url: '',\n title: '',\n description: ''\n};\n\nswitch (eventType) {\n case 'push':\n const commits = body.commits || [];\n result.title = `Push: ${commits.length} commit(s) to ${result.repo}`;\n result.description = commits.map(c => `- ${c.message}`).join('\\n');\n result.url = body.compare_url || body.compare || '';\n break;\n case 'issues':\n result.title = `Issue ${body.action}: ${body.issue?.title}`;\n result.description = body.issue?.body || '';\n result.url = body.issue?.html_url || '';\n break;\n case 'pull_request':\n result.title = `PR ${body.action}: ${body.pull_request?.title}`;\n result.description = body.pull_request?.body || '';\n result.url = body.pull_request?.html_url || '';\n break;\n case 'create':\n result.title = `Created ${body.ref_type}: ${body.ref}`;\n result.description = `New ${body.ref_type} created in ${result.repo}`;\n break;\n case 'star':\n case 'watch':\n result.title = `${result.sender} starred ${result.repo}`;\n result.description = `Repository now has ${body.repository?.stars_count || body.repository?.stargazers_count || '?'} stars`;\n break;\n default:\n result.title = `${eventType} event on ${result.repo}`;\n result.description = JSON.stringify(body).substring(0, 500);\n}\n\nreturn [{ json: result }];"
},
"id": "parse-event",
"name": "Parse Git Event",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [460, 300]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "is-significant",
"leftValue": "={{ $json.eventType }}",
"rightValue": "push,issues,pull_request,star",
"operator": {
"type": "string",
"operation": "contains"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "filter-significant",
"name": "Filter Significant Events",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [680, 300]
},
{
"parameters": {
"method": "POST",
"url": "https://crm.cosmolocal.world/api/v1/objects/notes",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $env.TWENTY_API_KEY }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"title\": \"[{{ $json.source }}] {{ $json.title }}\",\n \"body\": \"**Event**: {{ $json.eventType }}\\n**Repo**: {{ $json.repo }}\\n**By**: {{ $json.sender }}\\n\\n{{ $json.description }}\\n\\n{{ $json.url ? '[View on ' + $json.source + '](' + $json.url + ')' : '' }}\"\n}",
"options": {}
},
"id": "log-to-crm",
"name": "Log Activity to CRM",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [900, 240]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "has-email",
"leftValue": "={{ $('Parse Git Event').item.json.senderEmail }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "isNotEmpty"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "has-sender-email",
"name": "Sender Has Email?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [1120, 240]
},
{
"parameters": {
"method": "GET",
"url": "https://crm.cosmolocal.world/api/v1/objects/people",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $env.TWENTY_API_KEY }}"
}
]
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "filter",
"value": "={\"emails\":{\"primaryEmail\":{\"eq\":\"{{ $('Parse Git Event').item.json.senderEmail }}\"}}}"
}
]
},
"options": {}
},
"id": "find-contact",
"name": "Find Contact by Email",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [1340, 180]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "contact-found",
"leftValue": "={{ $json.data?.people?.length }}",
"rightValue": 0,
"operator": {
"type": "number",
"operation": "gt"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "contact-exists",
"name": "Contact Found?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [1560, 180]
},
{
"parameters": {
"method": "PATCH",
"url": "=https://crm.cosmolocal.world/api/v1/objects/people/{{ $json.data.people[0].id }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $env.TWENTY_API_KEY }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"updatedAt\": \"{{ new Date().toISOString() }}\"\n}",
"options": {}
},
"id": "touch-contact",
"name": "Touch Contact — Update Timestamp",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [1780, 120]
},
{
"parameters": {
"method": "POST",
"url": "https://crm.cosmolocal.world/api/v1/objects/people",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $env.TWENTY_API_KEY }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"name\": {\n \"firstName\": \"{{ $('Parse Git Event').item.json.sender }}\",\n \"lastName\": \"\"\n },\n \"emails\": {\n \"primaryEmail\": \"{{ $('Parse Git Event').item.json.senderEmail }}\"\n }\n}",
"options": {}
},
"id": "create-contributor-contact",
"name": "Create Contributor Contact",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [1780, 280]
},
{
"parameters": {},
"id": "no-op-skip",
"name": "Skip — Not Significant",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [900, 420]
}
],
"connections": {
"Webhook — Git Events": {
"main": [
[
{
"node": "Parse Git Event",
"type": "main",
"index": 0
}
]
]
},
"Parse Git Event": {
"main": [
[
{
"node": "Filter Significant Events",
"type": "main",
"index": 0
}
]
]
},
"Filter Significant Events": {
"main": [
[
{
"node": "Log Activity to CRM",
"type": "main",
"index": 0
}
],
[
{
"node": "Skip — Not Significant",
"type": "main",
"index": 0
}
]
]
},
"Log Activity to CRM": {
"main": [
[
{
"node": "Sender Has Email?",
"type": "main",
"index": 0
}
]
]
},
"Sender Has Email?": {
"main": [
[
{
"node": "Find Contact by Email",
"type": "main",
"index": 0
}
],
[]
]
},
"Find Contact by Email": {
"main": [
[
{
"node": "Contact Found?",
"type": "main",
"index": 0
}
]
]
},
"Contact Found?": {
"main": [
[
{
"node": "Touch Contact — Update Timestamp",
"type": "main",
"index": 0
}
],
[
{
"node": "Create Contributor Contact",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [
{
"name": "cosmolocal"
},
{
"name": "git"
},
{
"name": "crm"
}
],
"pinData": {}
}