This workflow follows the HTTP Request → Postgres recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"updatedAt": "2026-04-16T04:54:57.066Z",
"createdAt": "2026-03-29T09:02:36.080Z",
"id": "R2FCAquAvaDPTkWP",
"name": "\uacf5\uc720\ud68c_\uc54c\ub9bc\ud1a1_\ud06c\ub860",
"description": null,
"active": true,
"isArchived": false,
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 0 * * *"
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
0,
0
],
"name": "Schedule: \uc0c8 \uacf5\uc720\ud68c",
"id": "94626783-cced-412d-8a88-fa65e66d1bfc",
"disabled": true
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT iid, i_title_userside, i_full_schedule, i_eventdate, i_alimurl FROM item WHERE i_type = 'sharing' AND i_eventdate >= CURRENT_DATE AND i_open_sent_at IS NULL ORDER BY i_eventdate",
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
224,
0
],
"name": "Postgres: \uc0c8 \uacf5\uc720\ud68c",
"id": "6ad58dd1-4ae3-413c-bd1a-f4a6f169c8d3",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const items = $input.all().map(i => i.json);\nif (items.length === 0) return [];\nconst lines = items.map(i => `\u2022 *${i.i_title_userside}* \u2014 ${i.i_full_schedule || ''} (${i.iid})`).join('\\n');\nconst blocks = [\n { type:'header', text:{ type:'plain_text', text:`\ud83d\udccb \uc624\ud508\uc54c\ub9bc \ubbf8\ubc1c\uc1a1 \uacf5\uc720\ud68c (${items.length}\uac1c)` }},\n { type:'section', text:{ type:'mrkdwn', text: lines }},\n { type:'divider' },\n { type:'section', text:{ type:'mrkdwn', text:'\ud83d\udc49 \uc5d0\ubc00\ub9ac: Claude Code\uc5d0\uc11c `/alimtalk \uacf5\uc720\ud68c \uc624\ud508\uc54c\ub9bc` \uc2e4\ud589\ud574\uc8fc\uc138\uc694' }}\n];\nreturn [{ json: { channel:'C0AN2NZ4L7L', text:`\uc624\ud508\uc54c\ub9bc \ubbf8\ubc1c\uc1a1 \uacf5\uc720\ud68c ${items.length}\uac1c`, blocks:JSON.stringify(blocks) }}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
464,
0
],
"name": "Code: \uc0c8 \uacf5\uc720\ud68c \uc54c\ub9bc",
"id": "953c34b5-8457-4acb-8903-5d307aa385ce"
},
{
"parameters": {
"method": "POST",
"url": "https://slack.com/api/chat.postMessage",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "slackApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"channel\": \"{{ $json.channel }}\",\n \"text\": {{ JSON.stringify($json.text) }},\n \"blocks\": {{ $json.blocks }}\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
688,
0
],
"name": "HTTP: \uc0c8 \uacf5\uc720\ud68c \uc2ac\ub799",
"id": "87e7feb6-2c9d-4432-9fb6-d1331f2949b5",
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 25 22 * * *"
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
0,
240
],
"name": "Schedule Trigger",
"id": "888d4ee2-8864-4012-b66e-2955fe99aa67"
},
{
"parameters": {
"jsCode": "// \uc624\ub298 \ub0a0\uc9dc \uae30\uc900\uc73c\ub85c \ud574\ub2f9\ub418\ub294 \uc54c\ub9bc\ud1a1 \uc804\ubd80 \ub9ac\ud134\nconst templates = [\n { num:1, name:'\uc624\ud508 \uc54c\ub9bc', tid:'KA01TP260224044955111rZoe0O3bxsZ', qt:'all_members',\n dsql:\"i_submitdate_first::date = CURRENT_DATE\", scheduledTime:'15:00',\n nm:false, ml:'', utm:'\uc624\ud508\uc54c\ub9bc' },\n { num:2, name:'\uc624\ud508 \ub9ac\ub9c8\uc778\ub4dc', tid:'KA01TP250718151456335cPBkIZJBkGt', qt:'non_subscribers',\n dsql:\"i_submitdate_first::date + CASE WHEN (i_eventdate - i_submitdate_first::date) <= 4 THEN INTERVAL '1 day' ELSE INTERVAL '2 days' END = CURRENT_DATE\", scheduledTime:'13:00',\n nm:false, ml:'', utm:'\uc624\ud508\ub9ac\ub9c8\uc778\ub4dc' },\n { num:3, name:'D-1 \ub9ac\ub9c8\uc778\ub4dc', tid:'KA01TP260328003811869hKleQPvW4us', qt:'subscribers',\n dsql:\"i_eventdate - INTERVAL '1 day' = CURRENT_DATE\", scheduledTime:'13:00',\n nm:true, ml:'\uc90c\ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694', utm:null },\n { num:4, name:'\ub2f9\uc77c \ub9ac\ub9c8\uc778\ub4dc', tid:'KA01TP260328004337699dPIbCrNF2yI', qt:'subscribers',\n dsql:\"i_eventdate = CURRENT_DATE\", scheduledTime:'14:00',\n nm:true, ml:'\uc90c\ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694', utm:null },\n { num:5, name:'\ud560\uc778\ucfe0\ud3f0', tid:'KA01TP250729145533585plTadCNvOYu', qt:'non_subscribers',\n dsql:\"i_eventdate = CURRENT_DATE\", scheduledTime:'13:00',\n nm:true, ml:'\uc2e0\uccad\ud398\uc774\uc9c0 \ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694', utm:'\ud61c\ud0dd\uc54c\ub9bc' },\n { num:6, name:'\uc785\uc7a5 \ub9c1\ud06c', tid:'KA01TP250417061338748mROUNOEEiOF', qt:'subscribers',\n dsql:\"i_eventdate = CURRENT_DATE\", scheduledTime:'19:00',\n nm:true, ml:'\uc90c\ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694', utm:null },\n { num:7, name:'\ub77c\uc774\ube0c \uc2dc\uc791 \uc54c\ub9bc', tid:'KA01TP260106142352438w6fSAZpbRg4', qt:'subscribers',\n dsql:\"i_eventdate = CURRENT_DATE\", scheduledTime:'20:00',\n nm:true, ml:'\uc90c\ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694', utm:null },\n { num:8, name:'\ud61c\ud0dd \uc548\ub0b4', tid:'KA01TP260328003106634WHeu4PCwrp6', qt:'subscribers',\n dsql:\"i_eventdate = CURRENT_DATE\", scheduledTime:'22:30',\n nm:true, ml:'\ub178\uc158 \ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694', utm:null },\n { num:9, name:'VOD \ubc1c\uc1a1', tid:'KA01TP250722045328826Fu3uUAWTGBI', qt:'subscribers',\n dsql:\"i_eventdate + INTERVAL '3 days' = CURRENT_DATE\", scheduledTime:'18:00',\n nm:true, ml:'VOD \ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694', utm:null },\n];\n\n// \ud83e\uddea \ud14c\uc2a4\ud2b8 \ubaa8\ub4dc: testTemplates\uc5d0 \uc788\ub294 \ubc88\ud638\ub9cc, iid_999\uc5d0 \ud55c\ud574\uc11c, \uc2e4\uc81c \ub0a0\uc9dc \uc870\uac74 \uadf8\ub300\ub85c \ud3c9\uac00\nconst testMode = true;\nconst testTemplates = [2]; // \uc11c\ubca0\uc774 \uc54c\ub9bc\ud1a1 \ud14c\uc2a4\ud2b8\n\nif (testMode) {\n return templates\n .filter(t => testTemplates.includes(t.num))\n .map(t => {\n t.program_sql = `SELECT iid, i_title_userside, i_full_schedule, i_alimurl, i_vodurl, i_eventdate, i_submitdate_first, i_submitdate_last, i_paid_tf, i_formid_webflow FROM item WHERE iid='iid_999' AND ${t.dsql}`;\n return { json: t };\n });\n}\n\n// \ud504\ub85c\ub355\uc158: \uac01 \uc870\uac74\uc5d0 \ub9de\ub294 \uac83\ub9cc \ub9ac\ud134\nreturn templates.map(t => {\n t.program_sql = `SELECT iid, i_title_userside, i_full_schedule, i_alimurl, i_vodurl, i_eventdate, i_submitdate_first, i_submitdate_last, i_paid_tf, i_formid_webflow FROM item WHERE i_type = 'sharing' AND ${t.dsql}`;\n return { json: t };\n});\n\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
240
],
"name": "Code: \uc54c\ub9bc\ud1a1 \ud310\ubcc4",
"id": "7d09cc39-40fb-4fa4-b718-c77c92742a99"
},
{
"parameters": {
"operation": "executeQuery",
"query": "{{ $json.program_sql }}",
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
464,
240
],
"name": "Postgres: \ud504\ub85c\uadf8\ub7a8 \uc870\ud68c",
"id": "7ffe217d-0408-4265-b2c8-1a407b0b06f6",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const t = $('Code: \uc54c\ub9bc\ud1a1 \ud310\ubcc4').item.json;\nconst item = $json;\nconst staticData = $getWorkflowStaticData('global');\nconst tm = (item.i_full_schedule || '').match(/(\\d{1,2}:\\d{2})/);\nconst time = tm ? tm[1] : '20:00';\nconst days = ['\uc77c','\uc6d4','\ud654','\uc218','\ubaa9','\uae08','\ud1a0'];\nlet ed = '';\nif (item.i_submitdate_last) { const d = new Date(item.i_submitdate_last); ed = `${d.getMonth()+1}\uc6d4${d.getDate()}\uc77c(${days[d.getDay()]})`; }\nlet vodDeadline = '';\nif (item.i_eventdate) { const vd = new Date(new Date(item.i_eventdate).getTime() + 7*24*3600000); vodDeadline = `${vd.getFullYear()}\ub144 ${vd.getMonth()+1}\uc6d4 ${vd.getDate()}\uc77c(${days[vd.getDay()]})`; }\nlet period = '';\nif (item.i_submitdate_first && item.i_submitdate_last) {\n const df = new Date(item.i_submitdate_first);\n const dl = new Date(item.i_submitdate_last);\n period = `${df.getMonth()+1}/${df.getDate()}~${dl.getMonth()+1}/${dl.getDate()}`;\n}\nconst sm = (item.i_alimurl || '').match(/\\/sharing\\/([^/?]+)/);\nconst slug = sm ? sm[1] : (item.i_formid_webflow || '');\nconst kd = new Date(Date.now() + 9*3600000);\nconst ymd = kd.toISOString().slice(2,10).replace(/-/g,'');\nlet utmUrl = '';\nif (t.utm) utmUrl = `www.selfishclub.xyz/sharing/${slug}?utm_medium=crm&utm_source=alimtalk&utm_campaign=${slug}&utm_content=${ymd}_${t.utm}&utm_term=inbound`;\nconst iid = (item.iid || '').replace(/[^a-zA-Z0-9_]/g, '');\n\n// \ud83e\uddea \ud06c\ub8e8 \ud14c\uc2a4\ud2b8: iid_999\uc77c \ub54c \uc804\ud654\ubc88\ud638 \ud654\uc774\ud2b8\ub9ac\uc2a4\ud2b8\nconst CREW_PHONES = ['01082948909','01024551899','01065271136','01049724705','01099984696','01028547990','01038128772'];\nconst crewFilter = iid === 'iid_999' ? ` AND u_phone IN (${CREW_PHONES.map(p => `'${p}'`).join(',')})` : '';\n\nlet csql;\nif (t.qt === 'subscribers') {\n csql = `SELECT COUNT(DISTINCT u_phone) as cnt FROM (SELECT p.u_phone FROM purchase p WHERE p.iid='${iid}' AND p.p_cancel_amount=0 AND p.u_name NOT ILIKE '%\ud14c\uc2a4\ud2b8%'${crewFilter.replace('u_phone', 'p.u_phone')} UNION SELECT e.u_phone FROM event e JOIN item i ON e.iid=i.iid WHERE e.iid='${iid}' AND i.i_paid_tf=false AND e.u_name NOT ILIKE '%\ud14c\uc2a4\ud2b8%'${crewFilter.replace('u_phone', 'e.u_phone')}) s`;\n} else if (t.qt === 'all_members') {\n csql = `SELECT COUNT(*) as cnt FROM member m WHERE m.u_membership_tf=true AND m.u_marketing_agree_tf=true AND m.u_phone IS NOT NULL AND m.u_name NOT ILIKE '%\ud14c\uc2a4\ud2b8%'${crewFilter.replace('u_phone', 'm.u_phone')}`;\n} else {\n csql = `SELECT COUNT(*) as cnt FROM member m WHERE m.u_membership_tf=true AND m.u_marketing_agree_tf=true AND m.u_phone IS NOT NULL AND m.u_name NOT ILIKE '%\ud14c\uc2a4\ud2b8%'${crewFilter.replace('u_phone', 'm.u_phone')} AND NOT EXISTS (SELECT 1 FROM purchase p WHERE p.u_phone=m.u_phone AND p.iid='${iid}' AND p.p_cancel_amount=0) AND NOT EXISTS (SELECT 1 FROM event e WHERE e.u_phone=m.u_phone AND e.iid='${iid}')`;\n}\nreturn { json: {\n ...t, iid: item.iid, name: item.i_title_userside, sched: item.i_full_schedule,\n time, ed, period, slug, utmUrl, alimurl: item.i_alimurl || '',\n lh: staticData.benefits || '\uacf5\uc720\ud68c \ub2e4\uc2dc\ubcf4\uae30 VOD \uc81c\uacf5\\n\ub77c\uc774\ube0c \uc644\uc8fc \uc2dc \ucd94\uac00 \ud61c\ud0dd \uacf5\uac1c',\n rh: staticData.benefits || '\uacf5\uc720\ud68c \ub2e4\uc2dc\ubcf4\uae30 VOD \uc81c\uacf5\\n\ub77c\uc774\ube0c \uc644\uc8fc \uc2dc \ucd94\uac00 \ud61c\ud0dd \uacf5\uac1c',\n cpn: '\uc774\uae30\uc801\uba64\ubc84\uc2ed \ud504\ub85c\uadf8\ub7a8 \ud560\uc778', link: t.num === 8 ? (item.i_alimurl || '') : t.num === 9 ? (item.i_vodurl || '') : [3,4,6,7].includes(t.num) ? (staticData.zoomUrl || '') : (utmUrl || item.i_alimurl || ''), vodDeadline, vodurl: item.i_vodurl || '', count_sql: csql\n}};\n",
"mode": "runOnceForEachItem"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
688,
240
],
"name": "Code: \ubcc0\uc218 \uc900\ube44",
"id": "6583c907-5da9-4500-9a7a-d5b3052c73a4"
},
{
"parameters": {
"operation": "executeQuery",
"query": "{{ $json.count_sql }}",
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
928,
240
],
"name": "Postgres: \ub300\uc0c1\uc790 \uc218",
"id": "3682844e-3cc3-4c41-9874-7d92b1d8ffbf",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const d = $('Code: \ubcc0\uc218 \uc900\ube44').item.json;\nconst cnt = $json.cnt || 0;\nif (cnt === 0) return;\n\nlet preview = '';\nswitch(d.num) {\n case 1:\n preview = `#{\uc774\ub984}${d.name_suffix?' '+d.name_suffix:''}\ub2d8, \uc54c\ub9bc\uc2e0\uccad\ud558\uc2e0\\n\uc774\uae30\uc801\uacf5\uc720\ud68c \ubaa8\uc9d1\uc774 \uc2dc\uc791\ub410\uc5b4\uc694!\\n\\n\ud83d\udfe8 \uacf5\uc720\ud68c\uba85 : ${d.name}\\n\ud83d\udfe8 \uc77c\uc815 : ${d.sched}\\n\ud83d\udfe8 \uc2e0\uccad\uae30\uac04 : ${d.period}`; break;\n case 2:\n preview = `#{\uc774\ub984}${d.name_suffix?' '+d.name_suffix:''}\ub2d8, \uc54c\ub9bc\uc2e0\uccad\ud558\uc2e0\n\uc774\uae30\uc801\uba64\ubc84\uc2ed \ud504\ub85c\uadf8\ub7a8 \ubaa8\uc9d1\uc774 \uc2dc\uc791\ub410\uc5b4\uc694!\n\n\ud83d\udfe8 \ud504\ub85c\uadf8\ub7a8\uba85 : ${d.name}\n\ud83d\udfe8 \uc77c\uc815: ${d.sched}\n\ud83d\udfe8 \uc2e0\uccad\uae30\uac04 : ${d.period}`; break;\n case 3:\n preview = `#{\uc774\ub984}\ub2d8,\n\uc2e0\uccad\ud558\uc2e0 \uc774\uae30\uc801\uacf5\uc720\ud68c\uac00\n\ub0b4\uc77c \uc9c4\ud589\ub429\ub2c8\ub2e4\ud83d\udc9b\n\n\u25fe\uacf5\uc720\ud68c\uba85 : ${d.name}\n\u25fe\uc77c\uc815 : ${d.sched}\n\n\ub77c\uc774\ube0c \uc785\uc7a5\ub9c1\ud06c\ub294\n\uc544\ub798 \ubc84\ud2bc\uc744 \ud655\uc778\ud558\uc138\uc694!`; break;\n case 4:\n preview = `#{\uc774\ub984}\ub2d8,\n\uc2e0\uccad\ud558\uc2e0 \uc774\uae30\uc801\uacf5\uc720\ud68c\uac00\n\uc624\ub298 \uc9c4\ud589\ub429\ub2c8\ub2e4.\n\n\u25fe\uacf5\uc720\ud68c\uba85 : ${d.name}\n\u25fe\uc77c\uc815 : ${d.sched}\n\n\ub2a6\uc9c0 \uc54a\uac8c \ub9cc\ub098\uc694\u2728`; break;\n case 5:\n preview = `#{\uc774\ub984}\ub2d8, \uac00\uc785\ud558\uc2e0 \uc774\uae30\uc801\uba64\ubc84\uc2ed\n\ud504\ub85c\uadf8\ub7a8 \ud560\uc778 \ucfe0\ud3f0\uc774 \ubc1c\uae09\ub418\uc5c8\uc2b5\ub2c8\ub2e4!\n\n\ud83c\udf81\ucfe0\ud3f0\uba85 : ${d.cpn}\n\u23f0\uc0ac\uc6a9 \uc885\ub8cc\uc77c : ${d.ed}\n\n\ud574\ub2f9 \ucfe0\ud3f0\uc740 \uc885\ub8cc\uc77c \uc774\ud6c4 \uc790\ub3d9 \uc18c\uba78\ub418\uc5b4 \uc801\uc6a9\uc774 \ubd88\uac00\ud569\ub2c8\ub2e4.`; break;\n case 6:\n preview = `#{\uc774\ub984}\ub2d8\uaed8\uc11c \uc2e0\uccad\ud558\uc2e0\n\uc774\uae30\uc801\uacf5\uc720\ud68c\uac00 ${d.time}\uc5d0 \uc2dc\uc791\ub429\ub2c8\ub2e4\ud83d\ude06\n\ub2a6\uc9c0 \uc54a\uac8c \uc785\uc7a5\ud574\uc8fc\uc138\uc694!\n\n\ud83d\udfe8 \uacf5\uc720\ud68c\uba85 : ${d.name}\n\ud83d\udfe8 \ub77c\uc774\ube0c\ud61c\ud0dd :\n${d.lh}\n\ud83d\udc47\ud558\ub2e8 '\ub77c\uc774\ube0c \uc785\uc7a5\ud558\uae30' \ud074\ub9ad\ud83d\udc47`; break;\n case 7:\n preview = `#{\uc774\ub984}\ub2d8!\n\uc2e0\uccad\ud558\uc2e0 \uc774\uae30\uc801\uacf5\uc720\ud68c\n${d.name}\uc774 \uc2dc\uc791\ub410\uc5b4\uc694\ud83d\udd25\n\n\ub77c\uc774\ube0c \ucc38\uc5ec\uc790\uc5d0\uac8c\ub9cc \uc81c\uacf5\ub418\ub294\n\ud2b9\ubcc4\ud55c \uc790\ub8cc\uc9d1\ub3c4 \ubc1b\uc544\uac00\uc138\uc694\ud83c\udf81\n\u2705 ${(d.rh || \"\").replace(/^\u2705\\s*/, \"\")}\n\n\uc544\ub798 \ub9c1\ud06c\ub97c \ud074\ub9ad\ud574 \ub77c\uc774\ube0c\uc5d0\n\ud83d\udc47\ud83c\udffb\ubc14\ub85c \ucc38\uc5ec\ud558\uc138\uc694\ud83d\udc47\ud83c\udffb`; break;\n case 8:\n preview = `#{\uc774\ub984}\ub2d8, \uc9c0\uae08 \ucc38\uc5ec\ud558\uc2e0\n\uacf5\uc720\ud68c \ub2e4\uc2dc\ubcf4\uae30 \ubc0f \uc790\uc138\ud55c \uc548\ub0b4\ub294\n\uc544\ub798 \ubc84\ud2bc\uc744 \ub20c\ub7ec \ud655\uc778\ud574\uc8fc\uc138\uc694!\n\n\u25fe\uacf5\uc720\ud68c\uba85 : ${d.name}`; break;\n case 9:\n preview = `\ud83d\udce2 #{\uc774\ub984}\ub2d8\uaed8\uc11c \uc2e0\uccad\ud558\uc2e0\n${d.name}\n\ub2e4\uc2dc\ubcf4\uae30 VOD\uac00 \ub3c4\ucc29\ud588\uc5b4\uc694!\n\n\u2705 \uc5f4\ub78c\uae30\ud55c : ${d.vodDeadline || d.ed || ''}\n\u2705 \uc5f4\ub78c\ubc29\ubc95 : ${d.cpn || '\uc140\ud53c\uc26c\ud074\ub7fd'}\n\n\ud83d\udc47\ud83c\udffb\uc544\ub798 \ubc84\ud2bc\uc744 \ub20c\ub7ec \ud655\uc778\ud574\uc8fc\uc138\uc694\ud83d\udc47\ud83c\udffb`; break;\n}\n\nconst cb = JSON.stringify({\n t:d.num, tid:d.tid, iid:d.iid, name:d.name, sched:d.sched,\n time:d.time, url:(d.num===9 ? d.vodurl : (d.utmUrl||d.alimurl)), slug:d.slug,\n nm:d.nm, ml:d.ml, cnt, lh:d.lh, rh:d.rh, cpn:d.cpn, ed:d.ed, period:d.period||'', qt:d.qt, link:d.link||'', scheduledTime:d.scheduledTime||''\n});\n\nconst numLabel = {1:'\uc624\ud508\uc54c\ub9bc',2:'\uc624\ud508\ub9ac\ub9c8\uc778\ub4dc',3:'D-1 \ub9ac\ub9c8\uc778\ub4dc',4:'\ub2f9\uc77c\ub9ac\ub9c8\uc778\ub4dc',5:'\ud560\uc778\ucfe0\ud3f0',6:'\uc785\uc7a5\ub9c1\ud06c',7:'\ub77c\uc774\ube0c\uc2dc\uc791',8:'\ud61c\ud0dd\uc548\ub0b4',9:'VOD\ubc1c\uc1a1'};\nconst em = {1:'\ud83d\udd14',2:'\ud83d\udce3',3:'\ud83d\udcc5',4:'\ud83d\udd14',5:'\ud83c\udf81',6:'\ud83d\udd17',7:'\ud83d\udd25',8:'\ud83d\udccb',9:'\ud83d\udcf9'};\nconst blocks = [\n { type:'header', text:{ type:'plain_text', text:`${em[d.num]||'\ud83d\udce2'} [#${d.num} ${numLabel[d.num]||d.name}] ${d.scheduledTime || \"\"} \ubc1c\uc1a1 \uc608\uc815` }},\n { type:'section', fields:[\n { type:'mrkdwn', text:`*\uacf5\uc720\ud68c:*\n${d.name}` },\n { type:'mrkdwn', text:`*\ub300\uc0c1:*\n${cnt}\uba85` },\n { type:'mrkdwn', text:`*\uc77c\uc815:*\n${d.sched}` },\n { type:'mrkdwn', text:`*\uc54c\ub9bc\ud1a1:*\n#${d.num} ${numLabel[d.num]||d.name}` }\n ]},\n { type:'divider' },\n { type:'section', text:{ type:'mrkdwn', text:`\ud83d\udccb *\uc54c\ub9bc\ud1a1 \ubbf8\ub9ac\ubcf4\uae30:*\n\\`\\`\\`\n${preview}\n\\`\\`\\`` }},\n { type:'divider' },\n { type:'context', elements:[{ type:'mrkdwn', text:'\u26a0\ufe0f *\uc2b9\uc778 \uc2dc \uc608\uc57d \ubc1c\uc1a1\uc774 \ud655\uc815\ub429\ub2c8\ub2e4.* \uce74\ud53c\u00b7\ub9c1\ud06c\u00b7\uc2dc\uac04\uc744 \ubc18\ub4dc\uc2dc \ud655\uc778 \ud6c4 \uc2b9\uc778\ud574\uc8fc\uc138\uc694.' }]},\n { type:'actions', elements:[\n { type:'button', text:{ type:'plain_text', text:'\u2705 \uc774\ub300\ub85c \ubc1c\uc1a1' }, style:'primary', action_id:'cron_approve', value:cb },\n { type:'button', text:{ type:'plain_text', text:'\u270f\ufe0f \uc218\uc815' }, action_id:'cron_edit', value:cb },\n { type:'button', text:{ type:'plain_text', text:'\u274c \ucde8\uc18c' }, style:'danger', action_id:'cron_reject', value:cb }\n ]}\n];\n\nreturn {\n channel: 'C0AN2NZ4L7L',\n text: `[#${d.num} ${numLabel[d.num]||d.name}] ${d.name} - ${cnt}\uba85`,\n blocks: JSON.stringify(blocks)\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1152,
240
],
"name": "Code: \uc2ac\ub799 \uba54\uc2dc\uc9c0",
"id": "5449c3e6-02d3-496f-aabd-6cea77cfd5c3"
},
{
"parameters": {
"method": "POST",
"url": "https://slack.com/api/chat.postMessage",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "slackApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"channel\": \"{{ $json.channel }}\",\n \"text\": {{ JSON.stringify($json.text) }},\n \"blocks\": {{ $json.blocks }}\n}",
"options": {
"batching": {
"batch": {
"batchSize": 1,
"batchInterval": 1000
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1376,
240
],
"name": "HTTP: \uc2ac\ub799 \uc804\uc1a1",
"id": "484031aa-b8f6-483f-b962-244c718291ee",
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"httpMethod": "POST",
"path": "alimtalk-approval",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
688
],
"name": "Webhook: \uc2b9\uc778",
"id": "f6cd1ed5-9098-4aa5-a7af-a27d040c4c8f"
},
{
"parameters": {
"jsCode": "const strip = u => (u||'').replace(/^https?:\\/\\//, '');\nconst payloadStr = $input.item.json.body?.payload;\nif (!payloadStr) return [{ json: { action: 'unknown' } }];\nconst payload = JSON.parse(payloadStr);\nconst staticData = $getWorkflowStaticData('global');\n\nif (payload.type === 'view_submission') {\n const cbid = payload.view?.callback_id;\n const meta = JSON.parse(payload.view?.private_metadata || '{}');\n const vals = payload.view?.state?.values || {};\n\n if (cbid === 'alimtalk_edit') {\n const updated = { ...meta };\n if (vals.f_name?.v?.value) updated.name = vals.f_name.v.value;\n if (vals.f_sched?.v?.value) updated.sched = vals.f_sched.v.value;\n if (vals.f_time?.v?.value) updated.time = vals.f_time.v.value;\n if (vals.f_lh?.v?.value) updated.lh = vals.f_lh.v.value;\n if (vals.f_rh?.v?.value) updated.rh = vals.f_rh.v.value;\n if (vals.f_cpn?.v?.value) updated.cpn = vals.f_cpn.v.value;\n if (vals.f_ed?.v?.value) updated.ed = vals.f_ed.v.value;\n if (vals.f_period?.v?.value) updated.period = vals.f_period.v.value;\n if (vals.f_link?.v?.value) updated.link = strip(vals.f_link.v.value);\n if (vals.f_scheduled?.v?.value) updated.scheduledTime = vals.f_scheduled.v.value;\n if (vals.f_name_suffix?.v?.value !== undefined) updated.name_suffix = vals.f_name_suffix.v.value;\n\n // \u2462 D-1: \uc90c\ub9c1\ud06c staticData\uc5d0 \uc800\uc7a5 \u2192 \u2463\u2465\u2466 \uc7ac\uc0ac\uc6a9\n if (updated.t === 3 && updated.link) {\n staticData.zoomUrl = strip(updated.link);\n }\n // \u2465 \uc785\uc7a5\ub9c1\ud06c: \ub77c\uc774\ube0c\ud61c\ud0dd staticData\uc5d0 \uc800\uc7a5 \u2192 \u2466 \uc7ac\uc0ac\uc6a9\n if (updated.t === 6 && updated.lh) {\n staticData.benefits = updated.lh;\n }\n // \u2468 VOD: VOD\ub9c1\ud06c staticData\uc5d0 \uc800\uc7a5\n if (updated.t === 9 && updated.link) {\n staticData.vodUrl = strip(updated.link);\n }\n\n return [{ json: { action: 'edit_submit', ...updated, user_name: payload.user?.name || '' } }];\n }\n\n if (cbid === 'alimtalk_url') {\n const url = strip(vals.url_block?.url_input?.value || '');\n const result = { action: 'modal_submit', input_url: url, ...meta, user_name: payload.user?.name || '' };\n\n // \u2462 URL \ubaa8\ub2ec\uc5d0\uc11c\ub3c4 \uc90c\ub9c1\ud06c \uc800\uc7a5\n if (meta.t === 3 && url) {\n staticData.zoomUrl = strip(url);\n }\n if (meta.t === 6 && url) {\n // \u2465\uc740 URL\uc774 \uc544\ub2c8\ub77c \ub77c\uc774\ube0c\ud61c\ud0dd\uc774\uc9c0\ub9cc, URL \ubaa8\ub2ec\uc774\uba74 \uc90c\ub9c1\ud06c\n }\n\n return [{ json: result }];\n }\n\n return [{ json: { action: 'unknown' } }];\n}\n\nconst act = payload.actions?.[0];\nconst cb = JSON.parse(act?.value || '{}');\nconst base = { ch: payload.channel?.id, ts: payload.message?.ts, user_name: payload.user?.name || '', ...cb };\n\nif (act?.action_id === 'cron_reject') return [{ json: { action: 'reject', ...base } }];\nif (act?.action_id === 'cron_edit') return [{ json: { action: 'edit', trigger_id: payload.trigger_id, ...base } }];\nif (act?.action_id === 'cron_approve') {\n // \u2463\u2466 \uc790\ub3d9\ubc1c\uc1a1: \uc90c\ub9c1\ud06c\uac00 staticData\uc5d0 \uc788\uc73c\uba74 \ubc14\ub85c \uc2b9\uc778\n if (cb.t === 4 || cb.t === 6 || cb.t === 7 || cb.t === 8 || cb.t === 9) {\n const link = (cb.t === 8 || cb.t === 9) ? (cb.link || cb.url || '') : (staticData.zoomUrl || cb.link || '');\n if (link) {\n return [{ json: { action: 'approve_direct', input_url: link, ...base, link } }];\n }\n }\n\n if (cb.nm && !cb.link) return [{ json: { action: 'approve_modal', trigger_id: payload.trigger_id, ...base } }];\n return [{ json: { action: 'approve_direct', input_url: cb.link || null, ...base } }];\n}\nreturn [{ json: { action: 'unknown' } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
688
],
"name": "Code: \ud30c\uc2f1",
"id": "c306c68d-41ae-4489-ad37-1b90f5dc155a"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "reject",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "reject"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "approve_direct",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "approve_direct"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "approve_modal",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "approve_modal"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "modal_submit",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "modal_submit"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "edit",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "edit"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "edit_submit",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "edit_submit"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
464,
688
],
"name": "Switch: \uc561\uc158",
"id": "80a44831-946a-48fa-a250-cf8e09dad8c3"
},
{
"parameters": {
"method": "POST",
"url": "https://slack.com/api/chat.postMessage",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "slackApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\"channel\": \"{{ $json.ch }}\", \"thread_ts\": \"{{ $json.ts }}\", \"text\": \"\u274c {{ $json.user_name }}\ub2d8\uc774 \ubc1c\uc1a1\uc744 \ucde8\uc18c\ud588\uc2b5\ub2c8\ub2e4. {{ $json.cancel_msg }}\"}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
704,
992
],
"name": "HTTP: \ucde8\uc18c \uba54\uc2dc\uc9c0",
"id": "babc6b61-c852-4959-9d0c-8e31ed67c966",
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://slack.com/api/views.open",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "slackApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ trigger_id: $json.trigger_id, view: {\n type: 'modal', callback_id: 'alimtalk_url', title: { type: 'plain_text', text: '\ub9c1\ud06c \uc785\ub825' },\n submit: { type: 'plain_text', text: '\ubc1c\uc1a1' }, close: { type: 'plain_text', text: '\ucde8\uc18c' },\n private_metadata: JSON.stringify({ t:$json.t, tid:$json.tid, iid:$json.iid, name:$json.name, sched:$json.sched, time:$json.time, slug:$json.slug, nm:$json.nm, ml:$json.ml, cnt:$json.cnt, lh:$json.lh, rh:$json.rh, cpn:$json.cpn, ed:$json.ed, period:$json.period||'', qt:$json.qt, link:'', ch:$json.ch, ts:$json.ts }),\n blocks: [{ type:'input', block_id:'url_block', element:{ type:'url_text_input', action_id:'url_input', placeholder:{ type:'plain_text', text: $json.ml } }, label:{ type:'plain_text', text: $json.ml } }]\n}}) }}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
704,
800
],
"name": "HTTP: \ub9c1\ud06c \ubaa8\ub2ec",
"id": "cb76d5e7-98cc-452f-acac-2e11f52399f9",
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const staticData = $getWorkflowStaticData('global');\nconst d = $json;\nconst meta = JSON.stringify({ t:d.t, tid:d.tid, iid:d.iid, name:d.name, sched:d.sched, time:d.time, url:d.url||'', slug:d.slug, nm:d.nm, ml:d.ml, cnt:d.cnt, lh:d.lh, rh:d.rh, cpn:d.cpn, ed:d.ed, period:d.period||'', qt:d.qt, link:d.link||'', ch:d.ch, ts:d.ts, name_suffix:d.name_suffix||'' });\n\nconst blocks = [];\n// \u2460 \uc624\ud508\uc54c\ub9bc \u2014 \uacf5\uc720\ud68c\uba85\uc5d0 \uce74\ud53c (multiline)\nif (d.t === 1) {\n blocks.push({ type:'input', block_id:'f_name', element:{ type:'plain_text_input', action_id:'v', multiline:true, initial_value: d.name||'' }, label:{ type:'plain_text', text:'\uacf5\uc720\ud68c\uba85 (\uce74\ud53c \uc785\ub825)' }});\n blocks.push({ type:'input', block_id:'f_sched', element:{ type:'plain_text_input', action_id:'v', initial_value: d.sched||'' }, label:{ type:'plain_text', text:'\uc77c\uc815' }});\n blocks.push({ type:'input', block_id:'f_period', element:{ type:'plain_text_input', action_id:'v', initial_value: d.period||'' }, label:{ type:'plain_text', text:'\uc2e0\uccad\uae30\uac04' }});\n}\n// \u2460 \uc774\ub984 \ub4a4 \ubb38\uad6c + \uc778\uc0ac\ub9d0\nif (d.t === 1) {\n blocks.push({ type:'input', block_id:'f_name_suffix', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.name_suffix||'', placeholder:{ type:'plain_text', text:'\uc608: \uc124\ubb38 \ub300\uc0c1\uc790' }}, label:{ type:'plain_text', text:'\uc774\ub984 \ub4a4 \ubb38\uad6c (\uc635\uc158)' }});\n}\n// \u2460 URL \ud544\ub4dc \ucd94\uac00\nif (d.t === 1) {\n blocks.push({ type:\"input\", block_id:\"f_link\", optional:true, element:{ type:\"plain_text_input\", action_id:\"v\", initial_value: d.url||\"\", placeholder:{ type:\"plain_text\", text:\"UTM URL (\uc790\ub3d9\uc0dd\uc131\ub428, \uc218\uc815 \ud544\uc694\uc2dc\ub9cc)\" }}, label:{ type:\"plain_text\", text:\"URL (\uc635\uc158)\" }});\n}\n// \u2461 \uc624\ud508\ub9ac\ub9c8\uc778\ub4dc \u2014 \ud504\ub85c\uadf8\ub7a8\uba85\uc5d0 \uce74\ud53c (multiline)\nif (d.t === 2) {\n blocks.push({ type:'input', block_id:'f_name', element:{ type:'plain_text_input', action_id:'v', multiline:true, initial_value: d.name||'' }, label:{ type:'plain_text', text:'\ud504\ub85c\uadf8\ub7a8\uba85 (\uce74\ud53c \uc785\ub825)' }});\n blocks.push({ type:'input', block_id:'f_sched', element:{ type:'plain_text_input', action_id:'v', initial_value: d.sched||'' }, label:{ type:'plain_text', text:'\uc77c\uc815' }});\n blocks.push({ type:'input', block_id:'f_period', element:{ type:'plain_text_input', action_id:'v', initial_value: d.period||'' }, label:{ type:'plain_text', text:'\uc2e0\uccad\uae30\uac04 (\uc608: 3/18~3/31)' }});\n blocks.push({ type:'input', block_id:'f_name_suffix', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.name_suffix||'', placeholder:{ type:'plain_text', text:'\uc608: \uc124\ubb38 \ub300\uc0c1\uc790' }}, label:{ type:'plain_text', text:'\uc774\ub984 \ub4a4 \ubb38\uad6c (\uc635\uc158)' }});\n}\n// \u2462 D-1 \ub9ac\ub9c8\uc778\ub4dc \u2014 \uacf5\uc720\ud68c\uba85+\uc77c\uc815\nif (d.t === 3) {\n blocks.push({ type:'input', block_id:'f_name', element:{ type:'plain_text_input', action_id:'v', initial_value: d.name||'' }, label:{ type:'plain_text', text:'\uacf5\uc720\ud68c\uba85' }});\n blocks.push({ type:'input', block_id:'f_sched', element:{ type:'plain_text_input', action_id:'v', initial_value: d.sched||'' }, label:{ type:'plain_text', text:'\uc77c\uc815' }});\n blocks.push({ type:'input', block_id:'f_link', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.link||'', placeholder:{ type:'plain_text', text:'\uc90c\ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694' }}, label:{ type:'plain_text', text:'\uc90c\ub9c1\ud06c (\uc635\uc158)' }});\n}\n// \u2463 \ub2f9\uc77c \ub9ac\ub9c8\uc778\ub4dc \u2014 \uacf5\uc720\ud68c\uba85+\uc77c\uc815\nif (d.t === 4) {\n blocks.push({ type:'input', block_id:'f_name', element:{ type:'plain_text_input', action_id:'v', initial_value: d.name||'' }, label:{ type:'plain_text', text:'\uacf5\uc720\ud68c\uba85' }});\n blocks.push({ type:'input', block_id:'f_sched', element:{ type:'plain_text_input', action_id:'v', initial_value: d.sched||'' }, label:{ type:'plain_text', text:'\uc77c\uc815' }});\n blocks.push({ type:'input', block_id:'f_link', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.link||'', placeholder:{ type:'plain_text', text:'\uc90c\ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694' }}, label:{ type:'plain_text', text:'\uc90c\ub9c1\ud06c (\uc635\uc158)' }});\n}\n// \u2464 \ud560\uc778\ucfe0\ud3f0 \u2014 \ucfe0\ud3f0\uba85(multiline)+\uc885\ub8cc\uc77c\nif (d.t === 5) {\n blocks.push({ type:'input', block_id:'f_cpn', element:{ type:'plain_text_input', action_id:'v', multiline:true, initial_value: d.cpn||'' }, label:{ type:'plain_text', text:'\ucfe0\ud3f0\uba85 (\uce74\ud53c \uc785\ub825)' }});\n blocks.push({ type:'input', block_id:'f_ed', element:{ type:'plain_text_input', action_id:'v', multiline:true, initial_value: d.ed||'' }, label:{ type:'plain_text', text:'\uc885\ub8cc\uc77c + \uc548\ub0b4\ubb38\uad6c' }});\n}\n// \u2464 URL \ud544\ub4dc \ucd94\uac00\nif (d.t === 5) {\n blocks.push({ type:'input', block_id:'f_link', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.link||d.url||'', placeholder:{ type:'plain_text', text:'\uc2e0\uccad\ud398\uc774\uc9c0 \ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694' }}, label:{ type:'plain_text', text:'\uc2e0\uccad\ud398\uc774\uc9c0 URL' }});\n blocks.push({ type:'input', block_id:'f_name_suffix', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.name_suffix||'', placeholder:{ type:'plain_text', text:'\uc608: \uc124\ubb38 \ub300\uc0c1\uc790' }}, label:{ type:'plain_text', text:'\uc774\ub984 \ub4a4 \ubb38\uad6c (\uc635\uc158)' }});\n}\n// \u2465 \uc785\uc7a5\ub9c1\ud06c \u2014 \uacf5\uc720\ud68c\uba85+\uc2dc\uac04+\ub77c\uc774\ube0c\ud61c\ud0dd+\uc90c\ub9c1\ud06c\nif (d.t === 6) {\n blocks.push({ type:'input', block_id:'f_name', element:{ type:'plain_text_input', action_id:'v', initial_value: d.name||'' }, label:{ type:'plain_text', text:'\uacf5\uc720\ud68c\uba85' }});\n blocks.push({ type:'input', block_id:'f_time', element:{ type:'plain_text_input', action_id:'v', initial_value: d.time||'20:00' }, label:{ type:'plain_text', text:'\uc2dc\uac04' }});\n blocks.push({ type:'input', block_id:'f_lh', element:{ type:'plain_text_input', action_id:'v', multiline:true, initial_value: d.lh||'' }, label:{ type:'plain_text', text:'\ub77c\uc774\ube0c\ud61c\ud0dd' }});\n blocks.push({ type:'input', block_id:'f_link', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.link||'', placeholder:{ type:'plain_text', text:'\u2462\uc5d0\uc11c \uc785\ub825\ud55c \uc90c\ub9c1\ud06c\uac00 \uc790\ub3d9 \uc801\uc6a9\ub429\ub2c8\ub2e4' }}, label:{ type:'plain_text', text:'\uc90c\ub9c1\ud06c (\u2462 D-1 \uc790\ub3d9\uc801\uc6a9)' }});\n}\n// \u2466 \ub77c\uc774\ube0c \uc2dc\uc791\uc54c\ub9bc \u2014 \ud504\ub85c\uadf8\ub7a8\uba85+\uc790\ub8cc\uc9d1\ub9ac\uc2a4\ud2b8+\uc90c\ub9c1\ud06c\nif (d.t === 7) {\n blocks.push({ type:'input', block_id:'f_name', element:{ type:'plain_text_input', action_id:'v', initial_value: d.name||'' }, label:{ type:'plain_text', text:'\ud504\ub85c\uadf8\ub7a8\uba85' }});\n blocks.push({ type:'input', block_id:'f_rh', element:{ type:'plain_text_input', action_id:'v', multiline:true, initial_value: staticData.benefits||d.rh||'' }, label:{ type:'plain_text', text:'\uc790\ub8cc\uc9d1\ub9ac\uc2a4\ud2b8 (\u2465 \ub77c\uc774\ube0c\ud61c\ud0dd \uc790\ub3d9\uc801\uc6a9)' }});\n blocks.push({ type:'input', block_id:'f_link', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.link||'', placeholder:{ type:'plain_text', text:'\u2462\uc5d0\uc11c \uc785\ub825\ud55c \uc90c\ub9c1\ud06c\uac00 \uc790\ub3d9 \uc801\uc6a9\ub429\ub2c8\ub2e4' }}, label:{ type:'plain_text', text:'\uc90c\ub9c1\ud06c (\u2462 D-1 \uc790\ub3d9\uc801\uc6a9)' }});\n}\n// \u2467 \ud61c\ud0dd\uc548\ub0b4(\ub178\uc158) \u2014 \uacf5\uc720\ud68c\uba85(multiline)+\ub178\uc158\ub9c1\ud06c\nif (d.t === 8) {\n blocks.push({ type:'input', block_id:'f_name', element:{ type:'plain_text_input', action_id:'v', multiline:true, initial_value: d.name||'' }, label:{ type:'plain_text', text:'\uacf5\uc720\ud68c\uba85 (\uce74\ud53c \uc785\ub825)' }});\n blocks.push({ type:'input', block_id:'f_link', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.link||'', placeholder:{ type:'plain_text', text:'\ub178\uc158 \ub9c1\ud06c\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694' }}, label:{ type:'plain_text', text:'\ub178\uc158 \ub9c1\ud06c' }});\n}\n\n// \u2468 VOD \ubc1c\uc1a1 \u2014 \uacf5\uc720\ud68c\uba85+\uc5f4\ub78c\uae30\ud55c+\uc5f4\ub78c\ubc29\ubc95+VOD\ub9c1\ud06c\nif (d.t === 9) {\n blocks.push({ type:'input', block_id:'f_name', element:{ type:'plain_text_input', action_id:'v', initial_value: d.name||'' }, label:{ type:'plain_text', text:'\uacf5\uc720\ud68c\uba85' }});\n blocks.push({ type:'input', block_id:'f_ed', element:{ type:'plain_text_input', action_id:'v', initial_value: d.ed||d.vodDeadline||'' }, label:{ type:'plain_text', text:'\uc5f4\ub78c\uae30\ud55c (#{\ub0a0\uc9dc})' }});\n blocks.push({ type:'input', block_id:'f_cpn', element:{ type:'plain_text_input', action_id:'v', initial_value: d.cpn||'\uc140\ud53c\uc26c\ud074\ub7fd' }, label:{ type:'plain_text', text:'\uc5f4\ub78c\ubc29\ubc95 (#{\ucc44\ub110})' }});\n blocks.push({ type:'input', block_id:'f_link', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.link||'', placeholder:{ type:'plain_text', text:'VOD \ub9c1\ud06c (https:// \uc5c6\uc774)' }}, label:{ type:'plain_text', text:'VOD \ub9c1\ud06c' }});\n}\n\n// \ubaa8\ub4e0 \ud15c\ud50c\ub9bf\uc5d0 \ubc1c\uc1a1\uc2dc\uac04 \ubcc0\uacbd \ud544\ub4dc \ucd94\uac00\nblocks.push({ type:'input', block_id:'f_scheduled', optional:true, element:{ type:'plain_text_input', action_id:'v', initial_value: d.scheduledTime||'', placeholder:{ type:'plain_text', text:`${d.scheduledTime||'\ubbf8\uc815'} (\ube44\uc6b0\uba74 \uc989\uc2dc\ubc1c\uc1a1)` }}, label:{ type:'plain_text', text:`\ubc1c\uc1a1\uc2dc\uac04 (\uae30\ubcf8 ${d.scheduledTime||'\uc989\uc2dc'})` }});\n\nreturn [{ json: { trigger_id: d.trigger_id, meta, blocks: JSON.stringify(blocks) }}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
704,
592
],
"name": "Code: \uc218\uc815 \ubaa8\ub2ec \uc0dd\uc131",
"id": "6355cc1c-fc72-4646-9119-18e322715995"
},
{
"parameters": {
"method": "POST",
"url": "https://slack.com/api/views.open",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "slackApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"trigger_id\": \"{{ $json.trigger_id }}\",\n \"view\": {\n \"type\": \"modal\",\n \"callback_id\": \"alimtalk_edit\",\n \"title\": { \"type\": \"plain_text\", \"text\": \"\ubcc0\uc218 \uc218\uc815\" },\n \"submit\": { \"type\": \"plain_text\", \"text\": \"\uc218\uc815 \uc644\ub8cc\" },\n \"close\": { \"type\": \"plain_text\", \"text\": \"\ucde8\uc18c\" },\n \"private_metadata\": {{ JSON.stringify($json.meta) }},\n \"blocks\": {{ $json.blocks }}\n }\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
944,
592
],
"name": "HTTP: \uc218\uc815 \ubaa8\ub2ec",
"id": "9da8eff3-8761-419a-a400-a24ad88afca3",
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const d = $json;\nlet preview = '';\nswitch(d.t) {\n case 1:\n preview = `\\{\uc774\ub984\\}${d.name_suffix?' '+d.name_suffix:''}\ub2d8, \uc54c\ub9bc\uc2e0\uccad\ud558\uc2e0\\n\uc774\uae30\uc801\uacf5\uc720\ud68c \ubaa8\uc9d1\uc774 \uc2dc\uc791\ub410\uc5b4\uc694!\\n\\n\ud83d\udfe8 \uacf5\uc720\ud68c\uba85 : ${d.name}\\n\ud83d\udfe8 \uc77c\uc815 : ${d.sched}\\n\ud83d\udfe8 \uc2e0\uccad\uae30\uac04 : ${d.period}`; break;\n case 2:\n preview = `\\{\uc774\ub984\\}${d.name_suffix?' '+d.name_suffix:''}\ub2d8, \uc54c\ub9bc\uc2e0\uccad\ud558\uc2e0\\n\uc774\uae30\uc801\uba64\ubc84\uc2ed \ud504\ub85c\uadf8\ub7a8 \ubaa8\uc9d1\uc774 \uc2dc\uc791\ub410\uc5b4\uc694!\\n\\n\ud83d\udfe8 \ud504\ub85c\uadf8\ub7a8\uba85 : ${d.name}\\n\ud83d\udfe8 \uc77c\uc815: ${d.sched}\\n\ud83d\udfe8 \uc2e0\uccad\uae30\uac04 : ${d.period}`; break;\n case 3:\n preview = `\\{\uc774\ub984\\}\ub2d8,\\n\uc2e0\uccad\ud558\uc2e0 \uc774\uae30\uc801\uacf5\uc720\ud68c\uac00\\n\ub0b4\uc77c \uc9c4\ud589\ub429\ub2c8\ub2e4\ud83d\udc9b\\n\\n\u25fe\uacf5\uc720\ud68c\uba85 : ${d.name}\\n\u25fe\uc77c\uc815 : ${d.sched}\\n\\n\ub77c\uc774\ube0c \uc785\uc7a5\ub9c1\ud06c\ub294\\n\uc544\ub798 \ubc84\ud2bc\uc744 \ud655\uc778\ud558\uc138\uc694!`; break;\n case 4:\n preview = `\\{\uc774\ub984\\}\ub2d8,\\n\uc2e0\uccad\ud558\uc2e0 \uc774\uae30\uc801\uacf5\uc720\ud68c\uac00\\n\uc624\ub298 \uc9c4\ud589\ub429\ub2c8\ub2e4.\\n\\n\u25fe\uacf5\uc720\ud68c\uba85 : ${d.name}\\n\u25fe\uc77c\uc815 : ${d.sched}\\n\\n\ub2a6\uc9c0 \uc54a\uac8c \ub9cc\ub098\uc694\u2728`; break;\n case 5:\n preview = `\\{\uc774\ub984\\}\ub2d8, \uac00\uc785\ud558\uc2e0 \uc774\uae30\uc801\uba64\ubc84\uc2ed\\n\ud504\ub85c\uadf8\ub7a8 \ud560\uc778 \ucfe0\ud3f0\uc774 \ubc1c\uae09\ub418\uc5c8\uc2b5\ub2c8\ub2e4!\\n\\n\ud83c\udf81\ucfe0\ud3f0\uba85 : ${d.cpn}\\n\u23f0\uc0ac\uc6a9 \uc885\ub8cc\uc77c : ${d.ed}\\n\\n\ud574\ub2f9 \ucfe0\ud3f0\uc740 \uc885\ub8cc\uc77c \uc774\ud6c4 \uc790\ub3d9 \uc18c\uba78\ub418\uc5b4 \uc801\uc6a9\uc774 \ubd88\uac00\ud569\ub2c8\ub2e4.`; break;\n case 6:\n preview = `\\{\uc774\ub984\\}\ub2d8\uaed8\uc11c \uc2e0\uccad\ud558\uc2e0\\n\uc774\uae30\uc801\uacf5\uc720\ud68c\uac00 ${d.time}\uc5d0 \uc2dc\uc791\ub429\ub2c8\ub2e4\ud83d\ude06\\n\ub2a6\uc9c0 \uc54a\uac8c \uc785\uc7a5\ud574\uc8fc\uc138\uc694!\\n\\n\ud83d\udfe8 \uacf5\uc720\ud68c\uba85 : ${d.name}\\n\ud83d\udfe8 \ub77c\uc774\ube0c\ud61c\ud0dd :\\n${d.lh}\\n\ud83d\udc47\ud558\ub2e8 '\ub77c\uc774\ube0c \uc785\uc7a5\ud558\uae30' \ud074\ub9ad\ud83d\udc47`; break;\n case 7:\n preview = `\\{\uc774\ub984\\}\ub2d8!\\n\uc2e0\uccad\ud558\uc2e0 \uc774\uae30\uc801\uacf5\uc720\ud68c\\n${d.name}\uc774 \uc2dc\uc791\ub410\uc5b4\uc694\ud83d\udd25\\n\\n\ub77c\uc774\ube0c \ucc38\uc5ec\uc790\uc5d0\uac8c\ub9cc \uc81c\uacf5\ub418\ub294\\n\ud2b9\ubcc4\ud55c \uc790\ub8cc\uc9d1\ub3c4 \ubc1b\uc544\uac00\uc138\uc694\ud83c\udf81\\n\u2705 ${(d.rh || \"\").replace(/^\u2705\\s*/, \"\")}\\n\\n\uc544\ub798 \ub9c1\ud06c\ub97c \ud074\ub9ad\ud574 \ub77c\uc774\ube0c\uc5d0\\n\ud83d\udc47\ud83c\udffb\ubc14\ub85c \ucc38\uc5ec\ud558\uc138\uc694\ud83d\udc47\ud83c\udffb`; break;\n case 8:\n preview = `\\{\uc774\ub984\\}\ub2d8, \uc9c0\uae08 \ucc38\uc5ec\ud558\uc2e0\\n\uacf5\uc720\ud68c \ub2e4\uc2dc\ubcf4\uae30 \ubc0f \uc790\uc138\ud55c \uc548\ub0b4\ub294\\n\uc544\ub798 \ubc84\ud2bc\uc744 \ub20c\ub7ec \ud655\uc778\ud574\uc8fc\uc138\uc694!\\n\\n\u25fe\uacf5\uc720\ud68c\uba85 : ${d.name}`; break;\n case 9:\n preview = `\ud83d\udce2 \\{\uc774\ub984\\}\ub2d8\uaed8\uc11c \uc2e0\uccad\ud558\uc2e0\\n${d.name}\\n\ub2e4\uc2dc\ubcf4\uae30 VOD\uac00 \ub3c4\ucc29\ud588\uc5b4\uc694!\\n\\n\u2705 \uc5f4\ub78c\uae30\ud55c : ${d.vodDeadline || d.ed || ''}\\n\u2705 \uc5f4\ub78c\ubc29\ubc95 : ${d.cpn || '\uc140\ud53c\uc26c\ud074\ub7fd'}\\n\\n\ud83d\udc47\ud83c\udffb\uc544\ub798 \ubc84\ud2bc\uc744 \ub20c\ub7ec \ud655\uc778\ud574\uc8fc\uc138\uc694\ud83d\udc47\ud83c\udffb`; break;\n}\nconst linkNote = d.link ? `\\n\u2705 \ub9c1\ud06c: ${d.link}` : (d.url ? `\\n\ud83d\udd17 URL: ${d.url}` : (d.nm ? '\\n\u26a0\ufe0f \ub9c1\ud06c \ubbf8\uc785\ub825 (\uc218\uc815\uc5d0\uc11c \uc785\ub825 \uac00\ub2a5)' : ''));\nconst timeNote = d.scheduledTime ? `\\n\u23f0 \ubc1c\uc1a1\uc2dc\uac04: ${d.scheduledTime}` : '';\nconst cb = JSON.stringify({\n t:d.t, tid:d.tid, iid:d.iid, name:d.name, sched:d.sched, time:d.time,\n url:d.url||'', slug:d.slug, nm:d.nm, ml:d.ml, cnt:d.cnt,\n lh:d.lh, rh:d.rh, cpn:d.cpn, ed:d.ed, period:d.period||'', qt:d.qt, link:d.link||'',\n scheduledTime:d.scheduledTime||'', vodDeadline:d.vodDeadline||''\n});\nconst em = {1:'\ud83d\udd14',2:'\ud83d\udce3',3:'\ud83d\udcc5',4:'\ud83d\udd14',5:'\ud83c\udf81',6:'\ud83d\udd17',7:'\ud83d\udcdd',8:'\ud83d\udccb',9:'\ud83d\udcf9'};\nconst numLabel = {1:'\uc624\ud508\uc54c\ub9bc',2:'\uc624\ud508\ub9ac\ub9c8\uc778\ub4dc',3:'D-1 \ub9ac\ub9c8\uc778\ub4dc',4:'\ub2f9\uc77c\ub9ac\ub9c8\uc778\ub4dc',5:'\ud560\uc778\ucfe0\ud3f0',6:'\uc785\uc7a5\ub9c1\ud06c',7:'\ub77c\uc774\ube0c\uc2dc\uc791',8:'\ud61c\ud0dd\uc548\ub0b4',9:'VOD\ubc1c\uc1a1'};\nconst shortName = (d.name||\"\uc54c\ub9bc\ud1a1\").split(\"\\n\")[0].substring(0,30);\nconst blocks = [\n { type:'header', text:{ type:'plain_text', text:`${em[d.t]||\"\ud83d\udce2\"} [#${d.t} ${numLabel[d.t]||'\uc54c\ub9bc\ud1a1'}] ${shortName} \u2014 \uc218\uc815\ub428 \u270f\ufe0f` }},\n { type:'section', text:{ type:'mrkdwn', text:`*\ub300\uc0c1:* ${d.cnt}\uba85${timeNote}${linkNote}` }},\n { type:'divider' },\n { type:'section', text:{ type:'mrkdwn', text:`\ud83d\udccb *\uc218\uc815\ub41c \ubbf8\ub9ac\ubcf4\uae30:*\\n\\`\\`\\`\\n${preview}\\n\\`\\`\\`` }},\n { type:'divider' },\n { type:'context', elements:[{ type:'mrkdwn', text:'\u26a0\ufe0f *\uc2b9\uc778 \uc2dc \uc608\uc57d \ubc1c\uc1a1\uc774 \ud655\uc815\ub429\ub2c8\ub2e4.* \uce74\ud53c\u00b7\ub9c1\ud06c\u00b7\uc2dc\uac04\uc744 \ubc18\ub4dc\uc2dc \ud655\uc778 \ud6c4 \uc2b9\uc778\ud574\uc8fc\uc138\uc694.' }]},\n { type:'actions', elements:[\n { type:'button', text:{ type:'plain_text', text:'\u2705 \uc774\ub300\ub85c \ubc1c\uc1a1' }, style:'primary', action_id:'cron_approve', value:cb },\n { type:'button', text:{ type:'plain_text', text:'\u270f\ufe0f \uc218\uc815' }, action_id:'cron_edit', value:cb },\n { type:'button', text:{ type:'plain_text', text:'\u274c \ucde8\uc18c' }, style:'danger', action_id:'cron_reject', value:cb }\n ]}\n];\nreturn [{ json: { channel: d.ch, text: `[\uc218\uc815\ub428] #${d.t} ${d.name}`, blocks: JSON.stringify(blocks) }}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
704,
448
],
"name": "Code: \uc218\uc815 \ubbf8\ub9ac\ubcf4\uae30",
"id": "a7ae77c0-454d-4893-8423-aafdcf04b536"
},
{
"parameters": {
"method": "POST",
"url": "https://slack.com/api/chat.postMessage",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "slackApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"channel\": \"{{ $json.channel }}\",\n \"text\": {{ JSON.stringify($json.text) }},\n \"blocks\": {{ $json.blocks }}\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
944,
448
],
"name": "HTTP: \uc218\uc815 \ubbf8\ub9ac\ubcf4\uae30 \uc804\uc1a1",
"id": "6187eca7-ee3d-427d-b317-1e2403dbb82e",
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://slack.com/api/chat.postMessage",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "slackApi",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"channel\": \"{{ $json.ch }}\",\n \"thread_ts\": \"{{ $json.ts }}\",\n \"text\": \"\u2705 {{ $json.user_name }}\ub2d8\uc774 \ubc1c\uc1a1\uc744 \uc2b9\uc778\ud588\uc2b5\ub2c8\ub2e4. {{ $json.cnt }}\uba85\uc5d0\uac8c \uc54c\ub9bc\ud1a1\uc744 \ubc1c\uc1a1\ud569\ub2c8\ub2e4.\"\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
816,
688
],
"name": "HTTP: \uc2b9\uc778 \ud655\uc778",
"id": "6487c857-db3b-4718-96a4-b156e266b089",
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const d = $('Code: \ud30c\uc2f1').item.json;\n\n// \ud83d\udcbe \ucde8\uc18c \uae30\ub2a5: \ubc84\uc804 \uce74\uc6b4\ud130 \ubc29\uc2dd\nconst staticData = $getWorkflowStaticData('global');\nconst verKey = `ver_${d.t}_${d.iid}`;\nstaticData[verKey] = (staticData[verKey] || 0) + 1;\nconst _ver = staticData[verKey];\n\nconst iid = (d.iid || '').replace(/[^a-zA-Z0-9_]/g, '');\n\n// \ud83e\uddea \ud06c\ub8e8 \ud14c\uc2a4\ud2b8: iid_999\uc77c \ub54c\ub9cc \ud06c\ub8e8 \ubc88\ud638 \ud654\uc774\ud2b8\ub9ac\uc2a4\ud2b8\nconst CREW_PHONES = ['01082948909','01024551899','01065271136','01049724705','01099984696','01028547990','01038128772'];\nconst crewFilter = iid === 'iid_999' ? ` AND u_phone IN (${CREW_PHONES.map(p => `'${p}'`).join(',')})` : '';\n\nlet sql;\nif (d.qt === 'subscribers') {\n sql = `SELECT DISTINCT sub.u_name, sub.u_phone FROM (SELECT p.u_name, p.u_phone FROM purchase p WHERE p.iid='${iid}' AND p.p_cancel_amount=0 AND p.u_name NOT ILIKE '%\ud14c\uc2a4\ud2b8%'${crewFilter.replace('u_phone', 'p.u_phone')} UNION SELECT e.u_name, e.u_phone FROM event e JOIN item i ON e.iid=i.iid WHERE e.iid='${iid}' AND i.i_paid_tf=false AND e.u_name NOT ILIKE '%\ud14c\uc2a4\ud2b8%'${crewFilter.replace('u_phone', 'e.u_phone')}) sub`;\n} else if (d.qt === 'all_members') {\n sql = `SELECT m.u_name, m.u_phone FROM member m WHERE m.u_membership_tf=true AND m.u_marketing_agree_tf=true AND m.u_phone IS NOT NULL AND m.u_name NOT ILIKE '%\ud14c\uc2a4\ud2b8%'${crewFilter.replace('u_phone', 'm.u_phone')}`;\n} else {\n sql = `SELECT m.u_name, m.u_phone FROM member m WHERE m.u_membership_tf=true AND m.u_marketing_agree_tf=true AND m.u_phone IS NOT NULL AND m.u_name NOT ILIKE '%\ud14c\uc2a4\ud2b8%'${crewFilter.replace('u_phone', 'm.u_phone')} AND NOT EXISTS (SELECT 1 FROM purchase p WHERE p.u_phone=m.u_phone AND p.iid='${iid}' AND p.p_cancel_amount=0) AND NOT EXISTS (SELECT 1 FROM event e WHERE e.u_phone=m.u_phone AND e.iid='${iid}')`;\n}\n// scheduledDate \uacc4\uc0b0 (KST -> UTC)\nconst scheduledTime = d.scheduledTime || '';\nlet scheduledDate = null;\nif (scheduledTime) {\n const today = new Date();\n const [h, m] = scheduledTime.split(':').map(Number);\n const kstDate = new Date(today.getFullYear(), today.getMonth(), today.getDate(), h, m, 0);\n scheduledDate = new Date(kstDate.getTime() - 9 * 60 * 60 * 1000).toISOString();\n}\n\nreturn [{ json: { recipients_sql: sql, scheduledDate, _ver, ...d } }];\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1040,
688
],
"name": "Code: SQL \uc7ac\uc0dd\uc131",
"id": "7daef113-7bd5-4374-bee9-6e8e674147b3"
},
{
"parameters": {
"operation": "executeQuery",
"query": "{{ $json.recipients_sql }}",
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
1264,
688
],
"name": "Postgres: \ub300\uc0c1\uc790 \uc870\ud68c",
"id": "c5c22ce5-5c4e-496b-bcd9-6a073ce5fd6e",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const strip = u => (u||'').replace(/^https?:\\/\\//, '');\nconst staticData = $getWorkflowStaticData('global');\nconst d = staticData._currentSend || {};\nconst scheduledDate = d.scheduledDate || null;\n\nconst recipients = $input.all().map(i => i.json);\nreturn recipients.map(r => {\n const base = { u_phone: r.u_phone, u_name: r.u_name, t: d.t, tid: d.tid, scheduledDate };\n switch(d.t) {\n case 1:\n return { json: { ...base, v_\uc774\ub984:r.u_name+(d.name_suffix?' '+d.name_suffix:''), v_\uacf5\uc720\ud68c\uba85:d.name, v_\ud504\ub85c\uadf8\ub7a8\uba85:d.name, v_\uc77c\uc815:d.sched, v_\uae30\uac04:d.period||'', v_url:strip(d.url||'') }};\n case 2:\n return { json: { ...base, v_\uc774\ub984:r.u_name+(d.name_suffix?' '+d.name_suffix:''), v_\uacf5\uc720\ud68c\uba85:d.name, v_\uc77c\uc815:d.sched, v_\uae30\uac04:d.period||'', v_url:strip(d.url||'') }};\n case 3: case 4:\n return { json: { ...base, v_\uc774\ub984:r.u_name, v_\uc2dc\uac04:d.time, v_\uacf5\uc720\ud68c\uba85:d.name, v_\uc77c\uc815:d.sched, v_\ub77c\uc774\ube0c\ud61c\ud0dd:d.lh, v_url:strip(d.input_url||d.link||'') }};\n case 5:\n return { json: { ...base, v_\uc774\ub984:r.u_name+(d.name_suffix?' '+d.name_suffix:''), v_\ucfe0\ud3f0\uba85:d.cpn, v_\uc885\ub8cc\uc77c:d.ed, v_url:strip(d.url||'') }};\n case 6:\n return { json: { ...base, v_\uc774\ub984:r.u_name, v_\uc2dc\uac04:d.time, v_\uacf5\uc720\ud68c\uba85:d.name, v_\ub77c\uc774\ube0c\ud61c\ud0dd:d.lh, v_url:strip(d.input_url||d.link||'') }};\n case 7: {\n const rh = (d.rh || '').replace(/^\u2705\\s*/, '');\n return { json: { ...base, v_\uc774\ub984:r.u_name, v_\ud504\ub85c\uadf8\ub7a8\uba85:d.name, v_\uc790\ub8cc\uc9d1\ub9ac\uc2a4\ud2b8:rh, v_url:strip(d.input_url||d.link||'') }}; }\n case 8:\n return { json: { ...base, v_\uc774\ub984:r.u_name, v_\uacf5\uc720\ud68c\uba85:d.name, v_url:strip(d.input_url||d.link||'') }};\n case 9:\n return { json: { ...base, v_\uc774\ub984:r.u_name, v_\uacf5\uc720\ud68c\uba85:d.name, v_\ub0a0\uc9dc:d.ed||d.vodDeadline||'', v_\ucc44\ub110:d.cpn||'\uc140\ud53c\uc26c\ud074\ub7fd', v_url:strip(d.input_url||d.link||'') }};\n default: return { json: base };\n }\n});"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1504,
688
],
"name": "Code: \ubc1c\uc1a1 \ub370\uc774\ud130",
"id": "509f81fa-21b0-4243-98e3-dd7ef85b5468"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
1728,
688
],
"name": "SplitInBatches",
"id": "b0e28331-44de
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
postgresslackApisolapiApiKeyApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
공유회_알림톡_크론. Uses postgres, httpRequest, n8n-nodes-solapi. Scheduled trigger; 35 nodes.
Source: https://github.com/selfishclub-all/selfishclub-ax/blob/74b57c627e2e07e97f85f2974cd54bca2073724b/emily-crm/scripts/n8n-patch-alimtalk-vod-9.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
공유회_알림톡_크론. Uses postgres, httpRequest, n8n-nodes-solapi. Scheduled trigger; 39 nodes.
Disparador 1.8. Uses itemLists, postgres, emailSend, httpRequest. Scheduled trigger; 85 nodes.
QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.
Automated Knowledge Management Backup & Recovery. Uses executeCommand, postgres, httpRequest, googleDrive. Scheduled trigger; 30 nodes.
This workflow is a multi-system document synchronization pipeline built in n8n, designed to automatically sync and back up files between Microsoft SharePoint, Supabase/Postgres, and Google Drive.