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

[NEW] Direct message between multiple users #16761

Merged
merged 83 commits into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from 72 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
101f77d
improve room types usage
ggazzo Feb 28, 2020
4fb654c
improve room types usage
ggazzo Feb 28, 2020
2bf8851
Merge branch 'dm/multiple-users' into roomTypes/improve
ggazzo Feb 28, 2020
69da2cf
fix admin actions
ggazzo Feb 29, 2020
2af1f32
allow create dm between multiple users
ggazzo Mar 1, 2020
b82cfb7
Update openRoom.js
ggazzo Mar 1, 2020
c5336ff
fix open
ggazzo Mar 2, 2020
04512eb
Merge branch 'dm/multiple-users' of github.com:RocketChat/Rocket.Chat…
ggazzo Mar 2, 2020
b845c7c
improve name generation
ggazzo Mar 2, 2020
678f832
throw error on creating a dm with more users
ggazzo Mar 2, 2020
44d5c50
more harcoded settings
ggazzo Mar 2, 2020
a7ad731
Merge branch 'roomTypes/improve' into dm/multiple-users
ggazzo Mar 2, 2020
ec13454
fix review
ggazzo Mar 2, 2020
84b8dae
Merge branch 'roomTypes/improve' into dm/multiple-users
ggazzo Mar 13, 2020
f662783
create foreword component
ggazzo Mar 13, 2020
9afea45
fix review
ggazzo Mar 16, 2020
f0c2818
Merge branch 'roomTypes/improve' into dm/multiple-users
ggazzo Mar 16, 2020
aacb65b
fix review
ggazzo Mar 16, 2020
2f77af3
Merge branch 'roomTypes/improve' into dm/multiple-users
ggazzo Mar 16, 2020
31fbfdc
avatars and user info
ggazzo Mar 16, 2020
db7584d
create direct message modal
ggazzo Mar 16, 2020
8fdfbee
removed duplicated code
ggazzo Mar 16, 2020
bcc5fe1
Merge branch 'roomTypes/improve' into dm/multiple-users
ggazzo Mar 16, 2020
4ab0e57
fix undefined room
ggazzo Mar 17, 2020
9d52ff9
Merge branch 'develop' of github.com:RocketChat/Rocket.Chat into dm/m…
ggazzo Mar 19, 2020
16f782d
prevent errors
ggazzo Mar 19, 2020
69e2840
update mention component
ggazzo Mar 20, 2020
20fb2b7
i18n
ggazzo Mar 20, 2020
7383683
Add avatar stack
ggazzo Mar 20, 2020
ff2c1df
private and public url by id
ggazzo Mar 20, 2020
8f3bbab
new old icon
ggazzo Mar 20, 2020
9363b26
old icon
ggazzo Mar 20, 2020
d9f0a1e
updage fuselage
ggazzo Mar 20, 2020
f4a71e8
Merge branch 'develop' of github.com:RocketChat/Rocket.Chat into dm/m…
ggazzo Mar 21, 2020
af3fac7
Change DM room _id
sampaiodiego Mar 21, 2020
a9dcb60
Use model
sampaiodiego Mar 21, 2020
41fb60e
Fix lint
sampaiodiego Mar 21, 2020
af95eaa
WIP
ggazzo Mar 21, 2020
532201a
Merge branch 'dm/multiple-users' of github.com:RocketChat/Rocket.Chat…
sampaiodiego Mar 21, 2020
e64ef38
Fix lint
sampaiodiego Mar 21, 2020
f113b17
Fix direct message creation
sampaiodiego Mar 21, 2020
e27655b
Fix loading from URL
sampaiodiego Mar 21, 2020
e82ef9a
Fix loading from URL
sampaiodiego Mar 21, 2020
32e9ce1
Merge branch 'dm/multiple-users' of github.com:RocketChat/Rocket.Chat…
sampaiodiego Mar 21, 2020
11ac5cc
Undo public private room type find
sampaiodiego Mar 21, 2020
d153e9f
Use single function to update name and username
sampaiodiego Mar 21, 2020
59f8466
improve openRoom
ggazzo Mar 22, 2020
9557f91
Merge branch 'develop' into dm/multiple-users
ggazzo Mar 22, 2020
a3702ee
Federation support
ggazzo Mar 22, 2020
ca6ce2f
Merge branch 'dm/multiple-users' of github.com:RocketChat/Rocket.Chat…
ggazzo Mar 22, 2020
b5d820b
fix usser set username
ggazzo Mar 22, 2020
4fd5c03
Better error handling
sampaiodiego Mar 23, 2020
d56c917
Show error
sampaiodiego Mar 23, 2020
1165599
Update group DMs when removing an user
sampaiodiego Mar 23, 2020
9023e7f
Do not update undefined values
sampaiodiego Mar 23, 2020
4d55cfd
Add migration to set uids field for existent DMs
sampaiodiego Mar 23, 2020
0d92986
Use Future to lock up the migration until it finishes
sampaiodiego Mar 24, 2020
501fea2
Fix user creation
sampaiodiego Mar 24, 2020
318e43a
Get other uid from room object
sampaiodiego Mar 24, 2020
18e4bf4
Fix avatar when using Real Names
sampaiodiego Mar 24, 2020
ae50b48
Add space to room name
sampaiodiego Mar 24, 2020
18d5d50
Fix migration for small datasets
sampaiodiego Mar 24, 2020
51ec997
Merge branch 'develop' into dm/multiple-users
sampaiodiego Mar 24, 2020
16f5190
Fix: StreamCast was not working correctly (#16983)
rodrigok Mar 24, 2020
1bf9f2b
direct message rid
ggazzo Mar 24, 2020
772def5
room info
ggazzo Mar 24, 2020
ab7a004
open room
ggazzo Mar 24, 2020
a0bae6a
?
ggazzo Mar 24, 2020
22e2ab8
update fuselage
ggazzo Mar 24, 2020
6e5c1c8
Merge branch 'dm/multiple-users' of github.com:RocketChat/Rocket.Chat…
sampaiodiego Mar 24, 2020
01055ee
Merge branch 'develop' into dm/multiple-users
sampaiodiego Mar 24, 2020
9e53578
Add support to group DMs to Apps engine
sampaiodiego Mar 25, 2020
4d933f8
Code style
sampaiodiego Mar 25, 2020
f587f0d
Rename field on Apps Engine uids -> userIds
sampaiodiego Mar 25, 2020
abaf370
Merge branch 'develop' of github.com:RocketChat/Rocket.Chat into dm/m…
ggazzo Mar 25, 2020
9d64a4e
fix review
ggazzo Mar 25, 2020
203561d
Merge branch 'dm/multiple-users' of github.com:RocketChat/Rocket.Chat…
ggazzo Mar 25, 2020
fa4a3e2
Merge branch 'develop' into dm/multiple-users
sampaiodiego Mar 25, 2020
0973778
Move migration to 179
sampaiodiego Mar 25, 2020
8c3aeb9
Update Apps Engine beta version
sampaiodiego Mar 25, 2020
8caeae8
Final items
sampaiodiego Mar 25, 2020
ebbbd09
Fix user info
sampaiodiego Mar 26, 2020
61902da
Deprecate old room _id for DMs
sampaiodiego Mar 26, 2020
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
5 changes: 2 additions & 3 deletions app/apps/server/bridges/rooms.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Meteor } from 'meteor/meteor';
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';

import { Rooms, Subscriptions, Users } from '../../../models';
import { Rooms, Subscriptions, Users } from '../../../models/server';
import { addUserToRoom } from '../../../lib/server/functions/addUserToRoom';

export class AppRoomBridge {
Expand Down Expand Up @@ -38,8 +38,7 @@ export class AppRoomBridge {
delete extraData.customFields;
let info;
if (room.type === RoomType.DIRECT_MESSAGE) {
members.splice(members.indexOf(room.creator.username), 1);
info = Meteor.call(method, members[0]);
info = Meteor.call(method, ...members);
} else {
info = Meteor.call(method, rcRoom.name, members, rcRoom.ro, rcRoom.customFields, extraData);
}
Expand Down
2 changes: 2 additions & 0 deletions app/apps/server/converters/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export class AppRoomsConverter {
servedBy,
closedBy,
members: room.members,
uids: room.uids,
default: typeof room.isDefault === 'undefined' ? false : room.isDefault,
ro: typeof room.isReadOnly === 'undefined' ? false : room.isReadOnly,
sysMes: typeof room.displaySystemMessages === 'undefined' ? true : room.displaySystemMessages,
Expand All @@ -105,6 +106,7 @@ export class AppRoomsConverter {
displayName: 'fname',
slugifiedName: 'name',
members: 'members',
uids: 'uids',
messageCount: 'msgs',
createdAt: 'ts',
updatedAt: '_updatedAt',
Expand Down
33 changes: 8 additions & 25 deletions app/federation/server/hooks/afterCreateDirectRoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,19 @@ async function afterCreateDirectRoom(room, extras) {
// Ensure a genesis event for this room
const genesisEvent = await FederationRoomEvents.createGenesisEvent(getFederationDomain(), normalizedRoom);

//
// Source User
//

// Add the source user to the room
const sourceUser = extras.from;
const normalizedSourceUser = normalizers.normalizeUser(sourceUser);

const sourceSubscription = Subscriptions.findOne({ rid: normalizedRoom._id, 'u._id': normalizedSourceUser._id });
const normalizedSourceSubscription = normalizers.normalizeSubscription(sourceSubscription);

// Build the source user event
const sourceUserEvent = await FederationRoomEvents.createAddUserEvent(getFederationDomain(), normalizedRoom._id, normalizedSourceUser, normalizedSourceSubscription);

//
// Target User
//

// Add the target user to the room
const targetUser = extras.to;
const normalizedTargetUser = normalizers.normalizeUser(targetUser);
const events = await Promise.all(extras.members.map((member) => {
const normalizedMember = normalizers.normalizeUser(member);

const targetSubscription = Subscriptions.findOne({ rid: normalizedRoom._id, 'u._id': normalizedTargetUser._id });
const normalizedTargetSubscription = normalizers.normalizeSubscription(targetSubscription);
const sourceSubscription = Subscriptions.findOne({ rid: normalizedRoom._id, 'u._id': normalizedMember._id });
const normalizedSourceSubscription = normalizers.normalizeSubscription(sourceSubscription);

// Dispatch the target user event
const targetUserEvent = await FederationRoomEvents.createAddUserEvent(getFederationDomain(), normalizedRoom._id, normalizedTargetUser, normalizedTargetSubscription);
// Build the user event
return FederationRoomEvents.createAddUserEvent(getFederationDomain(), normalizedRoom._id, normalizedMember, normalizedSourceSubscription);
}));

// Dispatch the events
dispatchEvents(normalizedRoom.federation.domains, [genesisEvent, sourceUserEvent, targetUserEvent]);
dispatchEvents(normalizedRoom.federation.domains, [genesisEvent, ...events]);
} catch (err) {
await deleteRoom(room._id);

Expand Down
35 changes: 21 additions & 14 deletions app/integrations/server/lib/triggerHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -496,28 +496,35 @@ integrations.triggerHandler = new class RocketChatIntegrationHandler {
if (room) {
switch (room.t) {
case 'd':
const id = room._id.replace(message.u._id, '');
const username = _.without(room.usernames, message.u.username)[0];

if (this.triggers[`@${ id }`]) {
for (const trigger of Object.values(this.triggers[`@${ id }`])) {
triggersToExecute.push(trigger);
}
}

if (this.triggers.all_direct_messages) {
for (const trigger of Object.values(this.triggers.all_direct_messages)) {
triggersToExecute.push(trigger);
}
}

if (id !== username && this.triggers[`@${ username }`]) {
for (const trigger of Object.values(this.triggers[`@${ username }`])) {
triggersToExecute.push(trigger);
}
if (!room.uids) {
return;
}
break;

room.uids.forEach((uid) => {
if (this.triggers[`@${ uid }`]) {
for (const trigger of Object.values(this.triggers[`@${ uid }`])) {
triggersToExecute.push(trigger);
}
}
});

room.usernames.forEach((username) => {
if (room.uids.includes(username) || username === message.u.username) {
return;
}
if (this.triggers[`@${ username }`]) {
for (const trigger of Object.values(this.triggers[`@${ username }`])) {
triggersToExecute.push(trigger);
}
}
});
break;
case 'c':
if (this.triggers.all_public_channels) {
for (const trigger of Object.values(this.triggers.all_public_channels)) {
Expand Down
26 changes: 26 additions & 0 deletions app/lib/client/defaultTabBars.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Session } from 'meteor/session';
import { TabBar } from '../../ui-utils';
import { Rooms } from '../../models';
import { hasAllPermission } from '../../authorization';
import { roomTypes } from '../../utils/client';

TabBar.addButton({
groups: ['channel', 'group', 'direct'],
Expand All @@ -20,6 +21,31 @@ TabBar.addButton({
icon: 'user',
template: 'membersList',
order: 2,
condition() {
const rid = Session.get('openedRoom');
const room = Rooms.findOne({
_id: rid,
});

return room && !roomTypes.getConfig(room.t).isGroupChat(room);
},
});

TabBar.addButton({
groups: ['direct'],
id: 'user-info-group',
i18nTitle: 'Members_List',
icon: 'team',
template: 'membersList',
order: 2,
condition() {
const rid = Session.get('openedRoom');
const room = Rooms.findOne({
_id: rid,
});

return room && roomTypes.getConfig(room.t).isGroupChat(room);
},
});

TabBar.addButton({
Expand Down
32 changes: 26 additions & 6 deletions app/lib/lib/roomTypes/direct.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,22 @@ import { getUserPreference, RoomTypeConfig, RoomTypeRouteConfig, RoomSettingsEnu
import { hasPermission, hasAtLeastOnePermission } from '../../../authorization';
import { settings } from '../../../settings';
import { getUserAvatarURL } from '../../../utils/lib/getUserAvatarURL';
import { getAvatarURL } from '../../../utils/lib/getAvatarURL';

export class DirectMessageRoomRoute extends RoomTypeRouteConfig {
constructor() {
super({
name: 'direct',
path: '/direct/:username',
path: '/direct/:rid',
});
}

action(params) {
return openRoom('d', params.username);
return openRoom('d', params.rid);
}

link(sub) {
return { username: sub.name };
return { rid: sub.rid || sub.name };
}
}

Expand All @@ -36,14 +37,25 @@ export class DirectMessageRoomType extends RoomTypeConfig {
});
}


getIcon(roomData) {
if (roomData.uids && roomData.uids.length > 2) {
return 'team';
}
return this.icon;
}

findRoom(identifier) {
if (!hasPermission('view-d-room')) {
return null;
}

const query = {
t: 'd',
name: identifier,
$or: [
{ name: identifier },
{ rid: identifier },
],
};

const subscription = Subscriptions.findOne(query);
Expand Down Expand Up @@ -161,11 +173,19 @@ export class DirectMessageRoomType extends RoomTypeConfig {
return { title, text };
}

getAvatarPath(roomData) {
return getUserAvatarURL(roomData.name || this.roomName(roomData));
getAvatarPath(roomData, subData) {
if (roomData && roomData.uids && roomData.uids.length > 2) {
return getAvatarURL({ username: roomData.uids.length + roomData.usernames.join() });
}
const sub = subData || Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1 } });
return getUserAvatarURL(sub.name || this.roomName(roomData));
}

includeInDashboard() {
return true;
}

isGroupChat(room) {
return room.usernames && room.usernames.length > 2;
}
}
126 changes: 65 additions & 61 deletions app/lib/server/functions/createDirectRoom.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,87 @@
import { Rooms, Subscriptions } from '../../../models/server';
import { settings } from '../../../settings/lib/settings';
import { getDefaultSubscriptionPref } from '../../../utils/server';
import { callbacks } from '../../../callbacks/server';

export const createDirectRoom = function(source, target, extraData, options) {
const rid = [source._id, target._id].sort().join('');
const generateSubscription = (fname, name, user, extra) => ({
alert: false,
unread: 0,
userMentions: 0,
groupMentions: 0,
...user.customFields && { customFields: user.customFields },
...getDefaultSubscriptionPref(user),
...extra,
t: 'd',
fname,
name,
u: {
_id: user._id,
username: user.username,
},
});

const now = new Date();
const getFname = (members) => members.map(({ name, username }) => name || username).join(', ');
const getName = (members) => members.map(({ username }) => username).join(', ');

const roomUpsertResult = Rooms.upsert({ _id: rid }, {
$set: {
usernames: [source.username, target.username],
},
$setOnInsert: Object.assign({
t: 'd',
msgs: 0,
ts: now,
usersCount: 2,
}, extraData),
});
export const createDirectRoom = function(members, roomExtraData = {}, options = {}) {
if (members.length > (settings.get('DirectMesssage_maxUsers') || 1)) {
throw new Error('error-direct-message-max-user-exceeded');
}

const targetNotificationPref = getDefaultSubscriptionPref(target);
const sortedMembers = members.sort((u1, u2) => (u1.name || u1.username).localeCompare(u2.name || u2.username));

Subscriptions.upsert({ rid, 'u._id': target._id }, {
$setOnInsert: Object.assign({
fname: source.name,
name: source.username,
t: 'd',
open: false,
alert: false,
unread: 0,
userMentions: 0,
groupMentions: 0,
customFields: target.customFields,
u: {
_id: target._id,
username: target.username,
},
ts: now,
...targetNotificationPref,
}, options.subscriptionExtra),
});
const usernames = sortedMembers.map(({ username }) => username);
const uids = sortedMembers.map(({ _id }) => _id);

const room = Rooms.findDirectRoomContainingAllUserIDs(uids, { fields: { _id: 1 } });

const sourceNotificationPref = getDefaultSubscriptionPref(source);
const isNewRoom = !room;

Subscriptions.upsert({ rid, 'u._id': source._id }, {
$set: {
ls: now,
open: true,
...target.active === false && {
archived: true,
},
},
$setOnInsert: Object.assign({
fname: target.name,
name: target.username,
t: 'd',
alert: false,
unread: 0,
userMentions: 0,
groupMentions: 0,
customFields: source.customFields,
u: {
_id: source._id,
username: source.username,
},
ts: now,
...sourceNotificationPref,
}, options.subscriptionExtra),
const rid = room?._id || Rooms.insert({
t: 'd',
usernames,
usersCount: members.length,
msgs: 0,
ts: new Date(),
uids,
...roomExtraData,
});

if (members.length === 1) { // dm to yourself
Subscriptions.upsert({ rid, 'u._id': members[0]._id }, {
$set: { open: true },
$setOnInsert: generateSubscription(members[0].name || members[0].username, members[0].username, members[0], { ...options.subscriptionExtra }),
});
} else {
members.forEach((member) => {
const otherMembers = sortedMembers.filter(({ _id }) => _id !== member._id);

Subscriptions.upsert({ rid, 'u._id': member._id }, {
...options.creator === member._id && { $set: { open: true } },
$setOnInsert: generateSubscription(
getFname(otherMembers),
getName(otherMembers),
member,
{
...options.subscriptionExtra,
...options.creator !== member._id && { open: members.length > 2 },
},
),
});
});
}

// If the room is new, run a callback
if (roomUpsertResult.insertedId) {
if (isNewRoom) {
const insertedRoom = Rooms.findOneById(rid);

callbacks.run('afterCreateDirectRoom', insertedRoom, { from: source, to: target });
callbacks.run('afterCreateDirectRoom', insertedRoom, { members });
}

return {
_id: rid,
usernames,
t: 'd',
inserted: isNewRoom,
};
};
Loading