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

Add a few listener supports for the Rocket.Chat Apps #10154

Merged
merged 3 commits into from
Mar 16, 2018
Merged
Show file tree
Hide file tree
Changes from all 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
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.4.0',
'@rocket.chat/apps-ts-definition': '0.7.6'
'@rocket.chat/apps-engine': '0.4.8',
'@rocket.chat/apps-ts-definition': '0.7.15'
});
6 changes: 6 additions & 0 deletions packages/rocketchat-apps/server/bridges/bridges.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AppDetailChangesBridge } from './details';
import { AppCommandsBridge } from './commands';
import { AppEnvironmentalVariableBridge } from './environmental';
import { AppHttpBridge } from './http';
import { AppListenerBridge } from './listeners';
import { AppMessageBridge } from './messages';
import { AppPersistenceBridge } from './persistence';
import { AppRoomBridge } from './rooms';
Expand All @@ -20,6 +21,7 @@ export class RealAppBridges extends AppBridges {
this._detBridge = new AppDetailChangesBridge(orch);
this._envBridge = new AppEnvironmentalVariableBridge(orch);
this._httpBridge = new AppHttpBridge();
this._lisnBridge = new AppListenerBridge(orch);
this._msgBridge = new AppMessageBridge(orch);
this._persistBridge = new AppPersistenceBridge(orch);
this._roomBridge = new AppRoomBridge(orch);
Expand All @@ -39,6 +41,10 @@ export class RealAppBridges extends AppBridges {
return this._httpBridge;
}

getListenerBridge() {
return this._lisnBridge;
}

getMessageBridge() {
return this._msgBridge;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/rocketchat-apps/server/bridges/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AppActivationBridge } from './activation';
import { AppCommandsBridge } from './commands';
import { AppEnvironmentalVariableBridge } from './environmental';
import { AppHttpBridge } from './http';
import { AppListenerBridge } from './listeners';
import { AppMessageBridge } from './messages';
import { AppPersistenceBridge } from './persistence';
import { AppRoomBridge } from './rooms';
Expand All @@ -15,6 +16,7 @@ export {
AppCommandsBridge,
AppEnvironmentalVariableBridge,
AppHttpBridge,
AppListenerBridge,
AppMessageBridge,
AppPersistenceBridge,
AppRoomBridge,
Expand Down
15 changes: 15 additions & 0 deletions packages/rocketchat-apps/server/bridges/listeners.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export class AppListenerBridge {
constructor(orch) {
this.orch = orch;
}

messageEvent(inte, message) {
const msg = this.orch.getConverters().get('messages').convertMessage(message);
return this.orch.getManager().getListenerManager().executeListener(inte, msg);
}

roomEvent(inte, room) {
const rm = this.orch.getConverters().get('rooms').convertRoom(room);
return this.orch.getManager().getListenerManager().executeListener(inte, rm);
}
}
26 changes: 26 additions & 0 deletions packages/rocketchat-apps/server/bridges/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,30 @@ export class AppMessageBridge {

RocketChat.updateMessage(msg, editor);
}

notifyUser(user, message, appId) {
console.log(`The App ${ appId } is notifying a user.`);

const msg = this.orch.getConverters().get('messages').convertAppMessage(message);

RocketChat.Notifications.notifyUser(user.id, 'message', Object.assign(msg, {
_id: Random.id(),
ts: new Date(),
u: undefined,
editor: undefined
}));
}

notifyRoom(room, message, appId) {
console.log(`The App ${ appId } is notifying a room's users.`);

const msg = this.orch.getConverters().get('messages').convertAppMessage(message);

RocketChat.Notifications.notifyUsersOfRoom(room.id, 'message', Object.assign(msg, {
_id: Random.id(),
ts: new Date(),
u: undefined,
editor: undefined
}));
}
}
28 changes: 24 additions & 4 deletions packages/rocketchat-apps/server/bridges/persistence.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,47 @@ export class AppPersistenceBridge {
readByAssociations(associations, appId) {
console.log(`The App ${ appId } is searching for records that are associated with the following:`, associations);

throw new Error('Not implemented.');
const records = this.orch.getPersistenceModel().find({
appId,
associations: { $all: associations }
}).fetch();

return Array.isArray(records) ? records.map((r) => r.data) : [];
}

remove(id, appId) {
console.log(`The App ${ appId } is removing one of their records by the id: "${ id }"`);

const record = this.orch.getPersistenceModel().findOneById(id);
const record = this.orch.getPersistenceModel().findOne({ _id: id, appId });

if (!record) {
return undefined;
}

this.orch.getPersistenceModel().remove({ _id: id });
this.orch.getPersistenceModel().remove({ _id: id, appId });

return record.data;
}

removeByAssociations(associations, appId) {
console.log(`The App ${ appId } is removing records with the following associations:`, associations);

throw new Error('Not implemented.');
const query = {
appId,
associations: {
$all: associations
}
};

const records = this.orch.getPersistenceModel().find(query).fetch();

if (!records) {
return undefined;
}

this.orch.getPersistenceModel().remove(query);

return Array.isArray(records) ? records.map((r) => r.data) : [];
}

update(id, data, upsert, appId) {
Expand Down
14 changes: 11 additions & 3 deletions packages/rocketchat-apps/server/communication/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@ export class AppMethods {
this._addMethods();
}

isEnabled() {
return typeof this._manager !== 'undefined';
}

isLoaded() {
return typeof this._manager !== 'undefined' && this.manager.areAppsLoaded();
}

_addMethods() {
const manager = this._manager;
const instance = this;

Meteor.methods({
'apps/is-enabled'() {
return typeof manager !== 'undefined';
return instance.isEnabled();
},

'apps/is-loaded'() {
return typeof manager !== 'undefined' || manager.areAppsLoaded();
return instance.isLoaded();
}
});
}
Expand Down
15 changes: 12 additions & 3 deletions packages/rocketchat-apps/server/orchestrator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class AppServerOrchestrator {
this._logModel = new AppsLogsModel();
this._persistModel = new AppsPersistenceModel();
this._storage = new AppRealStorage(this._model);
this._logStorage = new AppRealLogsStorage(this._persistModel);
this._logStorage = new AppRealLogsStorage(this._logModel);

this._converters = new Map();
this._converters.set('messages', new AppMessagesConverter(this));
Expand Down Expand Up @@ -64,18 +64,27 @@ class AppServerOrchestrator {
getManager() {
return this._manager;
}

isEnabled() {
return true;
}

isLoaded() {
return this.getManager().areAppsLoaded();
}
}

Meteor.startup(function _appServerOrchestrator() {
// Ensure that everything is setup
if (process.env[AppManager.ENV_VAR_NAME_FOR_ENABLING] !== 'true' && process.env[AppManager.SUPER_FUN_ENV_ENABLEMENT_NAME] !== 'true') {
return new AppMethods();
global.Apps = new AppMethods();
return;
}

console.log('Orchestrating the app piece...');
global.Apps = new AppServerOrchestrator();

global.Apps.getManager().load()
.then(() => console.log('...done! ;)'))
.then(() => console.log('...done! :)'))
.catch((err) => console.warn('...failed!', err));
});
30 changes: 25 additions & 5 deletions packages/rocketchat-lib/server/functions/sendMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,27 @@ RocketChat.sendMessage = function(user, message, room, upsert = false) {
if (!user || !message || !room._id) {
return false;
}
if (message.ts == null) {
message.ts = new Date();
}
message.u = _.pick(user, ['_id', 'username', 'name']);

if (!Match.test(message.msg, String)) {
message.msg = '';
}

if (message.ts == null) {
message.ts = new Date();
}

message.rid = room._id;
message.u = _.pick(user, ['_id', 'username', 'name']);

if (!room.usernames || room.usernames.length === 0) {
const updated_room = RocketChat.models.Rooms.findOneById(room._id);
if (updated_room != null) {
if (updated_room) {
room = updated_room;
} else {
room.usernames = [];
}
}

if (message.parseUrls !== false) {
const urls = message.msg.match(/([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\(\)\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g);

Expand All @@ -44,6 +49,17 @@ RocketChat.sendMessage = function(user, message, room, upsert = false) {
sandstormSessionId = message.sandstormSessionId;
delete message.sandstormSessionId;
}

// For the Rocket.Chat Apps :)
if (Apps && Apps.isLoaded()) {
const prevent = Apps.getBridges().getListenerBridge().messageEvent('IPreMessageSentPrevent', message);
if (prevent) {
return false;
}

// TODO: The rest of the IPreMessageSent events
}

if (message._id && upsert) {
const _id = message._id;
delete message._id;
Expand All @@ -56,6 +72,10 @@ RocketChat.sendMessage = function(user, message, room, upsert = false) {
message._id = RocketChat.models.Messages.insert(message);
}

if (Apps && Apps.isLoaded()) {
Apps.getBridges().getListenerBridge().messageEvent('IPostMessageSent', message);
}

/*
Defer other updates as their return is not interesting to the user
*/
Expand Down