Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
alansikora committed Nov 18, 2021
1 parent cef5c26 commit b67f0c8
Show file tree
Hide file tree
Showing 21 changed files with 256 additions and 140 deletions.
3 changes: 3 additions & 0 deletions app/federation-legacy/server/lib/callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ function enableCallback(definition) {
}

export function registerCallback(callbackDefinition) {
// Prefix with legacy
callbackDefinition.id = `legacy-${ callbackDefinition.id }`;

callbackDefinitions.push(callbackDefinition);

if (settings.get('FEDERATION_Enabled')) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
enum AddMemberToRoomMembership {
JOIN = 'join'
export enum AddMemberToRoomMembership {
JOIN = 'join',
INVITE = 'invite',
LEAVE = 'leave',
}

export interface IMatrixEventContentAddMemberToRoom {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum SetRoomJoinRules {
JOIN = 'public'
JOIN = 'public',
INVITE = 'invite'
}
export interface IMatrixEventContentSetRoomJoinRules {
join_rule: SetRoomJoinRules;
Expand Down
86 changes: 71 additions & 15 deletions app/federation/server/bridge/addMemberToRoom.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,85 @@
// @ts-ignore
import { MatrixBridgedUser, MatrixBridgedRoom, Rooms, Users } from '../../../models';
import { MatrixBridgedUser, MatrixBridgedRoom, Users } from '../../../models';
// @ts-ignore
import { addUserToRoom, createRoom, removeUserFromRoom } from '../../../lib';
import { IMatrixEvent } from '../definitions/IMatrixEvent';
import { MatrixEventType } from '../definitions/MatrixEventType';
import { AddMemberToRoomMembership } from '../IMatrixEventContent/IMatrixEventContentAddMemberToRoom';
import { SetRoomJoinRules } from '../IMatrixEventContent/IMatrixEventContentSetRoomJoinRules';
import { currentServer, SERVER, servers } from '../servers';
import { createUser } from '../methods';
import { matrixEventQueue } from './bridge';

export const handleAddMemberToRoom = async (
event: IMatrixEvent<MatrixEventType.ADD_MEMBER_TO_ROOM>,
): Promise<void> => {
const { room_id: matrixRoomId, sender } = event;
const {
room_id: matrixRoomId,
sender: senderMatrixUserId,
state_key: affectedMatrixUserId,
content: { displayname: displayName, membership },
invite_room_state: inviteRoomState,
} = event;

// Find the bridged user id
const userId = await MatrixBridgedUser.getId(sender);
console.log(JSON.stringify(event, null, 2));

// Find the user
const user = await Users.findOneById(userId);
// // We ignore the bot
// if (affectedMatrixUserId.startsWith(`@rc_bot:`)) {
// return;
// }

// Find the bridged room id
const roomId = await MatrixBridgedRoom.getId(matrixRoomId);

Rooms.update({ _id: roomId }, {
$inc: { usersCount: 1 },
$set: {
u: {
_id: user._id,
username: user.username,
},
},
});
// Find the bridged user id
const senderUserId = await MatrixBridgedUser.getId(senderMatrixUserId);
const affectedUserId = await MatrixBridgedUser.getId(affectedMatrixUserId);

// Find the user
const senderUser = await Users.findOneById(senderUserId);
const affectedUser = await Users.findOneById(affectedUserId);

switch (membership) {
case AddMemberToRoomMembership.JOIN:
addUserToRoom(roomId, affectedUser);
break;
case AddMemberToRoomMembership.INVITE:
// // If the sender user does not exist, it means we need to create it
// let creatorUser = senderUser;
// if (!creatorUser) {
// creatorUser = createUser(senderMatrixUserId, senderMatrixUserId);
// }
//
// // If the invited user does not exist, it means we need to create it
// let invitedUser = affectedUser;
// if (!invitedUser) {
// invitedUser = createUser(affectedMatrixUserId, displayName);
// }

// // Create the room if necessary
// const destinationRoomId = roomId;

if (!roomId && inviteRoomState) {
// // Ensure we run all the room events first
// for (const event of inviteRoomState) {
// // TODO: Handle error
// matrixEventQueue.push(event).catch((err) => console.error(err));
// }
//
// // Re-add the current event to the queue
// // TODO: Handle error
// matrixEventQueue.push(event).catch((err) => console.error(err));

// Stop
return;
}

addUserToRoom(roomId, affectedUser, senderUser);
break;
case AddMemberToRoomMembership.LEAVE:
removeUserFromRoom(roomId, affectedUser, {
byUser: senderUser,
});
break;
}
};
108 changes: 62 additions & 46 deletions app/federation/server/bridge/bridge.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @ts-ignore
import yaml from 'js-yaml';
import * as fastq from 'fastq';
import type { queueAsPromised } from 'fastq';
import { AppServiceRegistration, Bridge } from 'matrix-appservice-bridge';

import { currentServer } from '../servers';
Expand All @@ -16,63 +17,78 @@ const registration: AppServiceRegistration = yaml.load(
currentServer.registrationFile,
);

// Define the event handler
const eventHandler = async (event: IMatrixEvent<MatrixEventType>): Promise<void> => {
switch (event.type) {
case MatrixEventType.CREATE_ROOM: {
await handleCreateRoom(event as IMatrixEvent<MatrixEventType.CREATE_ROOM>);

break;
}
case MatrixEventType.ADD_MEMBER_TO_ROOM: {
await handleAddMemberToRoom(event as IMatrixEvent<MatrixEventType.ADD_MEMBER_TO_ROOM>);

break;
}
case MatrixEventType.SET_ROOM_JOIN_RULES: {
await setRoomJoinRules(event as IMatrixEvent<MatrixEventType.SET_ROOM_JOIN_RULES>);

break;
}
case MatrixEventType.SET_ROOM_NAME: {
await setRoomName(event as IMatrixEvent<MatrixEventType.SET_ROOM_NAME>);

break;
}
case MatrixEventType.SET_ROOM_TOPIC: {
await setRoomTopic(event as IMatrixEvent<MatrixEventType.SET_ROOM_TOPIC>);

break;
}
case MatrixEventType.SEND_MESSAGE: {
await handleSendMessage(event as IMatrixEvent<MatrixEventType.SEND_MESSAGE>);

break;
}
case MatrixEventType.SET_ROOM_POWER_LEVELS:
case MatrixEventType.SET_ROOM_CANONICAL_ALIAS:
case MatrixEventType.SET_ROOM_HISTORY_VISIBILITY:
case MatrixEventType.SET_ROOM_GUEST_ACCESS: {
console.log(`Ignoring ${ event.type }`);

break;
}
default:
console.log(`Could not find handler for ${ event.type }`, event);
}
};

// Create the queue
export const matrixEventQueue: queueAsPromised<IMatrixEvent<MatrixEventType>> = fastq.promise(eventHandler, 1);

export const bridge = new Bridge({
homeserverUrl: currentServer.homeserverUrl,
domain: 'localhost',
registration,
suppressEcho: false,
suppressEcho: true,
disableStores: true,

controller: {
// onUserQuery(queriedUser) {
// return {}; // auto-provision users with no additional data
// },
onUserQuery(queriedUser): Record<string, unknown> {
console.log('==================================================================');
console.log('onUserQuery', queriedUser);
console.log('==================================================================');
return {}; // auto-provision users with no additional data
},

async onEvent(request/* , context*/): Promise<void> {
// Get the event
const event = request.getData() as unknown as IMatrixEvent<MatrixEventType>;

switch (event.type) {
case MatrixEventType.CREATE_ROOM: {
await handleCreateRoom(event as IMatrixEvent<MatrixEventType.CREATE_ROOM>);

break;
}
case MatrixEventType.ADD_MEMBER_TO_ROOM: {
await handleAddMemberToRoom(event as IMatrixEvent<MatrixEventType.ADD_MEMBER_TO_ROOM>);

break;
}
case MatrixEventType.SET_ROOM_JOIN_RULES: {
await setRoomJoinRules(event as IMatrixEvent<MatrixEventType.SET_ROOM_JOIN_RULES>);

break;
}
case MatrixEventType.SET_ROOM_NAME: {
await setRoomName(event as IMatrixEvent<MatrixEventType.SET_ROOM_NAME>);

break;
}
case MatrixEventType.SET_ROOM_TOPIC: {
await setRoomTopic(event as IMatrixEvent<MatrixEventType.SET_ROOM_TOPIC>);

break;
}
case MatrixEventType.SEND_MESSAGE: {
await handleSendMessage(event as IMatrixEvent<MatrixEventType.SEND_MESSAGE>);

break;
}
case MatrixEventType.SET_ROOM_POWER_LEVELS:
case MatrixEventType.SET_ROOM_CANONICAL_ALIAS:
case MatrixEventType.SET_ROOM_HISTORY_VISIBILITY: {
console.log(`Ignoring ${ event.type }`);

break;
}
default:
console.log(`Could not find handler for ${ event.type }`, event);
}
console.log(`Queueing ${ event.type }...`, event);

// TODO: Handle error
matrixEventQueue.push(event).catch((err) => console.error(err));
},
},
});
33 changes: 7 additions & 26 deletions app/federation/server/bridge/createRoom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// @ts-ignore
import { MatrixBridgedRoom, MatrixBridgedUser, Rooms, Subscriptions, Users } from '../../../models';
import { MatrixBridgedRoom, MatrixBridgedUser, Users } from '../../../models';
// @ts-ignore
import { createRoom } from '../../../lib';
import { IMatrixEvent } from '../definitions/IMatrixEvent';
import { MatrixEventType } from '../definitions/MatrixEventType';

Expand All @@ -14,31 +16,10 @@ export const handleCreateRoom = async (
// Find the user
const user = await Users.findOneById(userId);

const roomId = Rooms.insert({
description: '',
broadcast: false,
encrypted: false,
usersCount: 1,
u: {
_id: user._id,
username: user.username,
},
ts: new Date(),
_updatedAt: new Date(),
});
// Create temp room name
const roomName = `Federation-${ matrixRoomId.split(':')[0].replace('!', '') }`;

MatrixBridgedRoom.insert({ rid: roomId, mri: matrixRoomId });
const { rid: roomId } = createRoom('c', roomName, user.username);

Subscriptions.insert({
open: true,
alert: false,
ts: new Date(),
rid: roomId,
u: {
_id: user._id,
name: user.name,
username: user.username,
},
_updatedAt: new Date(),
});
MatrixBridgedRoom.insert({ rid: roomId, mri: matrixRoomId });
};
4 changes: 3 additions & 1 deletion app/federation/server/bridge/setRoomJoinRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ export const setRoomJoinRules = async (
let type;

switch (joinRule) {
case SetRoomJoinRules.INVITE:
type = 'p';
break;
case SetRoomJoinRules.JOIN:
default:
type = 'c';
}

Rooms.update({ _id: roomId }, {
$inc: { usersCount: 1 },
$set: {
t: type,
},
Expand Down
14 changes: 7 additions & 7 deletions app/federation/server/callbacks/afterAddedToRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { IRoom } from '../../../../definition/IRoom';
import { bridge } from '../bridge';

export async function afterAddedToRoom(_: any, room: IRoom): Promise<void> {
const intent = bridge.getIntent();

// Retrieve the matrix room
const roomMatrixId = MatrixBridgedRoom.getMatrixId(room._id);

// Add the user
await intent.invite(roomMatrixId, '@rocketchat_userb:b.rc.allskar.com');
// const intent = bridge.getIntent();
//
// // Retrieve the matrix room
// const roomMatrixId = MatrixBridgedRoom.getMatrixId(room._id);
//
// // Add the user
// await intent.invite(roomMatrixId, '@rocketchat_userb:b.rc.allskar.com');
}
28 changes: 12 additions & 16 deletions app/federation/server/callbacks/afterCreateRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,34 @@ import { IRoom } from '../../../../definition/IRoom';
import { bridge } from '../bridge';

export async function afterCreateRoom(user: IUser, room: IRoom): Promise<void> {
// Check if this room already exists (created by another method)
// and if so, ignore the callback
const roomMatrixId = MatrixBridgedRoom.getMatrixId(room._id);
if (roomMatrixId) {
return;
}

const intent = bridge.getIntent();

const roomName = `@rocketchat_${ room.name }`;
const roomName = `@rc_${ room.name }`;

// Create the matrix room
const matrixRoom = await intent.createRoom({
createAsClient: true,
options: {
name: roomName,
topic: room.topic,
visibility: 'public',
preset: 'public_chat',
visibility: room.t === 'p' ? 'invite' : 'public',
preset: room.t === 'p' ? 'private_chat' : 'public_chat',
},
});

// Retrieve the matrix user
const matrixId = MatrixBridgedUser.getMatrixId(user._id);
const userMatrixId = MatrixBridgedUser.getMatrixId(user._id);

// Add to the map
MatrixBridgedRoom.insert({ rid: room._id, mri: matrixRoom.room_id });

// Set room visibility
const roomDirectoryVisibility = await intent
.getClient()
.getRoomDirectoryVisibility(matrixRoom.room_id);

if (roomDirectoryVisibility !== 'public') {
await intent
.getClient()
.setRoomDirectoryVisibility(matrixRoom.room_id, 'public');
}

// Add our user
await intent.invite(matrixRoom.room_id, matrixId);
await intent.invite(matrixRoom.room_id, userMatrixId);
}
Loading

0 comments on commit b67f0c8

Please sign in to comment.