80 lines
4.9 KiB
Python
80 lines
4.9 KiB
Python
|
|
import json
|
||
|
|
|
||
|
|
with open('C:/Users/fam1n/projects/ajarbot/bfk_workflow.json', 'r', encoding='utf-8') as f:
|
||
|
|
wf = json.load(f)
|
||
|
|
|
||
|
|
for node in wf['nodes']:
|
||
|
|
if node['name'] == 'AI Generate Hooks':
|
||
|
|
# Fix: Use JSON.stringify() to properly escape the transcript text
|
||
|
|
# so special characters (quotes, newlines) don't break the JSON body.
|
||
|
|
# .slice(1,-1) removes the outer quotes that JSON.stringify adds.
|
||
|
|
new_body = '={{ JSON.stringify({\n' \
|
||
|
|
' "contents": [{\n' \
|
||
|
|
' "parts": [{\n' \
|
||
|
|
' "text": "You are a TikTok content expert for a blended family cooking channel called BlendedFamilyKitchen. Given this transcript from a cooking video, generate:\\n1) Three hook text options (max 8 words each, attention-grabbing, food-focused)\\n2) A caption/description with relevant hashtags (mix of popular and niche)\\n3) Three title options\\n\\nFormat your response as JSON with keys: hooks (array of 3 strings), caption (string), titles (array of 3 strings).\\n\\nTranscript: " + ($("Whisper Transcribe").item.json.data || $("Whisper Transcribe").item.json.text || "No transcript available")\n' \
|
||
|
|
' }]\n' \
|
||
|
|
' }],\n' \
|
||
|
|
' "generationConfig": {\n' \
|
||
|
|
' "temperature": 0.8,\n' \
|
||
|
|
' "maxOutputTokens": 500,\n' \
|
||
|
|
' "responseMimeType": "application/json"\n' \
|
||
|
|
' }\n' \
|
||
|
|
'}) }}'
|
||
|
|
|
||
|
|
node['parameters']['jsonBody'] = new_body
|
||
|
|
# Also need to change contentType to 'raw' and set rawContentType
|
||
|
|
# Actually the better approach: set specifyBody to 'string' mode
|
||
|
|
# But simplest: use the expression-based JSON approach with JSON.stringify
|
||
|
|
# wrapping the whole object so n8n sends it as a properly escaped JSON string
|
||
|
|
|
||
|
|
# Actually, the cleanest n8n fix: keep specifyBody as "json" but use
|
||
|
|
# the expression wrapper approach
|
||
|
|
node['parameters']['specifyBody'] = 'string'
|
||
|
|
node['parameters']['body'] = new_body
|
||
|
|
del node['parameters']['jsonBody']
|
||
|
|
# Hmm, let me reconsider. The "json" mode with jsonBody expects valid JSON.
|
||
|
|
# The issue is the expression injects raw text. JSON.stringify wrapping the
|
||
|
|
# whole thing as an expression should work.
|
||
|
|
|
||
|
|
# Actually simplest: keep specifyBody=json, but wrap entire object in JSON.stringify
|
||
|
|
# n8n will parse the expression result. If expression returns a string (from JSON.stringify),
|
||
|
|
# n8n's json mode should send it as-is.
|
||
|
|
#
|
||
|
|
# But wait - the error says "JSON parameter needs to be valid JSON"
|
||
|
|
# This means n8n validates the jsonBody template BEFORE expression evaluation.
|
||
|
|
# The raw transcript chars break the JSON template structure.
|
||
|
|
#
|
||
|
|
# Real fix: use specifyBody = "json" but build the body using n8n's
|
||
|
|
# built-in JSON key-value pairs, not a raw string. Or use a Code node.
|
||
|
|
#
|
||
|
|
# Cleanest approach: Insert a Set node before this one that builds the prompt
|
||
|
|
# text safely, then reference it. But that changes workflow structure.
|
||
|
|
#
|
||
|
|
# Simplest working fix: keep raw JSON mode but use JSON.stringify on the
|
||
|
|
# transcript portion only, and use proper escaping.
|
||
|
|
|
||
|
|
# Let me just do it right:
|
||
|
|
node['parameters'] = {
|
||
|
|
"method": "POST",
|
||
|
|
"url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=AIzaSyDQPi9kXbVpxW790RBuUCeC8t_UgyxX7m4",
|
||
|
|
"sendHeaders": True,
|
||
|
|
"headerParameters": {
|
||
|
|
"parameters": [
|
||
|
|
{"name": "Content-Type", "value": "application/json"}
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"sendBody": True,
|
||
|
|
"specifyBody": "json",
|
||
|
|
"jsonBody": "={{ JSON.stringify({ contents: [{ parts: [{ text: \"You are a TikTok content expert for a blended family cooking channel called BlendedFamilyKitchen. Given this transcript from a cooking video, generate:\\n1) Three hook text options (max 8 words each, attention-grabbing, food-focused)\\n2) A caption/description with relevant hashtags (mix of popular and niche)\\n3) Three title options\\n\\nFormat your response as JSON with keys: hooks (array of 3 strings), caption (string), titles (array of 3 strings).\\n\\nTranscript: \" + String($json.srt_content || $json.text || $('Whisper Transcribe').item.json.data || $('Whisper Transcribe').item.json.text || 'No transcript available') }] }], generationConfig: { temperature: 0.8, maxOutputTokens: 500, responseMimeType: \"application/json\" } }) }}",
|
||
|
|
"options": {}
|
||
|
|
}
|
||
|
|
|
||
|
|
print("Updated AI Generate Hooks node parameters")
|
||
|
|
print(f"New jsonBody: {node['parameters']['jsonBody'][:200]}...")
|
||
|
|
break
|
||
|
|
|
||
|
|
with open('C:/Users/fam1n/projects/ajarbot/bfk_workflow_fixed.json', 'w', encoding='utf-8') as f:
|
||
|
|
json.dump(wf, f)
|
||
|
|
|
||
|
|
print("\nSaved fixed workflow to bfk_workflow_fixed.json")
|