From e91635b6f9a52ae479bce6c495131e25763ed21c Mon Sep 17 00:00:00 2001 From: calzoneman Date: Sun, 27 Sep 2015 11:07:57 -0700 Subject: [PATCH] Implement migrator --- package.json | 1 + src/channel-storage/dbstore.js | 3 + src/channel-storage/migrator.js | 102 ++++++++++++++++++++++++++++++-- 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 9dcde330..8294458b 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/channel-storage/dbstore.js b/src/channel-storage/dbstore.js index 117d5731..00f34864 100644 --- a/src/channel-storage/dbstore.js +++ b/src/channel-storage/dbstore.js @@ -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; diff --git a/src/channel-storage/migrator.js b/src/channel-storage/migrator.js index 189e09a7..46e462c5 100644 --- a/src/channel-storage/migrator.js +++ b/src/channel-storage/migrator.js @@ -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, '
\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 => {