mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-08-26 21:16:23 +02:00
Merge remote-tracking branch 'origin/master' into email-revamp
This commit is contained in:
@@ -138,9 +138,7 @@ var db = require('./database.js'),
|
||||
db.getSortedSetRevRange('categories:' + cid + ':tid', start, stop, callback);
|
||||
};
|
||||
|
||||
Categories.getActiveUsers = function(cid, callback) {
|
||||
db.getSetMembers('cid:' + cid + ':active_users', callback);
|
||||
};
|
||||
|
||||
|
||||
Categories.getAllCategories = function(current_user, callback) {
|
||||
db.getListRange('categories:cid', 0, -1, function(err, cids) {
|
||||
@@ -217,6 +215,10 @@ var db = require('./database.js'),
|
||||
};
|
||||
|
||||
Categories.getRecentReplies = function(cid, count, callback) {
|
||||
if(count === 0) {
|
||||
return callback(null, []);
|
||||
}
|
||||
|
||||
db.getSortedSetRevRange('categories:recent_posts:cid:' + cid, 0, count - 1, function(err, pids) {
|
||||
|
||||
if (err) {
|
||||
@@ -264,25 +266,7 @@ var db = require('./database.js'),
|
||||
});
|
||||
};
|
||||
|
||||
Categories.moveActiveUsers = function(tid, oldCid, cid, callback) {
|
||||
function updateUser(uid) {
|
||||
Categories.addActiveUser(cid, uid);
|
||||
Categories.isUserActiveIn(oldCid, uid, function(err, active) {
|
||||
|
||||
if (!err && !active) {
|
||||
Categories.removeActiveUser(oldCid, uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
topics.getUids(tid, function(err, uids) {
|
||||
if (!err && uids) {
|
||||
for (var i = 0; i < uids.length; ++i) {
|
||||
updateUser(uids[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Categories.getCategoryData = function(cid, callback) {
|
||||
db.exists('category:' + cid, function(err, exists) {
|
||||
@@ -391,14 +375,38 @@ var db = require('./database.js'),
|
||||
});
|
||||
};
|
||||
|
||||
Categories.addActiveUser = function(cid, uid) {
|
||||
Categories.addActiveUser = function(cid, uid, timestamp) {
|
||||
if(parseInt(uid, 10)) {
|
||||
db.setAdd('cid:' + cid + ':active_users', uid);
|
||||
db.sortedSetAdd('cid:' + cid + ':active_users', timestamp, uid);
|
||||
}
|
||||
};
|
||||
|
||||
Categories.removeActiveUser = function(cid, uid) {
|
||||
db.setRemove('cid:' + cid + ':active_users', uid);
|
||||
db.sortedSetRemove('cid:' + cid + ':active_users', uid);
|
||||
};
|
||||
|
||||
Categories.getActiveUsers = function(cid, callback) {
|
||||
db.getSortedSetRevRange('cid:' + cid + ':active_users', 0, 15, callback);
|
||||
};
|
||||
|
||||
Categories.moveActiveUsers = function(tid, oldCid, cid, callback) {
|
||||
function updateUser(uid) {
|
||||
Categories.addActiveUser(cid, uid);
|
||||
Categories.isUserActiveIn(oldCid, uid, function(err, active) {
|
||||
|
||||
if (!err && !active) {
|
||||
Categories.removeActiveUser(oldCid, uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
topics.getUids(tid, function(err, uids) {
|
||||
if (!err && uids) {
|
||||
for (var i = 0; i < uids.length; ++i) {
|
||||
updateUser(uids[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Categories.onNewPostMade = function(uid, tid, pid, timestamp) {
|
||||
@@ -412,13 +420,7 @@ var db = require('./database.js'),
|
||||
db.sortedSetAdd('categories:' + cid + ':tid', timestamp, tid);
|
||||
}
|
||||
|
||||
db.setCount('cid:' + cid + ':active_users', function(err, amount) {
|
||||
if (amount > 15) {
|
||||
db.setRemoveRandom('cid:' + cid + ':active_users');
|
||||
}
|
||||
|
||||
Categories.addActiveUser(cid, uid);
|
||||
});
|
||||
Categories.addActiveUser(cid, uid, timestamp);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -738,6 +738,21 @@
|
||||
});
|
||||
}
|
||||
|
||||
module.listRemoveAll = function(key, value, callback) {
|
||||
db.collection('objects').update({_key: key }, { $pull: { array: value } }, function(err, result) {
|
||||
if(err) {
|
||||
if(callback) {
|
||||
return callback(err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(callback) {
|
||||
callback(null, result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.getListRange = function(key, start, stop, callback) {
|
||||
|
||||
if(stop === -1) {
|
||||
|
||||
@@ -402,6 +402,10 @@
|
||||
redisClient.rpop(key, callback);
|
||||
}
|
||||
|
||||
module.listRemoveAll = function(key, value, callback) {
|
||||
redisClient.lrem(key, 0, value, callback);
|
||||
}
|
||||
|
||||
module.getListRange = function(key, start, stop, callback) {
|
||||
redisClient.lrange(key, start, stop, callback);
|
||||
}
|
||||
|
||||
@@ -134,6 +134,11 @@ var async = require('async'),
|
||||
return next(new Error('unknown database : ' + config.database));
|
||||
}
|
||||
|
||||
var allQuestions = install.redisQuestions.concat(install.mongoQuestions);
|
||||
for(var x=0;x<allQuestions.length;x++) {
|
||||
delete config[allQuestions[x].name];
|
||||
}
|
||||
|
||||
config.bcrypt_rounds = 12;
|
||||
config.upload_path = '/public/uploads';
|
||||
config.use_port = config.use_port.slice(0, 1) === 'y';
|
||||
@@ -258,6 +263,21 @@ var async = require('async'),
|
||||
}, function (err) {
|
||||
meta.configs.init(next);
|
||||
});
|
||||
|
||||
if (install.values) {
|
||||
if (install.values['social:twitter:key'] && install.values['social:twitter:secret']) {
|
||||
meta.configs.setOnEmpty('social:twitter:key', install.values['social:twitter:key']);
|
||||
meta.configs.setOnEmpty('social:twitter:secret', install.values['social:twitter:secret']);
|
||||
}
|
||||
if (install.values['social:google:id'] && install.values['social:google:secret']) {
|
||||
meta.configs.setOnEmpty('social:google:id', install.values['social:google:id']);
|
||||
meta.configs.setOnEmpty('social:google:secret', install.values['social:google:secret']);
|
||||
}
|
||||
if (install.values['social:facebook:key'] && install.values['social:facebook:secret']) {
|
||||
meta.configs.setOnEmpty('social:facebook:app_id', install.values['social:facebook:app_id']);
|
||||
meta.configs.setOnEmpty('social:facebook:secret', install.values['social:facebook:secret']);
|
||||
}
|
||||
}
|
||||
},
|
||||
function (next) {
|
||||
// Check if an administrator needs to be created
|
||||
|
||||
@@ -137,7 +137,7 @@ var winston = require('winston'),
|
||||
events.logPostDelete(uid, pid);
|
||||
|
||||
posts.getPostFields(pid, ['tid', 'uid'], function(err, postData) {
|
||||
db.incrObjectFieldBy('topic:' + postData.tid, 'postcount', -1);
|
||||
topics.decreasePostCount(postData.tid);
|
||||
|
||||
user.decrementUserFieldBy(postData.uid, 'postcount', 1, function(err, postcount) {
|
||||
db.sortedSetAdd('users:postcount', postcount, postData.uid);
|
||||
@@ -193,7 +193,7 @@ var winston = require('winston'),
|
||||
events.logPostRestore(uid, pid);
|
||||
|
||||
posts.getPostFields(pid, ['tid', 'uid', 'content'], function(err, postData) {
|
||||
db.incrObjectFieldBy('topic:' + postData.tid, 'postcount', 1);
|
||||
topics.increasePostCount(postData.tid);
|
||||
|
||||
user.incrementUserFieldBy(postData.uid, 'postcount', 1);
|
||||
|
||||
|
||||
95
src/posts.js
95
src/posts.js
@@ -28,63 +28,70 @@ var db = require('./database'),
|
||||
return callback(new Error('invalid-user'), null);
|
||||
}
|
||||
|
||||
topics.isLocked(tid, function(err, locked) {
|
||||
if(err) {
|
||||
return callback(err, null);
|
||||
} else if(locked) {
|
||||
return callback(new Error('topic-locked'), null);
|
||||
}
|
||||
|
||||
db.incrObjectField('global', 'nextPid', function(err, pid) {
|
||||
if(err) {
|
||||
return callback(err, null);
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
topics.isLocked(tid, next);
|
||||
},
|
||||
function(locked, next) {
|
||||
if(locked) {
|
||||
return next(new Error('topic-locked'));
|
||||
}
|
||||
|
||||
db.incrObjectField('global', 'nextPid', next);
|
||||
},
|
||||
function(pid, next) {
|
||||
plugins.fireHook('filter:post.save', content, function(err, newContent) {
|
||||
next(err, pid, newContent)
|
||||
});
|
||||
},
|
||||
function(pid, newContent, next) {
|
||||
var timestamp = Date.now(),
|
||||
postData = {
|
||||
'pid': pid,
|
||||
'uid': uid,
|
||||
'tid': tid,
|
||||
'content': newContent,
|
||||
'timestamp': timestamp,
|
||||
'reputation': 0,
|
||||
'editor': '',
|
||||
'edited': 0,
|
||||
'deleted': 0
|
||||
};
|
||||
|
||||
db.setObject('post:' + pid, postData, function(err) {
|
||||
if(err) {
|
||||
return callback(err, null);
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var timestamp = Date.now(),
|
||||
postData = {
|
||||
'pid': pid,
|
||||
'uid': uid,
|
||||
'tid': tid,
|
||||
'content': newContent,
|
||||
'timestamp': timestamp,
|
||||
'reputation': 0,
|
||||
'editor': '',
|
||||
'edited': 0,
|
||||
'deleted': 0
|
||||
};
|
||||
|
||||
db.setObject('post:' + pid, postData);
|
||||
db.incrObjectField('global', 'postCount');
|
||||
|
||||
topics.onNewPostMade(tid, pid, timestamp);
|
||||
categories.onNewPostMade(uid, tid, pid, timestamp);
|
||||
user.onNewPostMade(uid, tid, pid, timestamp);
|
||||
|
||||
plugins.fireHook('filter:post.get', postData, function(err, newPostData) {
|
||||
if(err) {
|
||||
return callback(err, null);
|
||||
}
|
||||
|
||||
postTools.parse(newPostData.content, function(err, content) {
|
||||
if(err) {
|
||||
return callback(err, null);
|
||||
}
|
||||
newPostData.content = content;
|
||||
|
||||
plugins.fireHook('action:post.save', newPostData);
|
||||
|
||||
db.searchIndex('post', content, pid);
|
||||
|
||||
callback(null, newPostData);
|
||||
});
|
||||
});
|
||||
next(null, postData);
|
||||
});
|
||||
});
|
||||
},
|
||||
function(postData, next) {
|
||||
plugins.fireHook('filter:post.get', postData, next);
|
||||
},
|
||||
function(postData, next) {
|
||||
postTools.parse(postData.content, function(err, content) {
|
||||
if(err) {
|
||||
return next(err, null);
|
||||
}
|
||||
|
||||
postData.content = content;
|
||||
|
||||
plugins.fireHook('action:post.save', postData);
|
||||
|
||||
db.searchIndex('post', content, postData.pid);
|
||||
|
||||
next(null, postData);
|
||||
});
|
||||
}
|
||||
], function(err, postData) {
|
||||
callback(err, postData);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -55,9 +55,9 @@ var path = require('path'),
|
||||
});
|
||||
|
||||
function iterator(category, callback) {
|
||||
categories.getRecentReplies(category.cid, 2, function (err, posts) {
|
||||
categories.getRecentReplies(category.cid, parseInt(category.numRecentReplies, 10), function (err, posts) {
|
||||
category.posts = posts;
|
||||
category.post_count = posts.length > 2 ? 2 : posts.length;
|
||||
category.post_count = posts.length > 2 ? 2 : posts.length; // this was a hack to make metro work back in the day, post_count should just = length
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
|
||||
118
src/topics.js
118
src/topics.js
@@ -23,6 +23,50 @@ var async = require('async'),
|
||||
|
||||
(function(Topics) {
|
||||
|
||||
Topics.create = function(uid, title, cid, callback) {
|
||||
db.incrObjectField('global', 'nextTid', function(err, tid) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
db.setAdd('topics:tid', tid);
|
||||
|
||||
var slug = tid + '/' + utils.slugify(title),
|
||||
timestamp = Date.now();
|
||||
|
||||
db.setObject('topic:' + tid, {
|
||||
'tid': tid,
|
||||
'uid': uid,
|
||||
'cid': cid,
|
||||
'title': title,
|
||||
'slug': slug,
|
||||
'timestamp': timestamp,
|
||||
'lastposttime': 0,
|
||||
'postcount': 0,
|
||||
'viewcount': 0,
|
||||
'locked': 0,
|
||||
'deleted': 0,
|
||||
'pinned': 0
|
||||
}, function(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
db.searchIndex('topic', title, tid);
|
||||
|
||||
user.addTopicIdToUser(uid, tid);
|
||||
|
||||
// in future it may be possible to add topics to several categories, so leaving the door open here.
|
||||
db.sortedSetAdd('categories:' + cid + ':tid', timestamp, tid);
|
||||
db.incrObjectField('category:' + cid, 'topic_count');
|
||||
db.incrObjectField('global', 'topicCount');
|
||||
|
||||
feed.updateCategory(cid);
|
||||
|
||||
callback(null, tid);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Topics.post = function(uid, title, content, cid, callback) {
|
||||
|
||||
categoryTools.privileges(cid, uid, function(err, privileges) {
|
||||
@@ -61,41 +105,11 @@ var async = require('async'),
|
||||
return callback(new Error('too-many-posts'), null);
|
||||
}
|
||||
|
||||
db.incrObjectField('global', 'nextTid', function(err, tid) {
|
||||
Topics.create(uid, title, cid, function(err, tid) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
db.setAdd('topics:tid', tid);
|
||||
|
||||
var slug = tid + '/' + utils.slugify(title);
|
||||
var timestamp = Date.now();
|
||||
db.setObject('topic:' + tid, {
|
||||
'tid': tid,
|
||||
'uid': uid,
|
||||
'cid': cid,
|
||||
'title': title,
|
||||
'slug': slug,
|
||||
'timestamp': timestamp,
|
||||
'lastposttime': 0,
|
||||
'postcount': 0,
|
||||
'viewcount': 0,
|
||||
'locked': 0,
|
||||
'deleted': 0,
|
||||
'pinned': 0
|
||||
});
|
||||
|
||||
db.searchIndex('topic', title, tid);
|
||||
|
||||
user.addTopicIdToUser(uid, tid);
|
||||
|
||||
// in future it may be possible to add topics to several categories, so leaving the door open here.
|
||||
db.sortedSetAdd('categories:' + cid + ':tid', timestamp, tid);
|
||||
db.incrObjectField('category:' + cid, 'topic_count');
|
||||
db.incrObjectField('global', 'topicCount');
|
||||
|
||||
feed.updateCategory(cid);
|
||||
|
||||
Topics.reply(tid, uid, content, function(err, postData) {
|
||||
if(err) {
|
||||
return callback(err, null);
|
||||
@@ -184,6 +198,40 @@ var async = require('async'),
|
||||
});
|
||||
}
|
||||
|
||||
Topics.createTopicFromPost = function(pid, callback) {
|
||||
posts.getPostData(pid, function(err, postData) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
posts.getCidByPid(pid, function(err, cid) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// TODO : title should be given by client
|
||||
var title = postData.content.substr(0, 20);
|
||||
|
||||
Topics.create(postData.uid, title, cid, function(err, tid) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
Topics.removePostFromTopic(postData.tid, postData.pid);
|
||||
Topics.decreasePostCount(postData.tid);
|
||||
|
||||
posts.setPostField(pid, 'tid', tid);
|
||||
|
||||
Topics.onNewPostMade(tid, postData.pid, postData.timestamp);
|
||||
|
||||
Topics.getTopicData(tid, function(err, topicData) {
|
||||
callback(err, topicData);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Topics.getTopicData = function(tid, callback) {
|
||||
db.getObject('topic:' + tid, function(err, data) {
|
||||
if(err) {
|
||||
@@ -916,6 +964,10 @@ var async = require('async'),
|
||||
db.incrObjectField('topic:' + tid, 'postcount', callback);
|
||||
}
|
||||
|
||||
Topics.decreasePostCount = function(tid, callback) {
|
||||
db.decrObjectField('topic:' + tid, 'postcount', callback);
|
||||
}
|
||||
|
||||
Topics.increaseViewCount = function(tid, callback) {
|
||||
db.incrObjectField('topic:' + tid, 'viewcount', callback);
|
||||
}
|
||||
@@ -944,6 +996,10 @@ var async = require('async'),
|
||||
db.listAppend('tid:' + tid + ':posts', pid);
|
||||
}
|
||||
|
||||
Topics.removePostFromTopic = function(tid, pid) {
|
||||
db.listRemoveAll('tid:' + tid + ':posts', pid);
|
||||
}
|
||||
|
||||
Topics.getPids = function(tid, callback) {
|
||||
db.getListRange('tid:' + tid + ':posts', 0, -1, callback);
|
||||
}
|
||||
|
||||
105
src/upgrade.js
105
src/upgrade.js
@@ -14,7 +14,7 @@ var db = require('./database'),
|
||||
|
||||
Upgrade.check = function(callback) {
|
||||
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema
|
||||
var latestSchema = new Date(2014, 0, 1).getTime();
|
||||
var latestSchema = new Date(2014, 0, 5).getTime();
|
||||
|
||||
db.get('schemaDate', function(err, value) {
|
||||
if (parseInt(value, 10) >= latestSchema) {
|
||||
@@ -65,8 +65,16 @@ Upgrade.upgrade = function(callback) {
|
||||
|
||||
async.each(uids, function(uid, next) {
|
||||
User.getUserField(uid, 'username', function(err, username) {
|
||||
newUserSlug = Utils.slugify(username);
|
||||
User.setUserField(uid, 'userslug', newUserSlug, next);
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
if(username) {
|
||||
newUserSlug = Utils.slugify(username);
|
||||
User.setUserField(uid, 'userslug', newUserSlug, next);
|
||||
} else {
|
||||
winston.warn('uid '+ uid + ' doesn\'t have a valid username (' + username + '), skipping');
|
||||
next(null);
|
||||
}
|
||||
});
|
||||
}, function(err) {
|
||||
next(err);
|
||||
@@ -108,6 +116,97 @@ Upgrade.upgrade = function(callback) {
|
||||
winston.info('[2013/12/31] maximumTitleLength skipped');
|
||||
next();
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
// Custom classes for each category, adding link field for each category
|
||||
thisSchemaDate = new Date(2014, 0, 3).getTime();
|
||||
if (schemaDate < thisSchemaDate) {
|
||||
updatesMade = true;
|
||||
|
||||
db.getListRange('categories:cid', 0, -1, function(err, cids) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
for (var cid in cids) {
|
||||
db.setObjectField('category:' + cids[cid], 'link', '');
|
||||
db.setObjectField('category:' + cids[cid], 'class', 'col-md-3 col-xs-6');
|
||||
}
|
||||
|
||||
winston.info('[2014/1/3] Added categories.class, categories.link fields');
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
winston.info('[2014/1/3] categories.class, categories.link fields skipped');
|
||||
next();
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
// Custom classes for each category, adding link field for each category
|
||||
thisSchemaDate = new Date(2014, 0, 4).getTime();
|
||||
if (schemaDate < thisSchemaDate) {
|
||||
updatesMade = true;
|
||||
|
||||
db.getListRange('categories:cid', 0, -1, function(err, cids) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
for (var cid in cids) {
|
||||
db.setObjectField('category:' + cids[cid], 'numRecentReplies', '2');
|
||||
}
|
||||
|
||||
winston.info('[2014/1/4] Added categories.numRecentReplies fields');
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
winston.info('[2014/1/4] categories.numRecentReplies fields skipped');
|
||||
next();
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
thisSchemaDate = new Date(2014, 0, 5).getTime();
|
||||
if (schemaDate < thisSchemaDate) {
|
||||
updatesMade = true;
|
||||
|
||||
db.getListRange('categories:cid', 0, -1, function(err, cids) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var timestamp = Date.now();
|
||||
|
||||
function upgradeCategory(cid, next) {
|
||||
db.getSetMembers('cid:' + cid + ':active_users', function(err, uids) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
db.delete('cid:' + cid + ':active_users', function(err) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
for(var i=0; i<uids.length; ++i) {
|
||||
db.sortedSetAdd('cid:' + cid + ':active_users', timestamp, uids[i]);
|
||||
}
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async.each(cids, upgradeCategory, function(err) {
|
||||
if(err) {
|
||||
return next(err)
|
||||
}
|
||||
winston.info('[2014/1/5] Upgraded categories active users');
|
||||
next();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
winston.info('[2014/1/5] categories active users skipped');
|
||||
next();
|
||||
}
|
||||
}
|
||||
// Add new schema updates here
|
||||
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 17!!!
|
||||
|
||||
@@ -622,6 +622,12 @@ websockets.init = function(io) {
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('api:topic.createTopicFromPost', function(data, callback) {
|
||||
topics.createTopicFromPost(data.pid, function(err, data) {
|
||||
callback(err?{message:err.message}:null, data);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('api:topic.move', function(data) {
|
||||
threadTools.move(data.tid, data.cid, socket);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user