{ "id": "b0KRVIuuUxE5afHo", "meta": { "instanceId": "98bf0d6aef1dd8b7a752798121440fb171bf7686b95727fd617f43452393daa3", "templateCredsSetupCompleted": true }, "name": "Blog Automation TEMPLATE", "tags": [ { "id": "uumvgGHY5e6zEL7V", "name": "Published Template", "createdAt": "2025-02-10T11:18:10.923Z", "updatedAt": "2025-02-10T11:18:10.923Z" } ], "nodes": [ { "id": "20e00146-6bda-4a8a-9544-bf7e5fd4e12e", "name": "Settings", "type": "n8n-nodes-base.set", "position": [ -420, -160 ], "parameters": { "options": {}, "assignments": { "assignments": [ { "id": "528b371f-0fba-4be1-9801-0502652da23e", "name": "urlSpreadsheet", "type": "string", "value": "https://docs.google.com/spreadsheets/d/1Kg1-U6mJF4bahH1jCw8kT48MiKz1UMC5n-9q77BHM3Q/edit?gid=0#gid=0" }, { "id": "1be018c7-51fe-4ea2-967d-ce47a2e8795c", "name": "urlWordpress", "type": "string", "value": "SUBDOMAIN.wordpress.com" }, { "id": "95377f4f-184b-46a7-94c7-b2313c314cb2", "name": "wordpressUsername", "type": "string", "value": "YourUserName" }, { "id": "fdc99dc6-d9b0-4d2f-b770-1d8b6b360cad", "name": "wordpressApplicationPassword", "type": "string", "value": "y0ur app1 p4ss w0rd" }, { "id": "517cb9ff-24fc-41d6-8bcc-253078f56356", "name": "sheetSchedule", "type": "string", "value": "=Schedule" }, { "id": "584e11da-546b-4472-8674-33ca7e8f4f30", "name": "sheetConfig", "type": "string", "value": "Config" }, { "id": "ba38cb1e-fd97-4aed-9147-1946c318ddab", "name": "actionPublish", "type": "string", "value": "publish" }, { "id": "678394b5-20af-4718-9249-4ff6a3c77018", "name": "actionUpdate", "type": "string", "value": "" }, { "id": "f375b2fa-8772-4313-9d6b-a104edd918b3", "name": "sheetLog", "type": "string", "value": "Log" }, { "id": "3d7f9677-c753-4126-b33a-d78ef701771f", "name": "", "type": "string", "value": "" } ] } }, "typeVersion": 3.4 }, { "id": "35731842-9215-43df-9009-9b130d663237", "name": "ScheduleTrigger", "type": "n8n-nodes-base.scheduleTrigger", "position": [ -620, -280 ], "parameters": { "rule": { "interval": [ { "field": "hours" } ] } }, "typeVersion": 1.2 }, { "id": "4c284d44-ac46-4cdf-9dcb-727b464269a0", "name": "ManualTrigger", "type": "n8n-nodes-base.manualTrigger", "position": [ -620, -100 ], "parameters": {}, "typeVersion": 1 }, { "id": "b63e7345-67d0-4761-8c1a-49275f34e88d", "name": "Schedule", "type": "n8n-nodes-base.googleSheets", "position": [ -220, -80 ], "parameters": { "options": {}, "sheetName": { "__rl": true, "mode": "name", "value": "={{ $('Settings').item.json.sheetSchedule }}" }, "documentId": { "__rl": true, "mode": "url", "value": "={{ $('Settings').item.json.urlSpreadsheet }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XeXufn5uZvHp3lcX", "name": "Google Sheets account 2" } }, "notesInFlow": true, "typeVersion": 4.5 }, { "id": "5fed06a3-3188-4aed-8040-04e245b74e20", "name": "Config", "type": "n8n-nodes-base.code", "position": [ 40, -220 ], "parameters": { "jsCode": "let a = $(\"fetchConfig\").all();\nlet params = {};\na.forEach(p => params[p.json.Key] = p.json.Value);\n\nreturn params;\n" }, "typeVersion": 2 }, { "id": "685490c8-6b45-40c2-b4db-e97a81c4be8e", "name": "fetchConfig", "type": "n8n-nodes-base.googleSheets", "position": [ -220, -220 ], "parameters": { "options": {}, "sheetName": { "__rl": true, "mode": "name", "value": "={{ $('Settings').item.json.sheetConfig }}" }, "documentId": { "__rl": true, "mode": "url", "value": "={{ $('Settings').item.json.urlSpreadsheet }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XeXufn5uZvHp3lcX", "name": "Google Sheets account 2" } }, "notesInFlow": true, "typeVersion": 4.5 }, { "id": "52a39db8-f9cc-44bb-9c3e-a9abf5821a04", "name": "AgentLLM", "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", "position": [ -400, 440 ], "parameters": { "model": "={{ $json.model }}", "options": {} }, "credentials": { "openAiApi": { "id": "66JEQJ5kJel1P9t3", "name": "OpenRouter" } }, "typeVersion": 1.1 }, { "id": "6a311ac4-032b-42da-b06e-c916209d2843", "name": "IfScheduledNow", "type": "n8n-nodes-base.if", "position": [ -620, 780 ], "parameters": { "options": {}, "conditions": { "options": { "version": 2, "leftValue": "", "caseSensitive": true, "typeValidation": "loose" }, "combinator": "and", "conditions": [ { "id": "bb707069-b372-4bbd-8ba5-b7f6b492ab9d", "operator": { "type": "number", "operation": "gte" }, "leftValue": "={{ DateTime.now().ts }}", "rightValue": "={{ DateTime.fromFormat($json.row.Scheduled, \"yyyy-MM-dd HH:mm:ss\").ts }}" } ] }, "looseTypeValidation": true }, "typeVersion": 2.2 }, { "id": "845e419b-15ad-4548-86c5-44bda0433b71", "name": "PreparedData", "type": "n8n-nodes-base.code", "position": [ 40, -80 ], "parameters": { "mode": "runOnceForEachItem", "jsCode": "function replacePlaceholders(text, row, config) {\n function checkProp(prop, lookup) {\n // console.log('checkProp:' + prop);\n if (!lookup.hasOwnProperty(prop)) return false;\n let value = lookup[prop];\n if (typeof(value) == 'string') {\n value = value.trim();\n if (value == '') return false;\n }\n // console.log('checkProp found:', value)\n return value;\n }\n function replaceMatch(fullMatch, prop) { \n prop = prop.trim();\n // Return the corresponding value\n return checkProp(prop, row)\n || checkProp(prop, config)\n || checkProp(prop + checkProp('Context', row), config)\n || `[could not find \"${ prop }]\"`;\n }\n\n if (typeof(text) != 'string') return '';\n\n // Regex to capture {{ ... }}\n const pattern = /\\{\\{\\s*([^}]+)\\s*\\}\\}/g\n const result = text.replace(pattern, replaceMatch);\n return result.trim();\n}\n\nconst row = $json;\nconst settings = $(\"Settings\").first().json;\nconst config = $(\"Config\").first().json;\nconst prompt_key = 'prompt_' + row.Action;\nconst prompt = replacePlaceholders(config[prompt_key], row, config);\nconst model_key = prompt_key + '_model';\nconst model = replacePlaceholders(config[model_key], row, config);\nconst outputFormat = config[prompt_key + '_outputFormat'];\nconst takeAction = row.Action != row.Status;\nconst action = row.Action\n\n// console.log('prompt', prompt);\n\n// console.log(prompt);\nreturn { takeAction, action, model_key, model, prompt_key, prompt, outputFormat, row, config, settings }" }, "typeVersion": 2 }, { "id": "db294805-df67-4266-919f-94fb0f32c593", "name": "RecombinedDataRow", "type": "n8n-nodes-base.code", "position": [ 40, 280 ], "parameters": { "mode": "runOnceForEachItem", "jsCode": "/**\n * Attempts to parse the \"text\" property in a JSON object\n * that may contain malformed or incorrectly escaped JSON.\n *\n * @param {Object} raw - A string to parse.\n * @returns {Object|null} The parsed JSON object if successful, or null if all attempts fail.\n */\nfunction parseTextAsJson(raw) {\n // 1) First, try a direct parse.\n try {\n return JSON.parse(raw);\n } catch (e) {\n // Continue to next strategy\n }\n\n // Common \"fix-up\" strategies:\n // Strategy A: Attempt to remove over-escaped quotes like `\\\\\"` -> `\"`\n try {\n const fixedA = raw.replace(/\\\\\"/g, '\"');\n return JSON.parse(fixedA);\n } catch (e) {\n // Continue\n }\n\n // Strategy B: Remove escaped newlines, tabs, carriage returns if they’re suspected\n try {\n const fixedB = raw\n .replace(/\\\\n/g, ' ')\n .replace(/\\\\r/g, ' ')\n .replace(/\\\\t/g, ' ');\n return JSON.parse(fixedB);\n } catch (e) {\n // Continue\n }\n\n // Strategy C: Replace single quotes with double quotes (useful if the JSON was incorrectly quoted).\n // NOTE: This is a very rough fix. If your data legitimately includes single quotes you may need\n // a more nuanced approach.\n try {\n const fixedC = raw.replace(/'/g, '\"');\n return JSON.parse(fixedC);\n } catch (e) {\n // Continue\n }\n\n // Strategy D: Combine strategies or chain them if needed:\n // For example, single-quote fix plus removing new lines, etc.\n try {\n let fixedD = raw.replace(/\\\\\"/g, '\"');\n fixedD = fixedD.replace(/\\\\n|\\\\r|\\\\t/g, ' ');\n fixedD = fixedD.replace(/'/g, '\"');\n return JSON.parse(fixedD);\n } catch (e) {\n // If all attempts fail, log or handle the error as needed\n console.error('Could not parse \"text\" property as JSON.', e);\n return { 'Fulltext': raw };\n }\n}\n\nfunction isolateCurlySubstring(str) {\n // This pattern greedily matches everything from the first '{' to the last '}'.\n const match = str.match(/\\{[\\s\\S]*\\}/);\n \n // If a match is found, return it; otherwise return the entire string.\n return match ? match[0] : str;\n}\n\nfunction fixJsonSyntax(str) {\n str = str.replace('\\\"', '\"');\n str = str\n .split(/(\"[^\"]*\"|'[^']*')/)\n .map((part, i) => i % 2 ? part : part.replace(/\\n/g, \" \"))\n .join(\"\");\n return str;\n}\n\nfunction normalizeLLMOutput(param, iteration = 3) {\n // If it's not an object or it's null or an array, just return it as is.\n // (In some workflows, you might decide to throw an error or handle differently.)\n if (!iteration || typeof param !== 'object' || param === null || Array.isArray(param)) {\n return param;\n }\n\n // Get the object's own property keys\n const keys = Object.keys(param);\n\n // If there's more than one property, we assume it's already the complex object we want.\n if (keys.length > 1) {\n // console.log('keys > 1 → return param', param);\n return param;\n }\n\n // If there are no properties, just return it (though this is likely an empty object).\n if (keys.length === 0) {\n return param;\n }\n\n // If there's exactly one property, it might be a JSON-string that we need to parse.\n const singleKey = keys[0];\n const value = param[singleKey];\n // If that single property is a string, fix it and try to parse it as JSON.\n if (typeof value === 'string') {\n try {\n return parseTextAsJson(isolateCurlySubstring(value));\n } catch (e) {\n console.log('value is string → parse failed with error:', e.toString(), '→ return param:', param, 'value:', value);\n // Parsing failed; perhaps it's just a plain string or invalid JSON, so return as is.\n return param;\n }\n }\n\n // Otherwise, repeat this process itratively.\n return normalizeLLMOutput(value, iteration-1);\n}\n\nconst preparedData = $(\"PreparedData\").itemMatching($itemIndex).json;\nconst row = preparedData.row;\nlet gen = normalizeLLMOutput($json);\nlet fulltext = gen.hasOwnProperty('Fulltext') ? gen.Fulltext : gen;\n\n// Append any fulltext field returned to the field\n// in our data row corresponding to the current action. \ngen[row.Action] = fulltext;\n\n// Concatenate any generated fields with those already exisiting\n// in our data row (using seperator if necessary),\n// so we don't loose any pre-entered data.\nconst combined = {};\nObject.keys(gen).forEach(key => {\n const a = String(row[key] ?? \"\");\n const b = String(gen[key]);\n combined[key] = (a && b) ? (a + \"\\n---\\n\" + b) : (a || b);\n});\n\n// Add the row number and set the new status to the action just performed.\ncombined.row_number = row.row_number;\ncombined.Status = row.Action;\ncombined.model = preparedData.model;\n\nreturn combined;" }, "typeVersion": 2 }, { "id": "e0c993c1-678f-4236-8976-735cccb49fee", "name": "SaveBackToSheet", "type": "n8n-nodes-base.googleSheets", "position": [ 480, 280 ], "parameters": { "columns": { "value": {}, "schema": [ { "id": "ID", "type": "string", "display": true, "removed": false, "required": false, "displayName": "ID", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Topic", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Topic", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Scheduled", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Scheduled", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Status", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Status", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Action", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Action", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Context", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Context", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Idea", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Idea", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Content", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Content", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Length", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Length", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Media", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Media", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "LinksInternal", "type": "string", "display": true, "removed": false, "required": false, "displayName": "LinksInternal", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "LinksExternal", "type": "string", "display": true, "removed": false, "required": false, "displayName": "LinksExternal", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Title", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Title", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Sections", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Sections", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "MainPoints", "type": "string", "display": true, "removed": false, "required": false, "displayName": "MainPoints", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "GuidingPrinciple", "type": "string", "display": true, "removed": false, "required": false, "displayName": "GuidingPrinciple", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Metaphor", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Metaphor", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Draft", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Draft", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Final", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Final", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "internal notes", "type": "string", "display": true, "removed": false, "required": false, "displayName": "internal notes", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "row_number", "type": "string", "display": true, "removed": false, "readOnly": true, "required": false, "displayName": "row_number", "defaultMatch": false, "canBeUsedToMatch": true } ], "mappingMode": "autoMapInputData", "matchingColumns": [ "row_number" ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": { "handlingExtraData": "ignoreIt" }, "operation": "update", "sheetName": { "__rl": true, "mode": "name", "value": "={{ $('Settings').item.json.sheetSchedule }}" }, "documentId": { "__rl": true, "mode": "url", "value": "={{ $('Settings').item.json.urlSpreadsheet }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XeXufn5uZvHp3lcX", "name": "Google Sheets account 2" } }, "typeVersion": 4.5 }, { "id": "e0b982d9-d24e-4fd0-bc03-8642cd4c988b", "name": "IfActionPublish", "type": "n8n-nodes-base.if", "position": [ 500, -80 ], "parameters": { "options": {}, "conditions": { "options": { "version": 2, "leftValue": "", "caseSensitive": true, "typeValidation": "strict" }, "combinator": "and", "conditions": [ { "id": "c3735d0d-da54-44e7-afe6-fdfacb6117f2", "operator": { "name": "filter.operator.equals", "type": "string", "operation": "equals" }, "leftValue": "={{ $json.row.Action }}", "rightValue": "={{ $('Settings').item.json.actionPublish }}" } ] } }, "typeVersion": 2.2 }, { "id": "1d5c2731-61a1-434c-bdf1-294217e4ac1c", "name": "IfTakeAction", "type": "n8n-nodes-base.if", "position": [ 260, -80 ], "parameters": { "options": {}, "conditions": { "options": { "version": 2, "leftValue": "", "caseSensitive": true, "typeValidation": "strict" }, "combinator": "and", "conditions": [ { "id": "85536861-b213-4567-9c9a-f844a28b5405", "operator": { "type": "boolean", "operation": "true", "singleValue": true }, "leftValue": "={{ $json.takeAction }}", "rightValue": "" } ] } }, "typeVersion": 2.2 }, { "id": "aae766a4-d29e-4357-a344-74ee36a382e1", "name": "IfPromptExists", "type": "n8n-nodes-base.if", "position": [ -600, 280 ], "parameters": { "options": {}, "conditions": { "options": { "version": 2, "leftValue": "", "caseSensitive": true, "typeValidation": "strict" }, "combinator": "and", "conditions": [ { "id": "73333657-16ed-4b0d-a81f-34add6c22a1b", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true }, "leftValue": "={{ $json.prompt }}", "rightValue": "" } ] } }, "typeVersion": 2.2 }, { "id": "5b4c4bdf-8997-4c19-8e95-8c84b725404c", "name": "Basic LLM Chain", "type": "@n8n/n8n-nodes-langchain.chainLlm", "position": [ -360, 280 ], "parameters": { "text": "={{ $json.prompt }}", "promptType": "define" }, "typeVersion": 1.5 }, { "id": "8dc422a3-6b86-4f57-8c4c-df6422f72f57", "name": "CreatePost", "type": "n8n-nodes-base.httpRequest", "position": [ -220, 780 ], "parameters": { "url": "=https://{{ $('Settings').item.json.urlWordpress }}/xmlrpc.php", "body": "={{ $json.xmlRequestBody }}", "method": "POST", "options": {}, "sendBody": true, "contentType": "raw", "sendHeaders": true, "rawContentType": "text/xml", "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "text/xml" } ] } }, "typeVersion": 4.2 }, { "id": "6ad42453-d56b-4bae-aaf3-eb689df998cc", "name": "SetToPublish", "type": "n8n-nodes-base.googleSheets", "position": [ 700, 780 ], "parameters": { "columns": { "value": { "Status": "={{ $('Settings').item.json.actionPublish }}", "row_number": "={{ $('PreparedData').item.json.row.row_number }}" }, "schema": [ { "id": "ID", "type": "string", "display": true, "removed": false, "required": false, "displayName": "ID", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Topic", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Topic", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Scheduled", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Scheduled", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Status", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Status", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Action", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Action", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Context", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Context", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Ideas", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Ideas", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Content", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Content", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Length", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Length", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Media", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Media", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "LinksInternal", "type": "string", "display": true, "removed": false, "required": false, "displayName": "LinksInternal", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "LinksExternal", "type": "string", "display": true, "removed": false, "required": false, "displayName": "LinksExternal", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Sections", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Sections", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "MainPoints", "type": "string", "display": true, "removed": false, "required": false, "displayName": "MainPoints", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "GuidingPrinciple", "type": "string", "display": true, "removed": false, "required": false, "displayName": "GuidingPrinciple", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Metaphor", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Metaphor", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Title", "type": "string", "display": true, "removed": false, "required": false, "displayName": "Title", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "draft", "type": "string", "display": true, "removed": false, "required": false, "displayName": "draft", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "words", "type": "string", "display": true, "removed": false, "required": false, "displayName": "words", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "final", "type": "string", "display": true, "removed": false, "required": false, "displayName": "final", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "words", "type": "string", "display": true, "removed": false, "required": false, "displayName": "words", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "TeaserTitle", "type": "string", "display": true, "removed": false, "required": false, "displayName": "TeaserTitle", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "TeaserText", "type": "string", "display": true, "removed": false, "required": false, "displayName": "TeaserText", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "internal notes", "type": "string", "display": true, "removed": false, "required": false, "displayName": "internal notes", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "row_number", "type": "string", "display": true, "removed": false, "readOnly": true, "required": false, "displayName": "row_number", "defaultMatch": false, "canBeUsedToMatch": true } ], "mappingMode": "defineBelow", "matchingColumns": [ "row_number" ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {}, "operation": "update", "sheetName": { "__rl": true, "mode": "name", "value": "={{ $('Settings').item.json.sheetSchedule }}" }, "documentId": { "__rl": true, "mode": "url", "value": "={{ $('Settings').item.json.urlSpreadsheet }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XeXufn5uZvHp3lcX", "name": "Google Sheets account 2" } }, "typeVersion": 4.5 }, { "id": "a1af0f00-de59-48d4-93d2-9cc20e7f1c1c", "name": "PrepareXmlPost", "type": "n8n-nodes-base.code", "position": [ -380, 780 ], "parameters": { "mode": "runOnceForEachItem", "jsCode": "const username = $('Settings').item.json.wordpressUsername;\nconst password = $('Settings').item.json.wordpressApplicationPassword;\nconst blogId = 0;\nconst published = 1; // 0 = draft, 1 = published\nconst title = $json.row.Title;\nconst text = $json.row.final;\n\n// Helper function to escape XML special characters\nfunction escapeXml(unsafe) {\n return unsafe.replace(/[<>&'\"]/g, (c) => {\n switch (c) {\n case '<': return '<';\n case '>': return '>';\n case '&': return '&';\n case '\\'': return ''';\n case '\"': return '"';\n default: return c;\n }\n });\n}\n\n// Your actual post text, which may contain characters needing escaping\nconst titleEscaped = escapeXml(title);\nconst textEscaped = escapeXml(text);\n\n// Build the XML payload\nconst xmlData = `\n\n wp.newPost\n \n \n ${blogId}\n \n \n ${username}\n \n \n ${password}\n \n \n \n \n \n post_title\n ${titleEscaped}\n \n \n post_content\n ${textEscaped}\n \n \n \n \n \n ${published}\n \n \n`;\n\n\n// Add a new field called 'myNewField' to the JSON of the item\n$input.item.json.xmlRequestBody = xmlData;\n\nreturn $input.item;" }, "typeVersion": 2 }, { "id": "00e6d2ab-6dc4-42ba-8a92-04a35d104908", "name": "HandleXMLRPCResponse", "type": "n8n-nodes-base.code", "position": [ 40, 780 ], "parameters": { "mode": "runOnceForEachItem", "jsCode": "// Get the XML response from the incoming JSON\nconst xmlResponse = $json.data;\n\n// Helper function to extract a value by matching a regex pattern\nfunction extractValue(pattern, xml) {\n const match = xml.match(pattern);\n return match ? match[1] : null;\n}\n\n// Check if the XML contains a fault\nif (xmlResponse.indexOf(\"\") !== -1) {\n // Extract the faultCode and faultString using regex\n // This regex matches the value inside or for faultCode\n const faultCode = extractValue(/faultCode<\\/name>\\s*<(?:int|string)>(.*?)<\\/(?:int|string)>/s, xmlResponse);\n // This regex extracts the faultString from within \n const faultString = extractValue(/faultString<\\/name>\\s*(.*?)<\\/string>/s, xmlResponse);\n return { 'errorCode': faultCode, 'error': faultString };\n} else {\n // Otherwise, assume a successful response.\n // The post ID is contained inside a tag within \n const postId = extractValue(/[\\s\\S]*?(.*?)<\\/string>/, xmlResponse);\n return { postId };\n}" }, "typeVersion": 2 }, { "id": "23212e92-4ad1-4a8c-8e0a-04d8d2a4511d", "name": "PostingSuccessful", "type": "n8n-nodes-base.if", "position": [ 480, 780 ], "parameters": { "options": {}, "conditions": { "options": { "version": 2, "leftValue": "", "caseSensitive": true, "typeValidation": "strict" }, "combinator": "and", "conditions": [ { "id": "815d85a1-8f91-4338-977f-503f02c53ea2", "operator": { "type": "string", "operation": "exists", "singleValue": true }, "leftValue": "={{ $('HandleXMLRPCResponse').item.json.postId }}", "rightValue": "" } ] } }, "typeVersion": 2.2 }, { "id": "45c786f0-d795-4ed4-b6d2-f005b43e797f", "name": "LogStatus", "type": "n8n-nodes-base.googleSheets", "position": [ 260, 280 ], "parameters": { "columns": { "value": { "Date": "={{ $now }}", "Type": "=info", "Message": "=Status {{ $json.Status }} for row {{ $('PreparedData').item.json.row.row_number }}" }, "schema": [ { "id": "Date", "type": "string", "display": true, "required": false, "displayName": "Date", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Type", "type": "string", "display": true, "required": false, "displayName": "Type", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Message", "type": "string", "display": true, "required": false, "displayName": "Message", "defaultMatch": false, "canBeUsedToMatch": true } ], "mappingMode": "defineBelow", "matchingColumns": [], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {}, "operation": "append", "sheetName": { "__rl": true, "mode": "name", "value": "={{ $('Settings').item.json.sheetLog }}" }, "documentId": { "__rl": true, "mode": "url", "value": "={{ $('Settings').item.json.urlSpreadsheet }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XeXufn5uZvHp3lcX", "name": "Google Sheets account 2" } }, "typeVersion": 4.5 }, { "id": "f58306f5-a5e9-4e44-9c5d-3810e18e6605", "name": "LogPublished", "type": "n8n-nodes-base.googleSheets", "position": [ 260, 780 ], "parameters": { "columns": { "value": { "Date": "={{ $now }}", "Type": "={{ $json.errorCode ? 'error' : 'info' }}", "Message": "=Publishing row {{ $('PreparedData').item.json.row.row_number }}: {{ $json.postId }}{{ $json.errorCode }}{{ $json.error }}" }, "schema": [ { "id": "Date", "type": "string", "display": true, "required": false, "displayName": "Date", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Type", "type": "string", "display": true, "required": false, "displayName": "Type", "defaultMatch": false, "canBeUsedToMatch": true }, { "id": "Message", "type": "string", "display": true, "required": false, "displayName": "Message", "defaultMatch": false, "canBeUsedToMatch": true } ], "mappingMode": "defineBelow", "matchingColumns": [], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {}, "operation": "append", "sheetName": { "__rl": true, "mode": "name", "value": "={{ $('Settings').item.json.sheetLog }}" }, "documentId": { "__rl": true, "mode": "url", "value": "={{ $('Settings').item.json.urlSpreadsheet }}" } }, "credentials": { "googleSheetsOAuth2Api": { "id": "XeXufn5uZvHp3lcX", "name": "Google Sheets account 2" } }, "typeVersion": 4.5 }, { "id": "c227b790-e1ee-4370-9f24-a734443d1e97", "name": "Sticky Note", "type": "n8n-nodes-base.stickyNote", "position": [ -460, -300 ], "parameters": { "width": 180, "height": 360, "content": "## Settings" }, "typeVersion": 1 }, { "id": "904da209-68fd-4139-885f-bd3f25034aeb", "name": "Sticky Note1", "type": "n8n-nodes-base.stickyNote", "position": [ -440, 180 ], "parameters": { "color": 3, "width": 380, "height": 380, "content": "## Author Blog-Post\nUsing OpenRouter to make model fully configurable for each authoring stage" }, "typeVersion": 1 }, { "id": "29f35bf0-6dd3-4c3c-b688-73eb46781c87", "name": "Sticky Note2", "type": "n8n-nodes-base.stickyNote", "position": [ -40, -300 ], "parameters": { "color": 5, "height": 360, "content": "## Post-process Data\n{{ Placehoder }} replacement" }, "typeVersion": 1 }, { "id": "296c3257-836d-488c-b048-72261180e286", "name": "Sticky Note3", "type": "n8n-nodes-base.stickyNote", "position": [ 220, 180 ], "parameters": { "color": 4, "width": 180, "height": 380, "content": "## Log to Sheet" }, "typeVersion": 1 }, { "id": "42a06803-087f-4dc4-9dd5-1f0281942a30", "name": "Sticky Note4", "type": "n8n-nodes-base.stickyNote", "position": [ 420, 180 ], "parameters": { "color": 6, "width": 420, "height": 380, "content": "## Save Result To Sheet" }, "typeVersion": 1 }, { "id": "7a6393e9-ae81-4b9b-856b-7be18f783cf4", "name": "Sticky Note5", "type": "n8n-nodes-base.stickyNote", "position": [ -440, 620 ], "parameters": { "color": 3, "width": 380, "height": 380, "content": "## Publish Blog-Post\nUse a generic XMLHttpRequest with subsequent response handling, since the Wordpress node did not work at all." }, "typeVersion": 1 }, { "id": "2d154bd4-c3bc-4137-90ce-7885bac77c71", "name": "Sticky Note6", "type": "n8n-nodes-base.stickyNote", "position": [ -40, 180 ], "parameters": { "color": 5, "height": 380, "content": "## Post-process Data\nNormalize and re-merge output data structure. " }, "typeVersion": 1 }, { "id": "83834b00-a647-403f-b88a-4c38d9750eb0", "name": "Sticky Note7", "type": "n8n-nodes-base.stickyNote", "position": [ -40, 620 ], "parameters": { "color": 5, "height": 380, "content": "## Post-process Data\nExtract post id or error message from response." }, "typeVersion": 1 }, { "id": "e7494d0b-b796-437e-b977-a5350b1a8dc5", "name": "Sticky Note8", "type": "n8n-nodes-base.stickyNote", "position": [ 220, 620 ], "parameters": { "color": 4, "width": 180, "height": 380, "content": "## Log to Sheet" }, "typeVersion": 1 }, { "id": "1d036f6a-c6e4-428d-b0ce-1e710eb7d90c", "name": "Sticky Note9", "type": "n8n-nodes-base.stickyNote", "position": [ 420, 620 ], "parameters": { "color": 6, "width": 420, "height": 380, "content": "## Save Status To Sheet" }, "typeVersion": 1 }, { "id": "105e0743-b4e8-47d7-a4bf-3939df43a43c", "name": "Sticky Note10", "type": "n8n-nodes-base.stickyNote", "position": [ -640, 160 ], "parameters": { "color": 7, "width": 1500, "height": 420, "content": "## Authoring\n## Stage" }, "typeVersion": 1 }, { "id": "80fefb90-35b2-4f0b-b4d5-1cca8519361d", "name": "Sticky Note11", "type": "n8n-nodes-base.stickyNote", "position": [ -640, 600 ], "parameters": { "color": 7, "width": 1500, "height": 420, "content": "## Publishing\n## Stage" }, "typeVersion": 1 }, { "id": "99b0a7b7-6513-47b0-af16-ee66d37dd821", "name": "Sticky Note12", "type": "n8n-nodes-base.stickyNote", "position": [ -260, -300 ], "parameters": { "width": 200, "height": 360, "content": "## Config & Data" }, "typeVersion": 1 } ], "active": false, "pinData": {}, "settings": { "executionOrder": "v1" }, "versionId": "7005e556-a7ae-484c-af71-57c75abd3e17", "connections": { "Config": { "main": [ [] ] }, "AgentLLM": { "ai_languageModel": [ [ { "node": "Basic LLM Chain", "type": "ai_languageModel", "index": 0 } ] ] }, "Schedule": { "main": [ [ { "node": "PreparedData", "type": "main", "index": 0 } ] ] }, "Settings": { "main": [ [ { "node": "fetchConfig", "type": "main", "index": 0 }, { "node": "Schedule", "type": "main", "index": 0 } ] ] }, "LogStatus": { "main": [ [ { "node": "SaveBackToSheet", "type": "main", "index": 0 } ] ] }, "CreatePost": { "main": [ [ { "node": "HandleXMLRPCResponse", "type": "main", "index": 0 } ] ] }, "fetchConfig": { "main": [ [ { "node": "Config", "type": "main", "index": 0 } ] ] }, "IfTakeAction": { "main": [ [ { "node": "IfActionPublish", "type": "main", "index": 0 } ] ] }, "LogPublished": { "main": [ [ { "node": "PostingSuccessful", "type": "main", "index": 0 } ] ] }, "PreparedData": { "main": [ [ { "node": "IfTakeAction", "type": "main", "index": 0 } ] ] }, "SetToPublish": { "main": [ [] ] }, "ManualTrigger": { "main": [ [ { "node": "Settings", "type": "main", "index": 0 } ] ] }, "IfPromptExists": { "main": [ [ { "node": "Basic LLM Chain", "type": "main", "index": 0 } ] ] }, "IfScheduledNow": { "main": [ [ { "node": "PrepareXmlPost", "type": "main", "index": 0 } ] ] }, "PrepareXmlPost": { "main": [ [ { "node": "CreatePost", "type": "main", "index": 0 } ] ] }, "Basic LLM Chain": { "main": [ [ { "node": "RecombinedDataRow", "type": "main", "index": 0 } ] ] }, "IfActionPublish": { "main": [ [ { "node": "IfScheduledNow", "type": "main", "index": 0 } ], [ { "node": "IfPromptExists", "type": "main", "index": 0 } ] ] }, "SaveBackToSheet": { "main": [ [] ] }, "ScheduleTrigger": { "main": [ [ { "node": "Settings", "type": "main", "index": 0 } ] ] }, "PostingSuccessful": { "main": [ [ { "node": "SetToPublish", "type": "main", "index": 0 } ] ] }, "RecombinedDataRow": { "main": [ [ { "node": "LogStatus", "type": "main", "index": 0 } ] ] }, "HandleXMLRPCResponse": { "main": [ [ { "node": "LogPublished", "type": "main", "index": 0 } ] ] } } }