@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.
- package/.github/CODE_OF_CONDUCT.md +11 -0
- package/.github/contributing.md +60 -0
- package/.github/issue_template.md +48 -0
- package/.github/maintainers_guide.md +91 -0
- package/.github/pull_request_template.md +8 -0
- package/.github/workflows/ci-build.yml +74 -0
- package/LICENSE +22 -0
- package/README.md +29 -0
- package/docs/Gemfile +2 -0
- package/docs/README.md +15 -0
- package/docs/_config.yml +29 -0
- package/docs/_includes/analytics.html +7 -0
- package/docs/_includes/head.html +33 -0
- package/docs/_includes/page_header.html +20 -0
- package/docs/_includes/side_nav.html +22 -0
- package/docs/_includes/tag_manager.html +13 -0
- package/docs/_layouts/changelog.html +15 -0
- package/docs/_layouts/default.html +47 -0
- package/docs/_layouts/page.html +10 -0
- package/docs/_pages/FAQ.md +63 -0
- package/docs/_pages/about.md +16 -0
- package/docs/_pages/advanced_usage.md +102 -0
- package/docs/_pages/auth.md +44 -0
- package/docs/_pages/basic_usage.md +302 -0
- package/docs/_pages/changelog.html +17 -0
- package/docs/_pages/upgrading.md +49 -0
- package/docs/_posts/2016-07-15-v4.0.0.md +14 -0
- package/docs/_posts/2016-07-19-v4.0.1.md +5 -0
- package/docs/_posts/2016-08-03-v4.0.2.md +4 -0
- package/docs/_posts/2016-09-12-v4.0.3.md +8 -0
- package/docs/_posts/2016-09-12-v4.0.4.md +4 -0
- package/docs/_posts/2016-09-14-v4.0.5.md +4 -0
- package/docs/_posts/2016-09-21-v4.1.0.md +4 -0
- package/docs/_posts/2016-10-12-v4.2.0.md +4 -0
- package/docs/_posts/2016-10-12-v4.2.1.md +4 -0
- package/docs/_posts/2016-11-05-v4.2.2.md +8 -0
- package/docs/_posts/2017-01-05-v4.3.0.md +5 -0
- package/docs/_posts/2017-01-09-v4.3.1.md +5 -0
- package/docs/_posts/2017-02-15-v4.3.2.md +5 -0
- package/docs/_posts/2017-02-17-v4.3.3.md +4 -0
- package/docs/_posts/2017-03-29-v4.3.4.md +5 -0
- package/docs/_posts/2017-08-24-v4.4.0.md +7 -0
- package/docs/_posts/2018-06-08-v4.5.0.md +13 -0
- package/docs/_posts/2018-06-14-v4.5.1.md +4 -0
- package/docs/_posts/2018-07-03-v4.5.2.md +5 -0
- package/docs/_posts/2018-07-17-v4.5.3.md +12 -0
- package/docs/_posts/2018-08-10-v4.5.4.md +7 -0
- package/docs/_posts/2018-10-01-v4.5.5.md +7 -0
- package/docs/_posts/2018-12-21-v4.6.0.md +6 -0
- package/docs/_posts/2019-04-29-v4.7.0.md +6 -0
- package/docs/_posts/2019-04-30-v4.7.1.md +5 -0
- package/docs/_posts/2020-04-03-v4.7.2.md +6 -0
- package/docs/_posts/2020-05-19-v4.8.0.md +10 -0
- package/docs/_posts/2020-10-19-v4.8.1.md +7 -0
- package/docs/_posts/2021-01-26-v4.9.0.md +8 -0
- package/docs/_posts/2022-01-12-v4.10.0.md +8 -0
- package/docs/index.md +93 -0
- package/docs/styles/docs.css +37 -0
- package/package.json +50 -0
- package/slack.js +20 -0
- package/src/SlackAdapter.mjs +302 -0
- package/src/SlackAdapter.test.mjs +342 -0
- package/src/bot.js +526 -0
- package/src/client.js +445 -0
- package/src/extensions.js +82 -0
- package/src/mention.js +15 -0
- package/src/message.js +307 -0
- package/src/testing.mjs +24 -0
- package/test/bot.js +769 -0
- package/test/client.js +446 -0
- package/test/message.js +329 -0
- 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,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
|
+
* 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,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,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
|
+
}
|