UNPKG

audiovanish-plugin-dbsearch

Version:
513 lines (449 loc) 12.4 kB
'use strict'; var winston = require.main.require('winston'); var async = require.main.require('async'); var db = require.main.require('./src/database'); var tracks = require.main.require('./src/tracks'); var posts = require.main.require('./src/posts'); var utils = require.main.require('./public/src/utils'); var socketAdmin = require.main.require('./src/socket.io/admin'); var batch = require.main.require('./src/batch'); var nconf = require.main.require('nconf'); require('./' + nconf.get('database'))(db); (function(search) { var defaultPostLimit = 50; var defaultTrackLimit = 50; var postLimit = defaultPostLimit; var trackLimit = defaultTrackLimit; var batchSize = 500; var trackCount = 0; var postCount = 0; var tracksProcessed = 0; var postsProcessed = 0; search.init = function(params, callback) { params.router.get('/admin/plugins/dbsearch', params.middleware.applyCSRF, params.middleware.admin.buildHeader, renderAdmin); params.router.get('/api/admin/plugins/dbsearch', params.middleware.applyCSRF, renderAdmin); params.router.post('/api/admin/plugins/dbsearch/save', params.middleware.applyCSRF, save); callback(); db.getObject('audiovanish-plugin-dbsearch', function(err, data) { if (err) { return winston.error(err.error); } if (data) { postLimit = data.postLimit ? data.postLimit : defaultPostLimit; trackLimit = data.trackLimit ? data.trackLimit : defaultTrackLimit; } }); }; search.postSave = function(postData, callback) { callback = callback || function() {}; tracks.getTrackField(postData.tid, 'deleted', function(err, isTrackDeleted) { if (err) { return callback(err); } if (parseInt(isTrackDeleted, 10) === 1) { return callback(); } postsSave([postData], callback); }); }; search.postRestore = function(postData) { search.postSave(postData); }; search.postEdit = function(postData) { search.postSave(postData); }; search.postDelete = function(pid, callback) { db.searchRemove('post', [pid], callback); }; search.postMove = function(data) { tracks.getTrackFields(data.post.tid, ['cid', 'deleted'], function(err, track) { if (err) { return; } reIndexPids([data.post.pid], track); }); }; search.trackSave = function(trackData, callback) { callback = callback || function() {}; tracksSave([trackData], callback); }; search.trackRestore = function(trackData) { reIndexTids([trackData.tid]); }; search.trackEdit = function(trackData) { search.trackSave(trackData); }; search.trackDelete = function(trackData) { var tid = trackData.tid; async.parallel({ track: function(next) { db.searchRemove('track', [tid], next); }, mainPid: function(next) { tracks.getTrackField(tid, 'mainPid', function(err, mainPid) { if (err) { return next(err); } db.searchRemove('post', [mainPid], next); }); }, posts: function(next) { batch.processSortedSet('tid:' + tid + ':posts', function(pids, next) { db.searchRemove('post', pids, next); }, { batch: batchSize }, next); } }, function(err, results) { if (err) { winston.error(err); } }); }; search.trackMove = function(data) { reIndexTids([data.tid]); }; search.searchQuery = function(data, callback) { if (!data || !data.index) { return callback(null, []); } var limit = data.index === 'post' ? postLimit : trackLimit; var query = {}; if (data.cid) { query.cid = data.cid.filter(Boolean); } if (data.uid) { query.uid = data.uid.filter(Boolean); } if (data.content) { query.content = data.content; } if (!Object.keys(query).length) { return callback(null, []); } db.search(data.index, query, limit, callback); }; search.reindex = function(callback) { tracksProcessed = 0; postsProcessed = 0; db.getObjectFields('global', ['trackCount', 'postCount'], function(err, data) { if (err) { return callback(err); } trackCount = data.trackCount; postCount = data.postCount; async.parallel([ function (next) { reIndexTracks(next); }, function (next) { reIndexPosts(next); } ], function(err) { callback(err); }); }); }; function reIndexTracks(callback) { batch.processSortedSet('tracks:tid', function(tids, next) { async.waterfall([ function(next) { tracks.getTracksFields(tids, ['tid', 'title', 'uid', 'cid', 'deleted'], next); }, function(trackData, next) { tracksSave(trackData, next); }, ], function(err) { if (err) { return next(err); } tracksProcessed += tids.length; next(); }); }, { batch: batchSize }, function(err) { callback(err); }); } function tracksSave(tracks, callback) { tracks = tracks.filter(function(track) { return track && track.tid && parseInt(track.deleted, 10) !== 1; }); var data = tracks.map(function(trackData) { var indexData = {}; if (trackData.title) { indexData.content = trackData.title; } if (trackData.cid) { indexData.cid = trackData.cid; } if (trackData.uid) { indexData.uid = trackData.uid; } if (!Object.keys(indexData).length) { return null; } return indexData; }); data = data.filter(Boolean); if (!data.length) { return callback(); } var tids = tracks.map(function(track) { return track.tid; }); db.searchIndex('track', data, tids, callback); } function reIndexPosts(callback) { batch.processSortedSet('posts:pid', function(pids, next) { var postData; async.waterfall([ function(next) { posts.getPostsFields(pids, ['pid', 'content', 'uid', 'tid', 'deleted'], next); }, function(_postData, next) { postData = _postData.filter(function(post) { return post && parseInt(post.deleted, 10) !== 1; }); var tids = postData.map(function(post) { return post && post.tid; }); tracks.getTracksFields(tids, ['deleted', 'cid'], next); }, function(trackData, next) { postData.forEach(function(post, index) { if (post && trackData[index]) { post.cid = trackData[index].cid; } }); postData = postData.filter(function(post, index) { return post && parseInt(trackData[index].deleted, 10) !== 1; }); postsSave(postData, next); } ], function(err) { if (err) { return next(err); } postsProcessed += pids.length; next(); }); }, { batch: batchSize }, function(err) { callback(err); }); } function postsSave(posts, callback) { posts = posts.filter(function(post) { return post && post.pid && parseInt(post.deleted, 10) !== 1; }); var data = posts.map(function(postData) { var indexData = {}; if (postData.content) { indexData.content = postData.content; } if (postData.cid) { indexData.cid = postData.cid; } if (postData.uid) { indexData.uid = postData.uid; } if (!Object.keys(indexData).length) { return null; } return indexData; }); data = data.filter(Boolean); if (!data.length) { return callback(); } var pids = posts.map(function(post) { return post.pid; }); db.searchIndex('post', data, pids, callback); } function reIndexTids(tids, callback) { callback = callback || function() {}; if (!Array.isArray(tids) || !tids.length) { return callback(); } tracks.getTracksFields(tids, ['tid', 'title', 'uid', 'cid', 'deleted'], function(err, trackData) { if (err) { return callback(err); } trackData = trackData.filter(function(track) { return parseInt(track.tid, 10) && parseInt(track.deleted, 10) !== 1; }); if (!trackData.length) { return callback(err); } async.parallel([ function(next) { tracksSave(trackData, next); }, function(next) { async.each(trackData, function(track, next) { async.parallel([ function (next) { tracks.getTrackField(track.tid, 'mainPid', function(err, mainPid) { if (err) { return next(err); } reIndexPids([mainPid], track, next); }); }, function (next) { batch.processSortedSet('tid:' + track.tid + ':posts', function(pids, next) { reIndexPids(pids, track, next); }, { batch: batchSize }, next); } ], next); }, next); } ], callback); }); } function reIndexPids(pids, track, callback) { callback = callback || function() {}; if (!Array.isArray(pids) || !pids.length) { winston.warn('[audiovanish-plugin-dbsearch] invalid-pid, skipping'); return callback(); } if (parseInt(track.deleted) === 1) { return callback(); } async.waterfall([ function(next) { posts.getPostsFields(pids, ['pid', 'content', 'uid', 'tid', 'deleted'], next); }, function(posts, next) { posts.forEach(function(post) { if (post && track) { post.cid = track.cid; } }); postsSave(posts, next); } ], callback); } function renderAdmin(req, res, next) { async.parallel({ data: function(next) { db.getObject('audiovanish-plugin-dbsearch', next); }, global: function(next) { db.getObjectFields('global', ['trackCount', 'postCount'], next); } }, function(err, results) { if (err) { return next(err); } if (!results.data) { results.data = { trackLimit: defaultTrackLimit, postLimit: defaultPostLimit }; } results.data.trackCount = results.global.trackCount; results.data.postCount = results.global.postCount; results.data.csrf = req.csrfToken(); res.render('admin/plugins/dbsearch', results.data); }); } function save(req, res, next) { if (utils.isNumber(req.body.postLimit) && utils.isNumber(req.body.trackLimit)) { var data = { postLimit: req.body.postLimit, trackLimit: req.body.trackLimit }; db.setObject('audiovanish-plugin-dbsearch', data, function(err) { if (err) { return res.json(500, 'error-saving'); } postLimit = data.postLimit; trackLimit = data.trackLimit; res.json('Settings saved!'); }); } } socketAdmin.plugins.dbsearch = {}; socketAdmin.plugins.dbsearch.checkProgress = function(socket, data, callback) { var tracksPercent = trackCount ? (tracksProcessed / trackCount) * 100 : 0; var postsPercent = postCount ? (postsProcessed / postCount) * 100 : 0; var checkProgress = { tracksPercent: Math.min(100, tracksPercent.toFixed(2)), postsPercent: Math.min(100, postsPercent.toFixed(2)), tracksProcessed: tracksPercent >= 100 ? trackCount : tracksProcessed, postsProcessed: postsPercent >= 100 ? postCount : postsProcessed }; callback(null, checkProgress); }; socketAdmin.plugins.dbsearch.reindex = function(socket, data, callback) { search.reindex(function(err) { if (err) { return callback(err); } tracksProcessed = trackCount; postsProcessed = postCount; var data = {postsIndexed: postCount, tracksIndexed: trackCount}; db.setObject('audiovanish-plugin-dbsearch', data); callback(null, data); }); }; socketAdmin.plugins.dbsearch.clearIndex = function(socket, data, callback) { tracksProcessed = 0; postsProcessed = 0; db.getObjectFields('global', ['trackCount', 'postCount'], function(err, data) { if (err) { return callback(err); } trackCount = data.trackCount; postCount = data.postCount; async.parallel([ function (next) { clearSet('tracks:tid', 'track', next); }, function (next) { clearSet('posts:pid', 'post', next); } ], function(err) { if (err) { return callback(err); } db.setObject('audiovanish-plugin-dbsearch', {postsIndexed: 0, tracksIndexed: 0}); callback(); }); }); }; function clearSet(set, key, callback) { batch.processSortedSet(set, function(ids, next) { db.searchRemove(key, ids, function(err) { if (err) { return next(err); } if (key === 'track') { tracksProcessed += ids.length; } else if (key === 'post') { postsProcessed += ids.length; } next(); }); }, { batch: batchSize }, callback); } var admin = {}; admin.menu = function(custom_header, callback) { custom_header.plugins.push({ route: '/plugins/dbsearch', icon: 'fa-search', name: 'DB Search' }); callback(null, custom_header); }; search.admin = admin; }(module.exports));