|
|
@ -5,17 +5,74 @@ const tmi = require('tmi.js');
|
|
|
|
let bridge;
|
|
|
|
let bridge;
|
|
|
|
let tmiListener;
|
|
|
|
let tmiListener;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// permissions
|
|
|
|
|
|
|
|
const admins = process.env.ADMINS.split(',');
|
|
|
|
|
|
|
|
const users = process.env.USERS.split(',').concat(admins);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Matrix part
|
|
|
|
// Matrix part
|
|
|
|
|
|
|
|
async function checkAdminPermissions(sender) {
|
|
|
|
|
|
|
|
return admins.includes(sender);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function checkUserPermissions(sender) {
|
|
|
|
|
|
|
|
return users.includes(sender);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function bridgeRoom(sender, matrixRoom, remoteRoom) {
|
|
|
|
|
|
|
|
await bridge.getRoomStore().linkRooms(matrixRoom, remoteRoom);
|
|
|
|
|
|
|
|
console.log('Linked rooms', matrixRoom.roomId, 'and', remoteRoom.roomId, 'by', sender);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function unbridgeRoom(sender, roomId) {
|
|
|
|
|
|
|
|
await bridge.getRoomStore().removeEntriesByMatrixRoomId(roomId);
|
|
|
|
|
|
|
|
console.log('Removed Matrix room', roomId, 'by', sender);
|
|
|
|
|
|
|
|
}
|
|
|
|
async function matrixEventHandler(request, context) {
|
|
|
|
async function matrixEventHandler(request, context) {
|
|
|
|
const event = request.getData();
|
|
|
|
const event = request.getData();
|
|
|
|
|
|
|
|
|
|
|
|
if(event.type === 'm.room.message') {
|
|
|
|
if(event.type === 'm.room.message') {
|
|
|
|
const message = event.content.body;
|
|
|
|
const message = event.content.body;
|
|
|
|
|
|
|
|
|
|
|
|
const remoteUsers = await bridge.getUserStore().getRemoteUsersFromMatrixId(event.sender);
|
|
|
|
const remoteUsers = await bridge.getUserStore().getRemoteUsersFromMatrixId(event.sender);
|
|
|
|
// use the first user, multipe user mappings are unsupported
|
|
|
|
// use the first user, multipe user mappings are unsupported
|
|
|
|
const remoteUser = remoteUsers[0];
|
|
|
|
const remoteUser = remoteUsers[0];
|
|
|
|
|
|
|
|
if(!remoteUser) {
|
|
|
|
|
|
|
|
// ignore messages from users without tmi credentials
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// handle bot commands and return directly afterwards
|
|
|
|
|
|
|
|
const command = message.match(/^!tmi (?<subcommand>\w*)( (?<args>.*))?$/);
|
|
|
|
|
|
|
|
if(command) {
|
|
|
|
|
|
|
|
if(!await checkAdminPermissions(event.sender)) {
|
|
|
|
|
|
|
|
bridge.getIntent().sendText(event.room_id, event.sender+' is not permitted as admin of this bridge');
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (command.groups.subcommand) {
|
|
|
|
|
|
|
|
case 'bridge':
|
|
|
|
|
|
|
|
let channel = command.groups.args.toLowerCase();
|
|
|
|
|
|
|
|
if(!channel.match(/^#/)) {
|
|
|
|
|
|
|
|
channel = '#'+channel
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bridgeRoom(event.sender, new mx.MatrixRoom(event.room_id), new mx.RemoteRoom(channel));
|
|
|
|
|
|
|
|
bridge.getIntent().sendText(event.room_id, 'This room is now bridged to '+channel);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'unbridge':
|
|
|
|
|
|
|
|
unbridgeRoom(event.sender, event.room_id);
|
|
|
|
|
|
|
|
bridge.getIntent().sendText(event.room_id, 'Removed all bridges from this room');
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
bridge.getIntent().sendText(event.room_id, 'available commands: bridge, unbridge');
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!await checkUserPermissions(event.sender)) {
|
|
|
|
|
|
|
|
// no permissions; don't bridge
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const tmiUsername = remoteUser.id;
|
|
|
|
const tmiUsername = remoteUser.id;
|
|
|
|
const tmiPassword = remoteUser.data.password;
|
|
|
|
const tmiPassword = remoteUser.data.password;
|
|
|
|
|
|
|
|
|
|
|
|