@hubot-friends/hubot-slack 0.0.0-development

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/.github/CODE_OF_CONDUCT.md +11 -0
  2. package/.github/contributing.md +60 -0
  3. package/.github/issue_template.md +48 -0
  4. package/.github/maintainers_guide.md +91 -0
  5. package/.github/pull_request_template.md +8 -0
  6. package/.github/workflows/ci-build.yml +74 -0
  7. package/LICENSE +22 -0
  8. package/README.md +29 -0
  9. package/docs/Gemfile +2 -0
  10. package/docs/README.md +15 -0
  11. package/docs/_config.yml +29 -0
  12. package/docs/_includes/analytics.html +7 -0
  13. package/docs/_includes/head.html +33 -0
  14. package/docs/_includes/page_header.html +20 -0
  15. package/docs/_includes/side_nav.html +22 -0
  16. package/docs/_includes/tag_manager.html +13 -0
  17. package/docs/_layouts/changelog.html +15 -0
  18. package/docs/_layouts/default.html +47 -0
  19. package/docs/_layouts/page.html +10 -0
  20. package/docs/_pages/FAQ.md +63 -0
  21. package/docs/_pages/about.md +16 -0
  22. package/docs/_pages/advanced_usage.md +102 -0
  23. package/docs/_pages/auth.md +44 -0
  24. package/docs/_pages/basic_usage.md +302 -0
  25. package/docs/_pages/changelog.html +17 -0
  26. package/docs/_pages/upgrading.md +49 -0
  27. package/docs/_posts/2016-07-15-v4.0.0.md +14 -0
  28. package/docs/_posts/2016-07-19-v4.0.1.md +5 -0
  29. package/docs/_posts/2016-08-03-v4.0.2.md +4 -0
  30. package/docs/_posts/2016-09-12-v4.0.3.md +8 -0
  31. package/docs/_posts/2016-09-12-v4.0.4.md +4 -0
  32. package/docs/_posts/2016-09-14-v4.0.5.md +4 -0
  33. package/docs/_posts/2016-09-21-v4.1.0.md +4 -0
  34. package/docs/_posts/2016-10-12-v4.2.0.md +4 -0
  35. package/docs/_posts/2016-10-12-v4.2.1.md +4 -0
  36. package/docs/_posts/2016-11-05-v4.2.2.md +8 -0
  37. package/docs/_posts/2017-01-05-v4.3.0.md +5 -0
  38. package/docs/_posts/2017-01-09-v4.3.1.md +5 -0
  39. package/docs/_posts/2017-02-15-v4.3.2.md +5 -0
  40. package/docs/_posts/2017-02-17-v4.3.3.md +4 -0
  41. package/docs/_posts/2017-03-29-v4.3.4.md +5 -0
  42. package/docs/_posts/2017-08-24-v4.4.0.md +7 -0
  43. package/docs/_posts/2018-06-08-v4.5.0.md +13 -0
  44. package/docs/_posts/2018-06-14-v4.5.1.md +4 -0
  45. package/docs/_posts/2018-07-03-v4.5.2.md +5 -0
  46. package/docs/_posts/2018-07-17-v4.5.3.md +12 -0
  47. package/docs/_posts/2018-08-10-v4.5.4.md +7 -0
  48. package/docs/_posts/2018-10-01-v4.5.5.md +7 -0
  49. package/docs/_posts/2018-12-21-v4.6.0.md +6 -0
  50. package/docs/_posts/2019-04-29-v4.7.0.md +6 -0
  51. package/docs/_posts/2019-04-30-v4.7.1.md +5 -0
  52. package/docs/_posts/2020-04-03-v4.7.2.md +6 -0
  53. package/docs/_posts/2020-05-19-v4.8.0.md +10 -0
  54. package/docs/_posts/2020-10-19-v4.8.1.md +7 -0
  55. package/docs/_posts/2021-01-26-v4.9.0.md +8 -0
  56. package/docs/_posts/2022-01-12-v4.10.0.md +8 -0
  57. package/docs/index.md +93 -0
  58. package/docs/styles/docs.css +37 -0
  59. package/package.json +50 -0
  60. package/slack.js +20 -0
  61. package/src/SlackAdapter.mjs +302 -0
  62. package/src/SlackAdapter.test.mjs +342 -0
  63. package/src/bot.js +526 -0
  64. package/src/client.js +445 -0
  65. package/src/extensions.js +82 -0
  66. package/src/mention.js +15 -0
  67. package/src/message.js +307 -0
  68. package/src/testing.mjs +24 -0
  69. package/test/bot.js +769 -0
  70. package/test/client.js +446 -0
  71. package/test/message.js +329 -0
  72. package/test/stubs.js +388 -0
@@ -0,0 +1,13 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+ * Decouple RTM datastore from Hubot (#465) - thanks @shanedewael
5
+ * Create local maps to decrease Web API dependencies (#489, #491) - thanks @shanedewael
6
+ * Add flag to allow disabling loading all users on startup (#471) - thanks @sinisterstuf
7
+ * Add support for `rtm.connect` (#452) - thanks @lornajane
8
+ * Add support for `presence_changed` events (#438) - thanks @leschekfm
9
+ * Guarantee consistent user representations (#482) - thanks @shanedewael
10
+ * Implements pagination for `users.list` (#454) - thanks @aoberoi
11
+ * Modernize documentation (#478) - thanks @aoberoi
12
+ * Fixes typo in documentation (#487) - thanks @lukehsiao
13
+ * Updates Slack Standard OSS guidelines (#443) - thanks @aoberoi
@@ -0,0 +1,4 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+ * Fixes bug that would cause a crash on `user_change` events (#497)
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+ * Resolves security vulnerability warnings for CVE-2018-3728 by updating `@slack/client` (#486)
5
+ * Fixes issue processing messages with attachments (#500)
@@ -0,0 +1,12 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+ * Fixes an issue with the `res.message.user` object containing two nested `slack` properties (#505) - thanks @shanedewael.
5
+ * Fixes an issue where messages from bots with no bot user may have had `undefined` value for `res.messages.user` (#507) - thanks @shanedewael.
6
+ * Increases consistency of `EnterMessage` and `LeaveMessage` events by swapping to the events which are garaunteed
7
+ to be delivered (#296) - thanks @aoberoi.
8
+ * Fixes an issue where listeners were not matched because the text formatting did not properly account for messages
9
+ without `text` defined but which do contain valid `attachments`, such as from IFTTT (#504) - thanks @aoberoi.
10
+ * Fixes an issue where messages were delivered to Slack out of order (#379) - thanks @aoberoi.
11
+ * Documentation improvements (#372, #468) - thanks @aoberoi.
12
+ * Adds node v10 to the testing matrix (#510) - thanks @aoberoi.
@@ -0,0 +1,7 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * fixes bug where messages from slackbot would not be handled properly - thanks @Eibwen (#520)
6
+ * updates the version of lodash - thanks @mistydemeo (#521)
7
+ * fixes a typo in the documentation - thanks @ind1go (#517)
@@ -0,0 +1,7 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * updates to the latest security patch of `@slack/client@v3` - thanks @aoberoi (#529)
6
+ * adds testing across `hubot` major versions 2.x and 3.x - thanks @mistydemeo (#525)
7
+ * applies a fix to keep users out of the Hubot brain when setting the `DISABLE_USER_SYNC` environment variable - thanks @jplindquist (#524)
@@ -0,0 +1,6 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * Adds `fileShared` listener - thanks @daniel-beard (#546)
6
+ * Fixes a bug where extension methods weren't being added to the right prototype - thanks @shanedewael (#541)
@@ -0,0 +1,6 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * Adds ability to configure the lifetime of conversation data in the cache using the
6
+ `HUBOT_SLACK_CONVERSATION_CACHE_TTL_MS` environment variable (#560) thanks @aoberoi
@@ -0,0 +1,5 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * Fixes an issue parsing the `HUBOT_SLACK_CONVERSATION_CACHE_TTL_MS` as a number (#562) thanks @aoberoi and @mistydemeo
@@ -0,0 +1,6 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * Bot: catch and react to disconnection event (#572) thanks @mistydemeo
6
+ * Fix #586 hubot-slack calling bots.info a suspicious number of times (#588) thanks @mistydemeo @seratch
@@ -0,0 +1,10 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * #597 Fix #593 New option to ignore events by other workspace users in shared channels - thanks @seratch
6
+ * #596 Add timestamps for enter and leave messages - thanks @sinisterstuf
7
+ * #574 Use Coffeescript conditional assignment shorthand thanks @sinisterstuf
8
+ * #540 Add callback support to SlackBot::{send,reply} - thanks @rtlechow
9
+
10
+ Here is the list of all the issues/pull requests in this release: https://github.com/slackapi/hubot-slack/issues?q=milestone%3A4.8.0
@@ -0,0 +1,7 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * #609 Enable robot to hear thread_broadcast subtype messages - thanks @nitoyon
6
+
7
+ Here is the list of all the issues/pull requests in this release: https://github.com/slackapi/hubot-slack/issues?q=milestone%3A4.8.1
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * #557 #612 Enable to increase page size for Web API calls - thanks @kintarowins @iancward
6
+ * #615 #617 res.message.user is invalid when a message posted using a user token - thanks @buzztaiki
7
+
8
+ Here is the list of all the issues/pull requests in this release: https://github.com/slackapi/hubot-slack/issues?q=milestone%3A4.9.0
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: changelog
3
+ ---
4
+
5
+ * #637 #591 Add support for robot.hearMeMessage - thanks @benpbolton
6
+ * #633 Fix #632 Change the default settings to "useRtmConnect: true" - thanks @seratch
7
+
8
+ Here is the list of all the issues/pull requests in this release: https://github.com/slackapi/hubot-slack/milestone/3?closed=1
package/docs/index.md ADDED
@@ -0,0 +1,93 @@
1
+ ---
2
+ layout: page
3
+ permalink: /
4
+ order: 0
5
+ headings:
6
+ - title: Basic Setup
7
+ - title: Getting a Slack Token
8
+ - title: Running Hubot
9
+ - title: Trick it out
10
+ - title: Getting Help
11
+ ---
12
+
13
+ So you want to get started using Hubot and Slack? We've got you covered. {{ site.product_name }} is an
14
+ adapter that connects your Hubot scripts to your Slack team, giving you and your fellow teammates a new best friend:
15
+ your very own scriptable, pluggable bot.
16
+
17
+ [What is Hubot and when should I use it?](https://hubot.github.com/) In short, it makes developing ChatOps-style bots
18
+ quicker and easier. It's an application you host on a server that uses the Slack platform and behaves however you
19
+ script it to.
20
+
21
+ ### Important Notice
22
+
23
+ **This project is no longer under active development.** If you’re just getting started, we recommend taking a look at [Bolt for JS with Socket Mode](https://slack.dev/bolt-js/concepts#socket-mode) first. If you’ve been using this project, only critical issues (such as severe security issues) will be addressed, but we advise planning to migrate to the newer SDK.
24
+
25
+ ## Basic Setup
26
+
27
+ To get started, you'll need [Node.js](https://nodejs.org/en/) installed.
28
+
29
+ You will first want to create a new Hubot project. The simplest way is to use your computer's terminal app to install
30
+ [Yeoman](http://yeoman.io), a handy tool that builds projects from a template. We'll also install the the template for
31
+ Hubot projects, `generator-hubot`.
32
+
33
+ ```
34
+ npm install -g yo generator-hubot
35
+ ```
36
+
37
+ Now we can create that Hubot project:
38
+
39
+ ```
40
+ mkdir my-awesome-hubot && cd my-awesome-hubot
41
+ yo hubot --adapter=slack
42
+ ```
43
+
44
+ Yeoman will ask you a few easy questions about your project and fill your directory with a Hubot app, ready to run.
45
+
46
+ ## Getting a Slack Token
47
+
48
+ Next, you'll need a token from Slack to authenticate your Hubot. Use one of the following choices:
49
+
50
+ - **Create a [Classic Slack App](https://api.slack.com/authentication/migration#classic) with a Bot User (recommended)**: Slack apps are a container for many capabilities in the Slack platform, and let you access those capabilities in a single place. This is the recommended choice because it allows room for your Hubot to grow. To begin, you just need a Bot User.
51
+
52
+ 1. Create a new [Classic Slack app](https://api.slack.com/authentication/migration#classic) at the [app management page](https://api.slack.com/apps?new_classic_app=1). Pick a clever name and choose the workspace you want Hubot installed in.
53
+ 2. Navigate to the Bot User page and add a bot user. The display name is the name your team will use to mention your Hubot in Slack.
54
+ 3. Navigate to the Install App page and install the app into the workspace. Once you've authorized the installation, you'll be taken back to the Install App page, but this time you'll have a **Bot OAuth Access Token**. Copy that value, it will be your Slack token.
55
+
56
+ **⚠️** Although the admin page encourages you to upgrade your app's OAuth scope, please do not do so. The latest permission model does not support the RTM API, which is the underlying API of the Hubot adapter.
57
+
58
+ - **Create a configuration of the Hubot Integration**: The [Hubot Integration](https://my.slack.com/apps/A0F7XDU93-hubot) is an older way to use the Slack platform. Its main advantage is that you get more permissions out of the box. For those concerned with security, this may be undesirable and should be taken into consideration.
59
+
60
+ From the link above, click Install, choose a username, and finish by clicking Add Hubot Integration. On the following page, you'll see an **API Token**. Copy that value, as it will be your Slack token.
61
+
62
+ ## Running Hubot
63
+
64
+ Run the command below, pasting your own Slack token after the `=`.
65
+
66
+ ```
67
+ HUBOT_SLACK_TOKEN=xoxb-YOUR-TOKEN-HERE ./bin/hubot --adapter slack
68
+ ```
69
+
70
+ Before you can interact with your Hubot, you invite it into a channel (shortcut: `/invite @username`).
71
+
72
+ _Windows users_: The above command sets an environment variable correctly for Linux and macOS, but
73
+ [Windows is a little different](https://hubot.github.com/docs/deploying/windows/).
74
+
75
+ ## Trick it out
76
+
77
+ Hubot has many pre-written scripts that you can easy add by naming them in `external-scripts.json`. Take a look at all
78
+ the possibilites with the [hubot-scripts keyword in npm](https://www.npmjs.com/search?q=keywords:hubot-scripts).
79
+
80
+ Feeling inspired? You can jump into writing your own scripts by modifying `scripts/example.js`. It had tons of
81
+ helpful comments to guide you. You might also find the [Hubot scripting docs](https://hubot.github.com/docs/scripting/)
82
+ useful.
83
+
84
+ ## Getting Help
85
+
86
+ If you get stuck, we're here to help. The following are the best ways to get assistance working through your issue:
87
+
88
+ * [Issue Tracker](http://github.com/slackapi/{{ site.repo_name }}/issues) for reporting bugs or requesting features.
89
+
90
+ * [Bot Developer Hangout](https://community.botkit.ai) is a Slack community for developers building all types of bots.
91
+ You can find the maintainers and users of this package in **#slack-api.**
92
+
93
+ * Email us in Slack developer support: [developers@slack.com](mailto://developers@slack.com)
@@ -0,0 +1,37 @@
1
+ ---
2
+ ---
3
+
4
+ /* Updates body font */
5
+ body {
6
+ font-family: Slack-Lato,appleLogo,sans-serif;
7
+ }
8
+
9
+ /* Replaces old sidebar styled links */
10
+ .sidebar_menu h5 {
11
+ font-size: 0.8rem;
12
+ font-weight: 800;
13
+ margin-bottom: 3px;
14
+ }
15
+
16
+ /* Aligns footer navigation to the left of the sidebar */
17
+ .footer_nav {
18
+ margin: 0 !important;
19
+ }
20
+
21
+ /* Styles the signature all nice and pretty <3 */
22
+ #footer_signature {
23
+ color:#e01e5a;
24
+ font-size:.9rem;
25
+ margin-top: 10px;
26
+ }
27
+
28
+ /* Fixes link hover state */
29
+ a:hover {
30
+ text-decoration: underline;
31
+ }
32
+
33
+ /* Makes footer consistent */
34
+ footer {
35
+ background-color: transparent;
36
+ border: 0;
37
+ }
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@hubot-friends/hubot-slack",
3
+ "version": "0.0.0-development",
4
+ "description": "A new Slack adapter for Hubot",
5
+ "main": "./slack.js",
6
+ "scripts": {
7
+ "test": "node --test",
8
+ "test:watch": "node --test --watch"
9
+ },
10
+ "keywords": [
11
+ "hubot",
12
+ "adapter",
13
+ "slack"
14
+ ],
15
+ "author": "Joey Guerra",
16
+ "license": "MIT",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/hubot-friends/hubot-slack.git"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/hubot-friends/hubot-slack/issues"
23
+ },
24
+ "dependencies": {
25
+ "@slack/socket-mode": "^1.3.2",
26
+ "@slack/web-api": "^6.8.1"
27
+ },
28
+ "peerDependencies": {
29
+ "hubot": "^5.0.7"
30
+ },
31
+ "engines": {
32
+ "node": ">= 18.16.0",
33
+ "npm": ">= 9.5.1"
34
+ },
35
+ "devDependencies": {
36
+ "pino-pretty": "^10.0.1"
37
+ },
38
+ "release": {
39
+ "branches": [
40
+ "main",
41
+ "next"
42
+ ],
43
+ "dryRun": false
44
+ },
45
+ "homepage": "https://github.com/hubot-friends/hubot-slack#readme",
46
+ "directories": {
47
+ "doc": "docs",
48
+ "test": "test"
49
+ }
50
+ }
package/slack.js ADDED
@@ -0,0 +1,20 @@
1
+ const SlackBot = require('./src/bot');
2
+ require('./src/extensions');
3
+
4
+ exports.use = function(robot) {
5
+ let e;
6
+ const options = {
7
+ appToken: process.env.HUBOT_SLACK_APP_TOKEN,
8
+ botToken: process.env.HUBOT_SLACK_BOT_TOKEN,
9
+ disableUserSync: (process.env.DISABLE_USER_SYNC != null),
10
+ apiPageSize: process.env.API_PAGE_SIZE,
11
+ installedTeamOnly: (process.env.INSTALLED_TEAM_ONLY != null)
12
+ };
13
+ try {
14
+ options.socketModeOptions = JSON.parse(process.env.HUBOT_SLACK_SOCKET_MODE_OPTS || '{}');
15
+ } catch (error) {
16
+ e = error;
17
+ console.error(e);
18
+ }
19
+ return new SlackBot(robot, options);
20
+ };
@@ -0,0 +1,302 @@
1
+ import Adapter from 'hubot/src/adapter.js'
2
+ import { TextMessage } from 'hubot/src/message.js'
3
+ import User from 'hubot/src/user.js'
4
+ import { SocketModeClient } from '@slack/socket-mode'
5
+ import { WebClient } from '@slack/web-api'
6
+
7
+ export class SlackIdentity {
8
+ constructor(obj) {
9
+ this.installed_team_id = obj.installed_team_id
10
+ this.team_id = obj.team_id
11
+ this.team_name = obj.team_name
12
+ this.user_id = obj.user_id
13
+ this.user_token = obj.user_token
14
+ this.bot_token = obj.bot_token
15
+ this.bot_user_id = obj.bot_user_id
16
+ this.bot_id = obj.bot_id
17
+ }
18
+ }
19
+
20
+ export class ResponseMetadata {
21
+ constructor(obj) {
22
+ this.scopes = obj?.scopes
23
+ this.acceptedScopes = obj?.acceptedScopes
24
+ }
25
+ }
26
+ export class AuthenticationResponse {
27
+ constructor(obj) {
28
+ this.ok = obj?.ok
29
+ this.url = obj?.url
30
+ this.error = obj?.error
31
+ this.responseMetadata = new ResponseMetadata(obj?.responseMetadata)
32
+ }
33
+ }
34
+ export class AuthTestResponse {
35
+ constructor(obj) {
36
+ this.ok = obj?.ok
37
+ this.url = obj?.url
38
+ this.error = obj?.error
39
+ this.user = new User(obj?.user_id, {
40
+ name: obj?.user,
41
+ teamId: obj?.team_id,
42
+ team: obj?.team,
43
+ })
44
+ this.responseMetadata = new ResponseMetadata(obj?.response_metadata)
45
+ this.team = obj?.team
46
+ this.userId = obj?.user_id
47
+ this.botId = obj?.bot_id
48
+ this.isEnterpriseInstall = obj?.is_enterprise_install
49
+ }
50
+ }
51
+ export class SlackBotProfile {
52
+ constructor(obj) {
53
+ this.id = obj?.id
54
+ this.deleted = obj?.deleted
55
+ this.name = obj?.name
56
+ this.updated = obj?.updated
57
+ this.appId = obj?.app_id
58
+ this.icons = obj?.icons
59
+ this.teamId = obj?.team_id
60
+ }
61
+ }
62
+ export class SlackMessage {
63
+ constructor(obj) {
64
+ this.botId = obj?.bot_id
65
+ this.type = obj?.type
66
+ this.text = obj?.text
67
+ this.user = obj?.user
68
+ this.appId = obj?.app_id
69
+ this.blocks = obj?.blocks
70
+ this.team = obj?.team
71
+ this.botProfile = obj?.bot_profile
72
+ this.attachments = obj?.attachments
73
+ this.ts = obj?.ts
74
+ }
75
+ }
76
+ export class SlackMessageEvent {
77
+ constructor(obj) {
78
+ this.clientMsgId = obj?.client_msg_id
79
+ this.type = obj?.type
80
+ this.subType = obj?.subtype
81
+ this.message = obj?.message ? new SlackMessage(obj.message) : null
82
+ this.previousMessage = obj?.previous_message ? new SlackMessage(obj.previous_message) : null
83
+ this.text = obj?.text
84
+ this.user = obj?.user
85
+ this.botId = obj?.bot_id
86
+ this.blocks = obj?.blocks
87
+ this.team = obj?.team
88
+ this.channel = obj?.channel
89
+ this.hidden = obj?.hidden
90
+ this.ts = obj?.ts
91
+ this.eventTs = obj?.event_ts
92
+ this.channelType = obj?.channel_type
93
+ }
94
+ }
95
+ export class SlackMessageBody {
96
+ constructor(obj) {
97
+ this.token = obj?.token
98
+ this.teamId = obj?.team_id
99
+ this.contextTeamId = obj?.context_team_id
100
+ this.contextEnterpriseId = obj?.context_enterprise_id
101
+ this.apiAppId = obj?.api_app_id
102
+ this.event = new SlackMessageEvent(obj?.event)
103
+ this.type = obj?.type
104
+ this.eventId = obj?.event_id
105
+ this.eventTime = obj?.event_time
106
+ this.authorizations = obj?.authorizations
107
+ this.isExtSharedChannel = obj?.is_ext_shared_channel
108
+ this.eventContext = obj?.event_context
109
+ }
110
+ }
111
+ export class SlackChannel {
112
+ constructor(obj) {
113
+ this.id = obj?.id
114
+ this.name = obj?.name
115
+ this.isChannel = obj?.is_channel
116
+ this.isGroup = obj?.is_group
117
+ this.isIm = obj?.is_im
118
+ this.isMpIm = obj?.is_mpim
119
+ this.isPrivate = obj?.is_private
120
+ this.created = obj?.created
121
+ this.isArchived = obj?.is_archived
122
+ this.isGeneral = obj?.is_general
123
+ this.isOrgShared = obj?.is_org_shared
124
+ this.isShared = obj?.is_shared
125
+ this.isPendingExtShared = obj?.is_pending_ext_shared
126
+ this.pendingShared = obj?.pending_shared
127
+ this.contextTeamId = obj?.context_team_id
128
+ this.updated = obj?.updated
129
+ this.unlinked = obj?.unlinked
130
+ this.nameNormalized = obj?.name_normalized
131
+ this.user = obj?.user
132
+ this.lastRead = obj?.last_read
133
+ this.latest = obj?.latest
134
+ this.parentConversation = obj?.parent_conversation
135
+ this.creator = obj?.creator
136
+ this.isExtShared = obj?.is_ext_shared
137
+ this.sharedTeamIds = obj?.shared_team_ids
138
+ this.pendingConnectedTeamIds = obj?.pending_connected_team_ids
139
+ this.isMember = obj?.is_member
140
+ this.topic = obj?.topic
141
+ this.purpose = obj?.purpose
142
+ this.previousNames = obj?.previous_names
143
+ }
144
+ }
145
+ export class SlackResponse {
146
+ constructor(obj) {
147
+ this.ack = obj?.ack
148
+ this.envelopeId = obj?.envelope_id
149
+ this.body = new SlackMessageBody(obj?.body)
150
+ this.retryNum = obj?.retry_num
151
+ this.retryReason = obj?.retry_reason
152
+ this.acceptsResponsePayload = obj?.accepts_response_payload
153
+ }
154
+ }
155
+
156
+ class SlackAdapter extends Adapter {
157
+ #webSocketClient = null
158
+ #webClient = null
159
+ #options = null
160
+ #errors = []
161
+ constructor(robot, webSocketClient, webClient, options) {
162
+ super(robot)
163
+ this.name = 'Slack Adapter'
164
+ this.#options = options
165
+ this.#webSocketClient = webSocketClient
166
+ this.#webClient = webClient
167
+ this.#webSocketClient.on('authenticated', rtmStartData => this.#onAuthenticated(rtmStartData))
168
+ this.#webSocketClient.on('message', async message => await this.#onMessage(message))
169
+ this.#webSocketClient.on('open', () => this.#open())
170
+ this.#webSocketClient.on('close', () => this.#close())
171
+ this.#webSocketClient.on('disconnect', () => this.#disconnect())
172
+ this.#webSocketClient.on('error', error => this.#error(error))
173
+
174
+ }
175
+ async mapToHubotMessage(event) {
176
+ // console.error(event)
177
+ const fromBrain = this.robot.brain.users()[event.user]
178
+ if(!fromBrain) {
179
+ const response = await this.#webClient.users.info({
180
+ user: event.user
181
+ })
182
+ this.robot.brain.userForId(event.user, response.user)
183
+ }
184
+ const fromUser = this.robot.brain.users()[event.user]
185
+ return new TextMessage(new User(event.user, {
186
+ room: event.channel,
187
+ name: fromUser.name
188
+ }), event.text, event.ts)
189
+ }
190
+ #error(error) {
191
+ this.#errors.push(error)
192
+ this.emit('error', error)
193
+ }
194
+ #disconnect() {
195
+ this.emit('disconnected')
196
+ }
197
+ #close() {
198
+ this.#webClient.disconnect()
199
+ }
200
+ #open() {
201
+ this.robot.logger.info('Connected to Slack after open event')
202
+ return this.emit('connected');
203
+ }
204
+ replaceBotIdWithName(event) {
205
+ const botId = this.robot.self.id
206
+ const botName = this.robot.self.name
207
+ const text = event.text ?? event.message?.text
208
+ if(text.includes(`<@${botId}>`)) {
209
+ return text.replace(`<@${botId}>`, `@${botName}`)
210
+ }
211
+ return text
212
+ }
213
+ async #onMessage(message) {
214
+ const channelResponse = await this.#webClient.conversations.info({
215
+ channel: message.event.channel
216
+ })
217
+ const slackMessage = new SlackResponse(message)
218
+ if(slackMessage.body.event.botId && slackMessage.body.event.user === this.robot.self.id) {
219
+ this.robot.logger.info('Ignoring message from self')
220
+ return await message.ack()
221
+ }
222
+ // add the bot id to the message if it's a direct message
223
+ if(slackMessage.body.event.text
224
+ && slackMessage.body.event.channelType == 'im'
225
+ && !slackMessage.body.event?.text?.includes(this.robot.self.id)) {
226
+ slackMessage.body.event.text = `<@${this.robot.self.id}> ${slackMessage.body.event.text}`
227
+ }
228
+ this.robot.logger.info(`Received a message from Slack:`, slackMessage)
229
+ slackMessage.body.event.text = this.replaceBotIdWithName(slackMessage.body.event)
230
+ if(slackMessage.body.event.message) {
231
+ slackMessage.body.event.message.text = this.replaceBotIdWithName(slackMessage.body.event)
232
+ }
233
+ try {
234
+ const textMessage = await this.mapToHubotMessage(slackMessage.body.event)
235
+ this.robot.receive(textMessage)
236
+ } catch(error) {
237
+ this.robot.error(error)
238
+ }
239
+ await message.ack()
240
+ }
241
+ #onAuthenticated(rtmStartData) {
242
+ if(rtmStartData instanceof Error) {
243
+ this.#errors.push(rtmStartData)
244
+ this.emit('authenticated', rtmStartData, null)
245
+ return
246
+ }
247
+ this.emit('authenticated', null, new AuthenticationResponse(rtmStartData))
248
+ }
249
+ send(envelope, ...strings) {
250
+ const options = {
251
+ as_user: true,
252
+ link_names: 1,
253
+ unfurl_links: false,
254
+ unfurl_media: false
255
+ }
256
+ const message = strings.join(' ')
257
+ if(envelope.room[0] === 'D') {
258
+ options.channel = envelope.user.id
259
+ } else {
260
+ options.channel = envelope.room
261
+ }
262
+ this.#webClient.chat.postMessage({ channel: options.channel, text: message }).then(result => {
263
+ this.robot.logger.debug(`Successfully sent message to ${envelope.room}`)
264
+ }).catch(e => this.robot.logger.error(e))
265
+ }
266
+ reply(envelope, ...strings) {
267
+ this.robot.logger.info(`Replying to message in ${envelope.room}`)
268
+ return this.send(envelope, ...strings)
269
+ }
270
+ run() {
271
+ this.#webSocketClient.start().then(async result => {
272
+ // const channelResponse = await this.#webClient.conversations.list()
273
+ // console.log('channelResponse', channelResponse)
274
+ const response = await this.#webClient.auth.test()
275
+ this.robot.self = new AuthTestResponse(response).user
276
+ this.robot.logger.info('Connected to Slack after starting socket client.')
277
+ this.emit('connected')
278
+ }).catch(e => this.robot.logger.error(e))
279
+ }
280
+ }
281
+
282
+ export {
283
+ SlackAdapter
284
+ }
285
+
286
+ export default {
287
+ use(robot) {
288
+ const options = {
289
+ token: process.env.SLACK_APP_TOKEN,
290
+ disableUserSync: (process.env.DISABLE_USER_SYNC != null),
291
+ apiPageSize: process.env.API_PAGE_SIZE,
292
+ installedTeamOnly: (process.env.INSTALLED_TEAM_ONLY != null),
293
+ rtm: JSON.parse(process.env.HUBOT_SLACK_RTM_CLIENT_OPTS || '{}'),
294
+ rmStart: JSON.parse(process.env.HUBOT_SLACK_RTM_START_OPTS || '{}'),
295
+ }
296
+ options.rtm.useRtmConnect = true
297
+ return new SlackAdapter(robot, new SocketModeClient({ appToken: process.env.HUBOT_SLACK_APP_TOKEN }), new WebClient(process.env.HUBOT_SLACK_BOT_TOKEN, {
298
+ logger: robot.logger,
299
+ logLevel: process.env.HUBOT_SLACK_LOG_LEVEL || 'info'
300
+ }), options)
301
+ }
302
+ }