{ "kind": "open-flow-workflow", "version": 1, "name": "Share Product Hunt Matches to Slack", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_374cbc9253187be4": { "name": "Every day at 06:00 UTC", "kind": "cron", "cronTimes": [ { "type": "cron", "expression": "0 6 * * *", "timezone": "UTC" } ] }, "n_7c4ebfe6e77ca4db": { "inputs": { "url": { "kind": "value", "value": "https://api.airtop.ai/api/v1/sessions" }, "body": { "kind": "value", "value": {} }, "auth.token": { "kind": "unset" } }, "name": "Create an Airtop session", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "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": "Create an Airtop session", "executor": { "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "json", "authentication": { "type": "bearer" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_3208fd308c193783": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_7c4ebfe6e77ca4db", "output": "body" } ] } }, "name": "Check the session", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "windowUrl" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "terminateUrl" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "ready" } ], "name": "Check the session", "moduleId": "n_5fec4a8ca4d1637a", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_49cb49176e2432f9": { "inputs": {}, "name": "Session ready?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "ready", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_3208fd308c193783", "output": "ready" } }, "operator": "isTrue" } ] } ] } ] }, "n_4d885e0b6d7bbe6b": { "inputs": {}, "name": "Wait for the browser", "kind": "wait", "inputDefinitions": [], "prompt": "Wait for the browser", "autoContinue": { "kind": "after", "durationMs": 5000 } }, "n_53ad04e3c53e1687": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_3208fd308c193783", "output": "terminateUrl" } ] }, "auth.token": { "kind": "unset" } }, "name": "Check browser readiness", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "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": "Check browser readiness", "executor": { "method": "GET", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "bearer" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_cfc3448b383e1c13": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_53ad04e3c53e1687", "output": "body" } ] }, "previous": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cfc3448b383e1c13", "output": "state" } ] } }, "name": "Evaluate browser readiness", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previous" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "ready" } ], "name": "Evaluate browser readiness", "moduleId": "n_4d108fcac145d98b", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_83476cc461eebe6f": { "inputs": {}, "name": "Browser ready?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "ready", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_cfc3448b383e1c13", "output": "ready" } }, "operator": "isTrue" } ] } ] } ] }, "n_146a99f90c261eb4": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_3208fd308c193783", "output": "windowUrl" } ] }, "body": { "kind": "value", "value": { "url": "https://www.producthunt.com/" } }, "auth.token": { "kind": "unset" } }, "name": "Open Product Hunt", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "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": "Open Product Hunt", "executor": { "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "json", "authentication": { "type": "bearer" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_d847804508c0ee72": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_146a99f90c261eb4", "output": "body" } ] }, "terminateUrl": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_3208fd308c193783", "output": "terminateUrl" } ] }, "topic": { "kind": "value", "value": "AI Agents" } }, "name": "Prepare the product search", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "terminateUrl" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "topic" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "queryUrl" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "query" } ], "name": "Prepare the product search", "moduleId": "n_f624bc44c9699023", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_4548e81582a5e7e9": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_d847804508c0ee72", "output": "queryUrl" } ] }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_d847804508c0ee72", "output": "query" } ] }, "auth.token": { "kind": "unset" } }, "name": "Find matching launches", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "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": "Find matching launches", "executor": { "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "json", "authentication": { "type": "bearer" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_11e559ddf4feca96": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_4548e81582a5e7e9", "output": "body" } ] } }, "name": "Check the extracted launches", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" } ], "outputs": [ { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "send" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "text" } ], "name": "Check the extracted launches", "moduleId": "n_af3d69e50e78f719", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_d9de8f31a4e5b4db": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_3208fd308c193783", "output": "terminateUrl" } ] }, "auth.token": { "kind": "unset" } }, "name": "Close the Airtop session", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.token" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Close the Airtop session", "executor": { "method": "DELETE", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "none", "authentication": { "type": "bearer" }, "responseFormat": "text", "statusPolicy": "success", "kind": "http-request" } } }, "n_b01a2c0d31aef033": { "inputs": {}, "name": "Were matching products found?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "send", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_11e559ddf4feca96", "output": "send" } }, "operator": "isTrue" } ] } ] } ] }, "n_b9200ec8d357bb1b": { "inputs": { "channelId": { "kind": "value", "value": "YOUR_SLACK_CHANNEL_ID" }, "text": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_11e559ddf4feca96", "output": "text" } ] } }, "name": "Post the launches to Slack", "kind": "task", "task": { "inputs": [ { "description": "The Slack conversation or channel ID.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The Slack conversation or channel ID." }, "nullable": false, "handle": "channelId" }, { "description": "Plain text message content. When blocks are provided, Slack uses this as notification and accessibility fallback text.", "jsonSchema": { "type": "string", "description": "Plain text message content. When blocks are provided, Slack uses this as notification and accessibility fallback text." }, "nullable": true, "handle": "text", "value": null }, { "description": "Slack Block Kit blocks to render in the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "A Slack Block Kit block object. Pass the block exactly as Slack documents it." }, "minItems": 1, "description": "Slack Block Kit blocks to render in the message." }, "nullable": true, "handle": "blocks", "value": null }, { "description": "Slack legacy attachments to include in the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "A Slack legacy attachment object. Prefer blocks for new messages when possible." }, "minItems": 1, "description": "Slack legacy attachments to include in the message." }, "nullable": true, "handle": "attachments", "value": null }, { "description": "Whether Slack should unfurl links in the message.", "jsonSchema": { "type": "boolean", "description": "Whether Slack should unfurl links in the message." }, "nullable": true, "handle": "unfurlLinks", "value": null }, { "description": "Whether Slack should unfurl media in the message.", "jsonSchema": { "type": "boolean", "description": "Whether Slack should unfurl media in the message." }, "nullable": true, "handle": "unfurlMedia", "value": null }, { "description": "Slack message metadata to attach to the message.", "jsonSchema": { "type": "object", "properties": {}, "additionalProperties": true, "description": "Slack message metadata to attach to the message." }, "nullable": true, "handle": "metadata", "value": null } ], "outputs": [ { "description": "The timestamp identifier of the posted message.", "jsonSchema": { "type": "string", "description": "The timestamp identifier of the posted message." }, "nullable": false, "handle": "ts" }, { "description": "The channel ID where the message was posted.", "jsonSchema": { "type": "string", "description": "The channel ID where the message was posted." }, "nullable": false, "handle": "channelId" } ], "name": "Post the launches to Slack", "executor": { "kind": "connector", "action": "slack.post_message" } } } }, "edges": [ { "source": "n_374cbc9253187be4", "target": "n_7c4ebfe6e77ca4db" }, { "source": "n_7c4ebfe6e77ca4db", "target": "n_3208fd308c193783" }, { "source": "n_3208fd308c193783", "target": "n_49cb49176e2432f9" }, { "source": "n_49cb49176e2432f9", "target": "n_146a99f90c261eb4", "sourceHandle": "ready" }, { "source": "n_49cb49176e2432f9", "target": "n_4d885e0b6d7bbe6b", "sourceHandle": "otherwise" }, { "source": "n_4d885e0b6d7bbe6b", "target": "n_53ad04e3c53e1687", "sourceHandle": "continue" }, { "source": "n_53ad04e3c53e1687", "target": "n_cfc3448b383e1c13" }, { "source": "n_cfc3448b383e1c13", "target": "n_83476cc461eebe6f" }, { "source": "n_83476cc461eebe6f", "target": "n_146a99f90c261eb4", "sourceHandle": "ready" }, { "source": "n_83476cc461eebe6f", "target": "n_4d885e0b6d7bbe6b", "sourceHandle": "otherwise" }, { "source": "n_146a99f90c261eb4", "target": "n_d847804508c0ee72" }, { "source": "n_d847804508c0ee72", "target": "n_4548e81582a5e7e9" }, { "source": "n_4548e81582a5e7e9", "target": "n_11e559ddf4feca96" }, { "source": "n_11e559ddf4feca96", "target": "n_d9de8f31a4e5b4db" }, { "source": "n_d9de8f31a4e5b4db", "target": "n_b01a2c0d31aef033" }, { "source": "n_b01a2c0d31aef033", "target": "n_b9200ec8d357bb1b", "sourceHandle": "send" } ] } }, "modules": { "n_5fec4a8ca4d1637a": { "name": "Check the session", "imports": [], "source": "export default function session({body}){const x=body?.data;if(!x||typeof x.id!=='string'||!/^[-a-z0-9]+$/i.test(x.id)||body.errors?.length)throw Error('Invalid Airtop session');const base='https://api.airtop.ai/api/v1/sessions/'+encodeURIComponent(x.id);if(!['initializing','running','active'].includes(x.status))throw Error('Invalid Airtop session state');return {windowUrl:base+'/windows',terminateUrl:base,ready:x.status==='running'||x.status==='active'};}\n" }, "n_4d108fcac145d98b": { "name": "Evaluate browser readiness", "imports": [], "source": "export default function poll({body,previous}){const count=(previous?.count??0)+1;if(!Number.isInteger(count)||count>60)throw Error('Airtop session did not become ready');if(body?.errors?.length)throw Error('Airtop session status failed');const status=body?.data?.status;if(!['initializing','running','active'].includes(status))throw Error('Invalid Airtop session status');if(status==='initializing'&&count===60)throw Error('Airtop session did not become ready');return{state:{count},ready:status==='running'||status==='active'};}\n" }, "n_f624bc44c9699023": { "name": "Prepare the product search", "imports": [], "source": "export default function window({body,terminateUrl,topic}){const id=body?.data?.windowId;if(typeof id!=='string'||!/^[-a-z0-9]+$/i.test(id)||body.errors?.length||typeof topic!=='string'||!topic.trim()||topic.length>500)throw Error('Invalid Airtop window or topic');return{queryUrl:terminateUrl+'/windows/'+encodeURIComponent(id)+'/page-query',query:{prompt:`Extract up to 5 product launches that are ${topic} for each product extract the title and URL (if exists).\\n\\nReturn format:\\nToday's [${topic}] on Producthunt\\n1. Title 1 (URL 1)\\n2. Title 2 (URL 2)\\nand so on\\n\\nIf you cannot find any relevant products, return [NA]`,configuration:{experimental:{includeVisualAnalysis:'disabled'}}}};}\n" }, "n_af3d69e50e78f719": { "name": "Check the extracted launches", "imports": [], "source": "export default function result({body}){const text=body?.data?.modelResponse;if(typeof text!=='string'||!text.trim()||body.errors?.length||body.meta?.status==='error')throw Error('Invalid Airtop extraction result');return{send:!text.includes('[NA]'),text};}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }