parent
76b22c2962
commit
2678365dfe
@ -0,0 +1,85 @@ |
||||
RocketChat.API.v1.addRoute('commands.getOne', { authRequired: true }, { |
||||
get() { |
||||
const params = this.queryParams; |
||||
|
||||
if (typeof params.command !== 'string') { |
||||
return RocketChat.API.v1.failure('The query param "command" must be provided.'); |
||||
} |
||||
|
||||
const cmd = RocketChat.slashCommands.commands[params.command.toLowerCase()]; |
||||
|
||||
if (!cmd) { |
||||
return RocketChat.API.v1.failure(`There is no command in the system by the name of: ${ params.command }`); |
||||
} |
||||
|
||||
return RocketChat.API.v1.success({ command: cmd }); |
||||
} |
||||
}); |
||||
|
||||
RocketChat.API.v1.addRoute('commands.list', { authRequired: true }, { |
||||
get() { |
||||
const { offset, count } = this.getPaginationItems(); |
||||
const { sort, fields, query } = this.parseJsonQuery(); |
||||
|
||||
let commands = Object.values(RocketChat.slashCommands.commands); |
||||
|
||||
if (query.command) { |
||||
commands = commands.filter((command) => command.command === query.command); |
||||
} |
||||
|
||||
const totalCount = commands.length; |
||||
commands = RocketChat.models.Rooms.processQueryOptionsOnResult(commands, { |
||||
sort: sort ? sort : { name: 1 }, |
||||
skip: offset, |
||||
limit: count, |
||||
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude) |
||||
}); |
||||
|
||||
return RocketChat.API.v1.success({ |
||||
commands, |
||||
offset, |
||||
count: commands.length, |
||||
total: totalCount |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
// Expects a body of: { command: 'gimme', params: 'any string value', roomId: 'value' }
|
||||
RocketChat.API.v1.addRoute('commands.run', { authRequired: true }, { |
||||
post() { |
||||
const body = this.bodyParams; |
||||
const user = this.getLoggedInUser(); |
||||
|
||||
if (typeof body.command !== 'string') { |
||||
return RocketChat.API.v1.failure('You must provide a command to run.'); |
||||
} |
||||
|
||||
if (body.params && typeof body.params !== 'string') { |
||||
return RocketChat.API.v1.failure('The parameters for the command must be a single string.'); |
||||
} |
||||
const params = body.params ? body.params : ''; |
||||
|
||||
if (typeof body.roomId !== 'string') { |
||||
return RocketChat.API.v1.failure('The room\'s id where to execute this command must provided and be a string.'); |
||||
} |
||||
|
||||
const cmd = body.command.toLowerCase(); |
||||
if (!RocketChat.slashCommands.commands[body.command.toLowerCase()]) { |
||||
return RocketChat.API.v1.failure('The command provided does not exist (or is disabled).'); |
||||
} |
||||
|
||||
// This will throw an error if they can't or the room is invalid
|
||||
Meteor.call('canAccessRoom', body.roomId, user._id); |
||||
|
||||
let result; |
||||
Meteor.runAsUser(user._id, () => { |
||||
result = RocketChat.slashCommands.run(cmd, params, { |
||||
_id: Random.id(), |
||||
rid: body.roomId, |
||||
msg: `/${ cmd } ${ params }` |
||||
}); |
||||
}); |
||||
|
||||
return RocketChat.API.v1.success({ result }); |
||||
} |
||||
}); |
@ -0,0 +1 @@ |
||||
.npm |
@ -0,0 +1,12 @@ |
||||
export class RocketletWebsocketReceiver { |
||||
constructor(restApi) { |
||||
this.rest = restApi; |
||||
this.streamer = new Meteor.Streamer('rocketlets'); |
||||
|
||||
this.streamer.on('command/added', this.onCommandAdded); |
||||
} |
||||
|
||||
onCommandAdded(command) { |
||||
console.log('Added:', command); |
||||
} |
||||
} |
@ -0,0 +1,2 @@ |
||||
// Please see both server and client's repsective "orchestrator" file for the contents
|
||||
Rocketlets = {}; |
@ -0,0 +1,41 @@ |
||||
Package.describe({ |
||||
name: 'rocketchat:rocketlets', |
||||
version: '1.0.0' |
||||
}); |
||||
|
||||
Package.onUse(function(api) { |
||||
api.use([ |
||||
'ecmascript', |
||||
'rocketchat:lib', |
||||
'rocketchat:api' |
||||
]); |
||||
|
||||
api.addFiles('lib/Rocketlets.js', ['client', 'server']); |
||||
|
||||
api.addFiles('server/orchestrator.js', 'server'); |
||||
|
||||
api.addFiles('server/models/Rocketlets.js', 'server'); |
||||
|
||||
// Bridges
|
||||
api.addFiles([ |
||||
'server/bridges/commands.js' |
||||
], 'server'); |
||||
|
||||
// Communication pieces
|
||||
api.addFiles([ |
||||
'server/communication/rest.js', |
||||
'server/communication/websockets.js' |
||||
], 'server'); |
||||
|
||||
// Client communication pieces
|
||||
api.addFiles([ |
||||
'client/communication/websockets.js' |
||||
], 'client'); |
||||
|
||||
api.export('Rocketlets'); |
||||
}); |
||||
|
||||
Npm.depends({ |
||||
'temporary-rocketlets-server': '0.1.11', |
||||
'temporary-rocketlets-ts-definition': '0.6.2' |
||||
}); |
@ -0,0 +1,84 @@ |
||||
export class RocketletCommandsBridge { |
||||
constructor(converters) { |
||||
console.log('CommandsBridge constructor'); |
||||
this.converters = converters; |
||||
this.disabledCommands = new Map(); |
||||
} |
||||
|
||||
doesCommandExist(command, rocketletId) { |
||||
console.log(`The Rocketlet ${ rocketletId } is check if "${ command }" command exists.`); |
||||
|
||||
if (typeof command !== 'string') { |
||||
return false; |
||||
} |
||||
|
||||
return typeof RocketChat.slashCommands.commands[command.toLowerCase()] === 'object'; |
||||
} |
||||
|
||||
disableCommand(command, rocketletId) { |
||||
console.log(`The Rocketlet ${ rocketletId } is attempting to disable the command: "${ command }"`); |
||||
|
||||
if (typeof command !== 'string' || command.trim().length === 0) { |
||||
throw new Error('Invalid command parameter provided, must be a string.'); |
||||
} |
||||
|
||||
const cmd = command.toLowerCase(); |
||||
if (typeof RocketChat.slashCommands.commands[cmd] === 'undefined') { |
||||
throw new Error(`Command does not exist in the system currently (or it is disabled): ${ cmd }`); |
||||
} |
||||
|
||||
this.disabledCommands.set(cmd, RocketChat.slashCommands.commands[cmd]); |
||||
delete RocketChat.slashCommands.commands[cmd]; |
||||
|
||||
Rocketlets.getNotifier().commandDisabled(cmd); |
||||
} |
||||
|
||||
// command: { command, paramsExample, i18nDescription, executor: function }
|
||||
modifyCommand(command, rocketletId) { |
||||
console.log(`The Rocketlet ${ rocketletId } is attempting to modify the command: "${ command }"`); |
||||
|
||||
this._verifyCommand(command); |
||||
|
||||
const cmd = command.toLowerCase(); |
||||
if (typeof RocketChat.slashCommands.commands[cmd] === 'undefined') { |
||||
throw new Error(`Command does not exist in the system currently (or it is disabled): ${ cmd }`); |
||||
} |
||||
|
||||
const item = RocketChat.slashCommands.commands[cmd]; |
||||
item.params = command.paramsExample ? command.paramsExample : item.params; |
||||
item.description = command.i18nDescription ? command.i18nDescription : item.params; |
||||
item.callback = this._executorWrapper(command.executor); |
||||
|
||||
} |
||||
|
||||
_verifyCommand(command) { |
||||
if (typeof command !== 'object') { |
||||
throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); |
||||
} |
||||
|
||||
if (typeof command.command !== 'string') { |
||||
throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); |
||||
} |
||||
|
||||
if (command.paramsExample && typeof command.paramsExample !== 'string') { |
||||
throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); |
||||
} |
||||
|
||||
if (command.i18nDescription && typeof command.i18nDescription !== 'string') { |
||||
throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); |
||||
} |
||||
|
||||
if (typeof command.executor !== 'function') { |
||||
throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); |
||||
} |
||||
} |
||||
|
||||
_executorWrapper(executor) { |
||||
return function _wrappedExecutor(command, params, message) { |
||||
// TODO: Converters
|
||||
this.converters.get('messages').translate(message); |
||||
|
||||
executor(command); |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,3 @@ |
||||
import { RocketletCommandsBridge } from './commands'; |
||||
|
||||
export { RocketletCommandsBridge }; |
@ -0,0 +1,5 @@ |
||||
import { RocketletWebsocketNotifier } from './websockets'; |
||||
|
||||
export { |
||||
RocketletWebsocketNotifier |
||||
}; |
@ -0,0 +1,8 @@ |
||||
/* Rocketlets.API = new RocketChat.API.ApiClass({ |
||||
version: 'rocketlets', |
||||
useDefaultAuth: true, |
||||
prettyJson: true, |
||||
enableCors: false, |
||||
auth: RocketChat.API.getUserAuth() |
||||
}); |
||||
*/ |
@ -0,0 +1,16 @@ |
||||
export class RocketletWebsocketNotifier { |
||||
constructor() { |
||||
this.streamer = new Meteor.Streamer('rocketlets', { retransmit: false }); |
||||
this.streamer.allowRead('all'); |
||||
this.streamer.allowEmit('all'); |
||||
this.streamer.allowWrite('none'); |
||||
} |
||||
|
||||
commandAdded(command) { |
||||
this.streamer.emit('command/added', command); |
||||
} |
||||
|
||||
commandDisabled(command) { |
||||
this.streamer.emit('command/disabled', command); |
||||
} |
||||
} |
@ -0,0 +1,9 @@ |
||||
import { RocketletMessagesConverter } from './messages'; |
||||
import { RocketletRoomsConverter } from './rooms'; |
||||
import { RocketletUsersConverter } from './users'; |
||||
|
||||
export { |
||||
RocketletMessagesConverter, |
||||
RocketletRoomsConverter, |
||||
RocketletUsersConverter |
||||
}; |
@ -0,0 +1,21 @@ |
||||
export class RocketletMessagesConverter { |
||||
constructor(converters) { |
||||
this.converters = converters; |
||||
} |
||||
|
||||
convertById(msgId) { |
||||
const msg = RocketChat.models.Messages.getOneById(msgId); |
||||
|
||||
return { |
||||
id: msg._id, |
||||
text: msg.msg |
||||
}; |
||||
} |
||||
|
||||
convertMessage(msgObj) { |
||||
return { |
||||
id: msgObj._id, |
||||
text: msgObj.msg |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
export class RocketletRoomsConverter { |
||||
constructor(converters) { |
||||
this.converters = converters; |
||||
} |
||||
|
||||
convertById(roomId) { |
||||
const room = RocketChat.models.Rooms.findOneById(roomId); |
||||
|
||||
return { |
||||
id: room._id |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
export class RocketletUsersConverter { |
||||
constructor(converters) { |
||||
this.converters = converters; |
||||
} |
||||
|
||||
convertById(userId) { |
||||
const user = RocketChat.models.Users.findOneById(userId); |
||||
|
||||
return { |
||||
id: user._id |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,5 @@ |
||||
export class RocketletsModel extends RocketChat.models._Base { |
||||
constructor() { |
||||
super('rocketlets'); |
||||
} |
||||
} |
@ -0,0 +1,42 @@ |
||||
import { RocketletCommandsBridge } from './bridges'; |
||||
import { RocketletWebsocketNotifier } from './communication'; |
||||
import { RocketletMessagesConverter, RocketletRoomsConverter } from './converters'; |
||||
import { RocketletsModel } from './models/Rocketlets'; |
||||
|
||||
class RocketletServerOrchestrator { |
||||
constructor() { |
||||
this._model = new RocketletsModel(); |
||||
|
||||
this._converters = new Map(); |
||||
this._converters.set('messages', new RocketletMessagesConverter(this._converters)); |
||||
this._converters.set('rooms', new RocketletRoomsConverter(this._converters)); |
||||
|
||||
this._bridges = new Map(); |
||||
this._bridges.set('commands', new RocketletCommandsBridge(this._converters)); |
||||
|
||||
this._communicators = new Map(); |
||||
this._communicators.set('notifier', new RocketletWebsocketNotifier()); |
||||
} |
||||
|
||||
getModel() { |
||||
return this._model; |
||||
} |
||||
|
||||
getConverters() { |
||||
return this._converters; |
||||
} |
||||
|
||||
getBridges() { |
||||
return this._bridges; |
||||
} |
||||
|
||||
getNotifier() { |
||||
return this._communicators.get('notifier'); |
||||
} |
||||
} |
||||
|
||||
Meteor.startup(function _rocketletServerOrchestrator() { |
||||
console.log('Orchestrating the rocketlet piece...'); |
||||
Rocketlets = new RocketletServerOrchestrator(); |
||||
console.log('...done! :)'); |
||||
}); |
Loading…
Reference in new issue