Implement migrator
This commit is contained in:
parent
10dbbcd3ff
commit
e91635b6f9
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel": "^5.8.23",
|
"babel": "^5.8.23",
|
||||||
"bcrypt": "^0.8.5",
|
"bcrypt": "^0.8.5",
|
||||||
|
"bluebird": "^2.10.1",
|
||||||
"body-parser": "^1.14.0",
|
"body-parser": "^1.14.0",
|
||||||
"cheerio": "^0.19.0",
|
"cheerio": "^0.19.0",
|
||||||
"compression": "^1.5.2",
|
"compression": "^1.5.2",
|
||||||
|
|
|
@ -69,6 +69,9 @@ export class DatabaseStore {
|
||||||
const id = rows[0].id;
|
const id = rows[0].id;
|
||||||
const substitutions = [];
|
const substitutions = [];
|
||||||
for (const key of Object.keys(data)) {
|
for (const key of Object.keys(data)) {
|
||||||
|
if (typeof data[key] === 'undefined') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
rowCount++;
|
rowCount++;
|
||||||
const value = JSON.stringify(data[key]);
|
const value = JSON.stringify(data[key]);
|
||||||
totalSize += value.length;
|
totalSize += value.length;
|
||||||
|
|
|
@ -3,8 +3,24 @@ import Promise from 'bluebird';
|
||||||
import db from '../database';
|
import db from '../database';
|
||||||
import { FileStore } from './filestore';
|
import { FileStore } from './filestore';
|
||||||
import { DatabaseStore } from './dbstore';
|
import { DatabaseStore } from './dbstore';
|
||||||
|
import { sanitizeHTML } from '../xss';
|
||||||
|
import { ChannelNotFoundError } from '../errors';
|
||||||
|
|
||||||
const QUERY_CHANNEL_NAMES = 'SELECT name FROM channels WHERE 1';
|
const QUERY_CHANNEL_NAMES = 'SELECT name FROM channels WHERE 1';
|
||||||
|
const EXPECTED_KEYS = [
|
||||||
|
'chatbuffer',
|
||||||
|
'chatmuted',
|
||||||
|
'css',
|
||||||
|
'emotes',
|
||||||
|
'filters',
|
||||||
|
'js',
|
||||||
|
'motd',
|
||||||
|
'openPlaylist',
|
||||||
|
'opts',
|
||||||
|
'permissions',
|
||||||
|
'playlist',
|
||||||
|
'poll'
|
||||||
|
];
|
||||||
|
|
||||||
function queryAsync(query, substitutions) {
|
function queryAsync(query, substitutions) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -22,7 +38,79 @@ function queryAsync(query, substitutions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function fixOldChandump(data) {
|
function fixOldChandump(data) {
|
||||||
return data;
|
const converted = {};
|
||||||
|
for (const key of EXPECTED_KEYS) {
|
||||||
|
converted[key] = data[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.queue) {
|
||||||
|
converted.playlist = {
|
||||||
|
pl: data.queue.map(item => {
|
||||||
|
return {
|
||||||
|
media: {
|
||||||
|
id: item.id,
|
||||||
|
title: item.title,
|
||||||
|
seconds: item.seconds,
|
||||||
|
duration: item.duration,
|
||||||
|
type: item.type,
|
||||||
|
meta: {}
|
||||||
|
},
|
||||||
|
queueby: item.queueby,
|
||||||
|
temp: item.temp
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
pos: data.position,
|
||||||
|
time: data.currentTime
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.hasOwnProperty('openqueue')) {
|
||||||
|
converted.openPlaylist = data.openqueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.hasOwnProperty('playlistLock')) {
|
||||||
|
converted.openPlaylist = !data.playlistLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.chatbuffer) {
|
||||||
|
converted.chatbuffer = data.chatbuffer.map(entry => {
|
||||||
|
return {
|
||||||
|
username: entry.username,
|
||||||
|
msg: entry.msg,
|
||||||
|
meta: entry.meta || {
|
||||||
|
addClass: entry.msgclass ? entry.msgclass : undefined
|
||||||
|
},
|
||||||
|
time: entry.time
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.motd && data.motd.motd) {
|
||||||
|
converted.motd = sanitizeHTML(data.motd.motd).replace(/\n/g, '<br>\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.opts && data.opts.customcss) {
|
||||||
|
converted.opts.externalcss = data.opts.customcss;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.opts && data.opts.customjs) {
|
||||||
|
converted.opts.externaljs = data.opts.customjs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.filters && data.filters.length > 0 && Array.isArray(data.filters[0])) {
|
||||||
|
converted.filters = data.filters.map(filter => {
|
||||||
|
let [source, replace, active] = filter;
|
||||||
|
return {
|
||||||
|
source: source,
|
||||||
|
replace: replace,
|
||||||
|
flags: 'g',
|
||||||
|
active: active,
|
||||||
|
filterlinks: false
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
function migrate(src, dest) {
|
function migrate(src, dest) {
|
||||||
|
@ -34,13 +122,11 @@ function migrate(src, dest) {
|
||||||
// uppercase letters in the name.
|
// uppercase letters in the name.
|
||||||
//
|
//
|
||||||
// If another chandump exists which is all lowercase, then that one is
|
// If another chandump exists which is all lowercase, then that one is
|
||||||
// canonical. Otherwise, it's safe to just lowercase the name and convert
|
// canonical. Otherwise, it's safe to load the existing capitalization,
|
||||||
// it.
|
// convert it, and save.
|
||||||
if (name !== name.toLowerCase()) {
|
if (name !== name.toLowerCase()) {
|
||||||
if (names.indexOf(name.toLowerCase()) >= 0) {
|
if (names.indexOf(name.toLowerCase()) >= 0) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
} else {
|
|
||||||
name = name.toLowerCase();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +135,8 @@ function migrate(src, dest) {
|
||||||
return dest.save(name, data);
|
return dest.save(name, data);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
console.log(`Migrated /r/${name}`);
|
console.log(`Migrated /r/${name}`);
|
||||||
|
}).catch(ChannelNotFoundError, err => {
|
||||||
|
console.log(`Skipping /r/${name} (not present in the database)`);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error(`Failed to migrate /r/${name}: ${err.stack}`);
|
console.error(`Failed to migrate /r/${name}: ${err.stack}`);
|
||||||
});
|
});
|
||||||
|
@ -62,7 +150,9 @@ function main() {
|
||||||
const src = new FileStore();
|
const src = new FileStore();
|
||||||
const dest = new DatabaseStore();
|
const dest = new DatabaseStore();
|
||||||
|
|
||||||
migrate(src, dest).then(() => {
|
Promise.delay(1000).then(() => {
|
||||||
|
return migrate(src, dest);
|
||||||
|
}).then(() => {
|
||||||
console.log('Migration complete');
|
console.log('Migration complete');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
|
Loading…
Reference in a new issue