Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apps: Command Previews, Message and Room Removal Events #10822

Merged
merged 6 commits into from
May 21, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 79 additions & 1 deletion packages/rocketchat-api/server/v1/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ RocketChat.API.v1.addRoute('commands.run', { authRequired: true }, {
}

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.');
return RocketChat.API.v1.failure('The room\'s id where to execute this command must be provided and be a string.');
}

const cmd = body.command.toLowerCase();
Expand All @@ -84,3 +84,81 @@ RocketChat.API.v1.addRoute('commands.run', { authRequired: true }, {
return RocketChat.API.v1.success({ result });
}
});

RocketChat.API.v1.addRoute('commands.preview', { authRequired: true }, {
// Expects these query params: command: 'giphy', params: 'mine', roomId: 'value'
get() {
const query = this.queryParams;
const user = this.getLoggedInUser();

if (typeof query.command !== 'string') {
return RocketChat.API.v1.failure('You must provide a command to get the previews from.');
}

if (query.params && typeof query.params !== 'string') {
return RocketChat.API.v1.failure('The parameters for the command must be a single string.');
}

if (typeof query.roomId !== 'string') {
return RocketChat.API.v1.failure('The room\'s id where the previews are being displayed must be provided and be a string.');
}

const cmd = query.command.toLowerCase();
if (!RocketChat.slashCommands.commands[query.command.toLowerCase()]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to repeat query.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', query.roomId, user._id);

const params = query.params ? query.params : '';

let preview;
Meteor.runAsUser(user._id, () => {
preview = Meteor.call('getSlashCommandPreviews', { cmd, params, msg: { rid: query.roomId } });
});

return RocketChat.API.v1.success({ preview });
},
// Expects a body format of: { command: 'giphy', params: 'mine', roomId: 'value', previewItem: { id: 'sadf8' type: 'image', value: 'https://dev.null/gif } }
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 the preview item on.');
}

if (body.params && typeof body.params !== 'string') {
return RocketChat.API.v1.failure('The parameters for the command must be a single string.');
}

if (typeof body.roomId !== 'string') {
return RocketChat.API.v1.failure('The room\'s id where the preview is being executed in must be provided and be a string.');
}

if (typeof body.previewItem === 'undefined') {
return RocketChat.API.v1.failure('The preview item being executed must be provided.');
}

if (!body.previewItem.id || !body.previewItem.type || typeof body.previewItem.value === 'undefined') {
return RocketChat.API.v1.failure('The preview item being executed is in the wrong format.');
}

const cmd = body.command.toLowerCase();
if (!RocketChat.slashCommands.commands[body.command.toLowerCase()]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to repeat 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);

const params = body.params ? body.params : '';

Meteor.runAsUser(user._id, () => {
Meteor.call('executeSlashCommandPreview', { cmd, params, msg: { rid: body.roomId } }, body.previewItem);
});

return RocketChat.API.v1.success();
}
});
28 changes: 20 additions & 8 deletions packages/rocketchat-apps/client/admin/appInstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,26 @@ Template.appInstall.events({
if (url) {
try {
t.isInstalling.set(true);
const isUpdating = t.isUpdatingId.get();
let result;

if (t.isUpdatingId.get()) {
if (isUpdating) {
result = await RocketChat.API.post(`apps/${ t.isUpdatingId.get() }`, { url });
} else {
result = await RocketChat.API.post('apps', { url });
}

FlowRouter.go(`/admin/apps/${ result.app.id }`);
if (result.compilerErrors.length !== 0 || result.app.status === 'compiler_error') {
console.warn(`The App contains errors and could not be ${ isUpdating ? 'updated' : 'installed' }.`);
} else {
FlowRouter.go(`/admin/apps/${ result.app.id }`);
}
} catch (err) {
console.warn('err', err);
} finally {
t.isInstalling.set(false);
}

t.isInstalling.set(false);

return;
}

Expand All @@ -103,19 +108,26 @@ Template.appInstall.events({

t.isInstalling.set(true);
try {
const isUpdating = t.isUpdatingId.get();
let result;

if (t.isUpdatingId.get()) {
if (isUpdating) {
result = await RocketChat.API.upload(`apps/${ t.isUpdatingId.get() }`, data);
} else {
result = await RocketChat.API.upload('apps', data);
}

FlowRouter.go(`/admin/apps/${ result.app.id }`);
console.log('install result', result);

if (result.compilerErrors.length !== 0 || result.app.status === 'compiler_error') {
console.warn(`The App contains errors and could not be ${ isUpdating ? 'updated' : 'installed' }.`);
} else {
FlowRouter.go(`/admin/apps/${ result.app.id }`);
}
} catch (err) {
console.warn('err', err);
} finally {
t.isInstalling.set(false);
}

t.isInstalling.set(false);
}
});
11 changes: 7 additions & 4 deletions packages/rocketchat-apps/client/admin/appManage.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,14 @@ Template.appManage.events({
}

const setting = t.settings.get()[this.id];
setting.value = value;

if (setting.oldValue !== setting.value) {
t.settings.get()[this.id].hasChanged = true;
t.settings.set(t.settings.get());
if (setting) {
setting.value = value;

if (setting.oldValue !== setting.value) {
t.settings.get()[this.id].hasChanged = true;
t.settings.set(t.settings.get());
}
}
}, 500)
});
4 changes: 2 additions & 2 deletions packages/rocketchat-apps/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,6 @@ Package.onUse(function(api) {

Npm.depends({
'busboy': '0.2.13',
'@rocket.chat/apps-engine': '0.5.11',
'@rocket.chat/apps-ts-definition': '0.9.8'
'@rocket.chat/apps-engine': '0.6.7',
'@rocket.chat/apps-ts-definition': '0.9.13'
});
36 changes: 32 additions & 4 deletions packages/rocketchat-apps/server/bridges/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,27 @@ export class AppCommandsBridge {
item.params = command.paramsExample ? command.paramsExample : item.params;
item.description = command.i18nDescription ? command.i18nDescription : item.params;
item.callback = this._appCommandExecutor.bind(this);
item.providesPreview = command.providesPreview;
item.previewer = command.previewer ? this._appCommandPreviewer.bind(this) : item.previewer;
item.previewCallback = command.executePreviewItem ? this._appCommandPreviewExecutor.bind(this) : item.previewCallback;

RocketChat.slashCommands.commands[cmd] = item;
this.orch.getNotifier().commandUpdated(cmd);
}

registerCommand(command, appId) {
console.log(`The App ${ appId } is registering the command: "${ command.command }"`);
console.log(`The App ${ appId } is registerin the command: "${ command.command }"`);

this._verifyCommand(command);

const item = {
command: command.command.toLowerCase(),
params: command.paramsExample,
description: command.i18nDescription,
callback: this._appCommandExecutor.bind(this)
callback: this._appCommandExecutor.bind(this),
providesPreview: command.providesPreview,
previewer: !command.previewer ? undefined : this._appCommandPreviewer.bind(this),
previewCallback: !command.executePreviewItem ? undefined : this._appCommandPreviewExecutor.bind(this)
};

RocketChat.slashCommands.commands[command.command.toLowerCase()] = item;
Expand Down Expand Up @@ -117,14 +123,18 @@ export class AppCommandsBridge {
throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.');
}

if (command.paramsExample && typeof command.paramsExample !== 'string') {
if (command.i18nParamsExample && typeof command.i18nParamsExample !== '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.providesPreview !== 'boolean') {
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.');
}
Expand All @@ -136,6 +146,24 @@ export class AppCommandsBridge {
const params = parameters.length === 0 || parameters === ' ' ? [] : parameters.split(' ');

const context = new SlashCommandContext(Object.freeze(user), Object.freeze(room), Object.freeze(params));
this.orch.getManager().getCommandManager().executeCommand(command, context);
Promise.await(this.orch.getManager().getCommandManager().executeCommand(command, context));
}

_appCommandPreviewer(command, parameters, message) {
const user = this.orch.getConverters().get('users').convertById(Meteor.userId());
const room = this.orch.getConverters().get('rooms').convertById(message.rid);
const params = parameters.length === 0 || parameters === ' ' ? [] : parameters.split(' ');

const context = new SlashCommandContext(Object.freeze(user), Object.freeze(room), Object.freeze(params));
return Promise.await(this.orch.getManager().getCommandManager().getPreviews(command, context));
}

_appCommandPreviewExecutor(command, parameters, message, preview) {
const user = this.orch.getConverters().get('users').convertById(Meteor.userId());
const room = this.orch.getConverters().get('rooms').convertById(message.rid);
const params = parameters.length === 0 || parameters === ' ' ? [] : parameters.split(' ');

const context = new SlashCommandContext(Object.freeze(user), Object.freeze(room), Object.freeze(params));
Promise.await(this.orch.getManager().getCommandManager().executePreview(command, preview, context));
}
}
24 changes: 24 additions & 0 deletions packages/rocketchat-apps/server/bridges/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,30 @@ export class AppRoomBridge {
return this.orch.getConverters().get('rooms').convertByName(roomName);
}

async getCreatorById(roomId, appId) {
console.log(`The App ${ appId } is getting the room's creator by id: "${ roomId }"`);

const room = RocketChat.models.Rooms.findOneById(roomId);

if (!room || !room.u || !room.u._id) {
return undefined;
}

return this.orch.getConverters().get('users').convertById(room.u._id);
}

async getCreatorByName(roomName, appId) {
console.log(`The App ${ appId } is getting the room's creator by name: "${ roomName }"`);

const room = RocketChat.models.Rooms.findOneByName(roomName);

if (!room || !room.u || !room.u._id) {
return undefined;
}

return this.orch.getConverters().get('users').convertById(room.u._id);
}

async update(room, appId) {
console.log(`The App ${ appId } is updating a room.`);

Expand Down
16 changes: 14 additions & 2 deletions packages/rocketchat-apps/server/communication/rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,13 @@ export class AppsRestApi {

const aff = Promise.await(manager.add(buff.toString('base64'), false));
const info = aff.getAppInfo();
info.status = aff.getApp().getStatus();

// If there are compiler errors, there won't be an App to get the status of
if (aff.getApp()) {
info.status = aff.getApp().getStatus();
} else {
info.status = 'compiler_error';
}

return RocketChat.API.v1.success({
app: info,
Expand Down Expand Up @@ -134,7 +140,13 @@ export class AppsRestApi {

const aff = Promise.await(manager.update(buff.toString('base64')));
const info = aff.getAppInfo();
info.status = aff.getApp().getStatus();

// Should the updated version have compiler errors, no App will be returned
if (aff.getApp()) {
info.status = aff.getApp().getStatus();
} else {
info.status = 'compiler_error';
}

return RocketChat.API.v1.success({
app: info,
Expand Down
12 changes: 12 additions & 0 deletions packages/rocketchat-apps/server/storage/logs-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,16 @@ export class AppRealLogsStorage extends AppLogStorage {
resolve(docs);
});
}

removeEntriesFor(appId) {
return new Promise((resolve, reject) => {
try {
this.db.remove({ appId });
} catch (e) {
return reject(e);
}

resolve();
});
}
}
Loading