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

[FIX] IRC Bridge not working #19009

Merged
merged 9 commits into from
Oct 25, 2020
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