mirror of https://github.com/calzoneman/sync.git
deps: remove "q" (#731)
Insert Star Trek joke here. Also did significant refactoring of the surrounding logic for the things that depended on Q.
This commit is contained in:
parent
d5f5c91b05
commit
79556d9365
|
@ -0,0 +1,581 @@
|
||||||
|
const assert = require('assert');
|
||||||
|
const KickbanModule = require('../../lib/channel/kickban');
|
||||||
|
const database = require('../../lib/database');
|
||||||
|
const Promise = require('bluebird');
|
||||||
|
const testDB = require('../testutil/db').testDB;
|
||||||
|
|
||||||
|
database.init(testDB);
|
||||||
|
|
||||||
|
describe('KickbanModule', () => {
|
||||||
|
const channelName = `test_${Math.random().toString(31).substring(2)}`;
|
||||||
|
|
||||||
|
let mockChannel;
|
||||||
|
let mockUser;
|
||||||
|
let kickban;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockChannel = {
|
||||||
|
name: channelName,
|
||||||
|
refCounter: {
|
||||||
|
ref() { },
|
||||||
|
unref() { }
|
||||||
|
},
|
||||||
|
logger: {
|
||||||
|
log() { }
|
||||||
|
},
|
||||||
|
modules: {
|
||||||
|
permissions: {
|
||||||
|
canBan() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
users: []
|
||||||
|
};
|
||||||
|
|
||||||
|
mockUser = {
|
||||||
|
getName() {
|
||||||
|
return 'The_Admin';
|
||||||
|
},
|
||||||
|
|
||||||
|
getLowerName() {
|
||||||
|
return 'the_admin';
|
||||||
|
},
|
||||||
|
|
||||||
|
socket: {
|
||||||
|
emit(frame) {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
throw new Error(arguments[1].msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
account: {
|
||||||
|
effectiveRank: 3
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban = new KickbanModule(mockChannel);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await database.getDB().runTransaction(async tx => {
|
||||||
|
await tx.table('channel_bans')
|
||||||
|
.where({ channel: channelName })
|
||||||
|
.del();
|
||||||
|
await tx.table('channel_ranks')
|
||||||
|
.where({ channel: channelName })
|
||||||
|
.del();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#handleCmdBan', () => {
|
||||||
|
it('inserts a valid ban', done => {
|
||||||
|
let kicked = false;
|
||||||
|
|
||||||
|
mockChannel.refCounter.unref = () => {
|
||||||
|
assert(kicked, 'Expected user to be kicked');
|
||||||
|
|
||||||
|
database.getDB().runTransaction(async tx => {
|
||||||
|
const ban = await tx.table('channel_bans')
|
||||||
|
.where({
|
||||||
|
channel: channelName,
|
||||||
|
name: 'test_user'
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
assert.strictEqual(ban.ip, '*');
|
||||||
|
assert.strictEqual(ban.reason, 'because reasons');
|
||||||
|
assert.strictEqual(ban.bannedby, mockUser.getName());
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
mockChannel.users = [{
|
||||||
|
getLowerName() {
|
||||||
|
return 'test_user';
|
||||||
|
},
|
||||||
|
|
||||||
|
kick(reason) {
|
||||||
|
assert.strictEqual(reason, "You're banned!");
|
||||||
|
kicked = true;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
kickban.handleCmdBan(
|
||||||
|
mockUser,
|
||||||
|
'/ban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the user does not have ban permission', done => {
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
'You do not have ban permissions on this channel'
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mockChannel.modules.permissions.canBan = () => false;
|
||||||
|
|
||||||
|
kickban.handleCmdBan(
|
||||||
|
mockUser,
|
||||||
|
'/ban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the user tries to ban themselves', done => {
|
||||||
|
let costanza = false;
|
||||||
|
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
'You cannot ban yourself'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!costanza) {
|
||||||
|
throw new Error('Expected costanza for banning self');
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
} else if (frame === 'costanza') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
"You can't ban yourself"
|
||||||
|
);
|
||||||
|
|
||||||
|
costanza = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdBan(
|
||||||
|
mockUser,
|
||||||
|
'/ban the_Admin because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the user is ranked below the ban recipient', done => {
|
||||||
|
database.getDB().runTransaction(tx => {
|
||||||
|
return tx.table('channel_ranks')
|
||||||
|
.insert({
|
||||||
|
channel: channelName,
|
||||||
|
name: 'test_user',
|
||||||
|
rank: 5
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
"You don't have permission to ban test_user"
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdBan(
|
||||||
|
mockUser,
|
||||||
|
'/ban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the the ban recipient is already banned', done => {
|
||||||
|
database.getDB().runTransaction(tx => {
|
||||||
|
return tx.table('channel_bans')
|
||||||
|
.insert({
|
||||||
|
channel: channelName,
|
||||||
|
name: 'test_user',
|
||||||
|
ip: '*',
|
||||||
|
bannedby: 'somebody',
|
||||||
|
reason: 'I dunno'
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
'test_user is already banned'
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdBan(
|
||||||
|
mockUser,
|
||||||
|
'/ban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#handleCmdIPBan', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await database.getDB().runTransaction(async tx => {
|
||||||
|
await tx.table('aliases')
|
||||||
|
.insert([{
|
||||||
|
name: 'test_user',
|
||||||
|
ip: '1.2.3.4'
|
||||||
|
}]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await database.getDB().runTransaction(async tx => {
|
||||||
|
await tx.table('aliases')
|
||||||
|
.where({ name: 'test_user' })
|
||||||
|
.orWhere({ ip: '1.2.3.4' })
|
||||||
|
.del();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inserts a valid ban', done => {
|
||||||
|
let firstUserKicked = false;
|
||||||
|
let secondUserKicked = false;
|
||||||
|
|
||||||
|
mockChannel.refCounter.unref = () => {
|
||||||
|
assert(firstUserKicked, 'Expected banned user to be kicked');
|
||||||
|
assert(
|
||||||
|
secondUserKicked,
|
||||||
|
'Expected user with banned IP to be kicked'
|
||||||
|
);
|
||||||
|
|
||||||
|
database.getDB().runTransaction(async tx => {
|
||||||
|
const nameBan = await tx.table('channel_bans')
|
||||||
|
.where({
|
||||||
|
channel: channelName,
|
||||||
|
name: 'test_user',
|
||||||
|
ip: '*'
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
assert.strictEqual(nameBan.reason, 'because reasons');
|
||||||
|
assert.strictEqual(nameBan.bannedby, mockUser.getName());
|
||||||
|
|
||||||
|
const ipBan = await tx.table('channel_bans')
|
||||||
|
.where({
|
||||||
|
channel: channelName,
|
||||||
|
ip: '1.2.3.4'
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
assert.strictEqual(ipBan.name, 'test_user');
|
||||||
|
assert.strictEqual(ipBan.reason, 'because reasons');
|
||||||
|
assert.strictEqual(ipBan.bannedby, mockUser.getName());
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
mockChannel.users = [{
|
||||||
|
getLowerName() {
|
||||||
|
return 'test_user';
|
||||||
|
},
|
||||||
|
|
||||||
|
realip: '1.2.3.4',
|
||||||
|
|
||||||
|
kick(reason) {
|
||||||
|
assert.strictEqual(reason, "You're banned!");
|
||||||
|
firstUserKicked = true;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
getLowerName() {
|
||||||
|
return 'second_user_same_ip';
|
||||||
|
},
|
||||||
|
|
||||||
|
realip: '1.2.3.4',
|
||||||
|
|
||||||
|
kick(reason) {
|
||||||
|
assert.strictEqual(reason, "You're banned!");
|
||||||
|
secondUserKicked = true;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inserts a valid range ban', done => {
|
||||||
|
mockChannel.refCounter.unref = () => {
|
||||||
|
database.getDB().runTransaction(async tx => {
|
||||||
|
const ipBan = await tx.table('channel_bans')
|
||||||
|
.where({
|
||||||
|
channel: channelName,
|
||||||
|
ip: '1.2.3'
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
assert.strictEqual(ipBan.name, 'test_user');
|
||||||
|
assert.strictEqual(ipBan.reason, 'because reasons');
|
||||||
|
assert.strictEqual(ipBan.bannedby, mockUser.getName());
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user range because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inserts a valid wide-range ban', done => {
|
||||||
|
mockChannel.refCounter.unref = () => {
|
||||||
|
database.getDB().runTransaction(async tx => {
|
||||||
|
const ipBan = await tx.table('channel_bans')
|
||||||
|
.where({
|
||||||
|
channel: channelName,
|
||||||
|
ip: '1.2'
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
assert.strictEqual(ipBan.name, 'test_user');
|
||||||
|
assert.strictEqual(ipBan.reason, 'because reasons');
|
||||||
|
assert.strictEqual(ipBan.bannedby, mockUser.getName());
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user wrange because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('inserts a valid IPv6 ban', done => {
|
||||||
|
const longIP = require('../../lib/utilities').expandIPv6('::abcd');
|
||||||
|
|
||||||
|
mockChannel.refCounter.unref = () => {
|
||||||
|
database.getDB().runTransaction(async tx => {
|
||||||
|
const ipBan = await tx.table('channel_bans')
|
||||||
|
.where({
|
||||||
|
channel: channelName,
|
||||||
|
ip: longIP
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
assert.strictEqual(ipBan.name, 'test_user');
|
||||||
|
assert.strictEqual(ipBan.reason, 'because reasons');
|
||||||
|
assert.strictEqual(ipBan.bannedby, mockUser.getName());
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
database.getDB().runTransaction(async tx => {
|
||||||
|
await tx.table('aliases')
|
||||||
|
.insert({
|
||||||
|
name: 'test_user',
|
||||||
|
ip: longIP
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the user does not have ban permission', done => {
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
'You do not have ban permissions on this channel'
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mockChannel.modules.permissions.canBan = () => false;
|
||||||
|
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the user tries to ban themselves', done => {
|
||||||
|
let costanza = false;
|
||||||
|
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
'You cannot ban yourself'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!costanza) {
|
||||||
|
throw new Error('Expected costanza for banning self');
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
} else if (frame === 'costanza') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
"You can't ban yourself"
|
||||||
|
);
|
||||||
|
|
||||||
|
costanza = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban the_Admin because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the user is ranked below the ban recipient', done => {
|
||||||
|
database.getDB().runTransaction(tx => {
|
||||||
|
return tx.table('channel_ranks')
|
||||||
|
.insert({
|
||||||
|
channel: channelName,
|
||||||
|
name: 'test_user',
|
||||||
|
rank: 5
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
"You don't have permission to ban IP " +
|
||||||
|
"09l.TFb.5To.HBB"
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the user is ranked below an alias of the ban recipient', done => {
|
||||||
|
database.getDB().runTransaction(async tx => {
|
||||||
|
await tx.table('channel_ranks')
|
||||||
|
.insert({
|
||||||
|
channel: channelName,
|
||||||
|
name: 'another_user',
|
||||||
|
rank: 5
|
||||||
|
});
|
||||||
|
await tx.table('aliases')
|
||||||
|
.insert({
|
||||||
|
name: 'another_user',
|
||||||
|
ip: '1.2.3.3' // different IP, same /24 range
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
"You don't have permission to ban IP " +
|
||||||
|
"09l.TFb.5To.*"
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user range because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects if the the ban recipient IP is already banned', done => {
|
||||||
|
database.getDB().runTransaction(tx => {
|
||||||
|
return tx.table('channel_bans')
|
||||||
|
.insert({
|
||||||
|
channel: channelName,
|
||||||
|
name: 'another_user',
|
||||||
|
ip: '1.2.3.4',
|
||||||
|
bannedby: 'somebody',
|
||||||
|
reason: 'I dunno'
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
mockUser.socket.emit = (frame, obj) => {
|
||||||
|
if (frame === 'errorMsg') {
|
||||||
|
assert.strictEqual(
|
||||||
|
obj.msg,
|
||||||
|
'09l.TFb.5To.HBB is already banned'
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('still adds the IP ban even if the name is already banned', done => {
|
||||||
|
mockChannel.refCounter.unref = () => {
|
||||||
|
database.getDB().runTransaction(async tx => {
|
||||||
|
const ipBan = await tx.table('channel_bans')
|
||||||
|
.where({
|
||||||
|
channel: channelName,
|
||||||
|
ip: '1.2.3.4'
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
assert.strictEqual(ipBan.name, 'test_user');
|
||||||
|
assert.strictEqual(ipBan.reason, 'because reasons');
|
||||||
|
assert.strictEqual(ipBan.bannedby, mockUser.getName());
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
database.getDB().runTransaction(tx => {
|
||||||
|
return tx.table('channel_bans')
|
||||||
|
.insert({
|
||||||
|
channel: channelName,
|
||||||
|
name: 'test_user',
|
||||||
|
ip: '*',
|
||||||
|
bannedby: 'somebody',
|
||||||
|
reason: 'I dunno'
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
kickban.handleCmdIPBan(
|
||||||
|
mockUser,
|
||||||
|
'/ipban test_user because reasons',
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -2,7 +2,7 @@
|
||||||
"author": "Calvin Montgomery",
|
"author": "Calvin Montgomery",
|
||||||
"name": "CyTube",
|
"name": "CyTube",
|
||||||
"description": "Online media synchronizer and chat",
|
"description": "Online media synchronizer and chat",
|
||||||
"version": "3.54.0",
|
"version": "3.55.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "http://github.com/calzoneman/sync"
|
"url": "http://github.com/calzoneman/sync"
|
||||||
},
|
},
|
||||||
|
@ -33,7 +33,6 @@
|
||||||
"prom-client": "^10.0.2",
|
"prom-client": "^10.0.2",
|
||||||
"proxy-addr": "^2.0.2",
|
"proxy-addr": "^2.0.2",
|
||||||
"pug": "^2.0.0-beta3",
|
"pug": "^2.0.0-beta3",
|
||||||
"q": "^1.4.1",
|
|
||||||
"redis": "^2.4.2",
|
"redis": "^2.4.2",
|
||||||
"sanitize-html": "^1.14.1",
|
"sanitize-html": "^1.14.1",
|
||||||
"serve-static": "^1.13.2",
|
"serve-static": "^1.13.2",
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
var db = require("./database");
|
import db from './database';
|
||||||
var Q = require("q");
|
import Promise from 'bluebird';
|
||||||
|
|
||||||
|
const dbGetGlobalRank = Promise.promisify(db.users.getGlobalRank);
|
||||||
|
const dbMultiGetGlobalRank = Promise.promisify(db.users.getGlobalRanks);
|
||||||
|
const dbGetChannelRank = Promise.promisify(db.channels.getRank);
|
||||||
|
const dbMultiGetChannelRank = Promise.promisify(db.channels.getRanks);
|
||||||
|
const dbGetAliases = Promise.promisify(db.getAliases);
|
||||||
|
|
||||||
const DEFAULT_PROFILE = Object.freeze({ image: '', text: '' });
|
const DEFAULT_PROFILE = Object.freeze({ image: '', text: '' });
|
||||||
|
|
||||||
|
@ -33,71 +39,21 @@ class Account {
|
||||||
|
|
||||||
module.exports.Account = Account;
|
module.exports.Account = Account;
|
||||||
|
|
||||||
module.exports.rankForName = function (name, opts, cb) {
|
module.exports.rankForName = async function rankForNameAsync(name, channel) {
|
||||||
if (!cb) {
|
const [globalRank, channelRank] = await Promise.all([
|
||||||
cb = opts;
|
dbGetGlobalRank(name),
|
||||||
opts = {};
|
dbGetChannelRank(channel, name)
|
||||||
}
|
]);
|
||||||
|
|
||||||
var rank = 0;
|
return Math.max(globalRank, channelRank);
|
||||||
Q.fcall(function () {
|
|
||||||
return Q.nfcall(db.users.getGlobalRank, name);
|
|
||||||
}).then(function (globalRank) {
|
|
||||||
rank = globalRank;
|
|
||||||
if (opts.channel) {
|
|
||||||
return Q.nfcall(db.channels.getRank, opts.channel, name);
|
|
||||||
} else {
|
|
||||||
return globalRank > 0 ? 1 : 0;
|
|
||||||
}
|
|
||||||
}).then(function (chanRank) {
|
|
||||||
setImmediate(function () {
|
|
||||||
cb(null, Math.max(rank, chanRank));
|
|
||||||
});
|
|
||||||
}).catch(function (err) {
|
|
||||||
cb(err, 0);
|
|
||||||
}).done();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.rankForIP = function (ip, opts, cb) {
|
module.exports.rankForIP = async function rankForIP(ip, channel) {
|
||||||
if (!cb) {
|
const aliases = await dbGetAliases(ip);
|
||||||
cb = opts;
|
const [globalRanks, channelRanks] = await Promise.all([
|
||||||
opts = {};
|
dbMultiGetGlobalRank(aliases),
|
||||||
}
|
dbMultiGetChannelRank(channel, aliases)
|
||||||
|
]);
|
||||||
|
|
||||||
var globalRank, rank, names;
|
return Math.max.apply(Math, globalRanks.concat(channelRanks));
|
||||||
|
|
||||||
var promise = Q.nfcall(db.getAliases, ip)
|
|
||||||
.then(function (_names) {
|
|
||||||
names = _names;
|
|
||||||
return Q.nfcall(db.users.getGlobalRanks, names);
|
|
||||||
}).then(function (ranks) {
|
|
||||||
ranks.push(0);
|
|
||||||
globalRank = Math.max.apply(Math, ranks);
|
|
||||||
rank = globalRank;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!opts.channel) {
|
|
||||||
promise.then(function () {
|
|
||||||
setImmediate(function () {
|
|
||||||
cb(null, globalRank);
|
|
||||||
});
|
|
||||||
}).catch(function (err) {
|
|
||||||
cb(err, null);
|
|
||||||
}).done();
|
|
||||||
} else {
|
|
||||||
promise.then(function () {
|
|
||||||
return Q.nfcall(db.channels.getRanks, opts.channel, names);
|
|
||||||
}).then(function (ranks) {
|
|
||||||
ranks.push(globalRank);
|
|
||||||
rank = Math.max.apply(Math, ranks);
|
|
||||||
}).then(function () {
|
|
||||||
setImmediate(function () {
|
|
||||||
cb(null, rank);
|
|
||||||
});
|
|
||||||
}).catch(function (err) {
|
|
||||||
setImmediate(function () {
|
|
||||||
cb(err, null);
|
|
||||||
});
|
|
||||||
}).done();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,12 @@ var db = require("../database");
|
||||||
var Flags = require("../flags");
|
var Flags = require("../flags");
|
||||||
var util = require("../utilities");
|
var util = require("../utilities");
|
||||||
var Account = require("../account");
|
var Account = require("../account");
|
||||||
var Q = require("q");
|
import Promise from 'bluebird';
|
||||||
|
|
||||||
|
const dbIsNameBanned = Promise.promisify(db.channels.isNameBanned);
|
||||||
|
const dbIsIPBanned = Promise.promisify(db.channels.isIPBanned);
|
||||||
|
const dbAddBan = Promise.promisify(db.channels.ban);
|
||||||
|
const dbGetIPs = Promise.promisify(db.getIPs);
|
||||||
|
|
||||||
const TYPE_UNBAN = {
|
const TYPE_UNBAN = {
|
||||||
id: "number",
|
id: "number",
|
||||||
|
@ -234,7 +239,11 @@ KickBanModule.prototype.handleCmdBan = function (user, msg, meta) {
|
||||||
|
|
||||||
const chan = this.channel;
|
const chan = this.channel;
|
||||||
chan.refCounter.ref("KickBanModule::handleCmdBan");
|
chan.refCounter.ref("KickBanModule::handleCmdBan");
|
||||||
this.banName(user, name, reason, function (err) {
|
|
||||||
|
this.banName(user, name, reason).catch(error => {
|
||||||
|
const message = error.message || error;
|
||||||
|
user.socket.emit("errorMsg", { msg: message });
|
||||||
|
}).finally(() => {
|
||||||
chan.refCounter.unref("KickBanModule::handleCmdBan");
|
chan.refCounter.unref("KickBanModule::handleCmdBan");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -261,23 +270,29 @@ KickBanModule.prototype.handleCmdIPBan = function (user, msg, meta) {
|
||||||
|
|
||||||
const chan = this.channel;
|
const chan = this.channel;
|
||||||
chan.refCounter.ref("KickBanModule::handleCmdIPBan");
|
chan.refCounter.ref("KickBanModule::handleCmdIPBan");
|
||||||
this.banAll(user, name, range, reason, function (err) {
|
|
||||||
|
this.banAll(user, name, range, reason).catch(error => {
|
||||||
|
//console.log('!!!', error.stack);
|
||||||
|
const message = error.message || error;
|
||||||
|
user.socket.emit("errorMsg", { msg: message });
|
||||||
|
}).finally(() => {
|
||||||
chan.refCounter.unref("KickBanModule::handleCmdIPBan");
|
chan.refCounter.unref("KickBanModule::handleCmdIPBan");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
KickBanModule.prototype.banName = function (actor, name, reason, cb) {
|
KickBanModule.prototype.checkChannelAlive = function checkChannelAlive() {
|
||||||
var self = this;
|
if (!this.channel || this.channel.dead) {
|
||||||
|
throw new Error("Channel not live");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
KickBanModule.prototype.banName = async function banName(actor, name, reason) {
|
||||||
reason = reason.substring(0, 255);
|
reason = reason.substring(0, 255);
|
||||||
|
|
||||||
var chan = this.channel;
|
var chan = this.channel;
|
||||||
var error = function (what) {
|
|
||||||
actor.socket.emit("errorMsg", { msg: what });
|
|
||||||
cb(what);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!chan.modules.permissions.canBan(actor)) {
|
if (!chan.modules.permissions.canBan(actor)) {
|
||||||
return error("You do not have ban permissions on this channel");
|
throw new Error("You do not have ban permissions on this channel");
|
||||||
}
|
}
|
||||||
|
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
|
@ -285,129 +300,126 @@ KickBanModule.prototype.banName = function (actor, name, reason, cb) {
|
||||||
actor.socket.emit("costanza", {
|
actor.socket.emit("costanza", {
|
||||||
msg: "You can't ban yourself"
|
msg: "You can't ban yourself"
|
||||||
});
|
});
|
||||||
return cb("Attempted to ban self");
|
|
||||||
|
throw new Error("You cannot ban yourself");
|
||||||
}
|
}
|
||||||
|
|
||||||
Q.nfcall(Account.rankForName, name, { channel: chan.name })
|
const rank = await Account.rankForName(name, chan.name);
|
||||||
.then(function (rank) {
|
this.checkChannelAlive();
|
||||||
|
|
||||||
if (rank >= actor.account.effectiveRank) {
|
if (rank >= actor.account.effectiveRank) {
|
||||||
throw "You don't have permission to ban " + name;
|
throw new Error("You don't have permission to ban " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Q.nfcall(db.channels.isNameBanned, chan.name, name);
|
const isBanned = await dbIsNameBanned(chan.name, name);
|
||||||
}).then(function (banned) {
|
this.checkChannelAlive();
|
||||||
if (banned) {
|
|
||||||
throw name + " is already banned";
|
if (isBanned) {
|
||||||
|
throw new Error(name + " is already banned");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan.dead) { throw null; }
|
await dbAddBan(chan.name, "*", name, reason, actor.getName());
|
||||||
|
this.checkChannelAlive();
|
||||||
|
|
||||||
return Q.nfcall(db.channels.ban, chan.name, "*", name, reason, actor.getName());
|
|
||||||
}).then(function () {
|
|
||||||
chan.logger.log("[mod] " + actor.getName() + " namebanned " + name);
|
chan.logger.log("[mod] " + actor.getName() + " namebanned " + name);
|
||||||
|
|
||||||
if (chan.modules.chat) {
|
if (chan.modules.chat) {
|
||||||
chan.modules.chat.sendModMessage(actor.getName() + " namebanned " + name,
|
chan.modules.chat.sendModMessage(
|
||||||
chan.modules.permissions.permissions.ban);
|
actor.getName() + " namebanned " + name,
|
||||||
|
chan.modules.permissions.permissions.ban
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}).then(function () {
|
this.kickBanTarget(name, null);
|
||||||
self.kickBanTarget(name, null);
|
|
||||||
setImmediate(function () {
|
|
||||||
cb(null);
|
|
||||||
});
|
|
||||||
}).catch(error).done();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
KickBanModule.prototype.banIP = function (actor, ip, name, reason, cb) {
|
KickBanModule.prototype.banIP = async function banIP(actor, ip, name, reason) {
|
||||||
var self = this;
|
|
||||||
reason = reason.substring(0, 255);
|
reason = reason.substring(0, 255);
|
||||||
var masked = util.cloakIP(ip);
|
var masked = util.cloakIP(ip);
|
||||||
|
|
||||||
var chan = this.channel;
|
var chan = this.channel;
|
||||||
var error = function (what) {
|
|
||||||
actor.socket.emit("errorMsg", { msg: what });
|
|
||||||
cb(what);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!chan.modules.permissions.canBan(actor)) {
|
if (!chan.modules.permissions.canBan(actor)) {
|
||||||
return error("You do not have ban permissions on this channel");
|
throw new Error("You do not have ban permissions on this channel");
|
||||||
}
|
}
|
||||||
|
|
||||||
Q.nfcall(Account.rankForIP, ip, { channel: chan.name }).then(function (rank) {
|
const rank = await Account.rankForIP(ip, chan.name);
|
||||||
|
this.checkChannelAlive();
|
||||||
|
|
||||||
if (rank >= actor.account.effectiveRank) {
|
if (rank >= actor.account.effectiveRank) {
|
||||||
throw "You don't have permission to ban IP " + masked;
|
// TODO: this message should be made friendlier
|
||||||
|
throw new Error("You don't have permission to ban IP " + masked);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Q.nfcall(db.channels.isIPBanned, chan.name, ip);
|
const isBanned = await dbIsIPBanned(chan.name, ip);
|
||||||
}).then(function (banned) {
|
this.checkChannelAlive();
|
||||||
if (banned) {
|
|
||||||
throw masked + " is already banned";
|
if (isBanned) {
|
||||||
|
// TODO: this message should be made friendlier
|
||||||
|
throw new Error(masked + " is already banned");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan.dead) { throw null; }
|
await dbAddBan(chan.name, ip, name, reason, actor.getName());
|
||||||
|
this.checkChannelAlive();
|
||||||
|
|
||||||
return Q.nfcall(db.channels.ban, chan.name, ip, name, reason, actor.getName());
|
|
||||||
}).then(function () {
|
|
||||||
var cloaked = util.cloakIP(ip);
|
var cloaked = util.cloakIP(ip);
|
||||||
chan.logger.log("[mod] " + actor.getName() + " banned " + cloaked + " (" + name + ")");
|
chan.logger.log(
|
||||||
|
"[mod] " + actor.getName() + " banned " + cloaked +
|
||||||
|
" (" + name + ")"
|
||||||
|
);
|
||||||
|
|
||||||
if (chan.modules.chat) {
|
if (chan.modules.chat) {
|
||||||
chan.modules.chat.sendModMessage(actor.getName() + " banned " +
|
chan.modules.chat.sendModMessage(
|
||||||
cloaked + " (" + name + ")",
|
actor.getName() + " banned " + cloaked + " (" + name + ")",
|
||||||
chan.modules.permissions.permissions.ban);
|
chan.modules.permissions.permissions.ban
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}).then(function () {
|
|
||||||
self.kickBanTarget(name, ip);
|
this.kickBanTarget(name, ip);
|
||||||
setImmediate(function () {
|
|
||||||
cb(null);
|
|
||||||
});
|
|
||||||
}).catch(error).done();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
KickBanModule.prototype.banAll = function (actor, name, range, reason, cb) {
|
KickBanModule.prototype.banAll = async function banAll(
|
||||||
var self = this;
|
actor,
|
||||||
|
name,
|
||||||
|
range,
|
||||||
|
reason
|
||||||
|
) {
|
||||||
reason = reason.substring(0, 255);
|
reason = reason.substring(0, 255);
|
||||||
|
|
||||||
var chan = self.channel;
|
var chan = this.channel;
|
||||||
var error = function (what) {
|
|
||||||
cb(what);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!chan.modules.permissions.canBan(actor)) {
|
if (!chan.modules.permissions.canBan(actor)) {
|
||||||
return error("You do not have ban permissions on this channel");
|
throw new Error("You do not have ban permissions on this channel");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.banName(actor, name, reason, function (err) {
|
const ips = await dbGetIPs(name);
|
||||||
if (err && err.indexOf("is already banned") === -1) {
|
this.checkChannelAlive();
|
||||||
cb(err);
|
|
||||||
} else {
|
const toBan = new Set();
|
||||||
db.getIPs(name, function (err, ips) {
|
for (let ip of ips) {
|
||||||
if (err) {
|
switch (range) {
|
||||||
return error(err);
|
case "range":
|
||||||
|
toBan.add(util.getIPRange(ip));
|
||||||
|
break;
|
||||||
|
case "wrange":
|
||||||
|
toBan.add(util.getWideIPRange(ip));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
toBan.add(ip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var seenIPs = {};
|
const promises = Array.from(toBan).map(ip =>
|
||||||
var all = ips.map(function (ip) {
|
this.banIP(actor, ip, name, reason)
|
||||||
if (range === "range") {
|
);
|
||||||
ip = util.getIPRange(ip);
|
|
||||||
} else if (range === "wrange") {
|
if (!await dbIsNameBanned(chan.name, name)) {
|
||||||
ip = util.getWideIPRange(ip);
|
promises.push(this.banName(actor, name, reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seenIPs.hasOwnProperty(ip)) {
|
await Promise.all(promises);
|
||||||
return;
|
this.checkChannelAlive();
|
||||||
} else {
|
|
||||||
seenIPs[ip] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Q.nfcall(self.banIP.bind(self), actor, ip, name, reason);
|
|
||||||
});
|
|
||||||
|
|
||||||
Q.all(all).then(function () {
|
|
||||||
setImmediate(cb);
|
|
||||||
}).catch(error).done();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
KickBanModule.prototype.kickBanTarget = function (name, ip) {
|
KickBanModule.prototype.kickBanTarget = function (name, ip) {
|
||||||
|
|
|
@ -2,6 +2,9 @@ var ChannelModule = require("./module");
|
||||||
var Flags = require("../flags");
|
var Flags = require("../flags");
|
||||||
var Account = require("../account");
|
var Account = require("../account");
|
||||||
var db = require("../database");
|
var db = require("../database");
|
||||||
|
import Promise from 'bluebird';
|
||||||
|
|
||||||
|
const dbSetChannelRank = Promise.promisify(db.channels.setRank);
|
||||||
|
|
||||||
const TYPE_SET_CHANNEL_RANK = {
|
const TYPE_SET_CHANNEL_RANK = {
|
||||||
name: "string",
|
name: "string",
|
||||||
|
@ -177,17 +180,20 @@ RankModule.prototype.handleRankChange = function (user, data) {
|
||||||
|
|
||||||
RankModule.prototype.updateDatabase = function (data, cb) {
|
RankModule.prototype.updateDatabase = function (data, cb) {
|
||||||
var chan = this.channel;
|
var chan = this.channel;
|
||||||
Account.rankForName(data.name, { channel: this.channel.name }, function (err, rank) {
|
Account.rankForName(data.name, this.channel.name).then(rank => {
|
||||||
if (err) {
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rank >= data.userrank && !(rank === 4 && data.userrank === 4)) {
|
if (rank >= data.userrank && !(rank === 4 && data.userrank === 4)) {
|
||||||
cb("You can't promote or demote someone with equal or higher rank than you.");
|
throw new Error(
|
||||||
|
"You can't promote or demote someone" +
|
||||||
|
" with equal or higher rank than you."
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
db.channels.setRank(chan.name, data.name, data.rank, cb);
|
return dbSetChannelRank(chan.name, data.name, data.rank);
|
||||||
|
}).then(() => {
|
||||||
|
process.nextTick(cb);
|
||||||
|
}).catch(error => {
|
||||||
|
process.nextTick(cb, error.message || error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,8 @@ class Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.Database = Database;
|
module.exports.Database = Database;
|
||||||
|
module.exports.users = require("./database/accounts");
|
||||||
|
module.exports.channels = require("./database/channels");
|
||||||
|
|
||||||
module.exports.init = function (newDB) {
|
module.exports.init = function (newDB) {
|
||||||
if (newDB) {
|
if (newDB) {
|
||||||
|
@ -85,9 +87,6 @@ module.exports.init = function (newDB) {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
process.nextTick(legacySetup);
|
process.nextTick(legacySetup);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports.users = require("./database/accounts");
|
|
||||||
module.exports.channels = require("./database/channels");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.getDB = function getDB() {
|
module.exports.getDB = function getDB() {
|
||||||
|
|
|
@ -328,10 +328,10 @@ module.exports = {
|
||||||
var replace = "(" + names.map(function () { return "?"; }).join(",") + ")";
|
var replace = "(" + names.map(function () { return "?"; }).join(",") + ")";
|
||||||
|
|
||||||
/* Last substitution is the channel to select ranks for */
|
/* Last substitution is the channel to select ranks for */
|
||||||
names.push(chan);
|
const sub = names.concat([chan]);
|
||||||
|
|
||||||
db.query("SELECT * FROM `channel_ranks` WHERE name IN " +
|
db.query("SELECT * FROM `channel_ranks` WHERE name IN " +
|
||||||
replace + " AND channel=?", names,
|
replace + " AND channel=?", sub,
|
||||||
function (err, rows) {
|
function (err, rows) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err, []);
|
callback(err, []);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
var db = require("../database");
|
var db = require("../database");
|
||||||
var Q = require("q");
|
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
|
|
||||||
const LOGGER = require('@calzoneman/jsli')('database/update');
|
const LOGGER = require('@calzoneman/jsli')('database/update');
|
||||||
|
@ -41,15 +40,9 @@ module.exports.checkVersion = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
function update(version, cb) {
|
function update(version, cb) {
|
||||||
if (version < 4) {
|
if (version < 7) {
|
||||||
LOGGER.error('Cannot auto-upgrade: db_version 4 is too old!');
|
LOGGER.error('Cannot auto-upgrade: db_version 4 is too old!');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else if (version < 5) {
|
|
||||||
fixUtf8mb4(cb);
|
|
||||||
} else if (version < 6) {
|
|
||||||
fixCustomEmbeds(cb);
|
|
||||||
} else if (version < 7) {
|
|
||||||
fixCustomEmbedsInUserPlaylists(cb);
|
|
||||||
} else if (version < 8) {
|
} else if (version < 8) {
|
||||||
addUsernameDedupeColumn(cb);
|
addUsernameDedupeColumn(cb);
|
||||||
} else if (version < 9) {
|
} else if (version < 9) {
|
||||||
|
@ -61,110 +54,6 @@ function update(version, cb) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fixUtf8mb4(cb) {
|
|
||||||
var queries = [
|
|
||||||
"ALTER TABLE `users` MODIFY `profile` TEXT CHARACTER SET utf8mb4 NOT NULL",
|
|
||||||
"ALTER TABLE `global_bans` MODIFY `reason` VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL",
|
|
||||||
"ALTER TABLE `channel_libraries` MODIFY `title` VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL",
|
|
||||||
"ALTER TABLE `channel_bans` MODIFY `reason` VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL"
|
|
||||||
];
|
|
||||||
|
|
||||||
Q.allSettled(queries.map(function (query) {
|
|
||||||
return Q.nfcall(db.query, query);
|
|
||||||
})).then(function () {
|
|
||||||
LOGGER.info("Fixed utf8mb4");
|
|
||||||
cb();
|
|
||||||
}).catch(function (e) {
|
|
||||||
LOGGER.error("Failed to fix utf8mb4: " + e);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function fixCustomEmbeds(cb) {
|
|
||||||
var CustomEmbedFilter = require("../customembed").filter;
|
|
||||||
|
|
||||||
Q.nfcall(db.query, "SELECT * FROM `channel_libraries` WHERE type='cu'")
|
|
||||||
.then(function (rows) {
|
|
||||||
var all = [];
|
|
||||||
rows.forEach(function (row) {
|
|
||||||
if (row.id.indexOf("cu:") === 0) return;
|
|
||||||
|
|
||||||
all.push(Q.nfcall(db.query, "DELETE FROM `channel_libraries` WHERE `id`=? AND `channel`=?",
|
|
||||||
[row.id, row.channel]));
|
|
||||||
|
|
||||||
try {
|
|
||||||
var media = CustomEmbedFilter(row.id);
|
|
||||||
|
|
||||||
all.push(Q.nfcall(db.channels.addToLibrary, row.channel, media));
|
|
||||||
} catch(e) {
|
|
||||||
console.error("WARNING: Unable to convert " + row.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Q.allSettled(all).then(function () {
|
|
||||||
LOGGER.info("Converted custom embeds.");
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function fixCustomEmbedsInUserPlaylists(cb) {
|
|
||||||
var CustomEmbedFilter = require("../customembed").filter;
|
|
||||||
Q.nfcall(db.query, "SELECT * FROM `user_playlists` WHERE `contents` LIKE '%\"type\":\"cu\"%'")
|
|
||||||
.then(function (rows) {
|
|
||||||
var all = [];
|
|
||||||
rows.forEach(function (row) {
|
|
||||||
var data;
|
|
||||||
try {
|
|
||||||
data = JSON.parse(row.contents);
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var updated = [];
|
|
||||||
var item;
|
|
||||||
while ((item = data.shift()) !== undefined) {
|
|
||||||
if (item.type !== "cu") {
|
|
||||||
updated.push(item);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^cu:/.test(item.id)) {
|
|
||||||
updated.push(item);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var media;
|
|
||||||
try {
|
|
||||||
media = CustomEmbedFilter(item.id);
|
|
||||||
} catch (e) {
|
|
||||||
LOGGER.info("WARNING: Unable to convert " + item.id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
updated.push({
|
|
||||||
id: media.id,
|
|
||||||
title: item.title,
|
|
||||||
seconds: media.seconds,
|
|
||||||
type: media.type,
|
|
||||||
meta: {
|
|
||||||
embed: media.meta.embed
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
all.push(Q.nfcall(db.query, "UPDATE `user_playlists` SET `contents`=?, `count`=? WHERE `user`=? AND `name`=?",
|
|
||||||
[JSON.stringify(updated), updated.length, row.user, row.name]));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Q.allSettled(all).then(function () {
|
|
||||||
LOGGER.info('Fixed custom embeds in user_playlists');
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
}).catch(function (err) {
|
|
||||||
LOGGER.error(err.stack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addUsernameDedupeColumn(cb) {
|
function addUsernameDedupeColumn(cb) {
|
||||||
LOGGER.info("Adding name_dedupe column on the users table");
|
LOGGER.info("Adding name_dedupe column on the users table");
|
||||||
db.query("ALTER TABLE users ADD COLUMN name_dedupe VARCHAR(20) UNIQUE DEFAULT NULL", (error) => {
|
db.query("ALTER TABLE users ADD COLUMN name_dedupe VARCHAR(20) UNIQUE DEFAULT NULL", (error) => {
|
||||||
|
|
Loading…
Reference in New Issue