hubot 3.3.1 → 3.4.0
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/.env.example +2 -0
- package/.envrc +5 -0
- package/.github/workflows/nodejs-macos.yml +26 -0
- package/.github/workflows/nodejs-ubuntu.yml +28 -0
- package/.github/workflows/nodejs-windows.yml +26 -0
- package/README.md +0 -2
- package/bin/hubot.js +1 -5
- package/docs/deploying/windows.md +5 -5
- package/docs/patterns.md +14 -0
- package/es2015.js +1 -1
- package/package.json +7 -7
- package/src/adapters/campfire.js +18 -18
- package/src/adapters/shell.js +7 -5
- package/src/brain.js +8 -8
- package/src/datastore.js +3 -3
- package/src/httpclient.js +312 -0
- package/src/robot.js +18 -15
- package/src/user.js +2 -2
- package/test/adapter_test.js +1 -1
- package/test/brain_test.js +9 -9
- package/test/datastore_test.js +16 -16
- package/test/es2015_test.js +1 -1
- package/test/fixtures/mock-adapter.js +5 -0
- package/test/listener_test.js +2 -2
- package/test/middleware_test.js +18 -17
- package/test/robot_test.js +26 -11
- package/test/user_test.js +2 -2
- package/ROADMAP.md +0 -37
package/.env.example
ADDED
package/.envrc
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Node.js (macOS) CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "master" ]
|
|
6
|
+
schedule:
|
|
7
|
+
- cron: '5 4 * * 0'
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
npm-test:
|
|
11
|
+
|
|
12
|
+
runs-on: macos-latest
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
node-version: [18.x]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v3
|
|
20
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
21
|
+
uses: actions/setup-node@v3
|
|
22
|
+
with:
|
|
23
|
+
node-version: ${{ matrix.node-version }}
|
|
24
|
+
cache: 'npm'
|
|
25
|
+
- run: npm ci
|
|
26
|
+
- run: npm test
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Node.js (Ubuntu) CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "master" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ "master" ]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '5 4 * * 0'
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
npm-test:
|
|
13
|
+
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
node-version: [14.x, 16.x, 18.x, latest]
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v3
|
|
22
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
23
|
+
uses: actions/setup-node@v3
|
|
24
|
+
with:
|
|
25
|
+
node-version: ${{ matrix.node-version }}
|
|
26
|
+
cache: 'npm'
|
|
27
|
+
- run: npm ci
|
|
28
|
+
- run: npm test
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Node.js (Windows) CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "master" ]
|
|
6
|
+
schedule:
|
|
7
|
+
- cron: '5 4 * * 0'
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
npm-test:
|
|
11
|
+
|
|
12
|
+
runs-on: windows-latest
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
node-version: [18.x]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v3
|
|
20
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
21
|
+
uses: actions/setup-node@v3
|
|
22
|
+
with:
|
|
23
|
+
node-version: ${{ matrix.node-version }}
|
|
24
|
+
cache: 'npm'
|
|
25
|
+
- run: npm ci
|
|
26
|
+
- run: npm test
|
package/README.md
CHANGED
|
@@ -13,8 +13,6 @@ for details on getting up and running with your very own robot friend.
|
|
|
13
13
|
In most cases, you'll probably never have to hack on this repo directly if you
|
|
14
14
|
are building your own bot. But if you do, check out [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
15
15
|
|
|
16
|
-
If you'd like to chat with Hubot users and developers, [join us on Slack](https://hubot-slackin.herokuapp.com/).
|
|
17
|
-
|
|
18
16
|
## License
|
|
19
17
|
|
|
20
18
|
See the [LICENSE](LICENSE.md) file for license rights and limitations (MIT).
|
package/bin/hubot.js
CHANGED
|
@@ -23,7 +23,7 @@ const options = {
|
|
|
23
23
|
adapter: process.env.HUBOT_ADAPTER || 'shell',
|
|
24
24
|
alias: process.env.HUBOT_ALIAS || false,
|
|
25
25
|
create: process.env.HUBOT_CREATE || false,
|
|
26
|
-
enableHttpd: process.env.HUBOT_HTTPD
|
|
26
|
+
enableHttpd: process.env.HUBOT_HTTPD !== 'false',
|
|
27
27
|
scripts: process.env.HUBOT_SCRIPTS || [],
|
|
28
28
|
name: process.env.HUBOT_NAME || 'Hubot',
|
|
29
29
|
path: process.env.HUBOT_PATH || '.',
|
|
@@ -80,10 +80,6 @@ Parser.on((opt, value) => {
|
|
|
80
80
|
|
|
81
81
|
Parser.parse(process.argv)
|
|
82
82
|
|
|
83
|
-
if (process.platform !== 'win32') {
|
|
84
|
-
process.on('SIGTERM', () => process.exit(0))
|
|
85
|
-
}
|
|
86
|
-
|
|
87
83
|
if (options.create) {
|
|
88
84
|
console.error("'hubot --create' is deprecated. Use the yeoman generator instead:")
|
|
89
85
|
console.error(' npm install -g yo generator-hubot')
|
|
@@ -8,16 +8,16 @@ Hasn't been fully tested - YMMV
|
|
|
8
8
|
|
|
9
9
|
There are 4 primary steps to deploying and running hubot on a Windows machine:
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
* node and npm
|
|
12
|
+
* a way to get source code updated on the server
|
|
13
|
+
* setting up environment variables for hubot
|
|
14
|
+
* a way to start hubot, start it up if it crashes, and restart it when code updates
|
|
15
15
|
|
|
16
16
|
## node and npm
|
|
17
17
|
|
|
18
18
|
To start, your windows server will need node and npm.
|
|
19
19
|
The best way to do this is with [chocolatey](http://chocolatey.org) using the [nodejs.install](http://chocolatey.org/packages/nodejs.install) package.
|
|
20
|
-
I've found that sometimes the system path variable is not correctly set; ensure you can run node/npm from the command line. If needed set the PATH variable with
|
|
20
|
+
I've found that sometimes the system path variable is not correctly set; ensure you can run node/npm from the command line. If needed set the PATH variable with `set PATH=%PATH%;\"C:\Program Files\nodejs\"`
|
|
21
21
|
|
|
22
22
|
Your other option is to install directly from [NodeJS](https://nodejs.org/) and run the current download (v0.12.4 as of this documentation). This should set your PATH variables for you.
|
|
23
23
|
|
package/docs/patterns.md
CHANGED
|
@@ -218,3 +218,17 @@ Organizations that have a number of chat rooms that serve different purposes oft
|
|
|
218
218
|
|
|
219
219
|
Work on generalized blacklist solution is [ongoing](https://github.com/kristenmills/hubot-command-blacklist). A whitelist soultion could take a similar approach.
|
|
220
220
|
|
|
221
|
+
## Use scoped npm packages as adapter
|
|
222
|
+
|
|
223
|
+
It is possible to [install](https://docs.npmjs.com/cli/v7/commands/npm-install) package under a custom alias:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
npm install <alias>@npm:<name>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
So for example to use `@foo/hubot-adapter` package as the adapter, you can:
|
|
230
|
+
```bash
|
|
231
|
+
npm install hubot-foo@npm:@foo/hubot-adapter
|
|
232
|
+
|
|
233
|
+
bin/hubot --adapter foo
|
|
234
|
+
```
|
package/es2015.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hubot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"author": "hubot",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github",
|
|
@@ -21,21 +21,21 @@
|
|
|
21
21
|
"coffeescript": "1.6.3",
|
|
22
22
|
"connect-multiparty": "^2.1.1",
|
|
23
23
|
"express": "^4.16.3",
|
|
24
|
+
"express-basic-auth": "1.1.7",
|
|
24
25
|
"log": "1.4.0",
|
|
25
|
-
"optparse": "1.0.4"
|
|
26
|
-
"scoped-http-client": "0.11.0"
|
|
26
|
+
"optparse": "1.0.4"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"chai": "~2.1.0",
|
|
30
30
|
"coveralls": "^3.0.2",
|
|
31
31
|
"is-circular": "^1.0.2",
|
|
32
|
-
"mocha": "^
|
|
32
|
+
"mocha": "^10.2.0",
|
|
33
33
|
"mockery": "^1.4.0",
|
|
34
|
-
"nyc": "^
|
|
35
|
-
"semantic-release": "^
|
|
34
|
+
"nyc": "^15.1.0",
|
|
35
|
+
"semantic-release": "^21.0.1",
|
|
36
36
|
"sinon": "~1.17.0",
|
|
37
37
|
"sinon-chai": "^2.8.0",
|
|
38
|
-
"standard": "^
|
|
38
|
+
"standard": "^17.0.0"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": "> 4.0.0",
|
package/src/adapters/campfire.js
CHANGED
|
@@ -229,30 +229,30 @@ class CampfireStreaming extends EventEmitter {
|
|
|
229
229
|
},
|
|
230
230
|
|
|
231
231
|
speak (text, callback) {
|
|
232
|
-
const body = { message: {
|
|
232
|
+
const body = { message: { body: text } }
|
|
233
233
|
return self.post(`/room/${id}/speak`, body, callback)
|
|
234
234
|
},
|
|
235
235
|
|
|
236
236
|
message (text, type, callback) {
|
|
237
|
-
const body = { message: {
|
|
237
|
+
const body = { message: { body: text, type } }
|
|
238
238
|
return self.post(`/room/${id}/speak`, body, callback)
|
|
239
239
|
},
|
|
240
240
|
|
|
241
241
|
// listen for activity in channels
|
|
242
242
|
listen () {
|
|
243
243
|
const headers = {
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
Host: 'streaming.campfirenow.com',
|
|
245
|
+
Authorization: self.authorization,
|
|
246
246
|
'User-Agent': `Hubot/${this.robot != null ? this.robot.version : undefined} (${this.robot != null ? this.robot.name : undefined})`
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
const options = {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
250
|
+
agent: false,
|
|
251
|
+
host: 'streaming.campfirenow.com',
|
|
252
|
+
port: 443,
|
|
253
|
+
path: `/room/${id}/live.json`,
|
|
254
|
+
method: 'GET',
|
|
255
|
+
headers
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
const request = HTTPS.request(options, function (response) {
|
|
@@ -326,19 +326,19 @@ class CampfireStreaming extends EventEmitter {
|
|
|
326
326
|
const logger = this.robot.logger
|
|
327
327
|
|
|
328
328
|
const headers = {
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
Authorization: this.authorization,
|
|
330
|
+
Host: this.host,
|
|
331
331
|
'Content-Type': 'application/json',
|
|
332
332
|
'User-Agent': `Hubot/${this.robot != null ? this.robot.version : undefined} (${this.robot != null ? this.robot.name : undefined})`
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
const options = {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
336
|
+
agent: false,
|
|
337
|
+
host: this.host,
|
|
338
|
+
port: 443,
|
|
339
|
+
path,
|
|
340
|
+
method,
|
|
341
|
+
headers
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
if (method === 'POST' || method === 'PUT') {
|
package/src/adapters/shell.js
CHANGED
|
@@ -8,7 +8,7 @@ const chalk = require('chalk')
|
|
|
8
8
|
|
|
9
9
|
const Adapter = require('../adapter')
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const _require = require('../message')
|
|
12
12
|
|
|
13
13
|
const TextMessage = _require.TextMessage
|
|
14
14
|
|
|
@@ -82,7 +82,7 @@ class Shell extends Adapter {
|
|
|
82
82
|
})
|
|
83
83
|
|
|
84
84
|
this.cli.on('close', () => {
|
|
85
|
-
let
|
|
85
|
+
let history, i, item, len
|
|
86
86
|
|
|
87
87
|
history = this.cli.history()
|
|
88
88
|
|
|
@@ -90,13 +90,13 @@ class Shell extends Adapter {
|
|
|
90
90
|
return this.shutdown()
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
startIndex = history.length - historySize
|
|
93
|
+
const startIndex = history.length - historySize
|
|
94
94
|
history = history.reverse().splice(startIndex, historySize)
|
|
95
|
-
fileOpts = {
|
|
95
|
+
const fileOpts = {
|
|
96
96
|
mode: 0x180
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
outstream = fs.createWriteStream(historyPath, fileOpts)
|
|
99
|
+
const outstream = fs.createWriteStream(historyPath, fileOpts)
|
|
100
100
|
outstream.on('finish', this.shutdown.bind(this))
|
|
101
101
|
|
|
102
102
|
for (i = 0, len = history.length; i < len; i++) {
|
|
@@ -109,6 +109,8 @@ class Shell extends Adapter {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// Prevent output buffer "swallowing" every other character on OSX / Node version > 16.19.0.
|
|
113
|
+
process.stdout._handle.setBlocking(false)
|
|
112
114
|
exports.use = robot => new Shell(robot)
|
|
113
115
|
|
|
114
116
|
// load history from .hubot_history.
|
package/src/brain.js
CHANGED
|
@@ -10,19 +10,19 @@ const User = require('./user')
|
|
|
10
10
|
// 2. If the original object was a User object, the original object
|
|
11
11
|
// 3. If the original object was a plain JavaScript object, return
|
|
12
12
|
// a User object with all of the original object's properties.
|
|
13
|
-
|
|
13
|
+
const reconstructUserIfNecessary = function (user, robot) {
|
|
14
14
|
if (!user) {
|
|
15
15
|
return null
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
if (!user.constructor || (user.constructor && user.constructor.name !== 'User')) {
|
|
19
|
-
|
|
19
|
+
const id = user.id
|
|
20
20
|
delete user.id
|
|
21
21
|
// Use the old user as the "options" object,
|
|
22
22
|
// populating the new user with its values.
|
|
23
23
|
// Also add the `robot` field so it gets a reference.
|
|
24
24
|
user.robot = robot
|
|
25
|
-
|
|
25
|
+
const newUser = new User(id, user)
|
|
26
26
|
delete user.robot
|
|
27
27
|
|
|
28
28
|
return newUser
|
|
@@ -142,14 +142,14 @@ class Brain extends EventEmitter {
|
|
|
142
142
|
//
|
|
143
143
|
// Caveats: Deeply nested structures don't merge well.
|
|
144
144
|
mergeData (data) {
|
|
145
|
-
for (
|
|
145
|
+
for (const k in data || {}) {
|
|
146
146
|
this.data[k] = data[k]
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
// Ensure users in the brain are still User objects.
|
|
150
150
|
if (data && data.users) {
|
|
151
|
-
for (
|
|
152
|
-
|
|
151
|
+
for (const k in data.users) {
|
|
152
|
+
const user = this.data.users[k]
|
|
153
153
|
this.data.users[k] = reconstructUserIfNecessary(user, this.getRobot())
|
|
154
154
|
}
|
|
155
155
|
}
|
|
@@ -195,8 +195,8 @@ class Brain extends EventEmitter {
|
|
|
195
195
|
let result = null
|
|
196
196
|
const lowerName = name.toLowerCase()
|
|
197
197
|
|
|
198
|
-
for (
|
|
199
|
-
const userName = this.data.users[k]
|
|
198
|
+
for (const k in this.data.users || {}) {
|
|
199
|
+
const userName = this.data.users[k].name
|
|
200
200
|
if (userName != null && userName.toString().toLowerCase() === lowerName) {
|
|
201
201
|
result = this.data.users[k]
|
|
202
202
|
}
|
package/src/datastore.js
CHANGED
|
@@ -22,7 +22,7 @@ class DataStore {
|
|
|
22
22
|
// present, it's instantiated as an empty object.
|
|
23
23
|
setObject (key, objectKey, value) {
|
|
24
24
|
return this.get(key).then((object) => {
|
|
25
|
-
|
|
25
|
+
const target = object || {}
|
|
26
26
|
target[objectKey] = value
|
|
27
27
|
return this.set(key, target)
|
|
28
28
|
})
|
|
@@ -33,7 +33,7 @@ class DataStore {
|
|
|
33
33
|
// present, it's instantiated as an empty array.
|
|
34
34
|
setArray (key, value) {
|
|
35
35
|
return this.get(key).then((object) => {
|
|
36
|
-
|
|
36
|
+
const target = object || []
|
|
37
37
|
// Extend the array if the value is also an array, otherwise
|
|
38
38
|
// push the single value on the end.
|
|
39
39
|
if (Array.isArray(value)) {
|
|
@@ -56,7 +56,7 @@ class DataStore {
|
|
|
56
56
|
// contain an `objectKey`, returns `undefined`.
|
|
57
57
|
getObject (key, objectKey) {
|
|
58
58
|
return this.get(key).then((object) => {
|
|
59
|
-
|
|
59
|
+
const target = object || {}
|
|
60
60
|
return target[objectKey]
|
|
61
61
|
})
|
|
62
62
|
}
|