Implement migrator

This commit is contained in:
calzoneman 2015-09-27 11:07:57 -07:00
parent 10dbbcd3ff
commit e91635b6f9
3 changed files with 100 additions and 6 deletions

View file

@ -10,6 +10,7 @@
"dependencies": {
"babel": "^5.8.23",
"bcrypt": "^0.8.5",
"bluebird": "^2.10.1",
"body-parser": "^1.14.0",
"cheerio": "^0.19.0",
"compression": "^1.5.2",

View file

@ -69,6 +69,9 @@ export class DatabaseStore {
const id = rows[0].id;
const substitutions = [];
for (const key of Object.keys(data)) {
if (typeof data[key] === 'undefined') {
continue;
}
rowCount++;
const value = JSON.stringify(data[key]);
totalSize += value.length;

View file

@ -3,8 +3,24 @@ import Promise from 'bluebird';
import db from '../database';
import { FileStore } from './filestore';
import { DatabaseStore } from './dbstore';
import { sanitizeHTML } from '../xss';
import { ChannelNotFoundError } from '../errors';
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) {
return new Promise((resolve, reject) => {
@ -22,7 +38,79 @@ function queryAsync(query, substitutions) {
}
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) {
@ -34,13 +122,11 @@ function migrate(src, dest) {
// uppercase letters in the name.
//
// If another chandump exists which is all lowercase, then that one is
// canonical. Otherwise, it's safe to just lowercase the name and convert
// it.
// canonical. Otherwise, it's safe to load the existing capitalization,
// convert it, and save.
if (name !== name.toLowerCase()) {
if (names.indexOf(name.toLowerCase()) >= 0) {
return Promise.resolve();
} else {
name = name.toLowerCase();
}
}
@ -49,6 +135,8 @@ function migrate(src, dest) {
return dest.save(name, data);
}).then(() => {
console.log(`Migrated /r/${name}`);
}).catch(ChannelNotFoundError, err => {
console.log(`Skipping /r/${name} (not present in the database)`);
}).catch(err => {
console.error(`Failed to migrate /r/${name}: ${err.stack}`);
});
@ -62,7 +150,9 @@ function main() {
const src = new FileStore();
const dest = new DatabaseStore();
migrate(src, dest).then(() => {
Promise.delay(1000).then(() => {
return migrate(src, dest);
}).then(() => {
console.log('Migration complete');
process.exit(0);
}).catch(err => {