Files
portfolio/n8n-workflows/book-review.json
denshooter 8ff17c552b
All checks were successful
CI / CD / test-build (push) Successful in 10m19s
CI / CD / deploy-dev (push) Successful in 2m7s
CI / CD / deploy-production (push) Has been skipped
chore: update workflows, messages, and footer
2026-04-09 17:22:56 +02:00

219 lines
7.8 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"name": "Book Review",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 19
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
0,
-192
],
"id": "f0c86dde-aa19-4440-b17c-c572b582da5e",
"name": "Schedule Trigger"
},
{
"parameters": {
"method": "POST",
"url": "https://api.hardcover.app/v1/graphql",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpBearerAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "content-type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "query",
"value": "query GetFinishedBooks { me { user_books(where: {status_id: {_eq: 3}}, limit: 5) { book { id title contributions { author { name } } images { url } } last_read_date updated_at } } }"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
224,
-192
],
"id": "e5c28f64-29ed-40ae-804e-896c10f3bc58",
"name": "HTTP Request",
"credentials": {
"httpBearerAuth": {
"id": "Kmf2fBCFkuRuWWZa",
"name": "Hardcover"
}
}
},
{
"parameters": {
"jsCode": "const responseData = $input.first().json;\nconst meData = responseData?.data?.me;\nconst userBooks =\n (Array.isArray(meData) && meData[0]?.user_books) || meData?.user_books || [];\n\nconst newBooks = [];\n\nfor (const ub of userBooks) {\n const check = await this.helpers.httpRequest({\n method: \"GET\",\n url:\n \"https://cms.dk0.dev/items/book_reviews?filter[hardcover_id][_eq]=\" +\n ub.book.id +\n \"&fields=id,translations.id&limit=1\",\n headers: {\n Authorization: \"Bearer RF2QytqhcLXuVy6FO3PzWlsoR-ysCTwB\",\n },\n });\n\n const existing = check.data?.[0];\n const hasReview =\n existing && existing.translations && existing.translations.length > 0;\n\n if (!hasReview) {\n newBooks.push({\n json: {\n hardcover_id: String(ub.book.id),\n directus_id: existing ? existing.id : null,\n title: ub.book.title,\n author: ub.book.contributions?.[0]?.author?.name ?? \"Unknown\",\n image: ub.book.images?.[0]?.url ?? null,\n finished_at: ub.last_read_date ?? ub.updated_at ?? null,\n already_in_directus: !!existing,\n },\n });\n }\n}\n\nreturn newBooks.length > 0 ? newBooks[0] : [{ json: { skip: true } }];\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
448,
-192
],
"id": "60380362-e954-40ee-b0d0-7bc1edbaf9d3",
"name": "Filter books"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "b356ade3-5cf0-40dd-bb47-e977f354e803",
"leftValue": "={{ $json.skip }}",
"rightValue": "={{ $json.skip }}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
672,
-192
],
"id": "45f65c65-ae6a-46b0-9d96-46f0a32e59db",
"name": "If"
},
{
"parameters": {
"jsCode": "const book = $input.first().json;\nif (book.skip) return [{ json: { skip: true } }];\n\nconst parts = [];\nparts.push(\"Du hilfst jemandem eine Buchbewertung zu schreiben.\");\nparts.push(\"Das Buch ist \" + book.title + \" von \" + book.author + \".\");\nparts.push(\"Erstelle 4 kurze spezifische Fragen zum Buch.\");\nparts.push(\"Die Fragen sollen helfen eine Review zu schreiben.\");\nparts.push(\"Frage auf Deutsch.\");\nparts.push(\"Antworte NUR als JSON Array mit 4 Strings. Verwende keine Bindestriche, Em-Dashes oder Gedankenstriche (, —, -).\");\nconst prompt = parts.join(\" \");\n\nconst aiResponse = await this.helpers.httpRequest({\n method: \"POST\",\n url: \"https://openrouter.ai/api/v1/chat/completions\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: \"Bearer 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\",\n },\n body: {\n model: \"openrouter/free\",\n messages: [{ role: \"user\", content: prompt }],\n },\n});\n\nconst aiText = aiResponse.choices?.[0]?.message?.content ?? \"[]\";\nconst match = aiText.match(/\\[[\\s\\S]*\\]/);\n\nconst f1 = \"Wie hat dir das Buch gefallen?\";\nconst f2 = \"Was war der beste Teil?\";\nconst f3 = \"Was hast du mitgenommen?\";\nconst f4 = \"Wem empfiehlst du es?\";\nconst fallback = [f1, f2, f3, f4];\n\nconst questions = match ? JSON.parse(match[0]) : fallback;\n\nreturn [{ json: { ...book, questions } }];\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
896,
-192
],
"id": "b56ab681-90d8-4376-9408-dc3302ab55bd",
"name": "ai"
},
{
"parameters": {
"chatId": "145931600",
"text": "={{ '📚 ' + $json.title + ' von ' + $json.author + '\\n\\nBeantworte bitte:\\n\\n1. ' + $json.questions[0] + '\\n2. ' + $json.questions[1] + '\\n3. ' + $json.questions[2] + '\\n4. ' + $json.questions[3] + '\\n\\n⭐ Bewertung (1-5)?\\n\\nAntworte so (kopiere und ergänze):\\n\\n/review' + $json.hardcover_id + ' Hier deine Antworten als Text' }}",
"additionalFields": {}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1136,
-208
],
"id": "13087afe-8a1d-457f-a1f1-e0aa64fc0e26",
"name": "Send a text message",
"webhookId": "eaa44b55-b3b1-4747-9b6a-dfc920910b4b",
"credentials": {
"telegramApi": {
"id": "ADurvy9EKUDzbDdq",
"name": "DK0_Server"
}
}
}
],
"pinData": {},
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Filter books",
"type": "main",
"index": 0
}
]
]
},
"Filter books": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[],
[
{
"node": "ai",
"type": "main",
"index": 0
}
]
]
},
"ai": {
"main": [
[
{
"node": "Send a text message",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false
},
"versionId": "4c605d70-0428-4611-9ad8-d9452c2660a7",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "cb28e4db755465d5826da179e87f69603d81f833414cc52c327be9183a217b8d"
},
"id": "FDQ5Qmk9POy4Ajdd",
"tags": []
}