{ "kind": "open-flow-workflow", "version": 1, "name": "X Search Digest", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_dc83941402176095": { "name": "Search X", "kind": "start", "inputDefs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "query" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "limit" } ] }, "n_ae1eff22a0cf27f4": { "inputs": { "query": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_dc83941402176095", "output": "query" } ] }, "limit": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_dc83941402176095", "output": "limit" } ] } }, "name": "Validate search settings", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "query" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "limit" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "query" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "limit" } ], "name": "Validate search settings", "moduleId": "n_2f30f372d99be9b2", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_00ef04193ff5d5bd": { "inputs": { "url": { "kind": "value", "value": "https://xquik.com/api/v1/x/tweets/search" }, "query.q": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ae1eff22a0cf27f4", "output": "query" } ] }, "query.limit": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ae1eff22a0cf27f4", "output": "limit" } ] }, "auth.token": { "kind": "unset" } }, "name": "Search X with Xquik", "timeoutMs": 120000, "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "anyOf": [ { "type": [ "string", "number", "boolean" ] }, { "type": "array", "items": { "type": [ "string", "number", "boolean" ] } } ] }, "nullable": true, "handle": "query.q" }, { "jsonSchema": { "anyOf": [ { "type": [ "string", "number", "boolean" ] }, { "type": "array", "items": { "type": [ "string", "number", "boolean" ] } } ] }, "nullable": true, "handle": "query.limit" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.token" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Search X with Xquik", "executor": { "method": "GET", "query": { "mode": "fields", "names": [ "q", "limit" ] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "apiKey", "name": "X-API-Key", "in": "header" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_8151ba1e1fc61c80": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00ef04193ff5d5bd", "output": "body" } ] }, "query": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ae1eff22a0cf27f4", "output": "query" } ] } }, "name": "Build search digest", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "query" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "query" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "results_count" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "has_more" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "next_cursor" }, { "jsonSchema": { "type": "array", "items": { "type": "object" } }, "nullable": false, "handle": "tweets" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "digest" } ], "name": "Build search digest", "moduleId": "n_732b916b3233cac2", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_73c91e07ce9a3592": { "name": "Search results and digest", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "query" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "results_count" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "has_more" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "next_cursor" }, { "jsonSchema": { "type": "array", "items": { "type": "object" } }, "nullable": false, "handle": "tweets" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "digest" } ], "outputMappings": { "query": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8151ba1e1fc61c80", "output": "query" } ] }, "results_count": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8151ba1e1fc61c80", "output": "results_count" } ] }, "has_more": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8151ba1e1fc61c80", "output": "has_more" } ] }, "next_cursor": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8151ba1e1fc61c80", "output": "next_cursor" } ] }, "tweets": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8151ba1e1fc61c80", "output": "tweets" } ] }, "digest": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_8151ba1e1fc61c80", "output": "digest" } ] } } } }, "edges": [ { "source": "n_dc83941402176095", "target": "n_ae1eff22a0cf27f4" }, { "source": "n_ae1eff22a0cf27f4", "target": "n_00ef04193ff5d5bd" }, { "source": "n_00ef04193ff5d5bd", "target": "n_8151ba1e1fc61c80" }, { "source": "n_8151ba1e1fc61c80", "target": "n_73c91e07ce9a3592" } ] } }, "modules": { "n_2f30f372d99be9b2": { "name": "Validate search settings", "imports": [], "source": "export default function prepareSearch({query,limit}) {\n if(typeof query!=='string'||!query.trim()||query.length>4096)throw new Error('query must contain 1–4096 characters.');\n if(!Number.isInteger(limit)||limit<1||limit>10000)throw new Error('limit must be an integer from 1 to 10000.');\n return {query,limit};\n}\n" }, "n_732b916b3233cac2": { "name": "Build search digest", "imports": [], "source": "export default function buildDigest({body,query}) {\n if(!body||typeof body!=='object'||Array.isArray(body)||!Array.isArray(body.tweets))throw new Error('Xquik did not return a tweets array.');\n const more=body.has_next_page??body.has_more??false;\n if(typeof more!=='boolean')throw new Error('Xquik pagination flag must be boolean.');\n const cursor=body.next_cursor??'';\n if(typeof cursor!=='string')throw new Error('Xquik cursor must be text.');\n const tweets=body.tweets.map(tweet=>{\n if(!tweet||typeof tweet!=='object'||Array.isArray(tweet))throw new Error('Xquik returned an invalid tweet.');\n const sourceId=tweet.id??tweet.tweet_id??tweet.rest_id??'';\n if(typeof sourceId!=='string'&&!Number.isSafeInteger(sourceId))throw new Error('Xquik tweet ID must be text or a safe integer.');\n const id=String(sourceId);\n const text=tweet.text??tweet.full_text??tweet.content??'';\n const url=tweet.url??(id?'https://x.com/i/web/status/'+encodeURIComponent(id):'');\n const sourceAuthor=tweet.author??tweet.user??{};\n const author=sourceAuthor.username??sourceAuthor.screen_name??sourceAuthor.name??'';\n const created_at=tweet.createdAt??tweet.created_at??tweet.created??tweet.timestamp??'';\n if([text,url,author,created_at].some(value=>typeof value!=='string'))throw new Error('Xquik text, URL, author and timestamp must be strings.');\n const metrics=tweet.metrics??Object.fromEntries(['likeCount','retweetCount','replyCount','quoteCount','viewCount','bookmarkCount'].filter(name=>Object.hasOwn(tweet,name)).map(name=>[name,tweet[name]]));\n if(!metrics||typeof metrics!=='object'||Array.isArray(metrics))throw new Error('Xquik metrics must be an object.');\n return {id,url,text,author,created_at,metrics};\n });\n const lines=tweets.length?tweets.map((tweet,index)=>(index+1)+'. '+tweet.text+(tweet.author?' by '+tweet.author:'')+(tweet.url?'\\n'+tweet.url:'')):['No matching X posts found for this query.'];\n return {query,results_count:tweets.length,has_more:more,next_cursor:cursor,tweets,digest:lines.join('\\n\\n')};\n}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }