Skip to content

Commit

Permalink
[FIX] IRC Bridge not working (#19009)
Browse files Browse the repository at this point in the history
  • Loading branch information
pierre-lehnen-rc committed Oct 25, 2020
1 parent c3ca020 commit aa922cf
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 99 deletions.
96 changes: 81 additions & 15 deletions app/irc/server/irc-bridge/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import { Meteor } from 'meteor/meteor';
import Queue from 'queue-fifo';
import moment from 'moment';
import _ from 'underscore';

import * as peerCommandHandlers from './peerHandlers';
import * as localCommandHandlers from './localHandlers';
import { callbacks } from '../../../callbacks';
import * as servers from '../servers';
import { Settings } from '../../../models/server';

let removed = false;
const updateLastPing = _.throttle(Meteor.bindEnvironment(() => {
if (removed) {
return;
}
Settings.upsert({ _id: 'IRC_Bridge_Last_Ping' }, {
$set: {
value: new Date(),
},
});
}), 1000 * 10);

class Bridge {
constructor(config) {
Expand All @@ -27,7 +43,21 @@ class Bridge {
}

init() {
this.initTime = new Date();
removed = false;
this.loggedInUsers = [];

const lastPing = Settings.findOneById('IRC_Bridge_Last_Ping');
if (lastPing) {
if (Math.abs(moment(lastPing.value).diff()) < 1000 * 30) {
this.log('Not trying to connect.');
this.remove();
return;
}
}

this.log('Connecting.');
updateLastPing();
this.server.register();

this.server.on('registered', () => {
Expand All @@ -41,6 +71,13 @@ class Bridge {
this.server.disconnect();
}

remove() {
this.log('Removing current connection.');
removed = true;
this.server = null;
this.removeLocalHandlers();
}

/**
* Log helper
*/
Expand All @@ -64,6 +101,19 @@ class Bridge {
}

async runQueue() {
if (!this.server) {
return;
}

const lastResetTime = Settings.findOneById('IRC_Bridge_Reset_Time');
if (lastResetTime && lastResetTime.value > this.initTime) {
this.stop();
this.remove();
return;
}

updateLastPing();

// If it is empty, skip and keep the queue going
if (this.queue.isEmpty()) {
return setTimeout(this.runQueue.bind(this), this.queueTimeout);
Expand All @@ -75,21 +125,26 @@ class Bridge {
this.logQueue(`Processing "${ item.command }" command from "${ item.from }"`);

// Handle the command accordingly
switch (item.from) {
case 'local':
if (!localCommandHandlers[item.command]) {
throw new Error(`Could not find handler for local:${ item.command }`);
}

await localCommandHandlers[item.command].apply(this, item.parameters);
break;
case 'peer':
if (!peerCommandHandlers[item.command]) {
throw new Error(`Could not find handler for peer:${ item.command }`);
}

await peerCommandHandlers[item.command].apply(this, item.parameters);
break;
try {
// Handle the command accordingly
switch (item.from) {
case 'local':
if (!localCommandHandlers[item.command]) {
throw new Error(`Could not find handler for local:${ item.command }`);
}

await localCommandHandlers[item.command].apply(this, item.parameters);
break;
case 'peer':
if (!peerCommandHandlers[item.command]) {
throw new Error(`Could not find handler for peer:${ item.command }`);
}

await peerCommandHandlers[item.command].apply(this, item.parameters);
break;
}
} catch (e) {
this.logQueue(e);
}

// Keep the queue going
Expand Down Expand Up @@ -132,6 +187,17 @@ class Bridge {
callbacks.add('afterLogoutCleanUp', this.onMessageReceived.bind(this, 'local', 'onLogout'), callbacks.priority.LOW, 'irc-on-logout');
}

removeLocalHandlers() {
callbacks.remove('afterValidateLogin', 'irc-on-login');
callbacks.remove('afterCreateUser', 'irc-on-create-user');
callbacks.remove('afterCreateChannel', 'irc-on-create-channel');
callbacks.remove('afterCreateRoom', 'irc-on-create-room');
callbacks.remove('afterJoinRoom', 'irc-on-join-room');
callbacks.remove('afterLeaveRoom', 'irc-on-leave-room');
callbacks.remove('afterSaveMessage', 'irc-on-save-message');
callbacks.remove('afterLogoutCleanUp', 'irc-on-logout');
}

sendCommand(command, parameters) {
this.server.emit('onReceiveFromLocal', command, parameters);
}
Expand Down
2 changes: 1 addition & 1 deletion app/irc/server/irc-bridge/localHandlers/onCreateRoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default function handleOnCreateRoom(user, room) {
const users = Users.findByRoomId(room._id);

users.forEach((user) => {
if (user.profile.irc.fromIRC) {
if (user.profile?.irc?.fromIRC) {
this.sendCommand('joinChannel', { room, user });
} else {
this.sendCommand('joinedChannel', { room, user });
Expand Down
9 changes: 7 additions & 2 deletions app/irc/server/irc-bridge/localHandlers/onLogin.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ export default function handleOnLogin(login) {
});

this.sendCommand('registerUser', user);

const rooms = Rooms.findBySubscriptionUserId(user._id).fetch();

rooms.forEach((room) => this.sendCommand('joinedChannel', { room, user }));
rooms.forEach((room) => {
if (room.t === 'd') {
return;
}

this.sendCommand('joinedChannel', { room, user });
});
}
2 changes: 1 addition & 1 deletion app/irc/server/irc-bridge/localHandlers/onSaveMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default function handleOnSaveMessage(message, to) {
if (to.t === 'd') {
const subscriptions = Subscriptions.findByRoomId(to._id);
subscriptions.forEach((subscription) => {
if (subscription.u.username !== to.username) {
if (subscription.u._id !== message.u._id) {
const userData = Users.findOne({ username: subscription.u.username });
if (userData) {
if (userData.profile && userData.profile.irc && userData.profile.irc.nick) {
Expand Down
4 changes: 1 addition & 3 deletions app/irc/server/irc-bridge/peerHandlers/disconnected.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Meteor } from 'meteor/meteor';

import { Users, Rooms } from '../../../../models';
import { Users } from '../../../../models';

export default function handleQUIT(args) {
const user = Users.findOne({
Expand All @@ -12,6 +12,4 @@ export default function handleQUIT(args) {
status: 'offline',
},
});

Rooms.removeUsernameFromAll(user.username);
}
50 changes: 12 additions & 38 deletions app/irc/server/irc-bridge/peerHandlers/sentMessage.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,27 @@
import { Users, Rooms, Subscriptions } from '../../../../models';
import { sendMessage } from '../../../../lib';
import { Users, Rooms } from '../../../../models';
import { sendMessage, createDirectRoom } from '../../../../lib';
/*
*
* Get direct chat room helper
*
*
*/
const getDirectRoom = (source, target) => {
const rid = [source._id, target._id].sort().join('');
const uids = [source._id, target._id];
const { _id, ...extraData } = createDirectRoom([source, target]);

Rooms.upsert({ _id: rid }, {
$setOnInsert: {
const room = Rooms.findOneDirectRoomContainingAllUserIDs(uids);
if (room) {
return {
t: 'd',
msgs: 0,
ts: new Date(),
},
});

Subscriptions.upsert({ rid, 'u._id': target._id }, {
$setOnInsert: {
name: source.username,
t: 'd',
open: false,
alert: false,
unread: 0,
u: {
_id: target._id,
username: target.username,
},
},
});

Subscriptions.upsert({ rid, 'u._id': source._id }, {
$setOnInsert: {
name: target.username,
t: 'd',
open: false,
alert: false,
unread: 0,
u: {
_id: source._id,
username: source.username,
},
},
});
...room,
};
}

return {
_id: rid,
_id,
t: 'd',
...extraData,
};
};

Expand Down
51 changes: 24 additions & 27 deletions app/irc/server/methods/resetIrcConnection.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import { Meteor } from 'meteor/meteor';

import { Settings } from '../../../models/server';
import { settings } from '../../../settings';
import { t } from '../../../utils';
import Bridge from '../irc-bridge';

Meteor.methods({
resetIrcConnection() {
const ircEnabled = !!settings.get('IRC_Enabled') === true;

if (Meteor.ircBridge) {
Meteor.ircBridge.stop();
if (!ircEnabled) {
return {
message: 'Connection_Closed',
params: [],
};
}
const ircEnabled = Boolean(settings.get('IRC_Enabled'));
Settings.upsert({ _id: 'IRC_Bridge_Last_Ping' }, {
$set: {
value: new Date(0),
},
});
Settings.upsert({ _id: 'IRC_Bridge_Reset_Time' }, {
$set: {
value: new Date(),
},
});

if (!ircEnabled) {
return {
message: 'Connection_Closed',
params: [],
};
}

if (ircEnabled) {
if (Meteor.ircBridge) {
Meteor.ircBridge.init();
return {
message: 'Connection_Reset',
params: [],
};
}

setTimeout(Meteor.bindEnvironment(() => {
// Normalize the config values
const config = {
server: {
Expand All @@ -44,13 +43,11 @@ Meteor.methods({

Meteor.ircBridge = new Bridge(config);
Meteor.ircBridge.init();
}), 300);

return {
message: 'Connection_Reset',
params: [],
};
}

throw new Meteor.Error(t('IRC_Federation_Disabled'));
return {
message: 'Connection_Reset',
params: [],
};
},
});
2 changes: 1 addition & 1 deletion app/irc/server/servers/RFC2813/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class RFC2813 {
if (localCommandHandlers[command]) {
this.log(`Handling local command: ${ command }`);

localCommandHandlers[command].call(this, parameters);
localCommandHandlers[command].call(this, parameters, this);
} else {
this.log(`Unhandled local command: ${ JSON.stringify(command) }`);
}
Expand Down
34 changes: 23 additions & 11 deletions app/irc/server/servers/RFC2813/localCommandHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,19 @@ function joinChannel(parameters) {
});
}

function joinedChannel(parameters) {
const {
room: { name: roomName },
user: { profile: { irc: { nick } } },
} = parameters;
function joinedChannel(parameters, handler) {
const roomName = parameters.room?.name;
const nick = parameters.user?.profile?.irc?.nick;

if (!roomName) {
handler.log('Skipping room with no name.');
return;
}

if (!nick) {
handler.log('Skipping user with no irc nick.');
return;
}

this.write({
prefix: nick,
Expand Down Expand Up @@ -56,12 +64,16 @@ function sentMessage(parameters) {
message,
} = parameters;

this.write({
prefix: nick,
command: 'PRIVMSG',
parameters: [to],
trailer: message,
});
// eslint-disable-next-line no-control-regex
const lines = message.toString().split(/\r\n|\r|\n|\u0007/);
for (const line of lines) {
this.write({
prefix: nick,
command: 'PRIVMSG',
parameters: [to],
trailer: line,
});
}
}

function disconnected(parameters) {
Expand Down

0 comments on commit aa922cf

Please sign in to comment.