{"flow":{"id":54,"summary":"List Discord channels and send shared message in thread","versions":[204,205],"created_by":"henri186","created_at":"2024-03-18T13:40:56.185Z","votes":0,"approved":true,"apps":["discord"],"value":{"modules":[{"id":"a","value":{"tag":"","lock":"{\n  \"dependencies\": {}\n}\n//bun.lockb\n<empty>","type":"rawscript","content":"// import * as wmill from \"windmill-client\"\n\nexport async function main(inputText: string) {\n    const chunks = inputText.trim().split('\\n\\n');\n    const formattedEntries = [];\n\n    for (let i = 0; i < chunks.length; i += 2) {\n        const entry = chunks[i] + \"\\n\" + (chunks[i+1] ? chunks[i+1] : \"\");\n        formattedEntries.push(entry);\n    }\n\n    return formattedEntries;\n}","language":"bun","input_transforms":{"inputText":{"expr":"flow_input[\"Core content\"]","type":"javascript"}}},"summary":"Splits message content into thread"},{"id":"b","value":{"tag":"","lock":"{\n  \"dependencies\": {\n    \"discord.js\": \"latest\"\n  }\n}\n//bun.lockb\nIyEvdXNyL2Jpbi9lbnYgYnVuCmJ1bi1sb2NrZmlsZS1mb3JtYXQtdjAKAgAAACvPt3z7464jktCOOPjSRE2Obpghx/JI/rphJyv9g0eRVSkAAAAAAAAaAAAAAAAAAAgAAAAAAAAACAAAAAAAAACAAAAAAAAAADIaAAAAAAAAAAAAAAAAAAAAAAAAAAAKAACA7wAAAA0AAIDRAAAADwAAgOAAAAAPAACASAAAABUAAIB1bmRpY2kAAGcCAAAPAACAdHNsaWIAAADdAQAADgAAgHkAAAARAACASAEAAB8AAIBdAAAAEwAAgDMBAAAVAACAd3MAAAAAAABwAAAACQAAgNQEAAALAACAGQUAAAwAAIC8AAAAFQAAgKkAAAATAACAdHMtbWl4ZXKKAAAADwAAgPAFAAAUAACAbG9kYXNoAACZAAAAEAAAgEgAAAAVAACAAAAAAAAAAADthVN2SRHYk7ex5VanJbALmmKjxJe8SJHnC/wwI9/ezrUSNI3B5cQWf8xmPwgyCD663Wp+HrRxlUaf3aqiF7v4mPyc4szirQg0kicziknTnKkzdvfUSR4RyFrm5FrOXv5jWrjRTheEkAcESX24jjzLo8uYeZ9q0mmRL1qNJrU9OQlvPMbqUZq7q9ln6m34ix94ttzV2N8iWDJ361iVzm//GciRCd2FsKviDUdO8UeMEsDidj2dOU7Uo3AUx3aHizK1EjSNweXEFgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAoAAAA+AACADgAAAA4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAD8AAAANwAAgAEAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAZwEAADsAAIABAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAKIBAAA7AACAAgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAADrAQAARwAAgAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAMgIAADUAAIAFAAAAGwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAHYCAAA9AACAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAACzAgAAMgAAgAIAAAAGAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAA5QIAAEUAAIABAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAACoDAABMAACAAAAAACUAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAB2AwAAWgAAgAIAAAACAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAA0AMAAEQAAIADAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAABQEAABIAACAAQAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABcBAAALQAAgAgAAAAOAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAoQQAADMAAIAIAAAABQAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAN8EAAA6AACAFAAAAAsAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAlBQAAQQAAgAUAAAAaAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAZgUAAEcAAIAAAAAAAwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAK0FAABDAACAAQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAEBgAAOAAAgAYAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAPAYAAEYAAIADAAAAAQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAIIGAABGAACAAwAAAAkAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAADIBgAANgAAgAQAAAARAAAAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAA/gYAAEgAAIAEAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAEYHAABHAACAAQAAAAUAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAADgAAAA8AAAAJAAAAGAAAAAAAAAAYAAAACQAAACEAAAAAAAAAIQAAAAEAAAAiAAAAAAAAACIAAAAAAAAAIgAAAAAAAAAiAAAAAAAAACIAAAAAAAAAIgAAAAAAAAAiAAAAAAAAACIAAAACAAAAJAAAAAEAAAAlAAAAAQAAACYAAAAAAAAAJgAAAAEAAAAnAAAABwAAAC4AAAAAAAAALgAAAAAAAAAuAAAAAgAAADAAAAAAAAAAMAAAAAAAAAAwAAAAAAAAAAAAAAABAAAAAQAAAA4AAAAPAAAACQAAABgAAAAAAAAAGAAAAAkAAAAhAAAAAAAAACEAAAABAAAAIgAAAAAAAAAiAAAAAAAAACIAAAAAAAAAIgAAAAAAAAAiAAAAAAAAACIAAAAAAAAAIgAAAAAAAAAiAAAAAgAAACQAAAABAAAAJQAAAAEAAAAmAAAAAAAAACYAAAABAAAAJwAAAAcAAAAuAAAAAAAAAC4AAAAAAAAALgAAAAIAAAAwAAAAAAAAADAAAAAAAAAAMAAAAAAAAAAAAP4P/gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgaAAAAAAAAtBoAAAAAAAAKPHNyYy5pbnN0YWxsLmxvY2tmaWxlLlRyZWU+IDIwIHNpemVvZiwgNCBhbGlnbm9mCgAAAAAAAAAA/v////////8AAAAAGAAAAAEAAAANAAAAAAAAABgAAAABAAAAAgAAAA4AAAAAAAAAGQAAAAEAAADgGgAAAAAAAEgbAAAAAAAACjx1MzI+IDQgc2l6ZW9mLCA0IGFsaWdub2YKAAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAACQAAAAhAAAAJwAAACoAAAAYAAAAGgAAABwAAAAlAAAALwAAACAAAAAVAAAAeBsAAAAAAAA4HAAAAAAAAAo8dTMyPiA0IHNpemVvZiwgNCBhbGlnbm9mCgAAAAAAAQAAABkAAAAMAAAADwAAAAoAAAAVAAAAGAAAAAgAAAAGAAAADgAAABMAAAASAAAAAwAAAAQAAAACAAAADQAAAA8AAAALAAAACgAAAAgAAAAOAAAABQAAAAQAAAADAAAADQAAAAwAAAALAAAACgAAAAkAAAAIAAAABgAAAAMAAAAFAAAABwAAAP//////////EAAAABEAAAAKAAAAFgAAAAoAAAAVAAAAFAAAAAgAAAASAAAAAwAAABUAAAAXAAAAaBwAAAAAAABIIQAAAAAAAAo8WzI2XXU4PiAyNiBzaXplb2YsIDEgYWxpZ25vZgoAAAAAAAoAAIDthVN2SRHYkwICbGF0ZXN0AABIAAAAFQAAgLUSNI3B5cQWAgExLjUuMwAAAF0AAAATAACAyFrm5FrOXv4CATMuNS4xAAAAcAAAAAkAAICjy5h5n2rSaQIBOC41LjkAAAB5AAAAEQAAgDSSJzOKSdOcAgEwLjM3LjYxAIoAAAAPAACAGciRCd2FsKsCATMuMS4zAAAAmQAAABAAAICjcBTHdoeLMgIBNC4xLjEAAAB0c2xpYgAAAEaf3aqiF7v4AgEyLjYuMgAAAHVuZGljaQAAf8xmPwgyCD4CATUuMjcuMgAAd3MAAAAAAAAHBEl9uI48ywIBOC4xNC4yAACpAAAAEwAAgHi23NXY3yJYAgFeMS43LjAAALwAAAAVAACAq9ln6m34ix8CAV4wLjMuMwAA0QAAAA8AAICaYqPEl7xIkQIBXjEuMC4yAADgAAAADwAAgOcL/DAj397OAgFeMi4xLjAAAO8AAAANAACAt7HlVqclsAsCAV4xLjAuMgAAMwEAABUAAIBjWrjRTheEkAIBXjEuNS4wAABwAAAACQAAgKPLmHmfatJpAgFeOC41LjkAAEgBAAAfAACAqTN299RJHhECAV4yLjIuMgAAeQAAABEAAIA0kicziknTnAIBMC4zNy42MQB0c2xpYgAAAEaf3aqiF7v4AgFeMi42LjIAAHdzAAAAAAAABwRJfbiOPMsCAV44LjE0LjIASAAAABUAAIC1EjSNweXEFgIBXjIuMC4wAADgAAAADwAAgOcL/DAj397OAgFeMi4xLjAAANEAAAAPAACAmmKjxJe8SJECAV4xLjAuMgAAMwEAABUAAIBjWrjRTheEkAIBXjEuNS4wAABdAAAAEwAAgMha5uRazl7+AgFeMy41LjEAAEgBAAAfAACAqTN299RJHhECAV4yLjIuMgAAeQAAABEAAIA0kicziknTnAIBMC4zNy42MQDdAQAADgAAgJj8nOLM4q0IAgFeMS41LjAAAHRzbGliAAAARp/dqqIXu/gCAV4yLjYuMgAAdW5kaWNpAAB/zGY/CDIIPgIBNS4yNy4yAADRAAAADwAAgJpio8SXvEiRAgFeMS4wLjIAAEgAAAAVAACAtRI0jcHlxBYCAV4yLjAuMAAAZwIAAA8AAIC63Wp+HrRxlQIBXjIuMC4wAACJBAAACgAAgGhzrv/6D6tpFAFeNC4wLjEAAJMEAAAOAACA0DUUVFnc9AcUAT49NS4wLjIA1AQAAAsAAICRL1qNJrU9OQIBKgAAAAAAAAAZBQAADAAAgAlvPMbqUZq7AgF+NS4yNi40AHkAAAARAACANJInM4pJ05wCATAuMzcuNjEA8AUAABQAAIDiDUdO8UeMEgIBXjMuOS4zAAB5AAAAEQAAgDSSJzOKSdOcAgEwLjM3LjYxAIoAAAAPAACAGciRCd2FsKsCAV4zLjEuMwAAdHMtbWl4ZXIyd+tYlc5v/wIBXjYuMC4zAAB0c2xpYgAAAEaf3aqiF7v4AgFeMi42LjIAALwAAAAVAACAq9ln6m34ix8CAV4wLjMuMwAA0QAAAA8AAICaYqPEl7xIkQIBXjEuMC4yAACKAAAADwAAgBnIkQndhbCrAgFeMy4xLjMAAGxvZGFzaAAAwOJ2PZ05TtQCAV40LjE3LjIxkiEAAAAAAACSIQAAAAAAAAo8c3JjLmluc3RhbGwuc2VtdmVyLkV4dGVybmFsU3RyaW5nPiAxNiBzaXplb2YsIDggYWxpZ25vZgrAIQAAAAAAAE0pAAAAAAAACjx1OD4gMSBzaXplb2YsIDEgYWxpZ25vZgoAAAAAZGlzY29yZC5qc2h0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL2Rpc2NvcmQuanMvLS9kaXNjb3JkLmpzLTE0LjE0LjEudGd6QGRpc2NvcmRqcy9jb2xsZWN0aW9uQHNhcHBoaXJlL3Nub3dmbGFrZUB0eXBlcy93c2Rpc2NvcmQtYXBpLXR5cGVzZmFzdC1kZWVwLWVxdWFsbG9kYXNoLnNuYWtlY2FzZUBkaXNjb3JkanMvYnVpbGRlcnNAZGlzY29yZGpzL2Zvcm1hdHRlcnNAZGlzY29yZGpzL3V0aWxAZGlzY29yZGpzL3Jlc3RAZGlzY29yZGpzL3dzaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvQGRpc2NvcmRqcy93cy8tL3dzLTEuMC4yLnRnekBzYXBwaGlyZS9hc3luYy1xdWV1ZUB2bGFkZnJhbmd1L2FzeW5jX2V2ZW50X2VtaXR0ZXJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9AZGlzY29yZGpzL3V0aWwvLS91dGlsLTEuMC4yLnRnemh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL0BkaXNjb3JkanMvcmVzdC8tL3Jlc3QtMi4yLjAudGd6bWFnaWMtYnl0ZXMuanNodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9AZGlzY29yZGpzL2NvbGxlY3Rpb24vLS9jb2xsZWN0aW9uLTIuMC4wLnRnemh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL3VuZGljaS8tL3VuZGljaS01LjI3LjIudGd6QGZhc3RpZnkvYnVzYm95aHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvQGZhc3RpZnkvYnVzYm95Ly0vYnVzYm95LTIuMS4xLnRnemh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL3RzbGliLy0vdHNsaWItMi42LjIudGd6aHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvbWFnaWMtYnl0ZXMuanMvLS9tYWdpYy1ieXRlcy5qcy0xLjEwLjAudGd6aHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvZGlzY29yZC1hcGktdHlwZXMvLS9kaXNjb3JkLWFwaS10eXBlcy0wLjM3LjYxLnRnemh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL0B2bGFkZnJhbmd1L2FzeW5jX2V2ZW50X2VtaXR0ZXIvLS9hc3luY19ldmVudF9lbWl0dGVyLTIuMi40LnRnemh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL0BzYXBwaGlyZS9zbm93Zmxha2UvLS9zbm93Zmxha2UtMy41LjEudGd6aHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvQHNhcHBoaXJlL2FzeW5jLXF1ZXVlLy0vYXN5bmMtcXVldWUtMS41LjIudGd6aHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvd3MvLS93cy04LjE0LjIudGd6YnVmZmVydXRpbHV0Zi04LXZhbGlkYXRlaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvQHR5cGVzL3dzLy0vd3MtOC41LjkudGd6QHR5cGVzL25vZGVodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9AdHlwZXMvbm9kZS8tL25vZGUtMjAuMTEuMjgudGd6dW5kaWNpLXR5cGVzaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvdW5kaWNpLXR5cGVzLy0vdW5kaWNpLXR5cGVzLTUuMjYuNS50Z3podHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9AZGlzY29yZGpzL2Zvcm1hdHRlcnMvLS9mb3JtYXR0ZXJzLTAuMy4zLnRnemh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL0BkaXNjb3JkanMvYnVpbGRlcnMvLS9idWlsZGVycy0xLjcuMC50Z3pAc2FwcGhpcmUvc2hhcGVzaGlmdGh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL3RzLW1peGVyLy0vdHMtbWl4ZXItNi4wLjQudGd6aHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvZmFzdC1kZWVwLWVxdWFsLy0vZmFzdC1kZWVwLWVxdWFsLTMuMS4zLnRnemh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL0BzYXBwaGlyZS9zaGFwZXNoaWZ0Ly0vc2hhcGVzaGlmdC0zLjkuNi50Z3podHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9sb2Rhc2gvLS9sb2Rhc2gtNC4xNy4yMS50Z3podHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9sb2Rhc2guc25ha2VjYXNlLy0vbG9kYXNoLnNuYWtlY2FzZS00LjEuMS50Z3podHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9AZGlzY29yZGpzL2NvbGxlY3Rpb24vLS9jb2xsZWN0aW9uLTEuNS4zLnRnegAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","type":"rawscript","content":"// Importing necessary types and functions from the discord.js library\nimport { Client, GatewayIntentBits, TextChannel } from 'discord.js';\n\n// Defining the resource type as per the instructions\ntype DiscordBotConfiguration = {\n  public_key: string,\n  application_id: string\n};\n\n// The main function that lists all Discord channel names and IDs\nexport async function main(discordBotConfigurationResource: DiscordBotConfiguration) {\n  // Creating a new Discord client with the necessary intents\n  const client = new Client({\n    intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]\n  });\n\n  // Logging in to Discord with the bot token\n  await client.login(discordBotConfigurationResource.public_key);\n\n  // A promise to wait for the client to be ready\n  await new Promise<void>((resolve) => {\n    client.once('ready', () => resolve());\n  });\n\n  // Fetching all guilds (servers) the bot is in\n  const guilds = await client.guilds.fetch();\n\n  // Preparing an array to hold the channel information\n  const channelsInfo: { name: string; id: string }[] = [];\n\n  // Iterating over each guild to get its channels\n  for (const guild of guilds.values()) {\n    const guildDetails = await guild.fetch();\n    const channels = await guildDetails.channels.fetch();\n\n    // Filtering out text channels and adding their names and IDs to the array\n    channels.forEach(channel => {\n      // Fixed: Use instanceof to check if the channel is a TextChannel\n      if (channel instanceof TextChannel) {\n        channelsInfo.push({ name: channel.name, id: channel.id });\n      }\n    });\n  }\n\n  // Logging out the bot client\n  client.destroy();\n\n  // Returning the array of channel names and IDs\n  return channelsInfo;\n}","language":"bun","input_transforms":{"discordBotConfigurationResource":{"expr":"flow_input[\"Discord Bot Configuration\"]","type":"javascript"}}},"summary":"List Discord channel names and IDs","cache_ttl":86400},{"id":"c","value":{"tag":"","lock":"{\n  \"dependencies\": {\n    \"windmill-client\": \"latest\"\n  }\n}\n//bun.lockb\nIyEvdXNyL2Jpbi9lbnYgYnVuCmJ1bi1sb2NrZmlsZS1mb3JtYXQtdjAKAgAAACC3RSpj1ahds/w5TnlRFqiB+1+1bQ3mbcfP/rMFI82oVwQAAAAAAAACAAAAAAAAAAgAAAAAAAAACAAAAAAAAACAAAAAAAAAAHoCAAAAAAAAAAAAAAAAAAAAAAAAAAAPAACAAAAAAAAAAACZDWdj94+o/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA8AAABIAACAAQAAACMBAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAP4P/gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD+D/4BAAABAAAAAAAAAAAAAAAERXdgZSmQIAnvl1IBNzq45w0qpVj4ZLGiR16MG9VCxBVPDcmo6d23Ab22Pv8bgb0ZjD51maUUgL2xG1yah1nB4gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMACAAAAAAAA1AIAAAAAAAAKPHNyYy5pbnN0YWxsLmxvY2tmaWxlLlRyZWU+IDIwIHNpemVvZiwgNCBhbGlnbm9mCgAAAAAAAAAA/v////////8AAAAAAQAAAAADAAAAAAAABAMAAAAAAAAKPHUzMj4gNCBzaXplb2YsIDQgYWxpZ25vZgoAAAAAADADAAAAAAAANAMAAAAAAAAKPHUzMj4gNCBzaXplb2YsIDQgYWxpZ25vZgoAAQAAAGgDAAAAAAAAggMAAAAAAAAKPFsyNl11OD4gMjYgc2l6ZW9mLCAxIGFsaWdub2YKAAAAAAAAAAAADwAAgJkNZ2P3j6j/AgJsYXRlc3QAAMwDAAAAAAAAzAMAAAAAAAAKPHNyYy5pbnN0YWxsLnNlbXZlci5FeHRlcm5hbFN0cmluZz4gMTYgc2l6ZW9mLCA4IGFsaWdub2YK+AMAAAAAAABPBAAAAAAAAAo8dTg+IDEgc2l6ZW9mLCAxIGFsaWdub2YKAAB3aW5kbWlsbC1jbGllbnRodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy93aW5kbWlsbC1jbGllbnQvLS93aW5kbWlsbC1jbGllbnQtMS4yOTEuNC50Z3oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==","type":"rawscript","content":"import * as wmill from \"windmill-client\"\n\nexport async function main(channels: string[]) {\n  const resumeUrls = await wmill.getResumeUrls(\"approver1\")\n\n  // Sort the channels array in alphabetical order\n  const sortedChannels = channels.sort();\n\n  return {\n    resume: resumeUrls['resume'],\n    enums: {\n      Channels: sortedChannels\n    }\n  }\n}","language":"bun","input_transforms":{"channels":{"expr":"results.b.map(item => item.name);","type":"javascript"}}},"summary":"Approval","suspend":{"timeout":1800,"resume_form":{"schema":{"type":"object","order":["Channels"],"$schema":"https://json-schema.org/draft/2020-12/schema","required":[],"properties":{"Channels":{"type":"array","items":{"type":"string"},"default":[],"description":"Which channels to send message to"}}}},"required_events":1}},{"id":"d","value":{"tag":"","lock":"","type":"rawscript","content":"from typing import List, TypedDict\n\n# Define the input structure for channels_and_ids\nclass ChannelInfo(TypedDict):\n    id: str\n    name: str  # Note: This field might be optional in the actual data\n\n\ndef main(\n    channels_and_ids: List[ChannelInfo], selected_channels: List[str]\n) -> List[str]:\n    # Create a dictionary to map channel names to their IDs for quick lookup\n    channel_name_to_id = {\n        channel[\"name\"]: channel[\"id\"]\n        for channel in channels_and_ids\n        if \"name\" in channel\n    }\n\n    # Filter the IDs of the selected channels\n    selected_ids = [\n        channel_name_to_id[name]\n        for name in selected_channels\n        if name in channel_name_to_id\n    ]\n\n    return selected_ids\n","language":"python3","input_transforms":{"channels_and_ids":{"expr":"results.b","type":"javascript"},"selected_channels":{"expr":"resume[\"Channels\"]","type":"javascript"}}},"summary":"Map channel names to IDs filter selected"},{"id":"e","value":{"type":"forloopflow","modules":[{"id":"f","value":{"tag":"","lock":"{\n  \"dependencies\": {}\n}\n//bun.lockb\n<empty>","type":"rawscript","content":"type DiscordBotConfiguration = {\n  public_key: string,\n  application_id: string\n};\n\n/**\n * Creates a thread in Discord and sends a series of messages to it using the Discord bot configuration.\n * The series starts with a firstMessage, followed by the messages array, and ends with a lastMessage.\n * Before attempting to create the thread, it validates that all messages (including first and last) are within the character limit.\n * If any message exceeds the limit, it throws an error without creating the thread.\n * @param discordBotConfigResource Contains the Discord bot configuration necessary for API requests.\n * @param channelId The ID of the Discord channel where the thread will be created.\n * @param threadName The name of the thread to be created. Must be 100 characters or less.\n * @param firstMessage The first message to be sent to the thread. Must be 2000 characters or less.\n * @param messages An array of messages to be sent to the thread after the firstMessage and before the lastMessage. Each message must be 2000 characters or less.\n * @param lastMessage The last message to be sent to the thread. Must be 2000 characters or less.\n * @returns An object indicating the success status of thread creation and each message sent.\n * @throws Error if the thread creation or any message sending fails, or if input validations fail.\n */\nexport async function main(\n  discordBotConfigResource: DiscordBotConfiguration,\n  channelId: string,\n  messages: string[],\n  threadName: string,\n  firstMessage: string,\n  lastMessage: string\n): Promise<{ thread: boolean; messages: boolean[] }> {\n  // First, validate threadName length\n  if (threadName.length > 100) {\n    throw new Error(\"Thread name must be 100 characters or less.\");\n  }\n\n  // Validate firstMessage and lastMessage length\n  if (firstMessage.length > 2000) {\n    throw new Error(\"First message must be 2000 characters or less.\");\n  }\n  if (lastMessage.length > 2000) {\n    throw new Error(\"Last message must be 2000 characters or less.\");\n  }\n\n  // Next, validate each message length in the array. This ensures all messages are checked before any API request is made.\n  for (const message of messages) {\n    if (message.length > 2000) {\n      throw new Error(\"Each message must be 2000 characters or less.\");\n    }\n  }\n\n  // Initialize the result object\n  const result = {\n    thread: false,\n    messages: []\n  };\n\n  // Construct the URL for creating a thread\n  const createThreadUrl = `https://discord.com/api/v9/channels/${channelId}/threads`;\n\n  // Prepare the request body for creating a thread\n  const createThreadBody = JSON.stringify({\n    name: threadName,\n    auto_archive_duration: 60, // Automatically archive the thread after 60 minutes of inactivity\n    type: 11 // Type 11 represents a private thread\n  });\n\n  // Prepare the request headers\n  const headers = {\n    'Content-Type': 'application/json',\n    'Authorization': `Bot ${discordBotConfigResource.public_key}`\n  };\n\n  // Attempt to create the thread by sending a POST request\n  const createThreadResponse = await fetch(createThreadUrl, {\n    method: 'POST',\n    headers: headers,\n    body: createThreadBody\n  });\n\n  if (!createThreadResponse.ok) {\n    throw new Error(\"Failed to create thread\");\n  }\n\n  // Parse the response to get the thread ID\n  const threadInfo = await createThreadResponse.json();\n  const threadId = threadInfo.id;\n  result.thread = true; // Mark thread creation as successful\n\n  // Function to send a message to the created thread\nconst sendMessage = async (message: string) => {\n  // Construct the URL for sending a message to the thread\n  const sendMessageUrl = `https://discord.com/api/v9/channels/${threadId}/messages`;\n\n  // Prepare the request body for sending a message\n  const messageBody = JSON.stringify({\n    content: message\n  });\n\n  // Attempt to send the message by sending a POST request\n  const sendMessageResponse = await fetch(sendMessageUrl, {\n    method: 'POST',\n    headers: headers,\n    body: messageBody\n  });\n\n  // Check for rate limit response before checking if response is OK\n  if (sendMessageResponse.status === 429) { // 429 is the HTTP status code for Too Many Requests\n      const retryAfter = parseInt(sendMessageResponse.headers.get('Retry-After'), 10);\n      console.log(`Rate limit hit, retrying after ${retryAfter} seconds.`);\n      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000)); // Wait for the duration specified by Retry-After\n      return sendMessage(message); // Attempt to resend the message\n  }\n\n  if (!sendMessageResponse.ok) {\n    throw new Error(`Failed to send message: ${message}`);\n  }\n\n  // Record the success status of sending each message\n  result.messages.push(true);\n};\n\n  // Send the first message\n  await sendMessage(firstMessage);\n\n  // Send messages in the array\n  for (const message of messages) {\n    await sendMessage(message);\n  }\n\n  // Send the last message\n  await sendMessage(lastMessage);\n\n  return result;\n}","language":"bun","input_transforms":{"messages":{"expr":"results.a","type":"javascript"},"channelId":{"expr":"flow_input.iter.value","type":"javascript"},"threadName":{"expr":"flow_input[\"Thread name\"]","type":"javascript"},"lastMessage":{"expr":"flow_input[\"Last message\"]","type":"javascript"},"firstMessage":{"expr":"flow_input[\"First message\"]","type":"javascript"},"discordBotConfigResource":{"expr":"flow_input[\"Discord Bot Configuration\"]","type":"javascript"}}},"summary":"Create and send messages in Discord thread"}],"iterator":{"expr":"results.d","type":"javascript"},"parallel":false,"skip_failures":true}}]},"schema":{"type":"object","order":["Discord Bot Configuration","Thread name","First message","Core content","Last message"],"$schema":"https://json-schema.org/draft/2020-12/schema","required":["Discord Bot Configuration","Thread name","First message","Last message","Core content"],"properties":{"Thread name":{"type":"string","format":"","default":null,"description":""},"Core content":{"type":"string","format":"","default":"","description":"Core content that will be split as thread messages by step a"},"Last message":{"type":"string","format":"","default":null,"description":""},"First message":{"type":"string","format":"","default":null,"description":""},"Discord Bot Configuration":{"type":"object","format":"resource-discord_bot_configuration","default":"$res:u/henri/windmill_bot","required":[],"properties":{},"description":"Scopes: 'bot'\nPermissions: 'View Channels' , 'Send Messages' , 'Create Private Threads'"}}},"description":"This flow uses a Discord bot to list all channels and send a thread to the channels selected with an approval step.","recording":null,"vcreated_at":"2024-03-18T13:42:07.482Z","vcreated_by":"henri186","comments":[]}}