{"id":15714459,"url":"https://github.com/ubos-tech/node-red-contrib-slack-ubos","last_synced_at":"2026-02-03T19:03:07.800Z","repository":{"id":191408379,"uuid":"684603811","full_name":"UBOS-tech/node-red-contrib-slack-ubos","owner":"UBOS-tech","description":null,"archived":false,"fork":false,"pushed_at":"2024-07-25T12:46:29.000Z","size":29,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-31T16:47:02.806Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UBOS-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-29T13:31:01.000Z","updated_at":"2025-01-10T15:12:12.000Z","dependencies_parsed_at":"2024-10-24T11:59:05.384Z","dependency_job_id":"03fa5a98-8e81-40d8-b177-f90a9f9c3db7","html_url":"https://github.com/UBOS-tech/node-red-contrib-slack-ubos","commit_stats":null,"previous_names":["ubos-tech/node-red-contrib-slack-ubos"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/UBOS-tech/node-red-contrib-slack-ubos","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UBOS-tech%2Fnode-red-contrib-slack-ubos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UBOS-tech%2Fnode-red-contrib-slack-ubos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UBOS-tech%2Fnode-red-contrib-slack-ubos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UBOS-tech%2Fnode-red-contrib-slack-ubos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UBOS-tech","download_url":"https://codeload.github.com/UBOS-tech/node-red-contrib-slack-ubos/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UBOS-tech%2Fnode-red-contrib-slack-ubos/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261733895,"owners_count":23201747,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T21:37:16.856Z","updated_at":"2026-02-03T19:03:02.744Z","avatar_url":"https://github.com/UBOS-tech.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Node-RED Slack Integration with Global Credentials\n\nThis  version of the [node-red-contrib-slack](https://flows.nodered.org/node/node-red-contrib-slack) palette adds the ability to retrieve Slack credentials from global settings. \n\n# node-red-contrib-slack\n\nA \u003ca href=\"http://nodered.org\" target=\"_new\"\u003eNode-RED\u003c/a\u003e node to interact with\nthe \u003ca href=\"https://slack.com/\" target=\"_new\"\u003eSlack\u003c/a\u003e\n\u003ca href=\"https://api.slack.com/\" target=\"_new\"\u003eAPI\u003c/a\u003e.\n\n# Install\n\nRun the following command in the root directory of your Node-RED install:\n\n```\nnpm install --save node-red-contrib-slack\n```\n\nVersion `2.x` of this package is **NOT** compatible with older versions. Plese\nrefer to the [migration](#migration-from-012-or-earlier) section for help.\n\n# Usage\n\nThe nodes included in this package are **purposely** generic in nature. The\nusage very closely mimics the\n\u003ca href=\"https://api.slack.com/\" target=\"_new\"\u003eSlack API\u003c/a\u003e. Your best source\nof reference for input/output specifics will be from:\n\n- https://api.slack.com\n- https://api.slack.com/rtm\n- https://api.slack.com/web\n- https://api.slack.com/methods\n\n4 nodes are provided:\n\n- [`slack-rtm-in`](#slack-rtm-in)\n- [`slack-rtm-out`](#slack-rtm-out)\n- [`slack-web-out`](#slack-web-out)\n- [`slack-state`](#slack-state)\n\nThe `rtm` API/node(s) are connected to slack via web sockets and are useful for\nreceiving a real-time stream of events/data.\n\nThe `web` API/node(s) are useful for making traditional web service calls and\nhave a much broader use-case.\n\nCombining both `rtm` and `web` APIs provides a full solution to interact with\nthe \u003ca href=\"https://api.slack.com/\" target=\"_new\"\u003eSlack API\u003c/a\u003e in it's\nentirety facilitating powerful flows in `Node-RED`. Which nodes are\nappropriate to use for any given use-case can be subjective so familiarizing\nyouself with the documentation links above is **extremely** beneficial.\n\n## invoking methods\n\nTo invoke methods ([`slack-rtm-out`](#slack-rtm-out),\n[`slack-web-out`](#slack-web-out)) set the `msg.topic` to the name of the\nmethod and set the `msg.payload` to the args/params.\n\nThe `token` property is **NOT** required to be set in any `msg.payload`.\n\nAs an example of invoking the\n\u003ca href=\"https://api.slack.com/methods/chat.meMessage\"\u003e`chat.meMessage`\u003c/a\u003e\nmethod with the [`slack-web-out`](#slack-web-out) node you would do the\nfollowing:\n\n```\nmsg.topic = \"chat.meMessage\";\nmsg.payload = {\n    channel: \"...\",\n    text: \"...\"\n}\n\nreturn msg;\n```\n\n## `dressed` output\n\nThe following nodes each provide\n\u003ca href=\"https://api.slack.com/\" target=\"_new\"\u003eSlack API\u003c/a\u003e output:\n\n- [`slack-rtm-in`](#slack-rtm-in) - view details of each event in the\n  \u003ca href=\"https://api.slack.com/rtm\" target=\"_new\"\u003edocumentation\u003c/a\u003e\n- [`slack-rtm-out`](#slack-rtm-out) - view details of each event in the\n  \u003ca href=\"https://api.slack.com/rtm\" target=\"_new\"\u003edocumentation\u003c/a\u003e\n- [`slack-web-out`](#slack-web-out) - view `response` section of each method in\n  the \u003ca href=\"https://api.slack.com/methods\" target=\"_new\"\u003edocumentation\u003c/a\u003e\n\nThe respective events/responses are generally left unaltered and are directly\npassed through as `msg.payload`. However, before outputting the `msg` the data\nis traversed to enrich the `msg.payload` (examples provided below) with\ncomplete object data where otherwise only internal Slack IDs are present.\n\nAll of the lookups are done dynamically/generically so regardless of what API\nresponse you get if the node finds an attribute that appears to be a\nsupported object (`user`/`channel`/`team`/`bot`) in some shape or form, a\ncorresponding `\u003cattribute\u003eObject` attribute with the lookup value will be\nadded.\n\nFor example, if the response contains a `bot_id` attribute you would see\n`bot_idObject` added, or if it found an attribute called `bot` it would add\n`botObject` etc. Ultimately all the lookups come from\n[`slackState`](#slackstate) (see below) so it could be done on your own but\nit's added to simplify and for convenience.\n\nAn example\n\u003ca href=\"https://api.slack.com/events/user_typing\" target=\"_new\"\u003e`user_typing`\u003c/a\u003e\nevent from the [`slack-rtm-in`](#slack-rtm-in) node:\n\n```\n{\n  \"type\": \"user_typing\",\n  \"channel\": \"...\",\n  \"user\": \"...\"\n}\n```\n\nis `dressed` to be sent as:\n\n```\n{\n  \"type\": \"user_typing\",\n  \"channel\": \"...\",\n  \"user\": \"...\",\n  \"channelObject\": {\n    \"id\": \"...\",\n    \"name\": \"...\",\n    \"is_channel\": true,\n    \"is_group\": false,\n    \"is_im\": false,\n    \"created\": 1434735155,\n    ...\n  },\n  \"userObject\": {\n    \"id\": \"...\",\n    \"name\": \"...\",\n    \"real_name\": \"...\",\n    ...\n  }\n}\n```\n\n## Helpers\n\nAs a convenience for both the [`slack-web-out`](#slack-web-out) and\n[`slack-rtm-out`](#slack-rtm-out) nodes a special interface is supported that\nallows you to send a message with a simplified structure (`msg.topic` starts\nwith `@` or `#`):\n\n```\nmsg.topic = \"@some_user\";\n# or\nmsg.topic = \"#some_channel\";\n\nmsg.payload = \"a special message just for you\"\n\nreturn msg\n```\n\nAs an additional convenience, if you are invoking the\n\u003ca href=\"https://api.slack.com/methods/chat.meMessage\" target=\"_new\"\u003e`chat.meMessage`\u003c/a\u003e,\n\u003ca href=\"https://api.slack.com/methods/chat.postEphemeral\" target=\"_new\"\u003e`chat.postEphemeral`\u003c/a\u003e,\n\u003ca href=\"https://api.slack.com/methods/chat.postMessage\" target=\"_new\"\u003e`chat.postMessage`\u003c/a\u003e\nmethods ([`slack-web-out`](#slack-web-out)), or\n\u003ca href=\"https://api.slack.com/rtm\"\u003e`message`\u003c/a\u003e method\n([`slack-rtm-out`](#slack-rtm-out)) and the `channel` starts with `@` or `#`\nthe node will automatically lookup the appropriate `channel.id` from\n[`slackState`](#slackstate) (see below) and set it for you.\n\n## `slackState`\n\nAll outputs for all nodes include a `msg.slackState` object which has several\nproperties containing the lists of `members`/`channels`/`bots`/`team`/etc so\ndownstream nodes can do 'lookups' without re-hitting the API (this data is\ncurrently refreshed in the background every 10 minutes). Additionally the\ninternal state is connected to all relevant slack events and updates are\nreflected real-time in any new messages (ie: a user getting created\nautomatically updates the `slackState` even before the 10 minute refresh).\n\n## nodes\n\n### `slack-rtm-in`\n\nThe [`slack-rtm-in`](#slack-rtm-in) node listens to\n\u003ca href=\"https://api.slack.com/rtm\" target=\"_new\"\u003eSlack RTM\u003c/a\u003e events and\noutputs the [`dressed`](#dressed-output) response as the `msg.payload`.\n\nBy default the node will listen to \u003cb\u003eALL\u003c/b\u003e events. You can however filter\nevent types by setting the node \u003cem\u003eSlack Events\u003c/em\u003e property to a value\ntaking the form of `type[::subtype][,type[::subtype],...]`. For example\n`message` to receive only events of type `message` or `message::bot_message` to\nreceive only events of type `message` which additionally have a `subtype` of\n`bot_message`.\n\nExample output:\n\n```\n{\n  \"payload\" {\n    \"type\": \"user_typing\",\n    \"channel\": \"...\",\n    \"user\": \"...\",\n    \"channelObject\": {\n        \"id\": \"...\",\n        \"name\": \"...\",\n        \"is_channel\": true,\n        \"is_group\": false,\n        \"is_im\": false,\n        \"created\": 1434735155,\n        ...\n    },\n    \"userObject\": {\n        \"id\": \"...\",\n        \"name\": \"...\",\n        \"real_name\": \"...\",\n        ...\n    }\n  },\n  \"slackState\": {\n    ...\n  }\n}\n```\n\n### `slack-rtm-out`\n\nInvokes a \u003ca href=\"https://api.slack.com/rtm\" target=\"_new\"\u003eSlack RTM\u003c/a\u003e\nmethod and outputs the [`dressed`](#dressed-output) response as the\n`msg.payload`.\n\nAvailable methods:\n\n- `message`: send a message\n- `ping`: pong\n- \u003ca href=\"https://api.slack.com/events/presence_sub\" target=\"_new\"\u003e`presence_sub`\u003c/a\u003e:\n  to subscribe to\n  \u003ca href=\"https://api.slack.com/events/presence_change\" target=\"_new\"\u003e`presence_change`\u003c/a\u003e\n  events\n- \u003ca href=\"https://api.slack.com/events/presence_query\" target=\"_new\"\u003e`presence_query`\u003c/a\u003e:\n  to request a one-time\n  \u003ca href=\"https://api.slack.com/events/presence_change\" target=\"_new\"\u003e`presence_change`\u003c/a\u003e\n  status\n- `typing`: to send typing indicators\n\nUsing [`slack-rtm-out`](#slack-rtm-out) for sending messages should only be\nused for very basic messages, preference would be to use the\n\u003ca href=\"https://api.slack.com/methods/chat.postMessage\" target=\"_new\"\u003e`chat.postMessage`\u003c/a\u003e,\nmethod of the [`slack-web-out`](#slack-web-out) node for anything beyond the\nsimplest messaging use-case as it supports\n\u003ca href=\"https://api.slack.com/docs/attachments\" target=\"_new\"\u003e`attachments`\u003c/a\u003e\nas well as many other features.\n\n\u003ca href=\"https://api.slack.com/events/presence_sub\" target=\"_new\"\u003e`presence_sub`\u003c/a\u003e\nis a powerful [`slack-rtm-out`](#slack-rtm-out) method that allows you to\nreceive\n\u003ca href=\"https://api.slack.com/events/presence_change\" target=\"_new\"\u003e`presence_change`\u003c/a\u003e\nevents on the [`slack-rtm-in`](#slack-rtm-in) node. See the\n[presence](#presence) example below for further details.\n\nExample input:\n\n```\nmsg.topic = 'presence_query';\nmsg.payload = {\n    ids: [\n        '...'\n    ]\n}\nreturn msg;\n```\n\nExample output:\n\n```\n{\n  \"topic\": \"presence_query\",\n  \"payload\": {\n    \"ok\":true,\n    \"type\":\"presence_query\"\n  },\n  \"slackState\": {\n    ...\n  }\n}\n```\n\n### `slack-web-out`\n\nInvokes a \u003ca href=\"https://api.slack.com/methods\" target=\"_new\"\u003eSlack Web\u003c/a\u003e\nmethod and outputs the [`dressed`](#dressed-output) response as the\n`msg.payload`.\n\nSee the [sending a message](#sending-a-message) example for advanced message\nsending.\n\nExample input:\n\n```\nmsg.topic = \"chat.meMessage\";\nmsg.payload = {\n    channel: \"...\",\n    text: \"...\"\n}\n\nreturn msg;\n```\n\nExample output:\n\n```\n{\n  \"topic\": \"chat.meMessage\",\n  \"payload\": {\n    \"channel\": \"...\",\n    \"ts\": \"1552705036.049000\",\n    \"ok\": true,\n    \"scopes\": [\n      \"identify\",\n      \"read\",\n      \"post\",\n      \"client\",\n      \"apps\"\n    ],\n    \"acceptedScopes\": [\n      \"chat:write:user\",\n      \"post\"\n    ],\n    \"channelObject\": {\n      \"id\": \"...\",\n      ...\n      \"userObject\": {\n        \"id\": \"...\",\n        ...\n      }\n    }\n  },\n  \"slackState\": {\n    ...\n  }\n}\n```\n\n### `slack-state`\n\n[`slack-state`](#slack-state) outputs a message with\n[`msg.slackState`](#slackstate) added. If the `msg.payload` sent to\n[`slack-state`](#slack-state) is `true` then it will first do a full refresh of\nthe state (should not generally be necessary) and then output the `msg`.\n\nThe `state events` (2nd) output of the node emits a signal when the state has\nbeen fully initialized after (re)connect. This can be useful if you want to\nperform any post initilization tasks (ie:\n\u003ca href=\"https://api.slack.com/events/presence_sub\" target=\"_new\"\u003e`presence_sub`\u003c/a\u003e\n).\n\nExample input:\n\n```\nmsg.payload = true; // force a refresh\nreturn msg;\n```\n\nExample output (state):\n\n```\n{\n  \"slackState\": {\n    ...\n  }\n}\n```\n\nExample output (state events):\n\n```\n{\n  \"payload\": {\n    \"type\":\"ready\"\n  },\n  \"slackState\": {\n    ...\n  }\n}\n```\n\n# Examples / Advanced\n\n## sending a message\n\nWhile you can send messages using the simplified syntax (`msg.topic` starts\nwith `@` or `#` and `msg.payload` is the message) using either the\n[`slack-web-out`](#slack-web-out) or the [`slack-rtm-out`](#slack-rtm-out)\nnodes, your use-case may require more control. The most advanced message\nsending can be accomplished by invoking the\n\u003ca href=\"https://api.slack.com/methods/chat.postMessage\" target=\"_new\"\u003e`chat.postMessage`\u003c/a\u003e\nmethod of the [`slack-web-out`](#slack-web-out) node:\n\n```\nvar topic = \"chat.postMessage\";\n\nvar payload = {\n    // channel: \"@someuser\",\n    // or\n    // channel: \"#somechannel\",\n    text: \"hi from bot\",\n    ...\n    // review linked documentation for all options\n}\n\nmsg = {\n  topic: topic,\n  payload: payload\n}\n\nreturn msg;\n```\n\n## respond to keyword\n\nA simple respond to `keyword` example `function` node to place between a\n[`slack-rtm-in`](#slack-rtm-in) node and a [`slack-web-out`](#slack-web-out)\nnode:\n\n```\n// ignore anything but messages\nif (msg.payload.type != \"message\") {\n    return null;\n}\n\n// ignore deleted messages\nif (msg.payload.subtype == \"message_deleted\") {\n    return null;\n}\n\n// ignore messages from bots\nif (msg.payload.bot_id || (msg.payload.userObject \u0026\u0026 msg.payload.userObject.is_bot)) {\n    return null;\n}\n\n// if you only want to watch a specific channel put name here\nvar channel = \"\";\nif (channel \u0026\u0026 !msg.payload.channelObject) {\n    return null;\n}\n\nif (channel \u0026\u0026 msg.payload.channelObject.name != channel.replace(/^@/, \"\").replace(/^#/, \"\")) {\n    return null;\n}\n\n// only specific users\nvar username = \"\";\nif (username \u0026\u0026 !msq.payload.userObject) {\n    return null;\n}\n\nif (username \u0026\u0026 msq.payload.userObject.name.replace(/^@/, \"\") != username)) {\n    return null;\n}\n\n// check for keyword\n// could use regex etc\nif (!msg.payload.text.includes(\"keyword\")) {\n    return null;\n}\n\n// prepare outbound response\nvar topic = \"chat.postMessage\";\nvar payload = {\n    channel: msg.payload.channel, // respond to same channel\n    //text: '\u003c@' + msg.payload.userObject.name + '\u003e, thanks for chatting',\n    text: '\u003c@' + msg.payload.user + '\u003e, thanks for chatting',\n    //as_user: false,\n    //username: \"\",\n    //attachments: [],\n    //icon_emoji: \"\",\n}\n\nmsg = {\n    topic: topic,\n    payload: payload\n}\n\nreturn msg;\n```\n\n## presence\n\nWhile [`slackState`](#slackstate) does not automatically subscribe to\n\u003ca href=\"https://api.slack.com/events/presence_change\" target=\"_new\"\u003e`presence_change`\u003c/a\u003e\nevents for you, it will keep track of `presence` details in\n[`slackState`](#slackstate) if any\n\u003ca href=\"https://api.slack.com/events/presence_change\" target=\"_new\"\u003e`presence_change`\u003c/a\u003e\nevents are received (this is all done behind the scenes).\n\nTo subscribe to\n\u003ca href=\"https://api.slack.com/events/presence_change\" target=\"_new\"\u003e`presence_change`\u003c/a\u003e\nevents for all your users place the following `function` node between the\n`slack events` output of the [`slack-state`](#slack-state) node and the\n[`slack-rtm-out`](#slack-rtm-out) node:\n\n```\nmsg.topic = 'presence_sub';\nvar ids = [];\n\nfor (var id in msg.slackState.members) {\n  if (msg.slackState.members.hasOwnProperty(id)) {\n    ids.push(id)\n  }\n}\n\nmsg.payload = {\n    ids: ids\n}\nreturn msg;\n```\n\nThe theory of operation is:\n\n1.  wait for the [`slackState`](#slackstate) to be initialized so you have a\n    complete list of `members`\n1.  iterate that list to build up the appropriate request to\n    [`slack-rtm-out`](#slack-rtm-out)\n1.  subscribe to presence events by sending the message to\n    [`slack-rtm-out`](#slack-rtm-out)\n1.  receive presence events on the [`slack-rtm-in`](#slack-rtm-in) node\n\nImmediately after the request is sent you will see a flood of\n\u003ca href=\"https://api.slack.com/events/presence_change\" target=\"_new\"\u003e`presence_change`\u003c/a\u003e\nevents emitted on the [`slack-rtm-in`](#slack-rtm-in) node. Once the initial\nflood of messages has passed continued updates will come through as\nappropriate. Again, behind the scenes the [`slack-state`](#slack-state) nodes\nare listening for these events and updating the\n[`slackState.presence`](#slackstate) values appropriately for general\nusage/consumption in your flow(s).\n\nIf you are really interested in keeping the data updated you could capture\n`team_join` events from a [`slack-rtm-in`](#slack-rtm-in) node and wire those\nto the above `function` node as well triggering the same procedure when new\nusers join the `team`. You may need to put a `delay` node before the\n`function` node just to give [`slackState`](#slackstate) enough time to process\nthis same event and update.\n\nAn alternative would be to wire an `inject` node to the `function` node and put\nit on a sane `interval` such as every 10 minutes.\n\nIf you wanted to be **really** sure you are receiving all\n\u003ca href=\"https://api.slack.com/events/presence_change\" target=\"_new\"\u003e`presence_change`\u003c/a\u003e\nevents for the whole `team` do all the above.\n\n# migration from `0.1.2` or earlier\n\nIn order to replicate the previous behavior it is possible to introduce simple\n`function` nodes.\n\nRoughly speaking the node equivalents are:\n\n| `0.1.2`                           | `2.x`                             |\n| --------------------------------- | --------------------------------- |\n| [`slack`](#slack)                 | [`slack-web-out`](#slack-web-out) |\n| [`Slack Bot In`](#slack-bot-in)   | [`slack-rtm-in`](#slack-rtm-in)   |\n| [`Slack Bot Out`](#slack-bot-out) | [`slack-rtm-out`](#slack-rtm-out) |\n\n## `slack`\n\nTo replicate the `slack` node simply place the following `function` node just\nbefore the new [`slack-web-out`](#slack-web-out) node:\n\n```\n// https://api.slack.com/methods/chat.postMessage\nmsg.topic = \"chat.postMessage\"\nvar payload = {\n    text: msg.payload\n};\n\n// set default username (replicate the node configuration value)\nvar username = \"\";\nif (username) {\n    payload.username = username;\n    payload.as_user = false;\n} else if (msg.username) {\n    payload.username = msg.username;\n    payload.as_user = false;\n}\n\n// set default emojiIcon (replicate the node configuration value)\nvar emojiIcon = \"\";\nif (emojiIcon) {\n    payload.icon_emoji = emojiIcon;\n} else if (msg.emojiIcon) {\n    payload.icon_emoji = msg.emojiIcon;\n}\n\n// set default channel (replicate the node configuration value)\nvar channel = \"\";\nif (channel) {\n    payload.channel = channel;\n} else if (msg.channel) {\n    payload.channel = msg.channel\n}\n\nif (msg.attachments) {\n    payload.attachments = msg.attachments;\n}\n\nmsg.payload = payload;\n\nreturn msg;\n```\n\n## `Slack Bot In`\n\nTo replicate the `Slack Bot In` node simply place the following `function` node\ndownstream from the new [`slack-rtm-in`](#slack-rtm-in) node:\n\n```\n// https://api.slack.com/events/message\n\nif (msg.payload.type != \"message\") {\n    return null;\n}\n\n// if you only want to watch a specific channel put name here\nvar channel = \"\";\nif (channel \u0026\u0026 !msg.payload.channelObject) {\n    return null;\n}\n\nif (channel \u0026\u0026 msg.payload.channelObject.name != channel.replace(/^@/, \"\").replace(/^#/, \"\")) {\n    return null;\n}\n\nvar payload = \"\";\nif (msg.payload.text) {\n    payload += msg.payload.text;\n}\n\nif (msg.payload.attachments) {\n    if (payload) {\n        payload += \"\\n\";\n    }\n\n    msg.payload.attachments.forEach((attachment, index) =\u003e {\n        if (index \u003e 0) {\n            payload += \"\\n\";\n        }\n        payload += attachment.fallback;\n    })\n}\n\nvar slackObj = {\n    id: msg.payload.client_msg_id,\n    type: msg.payload.type,\n    text: msg.payload.text,\n    channelName: msg.payload.channelObject.name,\n    channel: msg.payload.channelObject,\n    fromUser: (msg.payload.userObject) ? msg.payload.userObject.name : \"\",\n    attachments: msg.payload.attachments\n};\n\nmsg = {\n    payload: payload,\n    slackObj: slackObj\n}\n\nreturn msg;\n```\n\n## `Slack Bot Out`\n\nTo replicate the `Slack Bot Out` node simply place the following `function`\nnode just before the new [`slack-rtm-out`](#slack-rtm-out) node:\n\n```\n// set channel\nvar channel = \"\";\nif (channel) {\n    // do nothing, use the provided channel\n} else if (msg.channel) {\n    channel = msg.channel;\n} else if (msg.slackObj \u0026\u0026 msg.slackObj.channel) {\n    channel = msg.slackObj.channel\n} else {\n    node.error(\"'slackChannel' is not defined, check you are specifying a channel in the message (msg.channel) or the node config.\");\n    node.error(\"Message: '\" + JSON.stringify(msg));\n    return null;\n}\n\nmsg = {\n    topic: channel,\n    payload: msg.payload\n}\n\nreturn msg;\n```\n\n# Additional Resources\n\n- \u003ca href=\"http://emoji-cheat-sheet.com\" target=\"_new\"\u003eEmoji Cheat Sheet\u003c/a\u003e\n- \u003ca href=\"https://api.slack.com/docs/attachments\" target=\"_new\"\u003eSlack Attachments\u003c/a\u003e\n- https://slack.dev/node-slack-sdk/\n- https://slack.dev/node-slack-sdk/rtm_api\n- https://slack.dev/node-slack-sdk/web_api\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fubos-tech%2Fnode-red-contrib-slack-ubos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fubos-tech%2Fnode-red-contrib-slack-ubos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fubos-tech%2Fnode-red-contrib-slack-ubos/lists"}