hubot 10.0.5 → 11.0.1
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/README.md +2 -3
- package/bin/{hubot.js → Hubot.mjs} +14 -22
- package/bin/hubot +2 -8
- package/index.mjs +52 -0
- package/package.json +2 -3
- package/src/{adapter.js → Adapter.mjs} +2 -2
- package/src/{brain.js → Brain.mjs} +3 -4
- package/src/{datastore.js → DataStore.mjs} +3 -3
- package/src/{GenHubot.js → GenHubot.mjs} +18 -6
- package/src/{httpclient.js → HttpClient.mjs} +9 -6
- package/src/{listener.js → Listener.mjs} +4 -5
- package/src/{message.js → Message.mjs} +7 -7
- package/src/{middleware.js → Middleware.mjs} +1 -1
- package/src/{OptParse.js → OptParse.mjs} +2 -2
- package/src/{response.js → Response.mjs} +1 -1
- package/src/{robot.js → Robot.mjs} +69 -51
- package/src/{user.js → User.mjs} +2 -2
- package/src/adapters/{campfire.js → Campfire.mjs} +10 -13
- package/src/adapters/{shell.js → Shell.mjs} +10 -6
- package/src/datastores/{memory.js → Memory.mjs} +2 -2
- package/es2015.js +0 -31
- package/index.js +0 -40
package/README.md
CHANGED
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
# Hubot
|
|
8
8
|
|
|
9
|
-
**Note: v10.0.4 contains the removal of CoffeeScript**
|
|
10
|
-
|
|
11
|
-
Semver is looking for **BREAKING CHANGE** singular, not **BREAKING CHANGES**. As a result, the removal of CoffeeScript was marked as the `v10.0.4` release.
|
|
9
|
+
**Note: v10.0.4 accidentaly contains the removal of CoffeeScript; v10.0.5 puts it back in**
|
|
10
|
+
**Note: v11 removes CoffeeScript and converts this codebase to ESM**
|
|
12
11
|
|
|
13
12
|
Hubot is a framework to build chat bots, modeled after GitHub's Campfire bot of the same name, hubot.
|
|
14
13
|
He's pretty cool. He's [extendable with scripts](https://hubotio.github.io/hubot/docs#scripts) and can work
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const Hubot = require('..')
|
|
9
|
-
const create = require('../src/GenHubot.js')
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import { resolve as pathResolve } from 'node:path'
|
|
5
|
+
import OptParse from '../src/OptParse.mjs'
|
|
6
|
+
import Hubot from '../index.mjs'
|
|
7
|
+
import create from '../src/GenHubot.mjs'
|
|
10
8
|
|
|
11
9
|
const switches = [
|
|
12
|
-
['-a', '--adapter HUBOT_ADAPTER', 'The Adapter to use, e.g. "
|
|
10
|
+
['-a', '--adapter HUBOT_ADAPTER', 'The Adapter to use, e.g. "Shell" (to load the default hubot Shell adapter)'],
|
|
13
11
|
['-f', '--file HUBOT_FILE', 'Path to adapter file, e.g. "./adapters/CustomAdapter.mjs"'],
|
|
14
12
|
['-c', '--create HUBOT_CREATE', 'Create a deployable hubot'],
|
|
15
13
|
['-d', '--disable-httpd HUBOT_HTTPD', 'Disable the HTTP server'],
|
|
@@ -97,13 +95,13 @@ if (options.file) {
|
|
|
97
95
|
}
|
|
98
96
|
|
|
99
97
|
const robot = Hubot.loadBot(options.adapter, options.enableHttpd, options.name, options.alias)
|
|
100
|
-
|
|
98
|
+
export default robot
|
|
101
99
|
|
|
102
100
|
async function loadScripts () {
|
|
103
101
|
await robot.load(pathResolve('.', 'scripts'))
|
|
104
102
|
await robot.load(pathResolve('.', 'src', 'scripts'))
|
|
105
103
|
|
|
106
|
-
loadExternalScripts()
|
|
104
|
+
await loadExternalScripts()
|
|
107
105
|
|
|
108
106
|
const tasks = options.scripts.map((scriptPath) => {
|
|
109
107
|
if (scriptPath[0] === '/') {
|
|
@@ -115,25 +113,19 @@ async function loadScripts () {
|
|
|
115
113
|
await Promise.all(tasks)
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
function loadExternalScripts () {
|
|
116
|
+
async function loadExternalScripts () {
|
|
119
117
|
const externalScripts = pathResolve('.', 'external-scripts.json')
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
fs.readFile(externalScripts, function (error, data) {
|
|
126
|
-
if (error) {
|
|
127
|
-
throw error
|
|
128
|
-
}
|
|
129
|
-
|
|
118
|
+
try {
|
|
119
|
+
const data = await fs.promises.readFile(externalScripts)
|
|
130
120
|
try {
|
|
131
121
|
robot.loadExternalScripts(JSON.parse(data))
|
|
132
122
|
} catch (error) {
|
|
133
123
|
console.error(`Error parsing JSON data from external-scripts.json: ${error}`)
|
|
134
124
|
process.exit(1)
|
|
135
125
|
}
|
|
136
|
-
})
|
|
126
|
+
} catch (e) {
|
|
127
|
+
robot.logger.info('No external-scripts.json found. Skipping.')
|
|
128
|
+
}
|
|
137
129
|
}
|
|
138
130
|
|
|
139
131
|
(async () => {
|
package/bin/hubot
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
# we left the `bin/hubot` file to remain in CoffeeScript in order prevent
|
|
5
|
-
# breaking existing 3rd party adapters of which some are still written in
|
|
6
|
-
# CoffeeScript themselves. We will deprecate and eventually remove this file
|
|
7
|
-
# in a future version of hubot
|
|
8
|
-
|
|
9
|
-
require './hubot.js'
|
|
3
|
+
import('./Hubot.mjs').then(async ({ default: robot }) => {})
|
package/index.mjs
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import User from './src/User.mjs'
|
|
4
|
+
import Brain from './src/Brain.mjs'
|
|
5
|
+
import Robot from './src/Robot.mjs'
|
|
6
|
+
import Adapter from './src/Adapter.mjs'
|
|
7
|
+
import Response from './src/Response.mjs'
|
|
8
|
+
import Middleware from './src/Middleware.mjs'
|
|
9
|
+
import { Listener, TextListener } from './src/Listener.mjs'
|
|
10
|
+
import { TextMessage, EnterMessage, LeaveMessage, TopicMessage, CatchAllMessage, Message } from './src/Message.mjs'
|
|
11
|
+
import { DataStore, DataStoreUnavailable } from './src/DataStore.mjs'
|
|
12
|
+
|
|
13
|
+
const loadBot = (adapter, enableHttpd, name, alias) => new Robot(adapter, enableHttpd, name, alias)
|
|
14
|
+
export {
|
|
15
|
+
Adapter,
|
|
16
|
+
User,
|
|
17
|
+
Brain,
|
|
18
|
+
Robot,
|
|
19
|
+
Response,
|
|
20
|
+
Listener,
|
|
21
|
+
TextListener,
|
|
22
|
+
Message,
|
|
23
|
+
TextMessage,
|
|
24
|
+
EnterMessage,
|
|
25
|
+
LeaveMessage,
|
|
26
|
+
TopicMessage,
|
|
27
|
+
CatchAllMessage,
|
|
28
|
+
DataStore,
|
|
29
|
+
DataStoreUnavailable,
|
|
30
|
+
Middleware,
|
|
31
|
+
loadBot
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default {
|
|
35
|
+
Adapter,
|
|
36
|
+
User,
|
|
37
|
+
Brain,
|
|
38
|
+
Robot,
|
|
39
|
+
Response,
|
|
40
|
+
Listener,
|
|
41
|
+
TextListener,
|
|
42
|
+
Message,
|
|
43
|
+
TextMessage,
|
|
44
|
+
EnterMessage,
|
|
45
|
+
LeaveMessage,
|
|
46
|
+
TopicMessage,
|
|
47
|
+
CatchAllMessage,
|
|
48
|
+
DataStore,
|
|
49
|
+
DataStoreUnavailable,
|
|
50
|
+
Middleware,
|
|
51
|
+
loadBot
|
|
52
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hubot",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.1",
|
|
4
4
|
"author": "hubot",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github",
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"url": "https://github.com/hubotio/hubot.git"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"coffeescript": "^2.7.0",
|
|
19
18
|
"connect-multiparty": "^2.2.0",
|
|
20
19
|
"express": "^4.18.2",
|
|
21
20
|
"express-basic-auth": "^1.2.1",
|
|
@@ -28,7 +27,7 @@
|
|
|
28
27
|
"node": ">= 18",
|
|
29
28
|
"npm": ">= 9"
|
|
30
29
|
},
|
|
31
|
-
"main": "./index",
|
|
30
|
+
"main": "./index.mjs",
|
|
32
31
|
"bin": {
|
|
33
32
|
"hubot": "./bin/hubot"
|
|
34
33
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import EventEmitter from 'node:events'
|
|
4
4
|
|
|
5
5
|
class Adapter extends EventEmitter {
|
|
6
6
|
// An adapter is a specific interface to a chat source for robots.
|
|
@@ -136,4 +136,4 @@ class Adapter extends EventEmitter {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
export default Adapter
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const User = require('./user')
|
|
3
|
+
import EventEmitter from 'node:events'
|
|
4
|
+
import User from './User.mjs'
|
|
6
5
|
|
|
7
6
|
// If necessary, reconstructs a User object. Returns either:
|
|
8
7
|
//
|
|
@@ -239,4 +238,4 @@ class Brain extends EventEmitter {
|
|
|
239
238
|
}
|
|
240
239
|
}
|
|
241
240
|
|
|
242
|
-
|
|
241
|
+
export default Brain
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
class DataStore {
|
|
3
|
+
export class DataStore {
|
|
4
4
|
// Represents a persistent, database-backed storage for the robot. Extend this.
|
|
5
5
|
//
|
|
6
6
|
// Returns a new Datastore with no storage.
|
|
@@ -83,9 +83,9 @@ class DataStore {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
class DataStoreUnavailable extends Error {}
|
|
86
|
+
export class DataStoreUnavailable extends Error {}
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
export default {
|
|
89
89
|
DataStore,
|
|
90
90
|
DataStoreUnavailable
|
|
91
91
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
2
|
+
import File from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
4
|
|
|
5
5
|
function runCommands (hubotDirectory, options) {
|
|
6
6
|
options.hubotInstallationPath = options?.hubotInstallationPath ?? 'hubot'
|
|
@@ -13,8 +13,19 @@ function runCommands (hubotDirectory, options) {
|
|
|
13
13
|
const envFilePath = path.resolve(process.cwd(), '.env')
|
|
14
14
|
process.chdir(hubotDirectory)
|
|
15
15
|
|
|
16
|
-
spawnSync('npm', ['init', '-y'])
|
|
17
|
-
|
|
16
|
+
let output = spawnSync('npm', ['init', '-y'])
|
|
17
|
+
console.log('npm init', output.stderr.toString())
|
|
18
|
+
if (options.hubotInstallationPath !== 'hubot') {
|
|
19
|
+
output = spawnSync('npm', ['pack', `${options.hubotInstallationPath}`])
|
|
20
|
+
console.log('npm pack', output.stderr.toString(), output.stdout.toString())
|
|
21
|
+
const customHubotPackage = JSON.parse(File.readFileSync(`${options.hubotInstallationPath}/package.json`, 'utf8'))
|
|
22
|
+
output = spawnSync('npm', ['i', `${customHubotPackage.name}-${customHubotPackage.version}.tgz`])
|
|
23
|
+
console.log(`npm i ${customHubotPackage.name}-${customHubotPackage.version}.tgz`, output.stderr.toString(), output.stdout.toString())
|
|
24
|
+
} else {
|
|
25
|
+
output = spawnSync('npm', ['i', 'hubot@latest'])
|
|
26
|
+
}
|
|
27
|
+
output = spawnSync('npm', ['i', 'hubot-help@latest', 'hubot-rules@latest', 'hubot-diagnostics@latest'].concat([options.adapter]).filter(Boolean))
|
|
28
|
+
console.log('npm i', output.stderr.toString(), output.stdout.toString())
|
|
18
29
|
spawnSync('mkdir', ['scripts'])
|
|
19
30
|
spawnSync('touch', ['external-scripts.json'])
|
|
20
31
|
|
|
@@ -50,6 +61,7 @@ export default (robot) => {
|
|
|
50
61
|
packageJson.scripts = {
|
|
51
62
|
start: 'hubot'
|
|
52
63
|
}
|
|
64
|
+
packageJson.description = 'A simple helpful robot for your Company'
|
|
53
65
|
if (options.adapter) {
|
|
54
66
|
packageJson.scripts.start += ` --adapter ${options.adapter}`
|
|
55
67
|
}
|
|
@@ -79,7 +91,7 @@ export default (robot) => {
|
|
|
79
91
|
console.log('.env file not found, continuing to the next operation.')
|
|
80
92
|
}
|
|
81
93
|
}
|
|
82
|
-
|
|
94
|
+
export default (hubotDirectory, options) => {
|
|
83
95
|
try {
|
|
84
96
|
runCommands(hubotDirectory, options)
|
|
85
97
|
} catch (error) {
|
|
@@ -33,10 +33,10 @@ Implement a phased approach to deprecate `robot.http` all together in favor of `
|
|
|
33
33
|
2. Add a deprecation warning to `robot.http`
|
|
34
34
|
3. Remove `robot.http` in a future release
|
|
35
35
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
import path from 'node:path'
|
|
37
|
+
import http from 'node:http'
|
|
38
|
+
import https from 'node:https'
|
|
39
|
+
import qs from 'node:querystring'
|
|
40
40
|
|
|
41
41
|
const nonPassThroughOptions = [
|
|
42
42
|
'headers', 'hostname', 'encoding', 'auth', 'port',
|
|
@@ -308,5 +308,8 @@ const reduce = function (a, b) {
|
|
|
308
308
|
}
|
|
309
309
|
return a
|
|
310
310
|
}
|
|
311
|
-
|
|
312
|
-
|
|
311
|
+
export default {
|
|
312
|
+
create (url, options) {
|
|
313
|
+
return new ScopedClient(url, options)
|
|
314
|
+
}
|
|
315
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const Middleware = require('./middleware')
|
|
3
|
+
import { inspect } from 'node:util'
|
|
4
|
+
import { TextMessage } from './Message.mjs'
|
|
5
|
+
import Middleware from './Middleware.mjs'
|
|
7
6
|
|
|
8
7
|
class Listener {
|
|
9
8
|
// Listeners receive every message from the chat source and decide if they
|
|
@@ -108,7 +107,7 @@ class TextListener extends Listener {
|
|
|
108
107
|
}
|
|
109
108
|
}
|
|
110
109
|
|
|
111
|
-
|
|
110
|
+
export {
|
|
112
111
|
Listener,
|
|
113
112
|
TextListener
|
|
114
113
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
class Message {
|
|
3
|
+
export class Message {
|
|
4
4
|
// Represents an incoming message from the chat.
|
|
5
5
|
//
|
|
6
6
|
// user - A User instance that sent the message.
|
|
@@ -18,7 +18,7 @@ class Message {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
class TextMessage extends Message {
|
|
21
|
+
export class TextMessage extends Message {
|
|
22
22
|
// Represents an incoming message from the chat.
|
|
23
23
|
//
|
|
24
24
|
// user - A User instance that sent the message.
|
|
@@ -52,23 +52,23 @@ class TextMessage extends Message {
|
|
|
52
52
|
// user - A User instance for the user who entered.
|
|
53
53
|
// text - Always null.
|
|
54
54
|
// id - A String of the message ID.
|
|
55
|
-
class EnterMessage extends Message {}
|
|
55
|
+
export class EnterMessage extends Message {}
|
|
56
56
|
|
|
57
57
|
// Represents an incoming user exit notification.
|
|
58
58
|
//
|
|
59
59
|
// user - A User instance for the user who left.
|
|
60
60
|
// text - Always null.
|
|
61
61
|
// id - A String of the message ID.
|
|
62
|
-
class LeaveMessage extends Message {}
|
|
62
|
+
export class LeaveMessage extends Message {}
|
|
63
63
|
|
|
64
64
|
// Represents an incoming topic change notification.
|
|
65
65
|
//
|
|
66
66
|
// user - A User instance for the user who changed the topic.
|
|
67
67
|
// text - A String of the new topic
|
|
68
68
|
// id - A String of the message ID.
|
|
69
|
-
class TopicMessage extends TextMessage {}
|
|
69
|
+
export class TopicMessage extends TextMessage {}
|
|
70
70
|
|
|
71
|
-
class CatchAllMessage extends Message {
|
|
71
|
+
export class CatchAllMessage extends Message {
|
|
72
72
|
// Represents a message that no matchers matched.
|
|
73
73
|
//
|
|
74
74
|
// message - The original message.
|
|
@@ -78,7 +78,7 @@ class CatchAllMessage extends Message {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
export default {
|
|
82
82
|
Message,
|
|
83
83
|
TextMessage,
|
|
84
84
|
EnterMessage,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import EventEmitter from 'node:events'
|
|
2
2
|
class OptParse extends EventEmitter {
|
|
3
3
|
constructor (switches) {
|
|
4
4
|
super()
|
|
@@ -41,4 +41,4 @@ ${this.switches.map(([key, description]) => ` ${key}, ${description}`).join('\n
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
export default OptParse
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
const EventEmitter = require('events').EventEmitter
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const path = require('path')
|
|
5
|
-
const pathToFileURL = require('url').pathToFileURL
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
import EventEmitter from 'node:events'
|
|
4
|
+
import fs from 'node:fs'
|
|
5
|
+
import path from 'node:path'
|
|
6
|
+
import { pathToFileURL, fileURLToPath } from 'node:url'
|
|
7
|
+
import pino from 'pino'
|
|
8
|
+
import HttpClient from './HttpClient.mjs'
|
|
9
|
+
import Brain from './Brain.mjs'
|
|
10
|
+
import Response from './Response.mjs'
|
|
11
|
+
import { Listener, TextListener } from './Listener.mjs'
|
|
12
|
+
import Message from './Message.mjs'
|
|
13
|
+
import Middleware from './Middleware.mjs'
|
|
14
|
+
|
|
15
|
+
const HUBOT_DEFAULT_ADAPTERS = ['Campfire', 'Shell']
|
|
17
16
|
const HUBOT_DOCUMENTATION_SECTIONS = ['description', 'dependencies', 'configuration', 'commands', 'notes', 'author', 'authors', 'examples', 'tags', 'urls']
|
|
18
17
|
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
19
|
+
const __dirname = path.dirname(__filename)
|
|
20
|
+
|
|
19
21
|
class Robot {
|
|
20
22
|
// Robots receive messages from a chat source (Campfire, irc, etc), and
|
|
21
23
|
// dispatch them to matching listeners.
|
|
@@ -37,6 +39,14 @@ class Robot {
|
|
|
37
39
|
this.brain = new Brain(this)
|
|
38
40
|
this.alias = alias
|
|
39
41
|
this.adapter = null
|
|
42
|
+
this.adaptername = 'Shell'
|
|
43
|
+
if (adapter && typeof (adapter) === 'object') {
|
|
44
|
+
this.adapter = adapter
|
|
45
|
+
this.adapterName = adapter.name ?? adapter.constructor.name
|
|
46
|
+
} else {
|
|
47
|
+
this.adapterName = adapter ?? this.adaptername
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
this.shouldEnableHttpd = httpd ?? true
|
|
41
51
|
this.datastore = null
|
|
42
52
|
this.Response = Response
|
|
@@ -56,7 +66,6 @@ class Robot {
|
|
|
56
66
|
this.globalHttpOptions = {}
|
|
57
67
|
|
|
58
68
|
this.parseVersion()
|
|
59
|
-
this.adapterName = adapter ?? 'shell'
|
|
60
69
|
this.errorHandlers = []
|
|
61
70
|
|
|
62
71
|
this.on('error', (err, res) => {
|
|
@@ -78,7 +87,7 @@ class Robot {
|
|
|
78
87
|
//
|
|
79
88
|
// Returns nothing.
|
|
80
89
|
listen (matcher, options, callback) {
|
|
81
|
-
this.listeners.push(new Listener
|
|
90
|
+
this.listeners.push(new Listener(this, matcher, options, callback))
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
// Public: Adds a Listener that attempts to match incoming messages based on
|
|
@@ -91,7 +100,7 @@ class Robot {
|
|
|
91
100
|
//
|
|
92
101
|
// Returns nothing.
|
|
93
102
|
hear (regex, options, callback) {
|
|
94
|
-
this.listeners.push(new
|
|
103
|
+
this.listeners.push(new TextListener(this, regex, options, callback))
|
|
95
104
|
}
|
|
96
105
|
|
|
97
106
|
// Public: Adds a Listener that attempts to match incoming messages directed
|
|
@@ -320,24 +329,22 @@ class Robot {
|
|
|
320
329
|
}
|
|
321
330
|
|
|
322
331
|
async loadmjs (filePath) {
|
|
323
|
-
const
|
|
332
|
+
const forImport = this.prepareForImport(filePath)
|
|
333
|
+
const script = await import(forImport)
|
|
324
334
|
if (typeof script?.default === 'function') {
|
|
325
335
|
script.default(this)
|
|
326
336
|
} else {
|
|
327
|
-
this.logger.warning(`Expected ${filePath} to assign a function to export default, got ${typeof script}`)
|
|
337
|
+
this.logger.warning(`Expected ${filePath} (after preparing for import ${forImport}) to assign a function to export default, got ${typeof script}`)
|
|
328
338
|
}
|
|
329
339
|
}
|
|
330
340
|
|
|
331
|
-
async loadcoffee (filePath) {
|
|
332
|
-
return await this.loadjs(filePath)
|
|
333
|
-
}
|
|
334
|
-
|
|
335
341
|
async loadjs (filePath) {
|
|
336
|
-
const
|
|
342
|
+
const forImport = this.prepareForImport(filePath)
|
|
343
|
+
const script = (await import(forImport)).default
|
|
337
344
|
if (typeof script === 'function') {
|
|
338
345
|
script(this)
|
|
339
346
|
} else {
|
|
340
|
-
this.logger.warning(`Expected ${filePath} to assign a function to module.exports, got ${typeof script}`)
|
|
347
|
+
this.logger.warning(`Expected ${filePath} (after preparing for import ${forImport}) to assign a function to module.exports, got ${typeof script}`)
|
|
341
348
|
}
|
|
342
349
|
}
|
|
343
350
|
|
|
@@ -352,7 +359,7 @@ class Robot {
|
|
|
352
359
|
const full = path.join(filepath, path.basename(filename))
|
|
353
360
|
|
|
354
361
|
// see https://github.com/hubotio/hubot/issues/1355
|
|
355
|
-
if (['js', 'mjs'
|
|
362
|
+
if (['js', 'mjs'].indexOf(ext) === -1) {
|
|
356
363
|
this.logger.debug(`Skipping unsupported file type ${full}`)
|
|
357
364
|
return
|
|
358
365
|
}
|
|
@@ -386,15 +393,19 @@ class Robot {
|
|
|
386
393
|
// packages - An Array of packages containing hubot scripts to load.
|
|
387
394
|
//
|
|
388
395
|
// Returns nothing.
|
|
389
|
-
loadExternalScripts (packages) {
|
|
396
|
+
async loadExternalScripts (packages) {
|
|
390
397
|
this.logger.debug('Loading external-scripts from npm packages')
|
|
391
398
|
|
|
392
399
|
try {
|
|
393
400
|
if (Array.isArray(packages)) {
|
|
394
|
-
|
|
401
|
+
for await (const pkg of packages) {
|
|
402
|
+
(await import(pkg)).default(this)
|
|
403
|
+
}
|
|
404
|
+
return
|
|
405
|
+
}
|
|
406
|
+
for await (const key of Object.keys(packages)) {
|
|
407
|
+
(await import(key)).default(this, packages[key])
|
|
395
408
|
}
|
|
396
|
-
|
|
397
|
-
Object.keys(packages).forEach(key => require(key)(this, packages[key]))
|
|
398
409
|
} catch (error) {
|
|
399
410
|
this.logger.error(`Error loading scripts from npm package - ${error.stack}`)
|
|
400
411
|
throw error
|
|
@@ -413,9 +424,9 @@ class Robot {
|
|
|
413
424
|
const limit = process.env.EXPRESS_LIMIT || '100kb'
|
|
414
425
|
const paramLimit = parseInt(process.env.EXPRESS_PARAMETER_LIMIT) || 1000
|
|
415
426
|
|
|
416
|
-
const express =
|
|
417
|
-
const basicAuth =
|
|
418
|
-
const multipart =
|
|
427
|
+
const express = (await import('express')).default
|
|
428
|
+
const basicAuth = (await import('express-basic-auth')).default
|
|
429
|
+
const multipart = (await import('connect-multiparty')).default
|
|
419
430
|
|
|
420
431
|
const app = express()
|
|
421
432
|
|
|
@@ -475,19 +486,23 @@ class Robot {
|
|
|
475
486
|
//
|
|
476
487
|
// Returns nothing.
|
|
477
488
|
async loadAdapter (adapterPath = null) {
|
|
489
|
+
if (this.adapter) {
|
|
490
|
+
this.adapter = await this.adapter.use(this)
|
|
491
|
+
return
|
|
492
|
+
}
|
|
478
493
|
this.logger.debug(`Loading adapter ${adapterPath ?? 'from npmjs:'} ${this.adapterName}`)
|
|
479
|
-
const ext = path.extname(adapterPath ?? '') ?? '.
|
|
494
|
+
const ext = path.extname(adapterPath ?? '') ?? '.mjs'
|
|
480
495
|
try {
|
|
481
496
|
if (Array.from(HUBOT_DEFAULT_ADAPTERS).indexOf(this.adapterName) > -1) {
|
|
482
|
-
this.adapter = this.requireAdapterFrom(path.resolve(path.join(__dirname, 'adapters', this.adapterName)))
|
|
483
|
-
} else if (['.js', '.cjs'
|
|
484
|
-
this.adapter = this.requireAdapterFrom(path.resolve(adapterPath))
|
|
497
|
+
this.adapter = await this.requireAdapterFrom(path.resolve(path.join(__dirname, 'adapters', `${this.adapterName}.mjs`)))
|
|
498
|
+
} else if (['.js', '.cjs'].includes(ext)) {
|
|
499
|
+
this.adapter = await this.requireAdapterFrom(path.resolve(adapterPath))
|
|
485
500
|
} else if (['.mjs'].includes(ext)) {
|
|
486
|
-
this.adapter = await this.importAdapterFrom(
|
|
501
|
+
this.adapter = await this.importAdapterFrom(path.resolve(adapterPath))
|
|
487
502
|
} else {
|
|
488
503
|
const adapterPathInCurrentWorkingDirectory = this.adapterName
|
|
489
504
|
try {
|
|
490
|
-
this.adapter = this.requireAdapterFrom(adapterPathInCurrentWorkingDirectory)
|
|
505
|
+
this.adapter = await this.requireAdapterFrom(adapterPathInCurrentWorkingDirectory)
|
|
491
506
|
} catch (err) {
|
|
492
507
|
if (err.name === 'SyntaxError') {
|
|
493
508
|
this.adapter = await this.importAdapterFrom(adapterPathInCurrentWorkingDirectory)
|
|
@@ -502,12 +517,13 @@ class Robot {
|
|
|
502
517
|
}
|
|
503
518
|
}
|
|
504
519
|
|
|
505
|
-
requireAdapterFrom (adapaterPath) {
|
|
506
|
-
return
|
|
520
|
+
async requireAdapterFrom (adapaterPath) {
|
|
521
|
+
return await this.importAdapterFrom(adapaterPath)
|
|
507
522
|
}
|
|
508
523
|
|
|
509
524
|
async importAdapterFrom (adapterPath) {
|
|
510
|
-
|
|
525
|
+
const forImport = this.prepareForImport(adapterPath)
|
|
526
|
+
return await (await import(forImport)).default.use(this)
|
|
511
527
|
}
|
|
512
528
|
|
|
513
529
|
// Public: Help Commands for Running Scripts.
|
|
@@ -519,12 +535,12 @@ class Robot {
|
|
|
519
535
|
|
|
520
536
|
// Private: load help info from a loaded script.
|
|
521
537
|
//
|
|
522
|
-
//
|
|
538
|
+
// filePath - A String path to the file on disk.
|
|
523
539
|
//
|
|
524
540
|
// Returns nothing.
|
|
525
|
-
parseHelp (
|
|
541
|
+
parseHelp (filePath) {
|
|
526
542
|
const scriptDocumentation = {}
|
|
527
|
-
const body = fs.readFileSync(
|
|
543
|
+
const body = fs.readFileSync(path.resolve(filePath), 'utf-8')
|
|
528
544
|
|
|
529
545
|
const useStrictHeaderRegex = /^["']use strict['"];?\s+/
|
|
530
546
|
const lines = body.replace(useStrictHeaderRegex, '').split(/(?:\n|\r\n|\r)/)
|
|
@@ -657,11 +673,15 @@ class Robot {
|
|
|
657
673
|
this.events.removeAllListeners()
|
|
658
674
|
}
|
|
659
675
|
|
|
676
|
+
prepareForImport (filePath) {
|
|
677
|
+
return pathToFileURL(filePath)
|
|
678
|
+
}
|
|
679
|
+
|
|
660
680
|
// Public: The version of Hubot from npm
|
|
661
681
|
//
|
|
662
682
|
// Returns a String of the version number.
|
|
663
683
|
parseVersion () {
|
|
664
|
-
const pkg =
|
|
684
|
+
const pkg = fs.readFileSync(path.join(__dirname, '..', 'package.json'))
|
|
665
685
|
this.version = pkg.version
|
|
666
686
|
|
|
667
687
|
return this.version
|
|
@@ -720,8 +740,6 @@ class Robot {
|
|
|
720
740
|
}
|
|
721
741
|
}
|
|
722
742
|
|
|
723
|
-
module.exports = Robot
|
|
724
|
-
|
|
725
743
|
function isCatchAllMessage (message) {
|
|
726
744
|
return message instanceof Message.CatchAllMessage
|
|
727
745
|
}
|
|
@@ -748,9 +766,7 @@ function removeCommentPrefix (line) {
|
|
|
748
766
|
return line.replace(/^[#/]+\s*/, '')
|
|
749
767
|
}
|
|
750
768
|
|
|
751
|
-
function extend (obj
|
|
752
|
-
const sources = [].slice.call(arguments, 1)
|
|
753
|
-
|
|
769
|
+
function extend (obj, ...sources) {
|
|
754
770
|
sources.forEach((source) => {
|
|
755
771
|
if (typeof source !== 'object') {
|
|
756
772
|
return
|
|
@@ -763,3 +779,5 @@ function extend (obj/* , ...sources */) {
|
|
|
763
779
|
|
|
764
780
|
return obj
|
|
765
781
|
}
|
|
782
|
+
|
|
783
|
+
export default Robot
|
package/src/{user.js → User.mjs}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { DataStoreUnavailable } from './DataStore.mjs'
|
|
4
4
|
|
|
5
5
|
class User {
|
|
6
6
|
// Represents a participating user in the chat.
|
|
@@ -62,4 +62,4 @@ class User {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
export default User
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const Message = require('../message')
|
|
9
|
-
|
|
10
|
-
const TextMessage = Message.TextMessage
|
|
11
|
-
const EnterMessage = Message.EnterMessage
|
|
12
|
-
const LeaveMessage = Message.LeaveMessage
|
|
13
|
-
const TopicMessage = Message.TopicMessage
|
|
3
|
+
import HTTPS from 'node:https'
|
|
4
|
+
import EventEmitter from 'node:events'
|
|
5
|
+
import Adapter from '../Adapter.mjs'
|
|
6
|
+
import { TextMessage, EnterMessage, LeaveMessage, TopicMessage } from '../Message.mjs'
|
|
14
7
|
|
|
15
8
|
class Campfire extends Adapter {
|
|
16
9
|
send (envelope/* , ...strings */) {
|
|
@@ -157,8 +150,6 @@ class Campfire extends Adapter {
|
|
|
157
150
|
}
|
|
158
151
|
}
|
|
159
152
|
|
|
160
|
-
exports.use = robot => new Campfire(robot)
|
|
161
|
-
|
|
162
153
|
class CampfireStreaming extends EventEmitter {
|
|
163
154
|
constructor (options, robot) {
|
|
164
155
|
super()
|
|
@@ -392,3 +383,9 @@ class CampfireStreaming extends EventEmitter {
|
|
|
392
383
|
return request.on('error', err => logger.error(`Campfire request error: ${err}`))
|
|
393
384
|
}
|
|
394
385
|
}
|
|
386
|
+
|
|
387
|
+
export default {
|
|
388
|
+
use (robot) {
|
|
389
|
+
return new Campfire(robot)
|
|
390
|
+
}
|
|
391
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import readline from 'node:readline'
|
|
5
|
+
import Adapter from '../Adapter.mjs'
|
|
6
|
+
import { TextMessage } from '../Message.mjs'
|
|
7
7
|
|
|
8
8
|
const historySize = process.env.HUBOT_SHELL_HISTSIZE != null ? parseInt(process.env.HUBOT_SHELL_HISTSIZE) : 1024
|
|
9
9
|
const historyPath = '.hubot_history'
|
|
@@ -16,7 +16,7 @@ const completer = line => {
|
|
|
16
16
|
}
|
|
17
17
|
const showHelp = () => {
|
|
18
18
|
console.log('usage:')
|
|
19
|
-
console.log('\\q, exit - close
|
|
19
|
+
console.log('\\q, exit - close Shell and exit')
|
|
20
20
|
console.log('\\?, help - show this help')
|
|
21
21
|
console.log('\\c, clear - clear screen')
|
|
22
22
|
}
|
|
@@ -112,4 +112,8 @@ class Shell extends Adapter {
|
|
|
112
112
|
|
|
113
113
|
// Prevent output buffer "swallowing" every other character on OSX / Node version > 16.19.0.
|
|
114
114
|
process.stdout._handle.setBlocking(false)
|
|
115
|
-
|
|
115
|
+
export default {
|
|
116
|
+
use (robot) {
|
|
117
|
+
return new Shell(robot)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { DataStore } from '../DataStore.mjs'
|
|
4
4
|
|
|
5
5
|
class InMemoryDataStore extends DataStore {
|
|
6
6
|
constructor (robot) {
|
|
@@ -20,4 +20,4 @@ class InMemoryDataStore extends DataStore {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
export default InMemoryDataStore
|
package/es2015.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const User = require('./src/user')
|
|
4
|
-
const Brain = require('./src/brain')
|
|
5
|
-
const Robot = require('./src/robot')
|
|
6
|
-
const Adapter = require('./src/adapter')
|
|
7
|
-
const Response = require('./src/response')
|
|
8
|
-
const Listener = require('./src/listener')
|
|
9
|
-
const Message = require('./src/message')
|
|
10
|
-
const DataStore = require('./src/datastore')
|
|
11
|
-
|
|
12
|
-
module.exports = {
|
|
13
|
-
User,
|
|
14
|
-
Brain,
|
|
15
|
-
Robot,
|
|
16
|
-
Adapter,
|
|
17
|
-
Response,
|
|
18
|
-
Listener: Listener.Listener,
|
|
19
|
-
TextListener: Listener.TextListener,
|
|
20
|
-
Message: Message.Message,
|
|
21
|
-
TextMessage: Message.TextMessage,
|
|
22
|
-
EnterMessage: Message.EnterMessage,
|
|
23
|
-
LeaveMessage: Message.LeaveMessage,
|
|
24
|
-
TopicMessage: Message.TopicMessage,
|
|
25
|
-
CatchAllMessage: Message.CatchAllMessage,
|
|
26
|
-
DataStore: DataStore.DataStore,
|
|
27
|
-
DataStoreUnavailable: DataStore.DataStoreUnavailable,
|
|
28
|
-
loadBot (adapter, enableHttpd, name, alias) {
|
|
29
|
-
return new module.exports.Robot(adapter, enableHttpd, name, alias)
|
|
30
|
-
}
|
|
31
|
-
}
|
package/index.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
require('coffeescript/register')
|
|
3
|
-
|
|
4
|
-
const inherits = require('util').inherits
|
|
5
|
-
|
|
6
|
-
const hubotExport = require('./es2015')
|
|
7
|
-
|
|
8
|
-
// make all es2015 class declarations compatible with CoffeeScript’s extend
|
|
9
|
-
// see https://github.com/hubotio/evolution/pull/4#issuecomment-306437501
|
|
10
|
-
module.exports = Object.keys(hubotExport).reduce((map, current) => {
|
|
11
|
-
if (current !== 'loadBot') {
|
|
12
|
-
map[current] = makeClassCoffeeScriptCompatible(hubotExport[current])
|
|
13
|
-
} else {
|
|
14
|
-
map[current] = hubotExport[current]
|
|
15
|
-
}
|
|
16
|
-
return map
|
|
17
|
-
}, {})
|
|
18
|
-
|
|
19
|
-
function makeClassCoffeeScriptCompatible (klass) {
|
|
20
|
-
function CoffeeScriptCompatibleClass () {
|
|
21
|
-
const Hack = Function.prototype.bind.apply(klass, [null].concat([].slice.call(arguments)))
|
|
22
|
-
const instance = new Hack()
|
|
23
|
-
|
|
24
|
-
// pass methods from child to returned instance
|
|
25
|
-
for (const key in this) {
|
|
26
|
-
instance[key] = this[key]
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// support for constructor methods which call super()
|
|
30
|
-
// in which this.* properties are set
|
|
31
|
-
for (const key in instance) {
|
|
32
|
-
this[key] = instance[key]
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return instance
|
|
36
|
-
}
|
|
37
|
-
inherits(CoffeeScriptCompatibleClass, klass)
|
|
38
|
-
|
|
39
|
-
return CoffeeScriptCompatibleClass
|
|
40
|
-
}
|