fix: remove review truncation and show full reviews; fix telegram-cms workflow bugs
- ReadBooks.tsx: remove line-clamp-3, readMore button, and review modal - Show full review text inline instead of truncated snippets - Remove unused AnimatePresence, X import, selectedReview state - Fix typo in 6 handler nodes - Fix Markdown/HTML mix (*text*</b> → <b>text</b>) - Fix Switch condition syntax (.action → .action) - Fix position collision (Review Info Handler) - Hardcode Telegram bot token, fix response handling in Publish Handler - Add AI-generated questions for .review flow (was .review HC_ID TEXT) - New .answer command for submitting review answers - Create/Refine Review: POST new translations if missing instead of skipping - Remove all substring truncations from Telegram messages
This commit is contained in:
417
n8n-workflows/docker-callback-handler.json
Normal file
417
n8n-workflows/docker-callback-handler.json
Normal file
@@ -0,0 +1,417 @@
|
||||
{
|
||||
"name": "Docker Event - Callback Handler",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"updates": [
|
||||
"callback_query"
|
||||
],
|
||||
"additionalFields": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.telegramTrigger",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
-880,
|
||||
288
|
||||
],
|
||||
"id": "a56a5174-3ccf-492f-810b-117be933560c",
|
||||
"name": "Telegram Trigger",
|
||||
"webhookId": "6e70b9ab-b76b-48dc-8e4d-5fe1bf0d7e39",
|
||||
"credentials": {
|
||||
"telegramApi": {
|
||||
"id": "ADurvy9EKUDzbDdq",
|
||||
"name": "DK0_Server"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const callback = $input.first().json;\nconst data = callback.callback_query?.data || '';\nconst chatId = callback.callback_query?.from?.id;\nconst messageId = callback.callback_query?.message?.message_id;\n\n// Parse: auto:slug, manual:slug, ignore:slug\nconst [action, slug] = data.split(':');\n\nreturn [{\n json: {\n action,\n slug,\n chatId,\n messageId,\n rawCallback: data\n }\n}];"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
-656,
|
||||
288
|
||||
],
|
||||
"id": "10e5a475-4194-4919-9186-1eb052fbd79b",
|
||||
"name": "Parse Callback"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"leftValue": ""
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"leftValue": "={{ $json.action }}",
|
||||
"rightValue": "auto",
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"renameOutput": true,
|
||||
"outputKey": "Auto"
|
||||
},
|
||||
{
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"leftValue": ""
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"leftValue": "={{ $json.action }}",
|
||||
"rightValue": "manual",
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"renameOutput": true,
|
||||
"outputKey": "Manual"
|
||||
},
|
||||
{
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"leftValue": ""
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"leftValue": "={{ $json.action }}",
|
||||
"rightValue": "ignore",
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"renameOutput": true,
|
||||
"outputKey": "Ignore"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"typeVersion": 3.2,
|
||||
"position": [
|
||||
-448,
|
||||
288
|
||||
],
|
||||
"id": "a533e527-b3c5-4946-9a26-6f499c7dd6c5",
|
||||
"name": "Switch Action"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "=https://cms.dk0.dev/items/projects?filter[slug][_eq]={{ $json.slug }}&limit=1",
|
||||
"authentication": "predefinedCredentialType",
|
||||
"nodeCredentialType": "httpBearerAuth",
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
-224,
|
||||
80
|
||||
],
|
||||
"id": "9fc55503-e890-4074-9823-f07001b6948a",
|
||||
"name": "Get Project from CMS"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "=https://git.dk0.dev/api/v1/repos/denshooter/{{ $json.slug }}/commits?limit=3",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"id": "a3fda0d9-0cc9-4744-be3e-9a95ef44dfb4",
|
||||
"name": "Get Commits"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "=https://git.dk0.dev/api/v1/repos/denshooter/{{ $json.slug }}/contents/README.md",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
0,
|
||||
128
|
||||
],
|
||||
"id": "7106b8c9-fb20-46d9-9e4e-06882115bf7a",
|
||||
"name": "Get README"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "openrouter/free",
|
||||
"options": {}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
448,
|
||||
192
|
||||
],
|
||||
"id": "9acce2c3-1a26-450f-a263-0dc3a1f1e3cf",
|
||||
"name": "OpenRouter Chat Model"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"promptType": "define",
|
||||
"text": "=Du bist ein technischer Autor für das Portfolio von Dennis (dk0.dev).\n\nNeues eigenes Projekt deployed:\nRepo: {{ $('Parse Callback').item.json.slug }}\n\nREADME:\n{{ $('Get README').first().json.content ? Buffer.from($('Get README').first().json.content, 'base64').toString('utf8').substring(0, 1000) : 'Kein README' }}\n\nLetzte Commits:\n{{ $('Get Commits').first().json.map(c => '- ' + c.commit.message).join('\\n') }}\n\nErstelle eine Portfolio-Beschreibung:\n- Was macht das Projekt (Features, Zweck)\n- Tech-Stack und Architektur\n- Highlights aus den Commits\n- Warum ist es cool/interessant\n\nKategorie: webdev (wenn Web-App), automation (wenn Tool/Script), oder selfhosted\n\nAntworte NUR als JSON:\n{\n \"title_en\": \"Aussagekräftiger Titel\",\n \"title_de\": \"Aussagekräftiger Titel\",\n \"description_en\": \"4-6 Sätze\",\n \"description_de\": \"4-6 Sätze\",\n \"content_en\": \"2-3 Absätze Markdown mit technischen Details\",\n \"content_de\": \"2-3 Absätze Markdown mit technischen Details\",\n \"category\": \"webdev|automation|selfhosted\",\n \"technologies\": [\"Next.js\", \"Docker\", \"...\"]\n}",
|
||||
"batching": {}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.chainLlm",
|
||||
"typeVersion": 1.9,
|
||||
"position": [
|
||||
224,
|
||||
80
|
||||
],
|
||||
"id": "2b011cf8-6ed3-4cb1-ab6f-7727912864fc",
|
||||
"name": "AI: Generate Description"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const raw = $input.first().json.text ?? \"\";\nconst match = raw.match(/\\{[\\s\\S]*\\}/);\nif (!match) throw new Error(\"No JSON found\");\nconst ai = JSON.parse(match[0]);\nreturn [{ json: ai }];"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
448,
|
||||
80
|
||||
],
|
||||
"id": "0cbdcf6e-e5d4-460e-b345-b6d47deed051",
|
||||
"name": "Parse JSON"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const ai = $input.first().json;\nconst ctx = $('Parse Callback').first().json;\n\nconst body = {\n slug: ctx.slug,\n status: \"draft\",\n featured: false,\n title: ai.title_en,\n category: ai.category,\n technologies: ai.technologies,\n tags: ai.technologies,\n date: new Date().toISOString().slice(0, 10),\n translations: {\n create: [\n {\n languages_code: \"en-US\",\n title: ai.title_en,\n description: ai.description_en,\n content: ai.content_en\n },\n {\n languages_code: \"de-DE\",\n title: ai.title_de,\n description: ai.description_de,\n content: ai.content_de\n }\n ]\n }\n};\n\nconst response = await this.helpers.httpRequest({\n method: \"POST\",\n url: \"https://cms.dk0.dev/items/projects\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"Bearer RF2QytqhcLXuVy6FO3PzWlsoR-ysCTwB\"\n },\n body\n});\n\nreturn [{ json: response }];"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
672,
|
||||
80
|
||||
],
|
||||
"id": "70aecf97-6b70-4f03-99e3-9ee44fc0830b",
|
||||
"name": "Add to Directus"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"chatId": "={{ $('Parse Callback').item.json.chatId }}",
|
||||
"text": "={{ \n'✅ Projekt erstellt: ' + $json.data.title + '\\n\\n' +\n'📝 ' + $('Parse JSON').first().json.description_de.substring(0, 200) + '...\\n\\n' +\n'Status: Draft (ID: ' + $json.data.id + ')\\n\\n' +\n'/publishproject' + $json.data.id + ' — Veröffentlichen\\n' + \n'/deleteproject' + $json.data.id + ' — Löschen' \n}}",
|
||||
"additionalFields": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.telegram",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
880,
|
||||
80
|
||||
],
|
||||
"id": "9a353247-7d25-4330-9cbf-580599428ae1",
|
||||
"name": "Notify Success",
|
||||
"webhookId": "b1d7284d-c2e5-4e87-b65d-272f1b9b8d6d"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"chatId": "={{ $json.chatId }}",
|
||||
"text": "✍️ OK, schreib mir jetzt was das Projekt macht (4-6 Sätze).\n\nIch formatiere das dann schön und erstelle einen Draft.",
|
||||
"additionalFields": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.telegram",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
-224,
|
||||
288
|
||||
],
|
||||
"id": "9160b847-5f07-4d64-9488-faeaeca926b9",
|
||||
"name": "Ask for Manual Input",
|
||||
"webhookId": "c4cb518d-a2e2-48af-b9b6-c3f645fd37db"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"chatId": "={{ $json.chatId }}",
|
||||
"text": "❌ OK, ignoriert.",
|
||||
"additionalFields": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.telegram",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
-224,
|
||||
480
|
||||
],
|
||||
"id": "1624b6f1-8202-4fd2-bd0a-52fa039ca696",
|
||||
"name": "Confirm Ignore",
|
||||
"webhookId": "4c5248f1-4420-403c-a506-2e1968c5579d",
|
||||
"credentials": {
|
||||
"telegramApi": {
|
||||
"id": "ADurvy9EKUDzbDdq",
|
||||
"name": "DK0_Server"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"Telegram Trigger": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Parse Callback",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Parse Callback": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Switch Action",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Switch Action": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Project from CMS",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Ask for Manual Input",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Confirm Ignore",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Project from CMS": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Commits",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Commits": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get README",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get README": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "AI: Generate Description",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenRouter Chat Model": {
|
||||
"ai_languageModel": [
|
||||
[
|
||||
{
|
||||
"node": "AI: Generate Description",
|
||||
"type": "ai_languageModel",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"AI: Generate Description": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Parse JSON",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Parse JSON": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Add to Directus",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Add to Directus": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notify Success",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1",
|
||||
"binaryMode": "separate",
|
||||
"availableInMCP": false
|
||||
},
|
||||
"versionId": "4636a407-7f8e-4833-9345-9d3296ec9b74",
|
||||
"meta": {
|
||||
"instanceId": "cb28e4db755465d5826da179e87f69603d81f833414cc52c327be9183a217b8d"
|
||||
},
|
||||
"id": "abnrtUuJ7BAWv9Hm",
|
||||
"tags": []
|
||||
}
|
||||
Reference in New Issue
Block a user