Skip to content

Commit

Permalink
code organization
Browse files Browse the repository at this point in the history
  • Loading branch information
alansikora committed Nov 18, 2021
1 parent bc91e46 commit 5dbd963
Show file tree
Hide file tree
Showing 33 changed files with 1,776 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export enum AddMemberToRoomMembership {
JOIN = 'join',
INVITE = 'invite',
LEAVE = 'leave',
}

export interface IMatrixEventContentAddMemberToRoom {
displayname: string;
membership: AddMemberToRoomMembership;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface IMatrixEventContentCreateRoom {
creator: string;
room_version: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export enum MatrixSendMessageType {
'm.text'
}

export interface IMatrixEventContentSendMessage {
body: string;
msgtype: MatrixSendMessageType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum SetRoomJoinRules {
JOIN = 'public',
INVITE = 'invite'
}
export interface IMatrixEventContentSetRoomJoinRules {
join_rule: SetRoomJoinRules;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IMatrixEventContentSetRoomName {
name: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IMatrixEventContentSetRoomTopic {
topic: string;
}
16 changes: 16 additions & 0 deletions app/federation-bridge/server/IMatrixEventContent/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { MatrixEventType } from '../definitions/MatrixEventType';
import { IMatrixEventContentCreateRoom } from './IMatrixEventContentCreateRoom';
import { IMatrixEventContentAddMemberToRoom } from './IMatrixEventContentAddMemberToRoom';
import { IMatrixEventContentSendMessage } from './IMatrixEventContentSendMessage';
import { IMatrixEventContentSetRoomJoinRules } from './IMatrixEventContentSetRoomJoinRules';
import { IMatrixEventContentSetRoomName } from './IMatrixEventContentSetRoomName';
import { IMatrixEventContentSetRoomTopic } from './IMatrixEventContentSetRoomTopic';

export type EventContent = {
[MatrixEventType.CREATE_ROOM]: IMatrixEventContentCreateRoom;
[MatrixEventType.ADD_MEMBER_TO_ROOM]: IMatrixEventContentAddMemberToRoom;
[MatrixEventType.SET_ROOM_JOIN_RULES]: IMatrixEventContentSetRoomJoinRules;
[MatrixEventType.SET_ROOM_NAME]: IMatrixEventContentSetRoomName;
[MatrixEventType.SET_ROOM_TOPIC]: IMatrixEventContentSetRoomTopic;
[MatrixEventType.SEND_MESSAGE]: IMatrixEventContentSendMessage;
};
85 changes: 85 additions & 0 deletions app/federation-bridge/server/bridge/addMemberToRoom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// @ts-ignore
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: senderMatrixUserId,
state_key: affectedMatrixUserId,
content: { displayname: displayName, membership },
invite_room_state: inviteRoomState,
} = event;

console.log(JSON.stringify(event, null, 2));

// // We ignore the bot
// if (affectedMatrixUserId.startsWith(`@rc_bot:`)) {
// return;
// }

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

// 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;
}
};
94 changes: 94 additions & 0 deletions app/federation-bridge/server/bridge/bridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
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';
import { IMatrixEvent } from '../definitions/IMatrixEvent';
import { MatrixEventType } from '../definitions/MatrixEventType';
import { handleSendMessage } from './sendMessage';
import { handleCreateRoom } from './createRoom';
import { handleAddMemberToRoom } from './addMemberToRoom';
import { setRoomJoinRules } from './setRoomJoinRules';
import { setRoomName } from './setRoomName';
import { setRoomTopic } from './setRoomTopic';

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: true,
disableStores: true,

controller: {
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>;

console.log(`Queueing ${ event.type }...`, event);

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

export const handleCreateRoom = async (
event: IMatrixEvent<MatrixEventType.CREATE_ROOM>,
): Promise<void> => {
const { room_id: matrixRoomId, sender } = event;

// Find the bridged user id
const userId = await MatrixBridgedUser.getId(sender);

// Find the user
const user = await Users.findOneById(userId);

// Create temp room name
const roomName = `Federation-${ matrixRoomId.split(':')[0].replace('!', '') }`;

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

MatrixBridgedRoom.insert({ rid: roomId, mri: matrixRoomId });
};
1 change: 1 addition & 0 deletions app/federation-bridge/server/bridge/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './bridge';
29 changes: 29 additions & 0 deletions app/federation-bridge/server/bridge/sendMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// @ts-ignore
import { MatrixBridgedRoom, MatrixBridgedUser, Messages, Users } from '../../../models';
import { IMatrixEvent } from '../definitions/IMatrixEvent';
import { MatrixEventType } from '../definitions/MatrixEventType';

export const handleSendMessage = async (
event: IMatrixEvent<MatrixEventType.SEND_MESSAGE>,
): Promise<void> => {
const { room_id: matrixRoomId, sender } = event;

// Find the bridged user id
const userId = await MatrixBridgedUser.getId(sender);

// Find the user
const user = await Users.findOneById(userId);

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

Messages.createWithTypeRoomIdMessageAndUser(
'm',
roomId,
event.content.body,
{
_id: user._id,
username: user.username,
},
);
};
37 changes: 37 additions & 0 deletions app/federation-bridge/server/bridge/setRoomJoinRules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// @ts-ignore
import { MatrixBridgedRoom, Rooms, Subscriptions } from '../../../models';
import { IMatrixEvent } from '../definitions/IMatrixEvent';
import { MatrixEventType } from '../definitions/MatrixEventType';
import { SetRoomJoinRules } from '../IMatrixEventContent/IMatrixEventContentSetRoomJoinRules';

export const setRoomJoinRules = async (
event: IMatrixEvent<MatrixEventType.SET_ROOM_JOIN_RULES>,
): Promise<void> => {
const { room_id: matrixRoomId, content: { join_rule: joinRule } } = event;

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

let type;

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

Rooms.update({ _id: roomId }, {
$set: {
t: type,
},
});

Subscriptions.update({ rid: roomId }, {
$set: {
t: type,
},
});
};
27 changes: 27 additions & 0 deletions app/federation-bridge/server/bridge/setRoomName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// @ts-ignore
import { MatrixBridgedRoom, Rooms, Subscriptions } from '../../../models';
import { IMatrixEvent } from '../definitions/IMatrixEvent';
import { MatrixEventType } from '../definitions/MatrixEventType';

export const setRoomName = async (
event: IMatrixEvent<MatrixEventType.SET_ROOM_NAME>,
): Promise<void> => {
const { room_id: matrixRoomId, content: { name } } = event;

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

Rooms.update({ _id: roomId }, {
$set: {
name,
fname: name,
},
});

Subscriptions.update({ rid: roomId }, {
$set: {
name,
fname: name,
},
});
};
19 changes: 19 additions & 0 deletions app/federation-bridge/server/bridge/setRoomTopic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// @ts-ignore
import { MatrixBridgedRoom, Rooms } from '../../../models';
import { IMatrixEvent } from '../definitions/IMatrixEvent';
import { MatrixEventType } from '../definitions/MatrixEventType';

export const setRoomTopic = async (
event: IMatrixEvent<MatrixEventType.SET_ROOM_TOPIC>,
): Promise<void> => {
const { room_id: matrixRoomId, content: { topic } } = event;

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

Rooms.update({ _id: roomId }, {
$set: {
description: topic,
},
});
};
14 changes: 14 additions & 0 deletions app/federation-bridge/server/callbacks/afterAddedToRoom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @ts-ignore
import { MatrixBridgedRoom } from '../../../models';
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');
}
Loading

0 comments on commit 5dbd963

Please sign in to comment.