mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-01-21 23:12:58 +01:00
@@ -61,27 +61,25 @@
|
||||
});
|
||||
|
||||
|
||||
|
||||
socket.emit('api:categories.getRecentReplies', cid);
|
||||
socket.on('api:categories.getRecentReplies', function(replies) {
|
||||
if (replies === false) {
|
||||
socket.on('api:categories.getRecentReplies', function(posts) {
|
||||
if (!posts || posts.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var users = replies.users,
|
||||
posts = replies.posts,
|
||||
recent_replies = document.getElementById('category_recent_replies');
|
||||
var recent_replies = document.getElementById('category_recent_replies');
|
||||
|
||||
recent_replies.innerHTML = '';
|
||||
for (var i=0, ii=posts.pids.length; i<ii; i++) {
|
||||
|
||||
for (var i=0, ii=posts.length; i<ii; i++) {
|
||||
|
||||
var a = document.createElement('a'),
|
||||
ul = document.createElement('ul'),
|
||||
username = users[posts.uid[i]].username,
|
||||
picture = users[posts.uid[i]].picture;
|
||||
username = posts[i].username,
|
||||
picture = posts[i].picture;
|
||||
|
||||
//temp until design finalized
|
||||
ul.innerHTML = '<li><img title="' + username + '" style="width: 48px; height: 48px; /*temporary*/" src="' + picture + '" class="" />'
|
||||
+ '<p><strong>' + username + '</strong>: ' + posts.content[i] + '</p><span>posted ' + utils.relativeTime(posts.timestamp[i]) + ' ago</span></li>';
|
||||
+ '<p><strong>' + username + '</strong>: ' + posts[i].content + '</p><span>posted ' + utils.relativeTime(posts[i].timestamp) + ' ago</span></li>';
|
||||
|
||||
a.appendChild(ul);
|
||||
recent_replies.appendChild(a);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
socket.emit('post.stats');
|
||||
socket.on('post.stats', function(data) {
|
||||
post_stats.innerHTML = "Our uses have created " + data.topics + " topics and made " + data.posts + " posts.";
|
||||
post_stats.innerHTML = "Our users have created " + data.topics + " topics and made " + data.posts + " posts.";
|
||||
});
|
||||
|
||||
socket.emit('user.latest', {});
|
||||
|
||||
@@ -434,14 +434,13 @@
|
||||
var pid = $(this).parents('li').attr('data-pid');
|
||||
|
||||
socket.once('api:posts.getRawPost', function(data) {
|
||||
|
||||
quoted = '> ' + data.post.replace(/\n/g, '\n> ') + '\n\n';
|
||||
require(['composer'], function(cmp) {
|
||||
cmp.push(tid, null, null, quoted);
|
||||
});
|
||||
});
|
||||
socket.emit('api:posts.getRawPost', { pid: pid });
|
||||
// $('.post-window textarea').val('> ' + $('#content_' + pid).html() + '\n');
|
||||
// });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<a href="/topic/{posts.tid}/{posts.pid}">
|
||||
<div class="topic-row img-polaroid clearfix">
|
||||
<span>{posts.content}</span>
|
||||
<span class="pull-right">{posts.timestamp} ago</span>
|
||||
<span class="pull-right">{posts.relativeTime} ago</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<a target="_blank" href="../../topic/{topics.slug}">{topics.title}</a>
|
||||
<ul>
|
||||
<li><i class="icon-time"></i> Posted {topics.relativeTime} ago by {topics.username}</li>
|
||||
<li><i class="icon-comments"></i> {topics.post_count} post(s)</li>
|
||||
<li><i class="icon-comments"></i> {topics.postcount} post(s)</li>
|
||||
</ul>
|
||||
<div class="clear"></div>
|
||||
</li>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.post_count}</span>{topics.title}</span></h3>
|
||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
||||
<small>
|
||||
<strong><i class="{topics.pin-icon}"></i><i class="{topics.lock-icon}"></i></strong>
|
||||
Posted {topics.relativeTime} ago by
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<ul class="topics">
|
||||
<!-- BEGIN topics -->
|
||||
<li>
|
||||
<a href="../../topic/{topics.slug}">{topics.title} ({topics.post_count})</a>
|
||||
<a href="../../topic/{topics.slug}">{topics.title} ({topics.postcount})</a>
|
||||
<div class="teaser">
|
||||
<img class="img-polaroid" src="../../graph/users/{topics.teaser_username}/picture" />
|
||||
<p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<li>
|
||||
<div class="row-fluid">
|
||||
<div class="span2">
|
||||
<img src="{main_posts.gravatar}" /><br />
|
||||
<img src="{main_posts.picture}" /><br />
|
||||
{main_posts.username}
|
||||
</div>
|
||||
<div class="span10">
|
||||
@@ -16,7 +16,7 @@
|
||||
<li>
|
||||
<div class="row-fluid">
|
||||
<div class="span2">
|
||||
<img src="{posts.gravatar}" /><br />
|
||||
<img src="{posts.picture}" /><br />
|
||||
{posts.username}
|
||||
</div>
|
||||
<div class="span10">
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.post_count}</span>{topics.title}</span></h3>
|
||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
||||
<small>
|
||||
<strong><i class="{topics.pin-icon}"></i><i class="{topics.lock-icon}"></i></strong>
|
||||
Posted {topics.relativeTime} ago by
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="span12">
|
||||
<div class="post-block">
|
||||
<a class="main-avatar" href="/users/{main_posts.userslug}">
|
||||
<img src="{main_posts.gravatar}?s=80&default=identicon" align="left" /><br />
|
||||
<img src="{main_posts.picture}?s=80&default=identicon" align="left" /><br />
|
||||
<div class="hover-overlay">
|
||||
{main_posts.username}<br />
|
||||
<i class="icon-star"></i><span class="user_rep_{main_posts.uid}">{main_posts.user_rep}</span>
|
||||
@@ -47,7 +47,7 @@
|
||||
<div id="content_{main_posts.pid}" class="post-content">{main_posts.content}</div>
|
||||
<div class="post-signature">{main_posts.signature}</div>
|
||||
<div class="profile-block">
|
||||
<img class="hidden-desktop" src="{main_posts.gravatar}?s=10&default=identicon" align="left" /> posted by <strong><a class="" href="/users/{main_posts.userslug}">{main_posts.username}</a></strong> {main_posts.relativeTime} ago
|
||||
<img class="hidden-desktop" src="{main_posts.picture}?s=10&default=identicon" align="left" /> posted by <strong><a class="" href="/users/{main_posts.userslug}">{main_posts.username}</a></strong> {main_posts.relativeTime} ago
|
||||
<span class="{main_posts.edited-class} hidden-phone">| last edited by <strong><a href="/users/{main_posts.editor}">{main_posts.editor}</a></strong> {main_posts.relativeEditTime} ago</span>
|
||||
<span class="{main_posts.edited-class}"><i class="icon-edit visible-phone" title="edited by {main_posts.editor} {main_posts.relativeEditTime} ago"></i></span>
|
||||
<div class="post-buttons visible-phone">
|
||||
@@ -65,7 +65,7 @@
|
||||
<div class="span1 profile-image-block visible-desktop">
|
||||
<!--<i class="icon-spinner icon-spin icon-2x pull-left"></i>-->
|
||||
<a href="/users/{posts.userslug}">
|
||||
<img src="{posts.gravatar}?s=80&default=identicon" align="left" />
|
||||
<img src="{posts.picture}?s=80&default=identicon" align="left" />
|
||||
</a>
|
||||
<i class="icon-star"></i><span class="user_rep_{posts.uid} formatted-number">{posts.user_rep}</span>
|
||||
<div id="ids_{posts.pid}_{posts.uid}" class="chat hidden-phone" title="Chat"><i class="icon-comment"></i></div>
|
||||
@@ -82,7 +82,7 @@
|
||||
<div id="favs_{posts.pid}_{posts.uid}" class="favourite hidden-phone" title="Favourite"><span class="post_rep_{posts.pid}">{posts.post_rep} </span><i class="{posts.fav_star_class}"></i></div>
|
||||
<div class="post_reply" title="Reply"><i class="icon-reply"></i></div>
|
||||
</span>
|
||||
<img class="hidden-desktop" src="{posts.gravatar}?s=10&default=identicon" align="left" /> posted by <strong><a class="username-field" href="/users/{posts.userslug}">{posts.username}</a></strong> {posts.relativeTime} ago
|
||||
<img class="hidden-desktop" src="{posts.picture}?s=10&default=identicon" align="left" /> posted by <strong><a class="username-field" href="/users/{posts.userslug}">{posts.username}</a></strong> {posts.relativeTime} ago
|
||||
<span class="{posts.edited-class} hidden-phone">| last edited by <strong><a href="/users/{posts.editor}">{posts.editor}</a></strong> {posts.relativeEditTime} ago</span>
|
||||
<span class="{posts.edited-class}"><i class="icon-edit visible-phone" title="edited by {posts.editor} {posts.relativeEditTime} ago"></i></span>
|
||||
</div>
|
||||
|
||||
@@ -11,14 +11,17 @@ var RDB = require('./../redis.js'),
|
||||
var slug = cid + '/' + utils.slugify(data.name);
|
||||
RDB.rpush('categories:cid', cid);
|
||||
|
||||
// Topic Info
|
||||
RDB.set('cid:' + cid + ':name', data.name);
|
||||
RDB.set('cid:' + cid + ':description', data.description);
|
||||
RDB.set('cid:' + cid + ':icon', data.icon);
|
||||
RDB.set('cid:' + cid + ':blockclass', data.blockclass);
|
||||
RDB.set('cid:' + cid + ':slug', slug);
|
||||
|
||||
RDB.set('category:slug:' + slug + ':cid', cid);
|
||||
RDB.hmset('category:' + cid, {
|
||||
cid: cid,
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
icon: data.icon,
|
||||
blockclass: data.blockclass,
|
||||
slug: slug,
|
||||
topic_count: 0
|
||||
});
|
||||
|
||||
RDB.set('categoryslug:' + slug + ':cid', cid);
|
||||
|
||||
if (callback) callback({'status': 1});
|
||||
});
|
||||
@@ -29,15 +32,15 @@ var RDB = require('./../redis.js'),
|
||||
|
||||
for (var cid in modified) {
|
||||
var category = modified[cid];
|
||||
|
||||
|
||||
for (var key in category) {
|
||||
RDB.set('cid:' + cid + ':' + key, category[key]);
|
||||
RDB.hset('category:' + cid, key, category[key]);
|
||||
|
||||
if (key == 'name') {
|
||||
// reset slugs if name is updated
|
||||
var slug = cid + '/' + utils.slugify(category[key]);
|
||||
RDB.set('cid:' + cid + ':slug', slug);
|
||||
RDB.set('category:slug:' + slug + ':cid', cid);
|
||||
RDB.hset('category:' + cid, 'slug', slug);
|
||||
RDB.set('categoryslug:' + slug + ':cid', cid);
|
||||
|
||||
RDB.smembers('categories:' + cid + ':tid', function(err, tids) {
|
||||
var pipe = RDB.multi();
|
||||
|
||||
@@ -9,14 +9,13 @@ var RDB = require('./redis.js'),
|
||||
|
||||
Categories.getCategoryById = function(category_id, current_user, callback) {
|
||||
RDB.smembers('categories:' + category_id + ':tid', function(err, tids) {
|
||||
RDB.multi()
|
||||
.get('cid:' + category_id + ':name')
|
||||
.smembers('cid:' + category_id + ':active_users')
|
||||
.get('cid:' + category_id + ':slug')
|
||||
.exec(function(err, replies) {
|
||||
var category_name = replies[0],
|
||||
active_users = replies[1],
|
||||
category_slug = replies[2];
|
||||
|
||||
Categories.getCategoryData(category_id, function(categoryData) {
|
||||
|
||||
var category_name = categoryData.name;
|
||||
category_slug = categoryData.slug;
|
||||
|
||||
RDB.smembers('cid:' + category_id + ':active_users', function(err, active_users) {
|
||||
|
||||
if (category_name === null) {
|
||||
callback(false);
|
||||
@@ -57,7 +56,7 @@ var RDB = require('./redis.js'),
|
||||
}
|
||||
|
||||
function getActiveUsers(next) {
|
||||
user.getMultipleUserFields(active_users, ['username','userslug'], function(users) {
|
||||
user.getMultipleUserFields(active_users, ['username', 'userslug'], function(users) {
|
||||
var activeUserData = [];
|
||||
for(var uid in users) {
|
||||
activeUserData.push(users[uid]);
|
||||
@@ -85,6 +84,7 @@ var RDB = require('./redis.js'),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,111 +115,83 @@ var RDB = require('./redis.js'),
|
||||
|
||||
// not the permanent location for this function
|
||||
Categories.getTopicsByTids = function(tids, current_user, callback, category_id /*temporary*/) {
|
||||
var title = [],
|
||||
uid = [],
|
||||
timestamp = [],
|
||||
lastposttime = [],
|
||||
slug = [],
|
||||
postcount = [],
|
||||
locked = [],
|
||||
deleted = [],
|
||||
pinned = [];
|
||||
|
||||
for (var i=0, ii=tids.length; i<ii; i++) {
|
||||
title.push('tid:' + tids[i] + ':title');
|
||||
uid.push('tid:' + tids[i] + ':uid');
|
||||
timestamp.push('tid:' + tids[i] + ':timestamp');
|
||||
lastposttime.push('tid:' + tids[i] + ':lastposttime');
|
||||
slug.push('tid:' + tids[i] + ':slug');
|
||||
postcount.push('tid:' + tids[i] + ':postcount');
|
||||
locked.push('tid:' + tids[i] + ':locked');
|
||||
deleted.push('tid:' + tids[i] + ':deleted');
|
||||
pinned.push('tid:' + tids[i] + ':pinned');
|
||||
}
|
||||
var retrieved_topics = [];
|
||||
var topicCountToLoad = tids.length;
|
||||
|
||||
function getTopicInfo(topicData, callback) {
|
||||
|
||||
function getUserName(next) {
|
||||
user.getUserField(topicData.uid, 'username', function(username) {
|
||||
next(null, username);
|
||||
});
|
||||
}
|
||||
|
||||
RDB.multi()
|
||||
.mget(title)
|
||||
.mget(uid)
|
||||
.mget(timestamp)
|
||||
.mget(lastposttime)
|
||||
.mget(slug)
|
||||
.mget(postcount)
|
||||
.mget(locked)
|
||||
.mget(deleted)
|
||||
.mget(pinned)
|
||||
.exec(function(err, replies) {
|
||||
var retrieved_topics = [];
|
||||
function hasReadTopic(next) {
|
||||
topics.hasReadTopics([topicData.tid], current_user, function(hasRead) {
|
||||
next(null, hasRead);
|
||||
});
|
||||
}
|
||||
|
||||
title = replies[0];
|
||||
uid = replies[1];
|
||||
timestamp = replies[2];
|
||||
lastposttime = replies[3];
|
||||
slug = replies[4];
|
||||
postcount = replies[5];
|
||||
locked = replies[6];
|
||||
deleted = replies[7];
|
||||
pinned = replies[8];
|
||||
|
||||
function getUserNames(next) {
|
||||
user.get_usernames_by_uids(uid, function(userNames) {
|
||||
next(null, userNames);
|
||||
});
|
||||
}
|
||||
function getTeaserInfo(next) {
|
||||
topics.getTeaser(topicData.tid, function(teaser) {
|
||||
next(null, teaser);
|
||||
});
|
||||
}
|
||||
|
||||
function hasReadTopics(next) {
|
||||
topics.hasReadTopics(tids, current_user, function(hasRead) {
|
||||
next(null, hasRead);
|
||||
});
|
||||
}
|
||||
// temporary. I don't think this call should belong here
|
||||
function getPrivileges(next) {
|
||||
Categories.privileges(category_id, current_user, function(user_privs) {
|
||||
next(null, user_privs);
|
||||
});
|
||||
}
|
||||
|
||||
function getTeaserInfo(next) {
|
||||
topics.get_teasers(tids, function(teasers) {
|
||||
next(null, teasers);
|
||||
});
|
||||
}
|
||||
async.parallel([getUserName, hasReadTopic, getTeaserInfo, getPrivileges], function(err, results) {
|
||||
var username = results[0],
|
||||
hasReadTopic = results[1],
|
||||
teaserInfo = results[2],
|
||||
privileges = results[3];
|
||||
|
||||
// temporary. I don't think this call should belong here
|
||||
function getPrivileges(next) {
|
||||
Categories.privileges(category_id, current_user, function(user_privs) {
|
||||
next(null, user_privs);
|
||||
});
|
||||
}
|
||||
|
||||
async.parallel([getUserNames, hasReadTopics, getTeaserInfo, getPrivileges], function(err, results) {
|
||||
var usernames = results[0],
|
||||
hasReadTopics = results[1],
|
||||
teaserInfo = results[2],
|
||||
privileges = results[3];
|
||||
|
||||
for (var i=0, ii=tids.length; i<ii; i++) {
|
||||
if (!deleted[i] || (deleted[i] && privileges.view_deleted) || uid[i] === current_user) {
|
||||
retrieved_topics.push({
|
||||
'tid' : tids[i],
|
||||
'title' : title[i],
|
||||
'uid' : uid[i],
|
||||
'username': usernames[i],
|
||||
'timestamp' : timestamp[i],
|
||||
'lastposttime' : lastposttime[i],
|
||||
'relativeTime': utils.relativeTime(timestamp[i]),
|
||||
'slug' : slug[i],
|
||||
'post_count' : postcount[i],
|
||||
'lock-icon': locked[i] === '1' ? 'icon-lock' : 'none',
|
||||
'deleted': deleted[i],
|
||||
'deleted-class': deleted[i] ? 'deleted' : '',
|
||||
'pinned': parseInt(pinned[i] || 0), // For sorting purposes
|
||||
'pin-icon': pinned[i] === '1' ? 'icon-pushpin' : 'none',
|
||||
'badgeclass' : (hasReadTopics[i] && current_user !=0) ? '' : 'badge-important',
|
||||
'teaser_text': teaserInfo[i].text,
|
||||
'teaser_username': teaserInfo[i].username,
|
||||
'teaser_timestamp': utils.relativeTime(teaserInfo[i].timestamp)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
callback(retrieved_topics);
|
||||
callback({
|
||||
username: username,
|
||||
hasread: hasReadTopic,
|
||||
teaserInfo: teaserInfo,
|
||||
privileges: privileges
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
for(var i=0; i<tids.length; ++i) {
|
||||
|
||||
topics.getTopicData(tids[i], function(topicData) {
|
||||
|
||||
getTopicInfo(topicData, function(topicInfo) {
|
||||
|
||||
topicData['pin-icon'] = topicData.pinned === '1' ? 'icon-pushpin' : 'none';
|
||||
topicData['lock-icon'] = topicData.locked === '1' ? 'icon-lock' : 'none';
|
||||
topicData['deleted-class'] = topicData.deleted === '1' ? 'deleted' : '';
|
||||
|
||||
topicData.relativeTime = utils.relativeTime(topicData.timestamp);
|
||||
|
||||
topicData.username = topicInfo.username;
|
||||
topicData.badgeclass = (topicInfo.hasread && current_user != 0) ? '' : 'badge-important';
|
||||
topicData.teaser_text = topicInfo.teaserInfo.text,
|
||||
topicData.teaser_username = topicInfo.teaserInfo.username;
|
||||
topicData.teaser_timestamp = utils.relativeTime(topicInfo.teaserInfo.timestamp);
|
||||
|
||||
if (!topicData.deleted || (topicData.deleted && topicInfo.privileges.view_deleted) || topicData.uid === current_user)
|
||||
retrieved_topics.push(topicData);
|
||||
else
|
||||
--topicCountToLoad;
|
||||
|
||||
if(retrieved_topics.length === topicCountToLoad)
|
||||
callback(retrieved_topics);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Categories.getAllCategories = function(callback, current_user) {
|
||||
@@ -300,8 +272,17 @@ var RDB = require('./redis.js'),
|
||||
});
|
||||
}
|
||||
|
||||
Categories.hasReadCategory = function(cid, uid, callback) {
|
||||
RDB.sismember('cid:' + cid + ':read_by_uid', uid, function(err, hasRead) {
|
||||
RDB.handle(err);
|
||||
|
||||
callback(hasRead);
|
||||
});
|
||||
}
|
||||
|
||||
Categories.getRecentReplies = function(cid, callback) {
|
||||
RDB.zrevrange('categories:recent_posts:cid:' + cid, 0, 4, function(err, pids) {
|
||||
|
||||
if (pids.length == 0) {
|
||||
callback(false);
|
||||
return;
|
||||
@@ -312,69 +293,40 @@ var RDB = require('./redis.js'),
|
||||
});
|
||||
}
|
||||
|
||||
Categories.getCategoryData = function(cid, callback) {
|
||||
RDB.hgetall('category:' + cid, function(err, data) {
|
||||
if(err === null)
|
||||
callback(data);
|
||||
else
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
Categories.getCategories = function(cids, callback, current_user) {
|
||||
if (cids.length === 0) {
|
||||
callback({'categories' : []});
|
||||
return;
|
||||
}
|
||||
|
||||
var name = [],
|
||||
description = [],
|
||||
icon = [],
|
||||
blockclass = [],
|
||||
slug = [],
|
||||
topic_count = [],
|
||||
has_read = {};
|
||||
|
||||
for (var i=0, ii=cids.length; i<ii; i++) {
|
||||
name.push('cid:' + cids[i] + ':name');
|
||||
description.push('cid:' + cids[i] + ':description');
|
||||
icon.push('cid:' + cids[i] + ':icon');
|
||||
blockclass.push('cid:' + cids[i] + ':blockclass');
|
||||
slug.push('cid:' + cids[i] + ':slug');
|
||||
topic_count.push('cid:' + cids[i] + ':topiccount');
|
||||
}
|
||||
|
||||
RDB.multi()
|
||||
.mget(name)
|
||||
.mget(description)
|
||||
.mget(icon)
|
||||
.mget(blockclass)
|
||||
.mget(slug)
|
||||
.mget(topic_count)
|
||||
.exec(function(err, replies) {
|
||||
name = replies[0];
|
||||
description = replies[1];
|
||||
icon = replies[2];
|
||||
blockclass = replies[3];
|
||||
slug = replies[4];
|
||||
topic_count = replies[5];
|
||||
var categories = [];
|
||||
|
||||
for(var i=0; i<cids.length; ++i) {
|
||||
Categories.getCategoryData(cids[i], function(categoryData) {
|
||||
|
||||
function generateCategories() {
|
||||
var categories = [];
|
||||
for (var i=0, ii=cids.length; i<ii; i++) {
|
||||
categories.push({
|
||||
'name' : name[i],
|
||||
'cid' : cids[i],
|
||||
'slug' : slug[i],
|
||||
'description' : description[i],
|
||||
'blockclass' : blockclass[i],
|
||||
'icon' : icon[i],
|
||||
'badgeclass' : (!topic_count[i] || (has_read[i] && current_user !=0)) ? '' : 'badge-important',
|
||||
'topic_count' : topic_count[i] || 0
|
||||
});
|
||||
}
|
||||
if(!categoryData)
|
||||
return;
|
||||
|
||||
callback({'categories': categories});
|
||||
}
|
||||
Categories.hasReadCategory(categoryData.cid, current_user, function(hasRead) {
|
||||
categoryData['badgeclass'] = (parseInt(categoryData.topic_count,10) === 0 || (hasRead && current_user != 0)) ? '' : 'badge-important';
|
||||
|
||||
Categories.hasReadCategories(cids, current_user, function(read_data) {
|
||||
has_read = read_data;
|
||||
generateCategories();
|
||||
});
|
||||
categories.push(categoryData);
|
||||
|
||||
if(categories.length === cids.length)
|
||||
callback({'categories': categories});
|
||||
|
||||
}) ;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}(exports));
|
||||
@@ -1,4 +1,5 @@
|
||||
var RDB = require('./redis.js'),
|
||||
posts = require('./posts.js'),
|
||||
user = require('./user.js');
|
||||
|
||||
(function(Favourites) {
|
||||
@@ -20,15 +21,15 @@ var RDB = require('./redis.js'),
|
||||
return;
|
||||
}
|
||||
|
||||
RDB.get('pid:' + pid + ':uid', function(err, uid_of_poster) {
|
||||
RDB.handle(err);
|
||||
posts.getPostField(pid, 'uid', function(uid_of_poster) {
|
||||
|
||||
Favourites.hasFavourited(pid, uid, function(hasFavourited) {
|
||||
if (hasFavourited == false) {
|
||||
RDB.sadd('pid:' + pid + ':users_favourited', uid);
|
||||
RDB.incr('pid:' + pid + ':rep');
|
||||
RDB.hincrby('post:' + pid, 'reputation', 1);
|
||||
|
||||
if (uid !== uid_of_poster) user.incrementUserFieldBy(uid_of_poster, 'reputation', 1);
|
||||
if (uid !== uid_of_poster)
|
||||
user.incrementUserFieldBy(uid_of_poster, 'reputation', 1);
|
||||
|
||||
if (room_id) {
|
||||
io.sockets.in(room_id).emit('event:rep_up', {uid: uid !== uid_of_poster ? uid_of_poster : 0, pid: pid});
|
||||
@@ -54,16 +55,16 @@ var RDB = require('./redis.js'),
|
||||
return;
|
||||
}
|
||||
|
||||
RDB.get('pid:' + pid + ':uid', function(err, uid_of_poster) {
|
||||
RDB.handle(err);
|
||||
posts.getPostField(pid, 'uid', function(uid_of_poster) {
|
||||
|
||||
Favourites.hasFavourited(pid, uid, function(hasFavourited) {
|
||||
if (hasFavourited == true) {
|
||||
|
||||
RDB.srem('pid:' + pid + ':users_favourited', uid);
|
||||
RDB.decr('pid:' + pid + ':rep');
|
||||
RDB.hincrby('post:' + pid, 'reputation', -1);
|
||||
|
||||
if (uid !== uid_of_poster) user.incrementUserFieldBy(uid_of_poster, 'reputation', -1);
|
||||
if (uid !== uid_of_poster)
|
||||
user.incrementUserFieldBy(uid_of_poster, 'reputation', -1);
|
||||
|
||||
if (room_id) {
|
||||
io.sockets.in(room_id).emit('event:rep_down', {uid: uid !== uid_of_poster ? uid_of_poster : 0, pid: pid});
|
||||
@@ -91,9 +92,10 @@ var RDB = require('./redis.js'),
|
||||
|
||||
data[post_id] = hasFavourited;
|
||||
loaded ++;
|
||||
if (loaded == pids.length) callback(data);
|
||||
if (loaded === pids.length)
|
||||
callback(data);
|
||||
});
|
||||
}(pids[i]))
|
||||
}(pids[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
34
src/feed.js
34
src/feed.js
@@ -29,24 +29,8 @@
|
||||
Feed.updateTopic = function(tid, cid) {
|
||||
var cache_time_in_seconds = 60;
|
||||
|
||||
function getTopicData(next) {
|
||||
topics.getTopicById(tid, 0, function(topicData) {
|
||||
next(null, topicData);
|
||||
});
|
||||
}
|
||||
|
||||
function getPostsData(next) {
|
||||
posts.getPostsByTid(tid, 0, -20, -1, function(postsData) {
|
||||
next(null, postsData);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async.parallel([getTopicData, getPostsData], function(err, results) {
|
||||
var topicData = results[0],
|
||||
postsData = results[1].postData,
|
||||
userData = results[1].userData,
|
||||
location = '/topic/' + topicData.slug,
|
||||
topics.getTopicWithPosts(tid, 0, function(topicData) {
|
||||
var location = '/topic/' + topicData.slug,
|
||||
xml_url = '/topic/' + tid + '.rss';
|
||||
|
||||
var post = topicData.main_posts[0];
|
||||
@@ -55,18 +39,20 @@
|
||||
var feed = createFeed(topicData.topic_name, '', location, xml_url, post.username, urn);
|
||||
var title;
|
||||
|
||||
for (var i = 0, ii = postsData.pid.length; i < ii; i++) {
|
||||
urn = 'urn:' + cid + ':' + tid + ':' + postsData.pid[i];
|
||||
title = 'Reply to ' + topicData.topic_name + ' on ' + (new Date(parseInt(postsData.timestamp[i], 10)).toUTCString());
|
||||
var topic_posts = topicData.main_posts.concat(topicData.posts);
|
||||
|
||||
for (var i = 0, ii = topic_posts.length; i < ii; i++) {
|
||||
urn = 'urn:' + cid + ':' + tid + ':' + topic_posts[i].pid;
|
||||
title = 'Reply to ' + topicData.topic_name + ' on ' + (new Date(parseInt(topic_posts[i].timestamp, 10)).toUTCString());
|
||||
|
||||
feed.addNewItem(
|
||||
title,
|
||||
location,
|
||||
postsData.timestamp[i],
|
||||
postsData.content[i],
|
||||
topic_posts[i].timestamp,
|
||||
topic_posts[i].content,
|
||||
{
|
||||
'urn' : urn,
|
||||
'username' : userData[postsData.uid[i]].username
|
||||
'username' : topic_posts[i].username
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
130
src/postTools.js
130
src/postTools.js
@@ -23,24 +23,22 @@ marked.setOptions({
|
||||
//todo: break early if one condition is true
|
||||
|
||||
function getThreadPrivileges(next) {
|
||||
posts.get_tid_by_pid(pid, function(tid) {
|
||||
threadTools.privileges(tid, uid, function(privileges) {
|
||||
next(null, privileges);
|
||||
});
|
||||
posts.getPostField(pid, 'tid', function(tid) {
|
||||
threadTools.privileges(tid, uid, function(privileges) {
|
||||
next(null, privileges);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function isOwnPost(next) {
|
||||
RDB.get('pid:' + pid + ':uid', function(err, author) {
|
||||
if (author && parseInt(author) > 0) {
|
||||
next(null, author === uid);
|
||||
}
|
||||
});
|
||||
posts.getPostField(pid, 'uid', function(author) {
|
||||
if (author && parseInt(author) > 0) {
|
||||
next(null, author === uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function hasEnoughRep(next) {
|
||||
// DRY fail in threadTools.
|
||||
|
||||
user.getUserField(uid, 'reputation', function(reputation) {
|
||||
next(null, reputation >= global.config['privileges:manage_content']);
|
||||
});
|
||||
@@ -55,23 +53,25 @@ marked.setOptions({
|
||||
}
|
||||
|
||||
PostTools.edit = function(uid, pid, title, content) {
|
||||
|
||||
var success = function() {
|
||||
RDB.set('pid:' + pid + ':content', content);
|
||||
RDB.set('pid:' + pid + ':edited', Date.now());
|
||||
RDB.set('pid:' + pid + ':editor', uid);
|
||||
posts.setPostField(pid, 'content', content);
|
||||
posts.setPostField(pid, 'edited', Date.now());
|
||||
posts.setPostField(pid, 'editor', uid);
|
||||
|
||||
posts.get_tid_by_pid(pid, function(tid) {
|
||||
PostTools.isMain(pid, tid, function(isMainPost) {
|
||||
if (isMainPost) RDB.set('tid:' + tid + ':title', title);
|
||||
posts.getPostField(pid, 'tid', function(tid) {
|
||||
PostTools.isMain(pid, tid, function(isMainPost) {
|
||||
if (isMainPost)
|
||||
topics.setTopicField(tid, 'title', title);
|
||||
|
||||
io.sockets.in('topic_' + tid).emit('event:post_edited', {
|
||||
pid: pid,
|
||||
title: title,
|
||||
content: marked(content || '')
|
||||
});
|
||||
io.sockets.in('topic_' + tid).emit('event:post_edited', {
|
||||
pid: pid,
|
||||
title: title,
|
||||
content: marked(content || '')
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
PostTools.privileges(pid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
@@ -82,14 +82,14 @@ marked.setOptions({
|
||||
|
||||
PostTools.delete = function(uid, pid) {
|
||||
var success = function() {
|
||||
RDB.set('pid:' + pid + ':deleted', 1);
|
||||
posts.setPostField(pid, 'deleted', 1);
|
||||
|
||||
posts.get_tid_by_pid(pid, function(tid) {
|
||||
io.sockets.in('topic_' + tid).emit('event:post_deleted', {
|
||||
pid: pid
|
||||
});
|
||||
posts.getPostField(pid, 'tid', function(tid) {
|
||||
io.sockets.in('topic_' + tid).emit('event:post_deleted', {
|
||||
pid: pid
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
PostTools.privileges(pid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
@@ -100,14 +100,14 @@ marked.setOptions({
|
||||
|
||||
PostTools.restore = function(uid, pid) {
|
||||
var success = function() {
|
||||
RDB.del('pid:' + pid + ':deleted');
|
||||
posts.setPostField(pid, 'deleted', 0);
|
||||
|
||||
posts.get_tid_by_pid(pid, function(tid) {
|
||||
io.sockets.in('topic_' + tid).emit('event:post_restored', {
|
||||
pid: pid
|
||||
});
|
||||
posts.getPostField(pid, 'tid', function(tid) {
|
||||
io.sockets.in('topic_' + tid).emit('event:post_restored', {
|
||||
pid: pid
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
PostTools.privileges(pid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
@@ -116,65 +116,5 @@ marked.setOptions({
|
||||
});
|
||||
}
|
||||
|
||||
PostTools.constructPostObject = function(rawPosts, tid, current_user, privileges, callback) {
|
||||
var postObj = [];
|
||||
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
if (!privileges) {
|
||||
threadTools.privileges(tid, current_user, function(privs) {
|
||||
privileges = privs;
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
var postData = rawPosts.postData,
|
||||
userData = rawPosts.userData,
|
||||
voteData = rawPosts.voteData;
|
||||
|
||||
if (!postData) {
|
||||
return next(null, []);
|
||||
}
|
||||
|
||||
for (var i=0, ii= postData.pid.length; i<ii; i++) {
|
||||
var uid = postData.uid[i],
|
||||
pid = postData.pid[i];
|
||||
|
||||
// ############ to be moved into posts.getPostsByTid ############
|
||||
if (postData.deleted[i] === null || (postData.deleted[i] === '1' && privileges.view_deleted) || current_user === uid) {
|
||||
var post_obj = {
|
||||
'pid' : pid,
|
||||
'uid' : uid,
|
||||
'content' : marked(postData.content[i] || ''),
|
||||
'post_rep' : postData.reputation[i] || 0,
|
||||
'timestamp' : postData.timestamp[i],
|
||||
'relativeTime': utils.relativeTime(postData.timestamp[i]),
|
||||
'username' : userData[uid].username || 'anonymous',
|
||||
'userslug' : userData[uid].userslug || '',
|
||||
'user_rep' : userData[uid].reputation || 0,
|
||||
'gravatar' : userData[uid].picture || 'http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e',
|
||||
'signature' : marked(userData[uid].signature || ''),
|
||||
'fav_star_class' : voteData[pid] ? 'icon-star' : 'icon-star-empty',
|
||||
'display_moderator_tools': (uid == current_user || privileges.editable) ? 'show' : 'none',
|
||||
'edited-class': postData.editor[i] !== null ? '' : 'none',
|
||||
'editor': postData.editor[i] !== null ? userData[postData.editor[i]].username : '',
|
||||
'relativeEditTime': postData.editTime !== null ? utils.relativeTime(postData.editTime[i]) : '',
|
||||
'deleted': postData.deleted[i] || '0'
|
||||
};
|
||||
|
||||
postObj.push(post_obj);
|
||||
}
|
||||
// ########## end to be moved into posts.getPostsByTid ############
|
||||
}
|
||||
|
||||
next(null);
|
||||
}
|
||||
], function(err) {
|
||||
callback(postObj);
|
||||
});
|
||||
}
|
||||
|
||||
}(exports));
|
||||
404
src/posts.js
404
src/posts.js
@@ -14,13 +14,14 @@ marked.setOptions({
|
||||
});
|
||||
|
||||
(function(Posts) {
|
||||
Posts.getPostsByTid = function(tid, current_user, start, end, callback) {
|
||||
|
||||
Posts.getPostsByTid = function(tid, start, end, callback) {
|
||||
RDB.lrange('tid:' + tid + ':posts', start, end, function(err, pids) {
|
||||
|
||||
RDB.handle(err);
|
||||
topics.markAsRead(tid, current_user);
|
||||
|
||||
if (pids.length) {
|
||||
Posts.getPostsByPids(pids, current_user, function(posts) {
|
||||
Posts.getPostsByPids(pids, function(posts) {
|
||||
callback(posts);
|
||||
});
|
||||
} else {
|
||||
@@ -30,130 +31,135 @@ marked.setOptions({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Posts.addUserInfoToPost = function(post, callback) {
|
||||
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'picture', 'signature'], function(userData) {
|
||||
|
||||
// todo, getPostsByPids has duplicated stuff, have that call this fn - after userinfo calls are pulled out.
|
||||
Posts.getPostSummaryByPids = function(pids, callback) {
|
||||
var content = [], uid = [], timestamp = [];
|
||||
for (var i=0, ii=pids.length; i<ii; i++) {
|
||||
content.push('pid:' + pids[i] + ':content');
|
||||
uid.push('pid:' + pids[i] + ':uid');
|
||||
timestamp.push('pid:' + pids[i] + ':timestamp');
|
||||
}
|
||||
post.username = userData.username || 'anonymous';
|
||||
post.userslug = userData.userslug || '';
|
||||
post.user_rep = userData.reputation || 0;
|
||||
post.picture = userData.picture || 'http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e';
|
||||
post.signature = marked(userData.signature || '');
|
||||
|
||||
RDB.multi()
|
||||
.mget(content)
|
||||
.mget(uid)
|
||||
.mget(timestamp)
|
||||
.exec(function(err, replies) {
|
||||
post_data = {
|
||||
pids: pids,
|
||||
content: replies[0],
|
||||
uid: replies[1],
|
||||
timestamp: replies[2]
|
||||
}
|
||||
|
||||
// below, to be deprecated
|
||||
user.getMultipleUserFields(post_data.uid, ['username','reputation','picture'], function(user_details) {
|
||||
callback({
|
||||
users: user_details,
|
||||
posts: post_data
|
||||
});
|
||||
});
|
||||
// above, to be deprecated
|
||||
});
|
||||
};
|
||||
|
||||
Posts.getPostsByPids = function(pids, current_user, callback) {
|
||||
var content = [], uid = [], timestamp = [], post_rep = [], editor = [], editTime = [], deleted = [], tid = [];
|
||||
|
||||
for (var i=0, ii=pids.length; i<ii; i++) {
|
||||
content.push('pid:' + pids[i] + ':content');
|
||||
uid.push('pid:' + pids[i] + ':uid');
|
||||
timestamp.push('pid:' + pids[i] + ':timestamp');
|
||||
post_rep.push('pid:' + pids[i] + ':rep');
|
||||
editor.push('pid:' + pids[i] + ':editor');
|
||||
editTime.push('pid:' + pids[i] + ':edited');
|
||||
deleted.push('pid:' + pids[i] + ':deleted');
|
||||
tid.push('pid:' + pids[i] + ':tid');
|
||||
}
|
||||
|
||||
|
||||
function getFavouritesData(next) {
|
||||
favourites.getFavouritesByPostIDs(pids, current_user, function(fav_data) {
|
||||
next(null, fav_data);
|
||||
}); // to be moved
|
||||
}
|
||||
|
||||
function getPostData(next) {
|
||||
RDB.multi()
|
||||
.mget(content)
|
||||
.mget(uid)
|
||||
.mget(timestamp)
|
||||
.mget(post_rep)
|
||||
.mget(editor)
|
||||
.mget(editTime)
|
||||
.mget(deleted)
|
||||
.mget(tid)
|
||||
.exec(function(err, replies) {
|
||||
post_data = {
|
||||
pid: pids,
|
||||
content: replies[0],
|
||||
uid: replies[1],
|
||||
timestamp: replies[2],
|
||||
reputation: replies[3],
|
||||
editor: replies[4],
|
||||
editTime: replies[5],
|
||||
deleted: replies[6],
|
||||
tid: replies[7]
|
||||
};
|
||||
|
||||
// below, to be deprecated
|
||||
// Add any editors to the user_data object
|
||||
for(var x = 0, numPosts = post_data.editor.length; x < numPosts; x++) {
|
||||
if (post_data.editor[x] !== null && post_data.uid.indexOf(post_data.editor[x]) === -1) {
|
||||
post_data.uid.push(post_data.editor[x]);
|
||||
}
|
||||
}
|
||||
|
||||
user.getMultipleUserFields(post_data.uid, ['username', 'userslug', 'reputation', 'picture', 'signature'], function(user_details) {
|
||||
next(null, {
|
||||
users: user_details,
|
||||
posts: post_data
|
||||
});
|
||||
});
|
||||
// above, to be deprecated
|
||||
});
|
||||
}
|
||||
|
||||
async.parallel([getFavouritesData, getPostData], function(err, results) {
|
||||
callback({
|
||||
'voteData' : results[0], // to be moved
|
||||
'userData' : results[1].users, // to be moved
|
||||
'postData' : results[1].posts
|
||||
});
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
Posts.get_tid_by_pid = function(pid, callback) {
|
||||
RDB.get('pid:' + pid + ':tid', function(err, tid) {
|
||||
if (tid && parseInt(tid) > 0) {
|
||||
callback(tid);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
Posts.getPostSummaryByPids = function(pids, callback) {
|
||||
|
||||
var returnData = [];
|
||||
|
||||
var loaded = 0;
|
||||
|
||||
for(var i=0, ii=pids.length; i<ii; ++i) {
|
||||
|
||||
(function(index, pid) {
|
||||
Posts.getPostFields(pids[i], ['pid', 'content', 'uid', 'timestamp'], function(postData) {
|
||||
Posts.addUserInfoToPost(postData, function() {
|
||||
|
||||
returnData[index] = postData;
|
||||
++loaded;
|
||||
|
||||
if(loaded === pids.length) {
|
||||
callback(returnData);
|
||||
}
|
||||
});
|
||||
});
|
||||
}(i, pids[i]));
|
||||
}
|
||||
};
|
||||
|
||||
Posts.getPostData = function(pid, callback) {
|
||||
RDB.hgetall('post:' + pid, function(err, data) {
|
||||
if(err === null)
|
||||
callback(data);
|
||||
else
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
Posts.getPostFields = function(uid, fields, callback) {
|
||||
RDB.hmget('post:' + uid, fields, function(err, data) {
|
||||
if(err === null) {
|
||||
var returnData = {};
|
||||
|
||||
for(var i=0, ii=fields.length; i<ii; ++i) {
|
||||
returnData[fields[i]] = data[i];
|
||||
}
|
||||
|
||||
callback(returnData);
|
||||
}
|
||||
else
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
Posts.getPostsByPids = function(pids, callback) {
|
||||
var posts = [],
|
||||
loaded = 0;
|
||||
|
||||
for(var i=0, ii=pids.length; i<ii; ++i) {
|
||||
(function(index, pid) {
|
||||
Posts.getPostData(pid, function(postData) {
|
||||
|
||||
if(postData) {
|
||||
postData.relativeTime = utils.relativeTime(postData.timestamp);
|
||||
postData.post_rep = postData.reputation;
|
||||
postData['edited-class'] = postData.editor !== '' ? '' : 'none';
|
||||
postData['relativeEditTime'] = postData.edited !== '0' ? utils.relativeTime(postData.edited) : '';
|
||||
|
||||
posts[index] = postData;
|
||||
}
|
||||
|
||||
++loaded;
|
||||
if(loaded === pids.length)
|
||||
callback(posts);
|
||||
});
|
||||
}(i, pids[i]));
|
||||
}
|
||||
}
|
||||
|
||||
Posts.getPostField = function(pid, field, callback) {
|
||||
RDB.hget('post:' + pid, field, function(err, data) {
|
||||
if(err === null)
|
||||
callback(data);
|
||||
else
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
Posts.setPostField = function(pid, field, value) {
|
||||
RDB.hset('post:' + pid, field, value);
|
||||
}
|
||||
|
||||
Posts.getPostFields = function(pid, fields, callback) {
|
||||
RDB.hmget('post:' + pid, fields, function(err, data) {
|
||||
if(err === null) {
|
||||
var returnData = {};
|
||||
|
||||
for(var i=0, ii=fields.length; i<ii; ++i) {
|
||||
returnData[fields[i]] = data[i];
|
||||
}
|
||||
|
||||
callback(returnData);
|
||||
}
|
||||
else
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
Posts.get_cid_by_pid = function(pid, callback) {
|
||||
Posts.get_tid_by_pid(pid, function(tid) {
|
||||
if (tid) topics.get_cid_by_tid(tid, function(cid) {
|
||||
if (cid) {
|
||||
callback(cid);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
})
|
||||
Posts.getPostField(pid, 'tid', function(tid) {
|
||||
if (tid) {
|
||||
topics.getTopicField(tid, 'cid', function(cid) {
|
||||
if (cid) {
|
||||
callback(cid);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Posts.reply = function(socket, tid, uid, content) {
|
||||
@@ -169,6 +175,7 @@ marked.setOptions({
|
||||
|
||||
|
||||
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
||||
|
||||
if(Date.now() - lastposttime < config.post_delay) {
|
||||
socket.emit('event:alert', {
|
||||
title: 'Too many posts!',
|
||||
@@ -183,7 +190,7 @@ marked.setOptions({
|
||||
if (pid > 0) {
|
||||
RDB.rpush('tid:' + tid + ':posts', pid);
|
||||
|
||||
RDB.del('tid:' + tid + ':read_by_uid'); // let everybody know there is an unread post
|
||||
RDB.del('tid:' + tid + ':read_by_uid');
|
||||
|
||||
Posts.get_cid_by_pid(pid, function(cid) {
|
||||
RDB.del('cid:' + cid + ':read_by_uid', function(err, data) {
|
||||
@@ -193,7 +200,12 @@ marked.setOptions({
|
||||
RDB.zadd('categories:recent_posts:cid:' + cid, Date.now(), pid);
|
||||
});
|
||||
|
||||
Posts.getTopicPostStats(socket);
|
||||
|
||||
// Send notifications to users who are following this topic
|
||||
threadTools.notify_followers(tid, uid);
|
||||
|
||||
|
||||
socket.emit('event:alert', {
|
||||
title: 'Reply Successful',
|
||||
message: 'You have successfully replied. Click here to view your reply.',
|
||||
@@ -201,38 +213,29 @@ marked.setOptions({
|
||||
timeout: 2000
|
||||
});
|
||||
|
||||
Posts.getTopicPostStats(socket);
|
||||
|
||||
// Send notifications to users who are following this topic
|
||||
threadTools.notify_followers(tid, uid);
|
||||
|
||||
user.getUserFields(uid, ['username','reputation','picture','signature'], function(data) {
|
||||
|
||||
var timestamp = Date.now();
|
||||
var socketData = {
|
||||
'posts' : [
|
||||
{
|
||||
'pid' : pid,
|
||||
'content' : marked(content || ''),
|
||||
'uid' : uid,
|
||||
'username' : data.username || 'anonymous',
|
||||
'user_rep' : data.reputation || 0,
|
||||
'post_rep' : 0,
|
||||
'gravatar' : data.picture,
|
||||
'signature' : marked(data.signature || ''),
|
||||
'timestamp' : timestamp,
|
||||
'relativeTime': utils.relativeTime(timestamp),
|
||||
'fav_star_class' :'icon-star-empty',
|
||||
'edited-class': 'none',
|
||||
'editor': '',
|
||||
}
|
||||
]
|
||||
};
|
||||
var timestamp = Date.now();
|
||||
var socketData = {
|
||||
'posts' : [
|
||||
{
|
||||
'pid' : pid,
|
||||
'content' : marked(content || ''),
|
||||
'uid' : uid,
|
||||
'post_rep' : 0,
|
||||
'timestamp' : timestamp,
|
||||
'relativeTime': utils.relativeTime(timestamp),
|
||||
'fav_star_class' :'icon-star-empty',
|
||||
'edited-class': 'none',
|
||||
'editor': '',
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
posts.addUserInfoToPost(socketData['posts'][0], function() {
|
||||
io.sockets.in('topic_' + tid).emit('event:new_post', socketData);
|
||||
io.sockets.in('recent_posts').emit('event:new_post', socketData);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
} else {
|
||||
socket.emit('event:alert', {
|
||||
title: 'Reply Unsuccessful',
|
||||
@@ -246,57 +249,53 @@ marked.setOptions({
|
||||
};
|
||||
|
||||
Posts.create = function(uid, tid, content, callback) {
|
||||
if (uid === null) return;
|
||||
if (uid === null) {
|
||||
callback(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
RDB.get('tid:' + tid + ':locked', function(err, locked) {
|
||||
RDB.handle(err);
|
||||
topics.isLocked(tid, function(locked) {
|
||||
|
||||
if (!locked || locked === '0') {
|
||||
RDB.incr('global:next_post_id', function(err, pid) {
|
||||
RDB.handle(err);
|
||||
|
||||
var timestamp = Date.now();
|
||||
// Posts Info
|
||||
RDB.set('pid:' + pid + ':content', content);
|
||||
RDB.set('pid:' + pid + ':uid', uid);
|
||||
RDB.set('pid:' + pid + ':timestamp', timestamp);
|
||||
RDB.set('pid:' + pid + ':rep', 0);
|
||||
RDB.set('pid:' + pid + ':tid', tid);
|
||||
|
||||
RDB.incr('tid:' + tid + ':postcount');
|
||||
RDB.zadd(schema.topics().recent, timestamp, tid);
|
||||
RDB.set('tid:' + tid + ':lastposttime', timestamp);
|
||||
RDB.hmset('post:' + pid, {
|
||||
'pid': pid,
|
||||
'uid': uid,
|
||||
'tid': tid,
|
||||
'content': content,
|
||||
'timestamp': timestamp,
|
||||
'reputation': 0,
|
||||
'editor': '',
|
||||
'edited': 0,
|
||||
'deleted': 0
|
||||
});
|
||||
|
||||
topics.increasePostCount(tid);
|
||||
topics.setTopicField(tid, 'lastposttime', timestamp);
|
||||
topics.addToRecent(tid, timestamp);
|
||||
|
||||
RDB.incr('totalpostcount');
|
||||
|
||||
topics.getTopicField(tid, 'cid', function(cid) {
|
||||
RDB.handle(err);
|
||||
|
||||
user.getUserFields(uid, ['username'], function(data) { // todo parallel
|
||||
//add active users to this category
|
||||
RDB.get('tid:' + tid + ':cid', function(err, cid) {
|
||||
RDB.handle(err);
|
||||
feed.updateTopic(tid, cid);
|
||||
|
||||
// this is a bit of a naive implementation, defn something to look at post-MVP
|
||||
RDB.scard('cid:' + cid + ':active_users', function(amount) {
|
||||
if (amount > 10) {
|
||||
RDB.spop('cid:' + cid + ':active_users');
|
||||
}
|
||||
|
||||
feed.updateTopic(tid, cid);
|
||||
|
||||
// this is a bit of a naive implementation, defn something to look at post-MVP
|
||||
RDB.scard('cid:' + cid + ':active_users', function(amount) {
|
||||
if (amount > 10) {
|
||||
RDB.spop('cid:' + cid + ':active_users');
|
||||
}
|
||||
|
||||
//RDB.sadd('cid:' + cid + ':active_users', data.username);
|
||||
RDB.sadd('cid:' + cid + ':active_users', uid);
|
||||
});
|
||||
RDB.sadd('cid:' + cid + ':active_users', uid);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// User Details - move this out later
|
||||
RDB.lpush('uid:' + uid + ':posts', pid);
|
||||
|
||||
user.incrementUserFieldBy(uid, 'postcount', 1);
|
||||
user.setUserField(uid, 'lastposttime', timestamp);
|
||||
|
||||
user.sendPostNotificationToFollowers(uid, tid, pid);
|
||||
user.onNewPostMade(uid, tid, pid, timestamp);
|
||||
|
||||
if (callback)
|
||||
callback(pid);
|
||||
@@ -306,40 +305,19 @@ marked.setOptions({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Posts.getRawContent = function(pid, callback) {
|
||||
RDB.get('pid:' + pid + ':content', function(err, raw) {
|
||||
callback(raw);
|
||||
});
|
||||
}
|
||||
|
||||
Posts.getPostsByUid = function(uid, callback) {
|
||||
Posts.getPostsByUid = function(uid, start, end, callback) {
|
||||
|
||||
RDB.lrange('uid:' + uid + ':posts', 0, 10, function(err, pids) {
|
||||
if(err === null) {
|
||||
|
||||
if(pids && pids.length) {
|
||||
|
||||
Posts.getPostsByPids(pids, uid, function(posts) {
|
||||
var returnData = [];
|
||||
|
||||
var len = posts.postData.pid.length;
|
||||
|
||||
for (var i=0; i < len; ++i) {
|
||||
returnData.push({
|
||||
pid: posts.postData.pid[i],
|
||||
content: posts.postData.content[i],
|
||||
timestamp: utils.relativeTime(posts.postData.timestamp[i]),
|
||||
tid: posts.postData.tid[i]
|
||||
});
|
||||
};
|
||||
|
||||
callback(returnData);
|
||||
});
|
||||
}
|
||||
else
|
||||
callback([]);
|
||||
user.getPostIds(uid, start, end, function(pids) {
|
||||
|
||||
if(pids && pids.length) {
|
||||
|
||||
Posts.getPostsByPids(pids, function(posts) {
|
||||
callback(posts);
|
||||
});
|
||||
}
|
||||
else
|
||||
callback([]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -255,10 +255,10 @@ var user = require('./../user.js'),
|
||||
|
||||
if (!req.params.section && !req.params.userslug) {
|
||||
user.getUserList(function(data) {
|
||||
data = data.sort(function(a, b) {
|
||||
return b.joindate - a.joindate;
|
||||
});
|
||||
res.json({search_display: 'none', users:data});
|
||||
data = data.sort(function(a, b) {
|
||||
return b.joindate - a.joindate;
|
||||
});
|
||||
res.json({search_display: 'none', users:data});
|
||||
});
|
||||
}
|
||||
else if(String(req.params.section).toLowerCase() === 'following') {
|
||||
@@ -292,7 +292,7 @@ var user = require('./../user.js'),
|
||||
|
||||
user.isFollowing(callerUID, userData.theirid, function(isFollowing) {
|
||||
|
||||
posts.getPostsByUid(userData.theirid, function(posts) {
|
||||
posts.getPostsByUid(userData.theirid, 0, 9, function(posts) {
|
||||
userData.posts = posts;
|
||||
userData.isFollowing = isFollowing;
|
||||
|
||||
|
||||
@@ -13,19 +13,6 @@
|
||||
Schema.topics = function(tid) {
|
||||
return {
|
||||
|
||||
/* strings */
|
||||
title: 'tid:' + tid + ':title',
|
||||
locked: 'tid:' + tid + ':locked',
|
||||
category_name: 'tid:' + tid + ':category_name',
|
||||
category_slug: 'tid:' + tid + ':category_slug',
|
||||
deleted: 'tid:' + tid + ':deleted',
|
||||
pinned: 'tid:' + tid + ':pinned',
|
||||
uid: 'tid:' + tid + ':uid',
|
||||
timestamp: 'tid:' + tid + ':timestamp',
|
||||
slug: 'tid:' + tid + ':slug',
|
||||
postcount: 'tid:' + tid + ':postcount',
|
||||
cid: 'tid:' + tid + ':cid',
|
||||
|
||||
/* sets */
|
||||
tid: 'topics:tid',
|
||||
read_by_uid: 'tid:' + tid + ':read_by_uid',
|
||||
|
||||
@@ -11,7 +11,7 @@ var RDB = require('./redis.js'),
|
||||
//todo: break early if one condition is true
|
||||
|
||||
function getCategoryPrivileges(next) {
|
||||
topics.get_cid_by_tid(tid, function(cid) {
|
||||
topics.getTopicField(tid, 'cid', function(cid) {
|
||||
categories.privileges(cid, uid, function(privileges) {
|
||||
next(null, privileges);
|
||||
});
|
||||
@@ -19,8 +19,6 @@ var RDB = require('./redis.js'),
|
||||
}
|
||||
|
||||
function hasEnoughRep(next) {
|
||||
// DRY fail in postTools
|
||||
|
||||
user.getUserField(uid, 'reputation', function(reputation) {
|
||||
next(null, reputation >= global.config['privileges:manage_topic']);
|
||||
});
|
||||
@@ -38,8 +36,7 @@ var RDB = require('./redis.js'),
|
||||
ThreadTools.lock = function(tid, uid, socket) {
|
||||
ThreadTools.privileges(tid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
// Mark thread as locked
|
||||
RDB.set('tid:' + tid + ':locked', 1);
|
||||
topics.setTopicField(tid, 'locked', 1);
|
||||
|
||||
if (socket) {
|
||||
io.sockets.in('topic_' + tid).emit('event:topic_locked', {
|
||||
@@ -59,8 +56,7 @@ var RDB = require('./redis.js'),
|
||||
ThreadTools.unlock = function(tid, uid, socket) {
|
||||
ThreadTools.privileges(tid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
// Mark thread as unlocked
|
||||
RDB.del('tid:' + tid + ':locked');
|
||||
topics.setTopicField(tid, 'locked', 0);
|
||||
|
||||
if (socket) {
|
||||
io.sockets.in('topic_' + tid).emit('event:topic_unlocked', {
|
||||
@@ -80,8 +76,8 @@ var RDB = require('./redis.js'),
|
||||
ThreadTools.delete = function(tid, uid, socket) {
|
||||
ThreadTools.privileges(tid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
// Mark thread as deleted
|
||||
RDB.set('tid:' + tid + ':deleted', 1);
|
||||
|
||||
topics.setTopicField(tid, 'deleted', 1);
|
||||
ThreadTools.lock(tid, uid);
|
||||
|
||||
if (socket) {
|
||||
@@ -102,8 +98,8 @@ var RDB = require('./redis.js'),
|
||||
ThreadTools.restore = function(tid, uid, socket) {
|
||||
ThreadTools.privileges(tid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
// Mark thread as restored
|
||||
RDB.del('tid:' + tid + ':deleted');
|
||||
|
||||
topics.setTopicField(tid, 'deleted', 0);
|
||||
ThreadTools.unlock(tid, uid);
|
||||
|
||||
if (socket) {
|
||||
@@ -124,8 +120,8 @@ var RDB = require('./redis.js'),
|
||||
ThreadTools.pin = function(tid, uid, socket) {
|
||||
ThreadTools.privileges(tid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
// Mark thread as pinned
|
||||
RDB.set('tid:' + tid + ':pinned', 1);
|
||||
|
||||
topics.setTopicField(tid, 'pinned', 1);
|
||||
|
||||
if (socket) {
|
||||
io.sockets.in('topic_' + tid).emit('event:topic_pinned', {
|
||||
@@ -145,8 +141,8 @@ var RDB = require('./redis.js'),
|
||||
ThreadTools.unpin = function(tid, uid, socket) {
|
||||
ThreadTools.privileges(tid, uid, function(privileges) {
|
||||
if (privileges.editable) {
|
||||
// Mark thread as unpinned
|
||||
RDB.del('tid:' + tid + ':pinned');
|
||||
|
||||
topics.setTopicField(tid, 'pinned', 0);
|
||||
|
||||
if (socket) {
|
||||
io.sockets.in('topic_' + tid).emit('event:topic_unpinned', {
|
||||
@@ -164,15 +160,17 @@ var RDB = require('./redis.js'),
|
||||
}
|
||||
|
||||
ThreadTools.move = function(tid, cid, socket) {
|
||||
RDB.get('tid:' + tid + ':cid', function(err, oldCid) {
|
||||
RDB.handle(err);
|
||||
|
||||
topics.getTopicField(tid, 'cid', function(oldCid) {
|
||||
|
||||
RDB.smove('categories:' + oldCid + ':tid', 'categories:' + cid + ':tid', tid, function(err, result) {
|
||||
if (!err && result === 1) {
|
||||
RDB.set('tid:' + tid + ':cid', cid);
|
||||
|
||||
topics.setTopicField(tid, 'cid', cid);
|
||||
|
||||
categories.getCategories([cid], function(data) {
|
||||
RDB.set('tid:' + tid + ':category_name', data.categories[0].name);
|
||||
RDB.set('tid:' + tid + ':category_slug', data.categories[0].slug);
|
||||
topics.setTopicField(tid, 'category_name', data.categories[0].name);
|
||||
topics.setTopicField(tid, 'category_slug', data.categories[0].slug);
|
||||
});
|
||||
|
||||
socket.emit('api:topic.move', {
|
||||
@@ -233,11 +231,16 @@ var RDB = require('./redis.js'),
|
||||
ThreadTools.notify_followers = function(tid, exceptUid) {
|
||||
async.parallel([
|
||||
function(next) {
|
||||
topics.get_topic(tid, 0, function(threadData) {
|
||||
notifications.create(threadData.teaser_username + ' has posted a reply to: "' + threadData.title + '"', null, '/topic/' + tid, 'topic:' + tid, function(nid) {
|
||||
next(null, nid);
|
||||
|
||||
topics.getTopicField(tid, 'title', function(title) {
|
||||
topics.getTeaser(tid, function(teaser) {
|
||||
notifications.create(teaser.username + ' has posted a reply to: "' + title + '"', null, '/topic/' + tid, 'topic:' + tid, function(nid) {
|
||||
next(null, nid);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
function(next) {
|
||||
ThreadTools.get_followers(tid, function(err, followers) {
|
||||
|
||||
391
src/topics.js
391
src/topics.js
@@ -9,39 +9,94 @@ var RDB = require('./redis.js')
|
||||
threadTools = require('./threadTools.js'),
|
||||
postTools = require('./postTools'),
|
||||
async = require('async'),
|
||||
feed = require('./feed.js');
|
||||
feed = require('./feed.js'),
|
||||
favourites = require('./favourites.js');
|
||||
|
||||
marked.setOptions({
|
||||
breaks: true
|
||||
});
|
||||
|
||||
(function(Topics) {
|
||||
Topics.getTopicById = function(tid, current_user, callback) {
|
||||
function getTopicData(next) {
|
||||
RDB.multi()
|
||||
.get(schema.topics(tid).title)
|
||||
.get(schema.topics(tid).locked)
|
||||
.get(schema.topics(tid).category_name)
|
||||
.get(schema.topics(tid).category_slug)
|
||||
.get(schema.topics(tid).deleted)
|
||||
.get(schema.topics(tid).pinned)
|
||||
.get(schema.topics(tid).slug)
|
||||
.exec(function(err, replies) {
|
||||
next(null, {
|
||||
topic_name: replies[0],
|
||||
locked: replies[1] || 0,
|
||||
category_name: replies[2],
|
||||
category_slug: replies[3],
|
||||
deleted: replies[4] || 0,
|
||||
pinned: replies[5] || 0,
|
||||
slug: replies[6]
|
||||
});
|
||||
|
||||
Topics.getTopicData = function(tid, callback) {
|
||||
RDB.hgetall('topic:' + tid, function(err, data) {
|
||||
if(err === null)
|
||||
callback(data);
|
||||
else
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
Topics.getTopicDataWithUsername = function(tid, callback) {
|
||||
Topics.getTopicData(tid, function(topic) {
|
||||
user.getUserField(topic.uid, 'username', function(username) {
|
||||
|
||||
topic.username = username;
|
||||
callback(topic);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Topics.getTopicPosts = function(tid, start, end, current_user, callback) {
|
||||
posts.getPostsByTid(tid, start, end, function(postData) {
|
||||
|
||||
function getFavouritesData(next) {
|
||||
var pids = [];
|
||||
for(var i=0; i<postData.length; ++i)
|
||||
pids.push(postData[i].pid);
|
||||
|
||||
favourites.getFavouritesByPostIDs(pids, current_user, function(fav_data) {
|
||||
next(null, fav_data);
|
||||
});
|
||||
}
|
||||
|
||||
function addUserInfoToPosts(next) {
|
||||
var done = 0;
|
||||
|
||||
for(var i=0, ii=postData.length; i<ii; ++i) {
|
||||
|
||||
posts.addUserInfoToPost(postData[i], function() {
|
||||
++done;
|
||||
if(done === postData.length)
|
||||
next(null, null);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getPrivileges(next) {
|
||||
threadTools.privileges(tid, current_user, function(privData) {
|
||||
next(null, privData);
|
||||
});
|
||||
}
|
||||
|
||||
async.parallel([getFavouritesData, addUserInfoToPosts, getPrivileges], function(err, results) {
|
||||
var fav_data = results[0],
|
||||
privileges = results[2];
|
||||
|
||||
for(var i=0; i<postData.length; ++i) {
|
||||
postData[i].fav_star_class = fav_data[postData[i].pid] ? 'icon-star' : 'icon-star-empty';
|
||||
postData[i]['display_moderator_tools'] = (postData[i].uid == current_user || privileges.editable) ? 'show' : 'none';
|
||||
}
|
||||
|
||||
callback(postData);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Topics.getTopicWithPosts = function(tid, current_user, callback) {
|
||||
|
||||
Topics.markAsRead(tid, current_user);
|
||||
|
||||
function getTopicData(next) {
|
||||
Topics.getTopicData(tid, function(topicData) {
|
||||
next(null, topicData);
|
||||
});
|
||||
}
|
||||
|
||||
function getTopicPosts(next) {
|
||||
posts.getPostsByTid(tid, current_user, 0, 9, function(postData) {
|
||||
next(null, postData);
|
||||
Topics.getTopicPosts(tid, 0, -1, current_user, function(topicPosts, privileges) {
|
||||
|
||||
next(null, topicPosts);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,100 +104,71 @@ marked.setOptions({
|
||||
threadTools.privileges(tid, current_user, function(privData) {
|
||||
next(null, privData);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async.parallel([getTopicData, getTopicPosts, getPrivileges], function(err, results) {
|
||||
var topicData = results[0],
|
||||
topicPosts = results[1],
|
||||
privileges = results[2];
|
||||
|
||||
postTools.constructPostObject(results[1], tid, current_user, privileges, function(postObj) {
|
||||
if (postObj.length) {
|
||||
var main_posts = postObj.splice(0, 1);
|
||||
var main_posts = topicPosts.splice(0, 1);
|
||||
|
||||
callback({
|
||||
'topic_name':topicData.topic_name,
|
||||
'category_name':topicData.category_name,
|
||||
'category_slug':topicData.category_slug,
|
||||
'locked': parseInt(topicData.locked) || 0,
|
||||
'deleted': parseInt(topicData.deleted) || 0,
|
||||
'pinned': parseInt(topicData.pinned) || 0,
|
||||
'slug': topicData.slug,
|
||||
'topic_id': tid,
|
||||
'expose_tools': privileges.editable ? 1 : 0,
|
||||
'posts': postObj,
|
||||
'main_posts': main_posts
|
||||
});
|
||||
} else {
|
||||
return callback(false);
|
||||
}
|
||||
callback({
|
||||
'topic_name':topicData.title,
|
||||
'category_name':topicData.category_name,
|
||||
'category_slug':topicData.category_slug,
|
||||
'locked': topicData.locked,
|
||||
'deleted': topicData.deleted,
|
||||
'pinned': topicData.pinned,
|
||||
'slug': topicData.slug,
|
||||
'topic_id': tid,
|
||||
'expose_tools': privileges.editable ? 1 : 0,
|
||||
'posts': topicPosts,
|
||||
'main_posts': main_posts
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Topics.get_topic = function(tid, uid, callback) {
|
||||
var topicData = {};
|
||||
|
||||
function get_topic_data(next) {
|
||||
RDB.mget([
|
||||
schema.topics(tid).title,
|
||||
schema.topics(tid).uid,
|
||||
schema.topics(tid).timestamp,
|
||||
schema.topics(tid).slug,
|
||||
schema.topics(tid).postcount,
|
||||
schema.topics(tid).locked,
|
||||
schema.topics(tid).pinned,
|
||||
schema.topics(tid).deleted
|
||||
], function(err, topic) {
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
topicData.title = topic[0];
|
||||
topicData.uid = topic[1];
|
||||
topicData.timestamp = topic[2];
|
||||
topicData.relativeTime = utils.relativeTime(topic[2]),
|
||||
topicData.slug = topic[3];
|
||||
topicData.post_count = topic[4];
|
||||
topicData.locked = topic[5];
|
||||
topicData.pinned = topic[6];
|
||||
topicData.deleted = topic[7];
|
||||
Topics.getTopicForCategoryView = function(tid, uid, callback) {
|
||||
|
||||
user.getUserField(topic[1], 'username', function(username) {
|
||||
topicData.username = username;
|
||||
|
||||
next();
|
||||
});
|
||||
function getTopicData(next) {
|
||||
Topics.getTopicDataWithUsername(tid, function(topic) {
|
||||
next(null, topic);
|
||||
});
|
||||
}
|
||||
|
||||
function get_read_status(next) {
|
||||
// posts.create calls this function - should be an option to skip this because its always true
|
||||
function getReadStatus(next) {
|
||||
if (uid && parseInt(uid) > 0) {
|
||||
RDB.sismember(schema.topics(tid).read_by_uid, uid, function(err, read) {
|
||||
topicData.badgeclass = read ? '' : 'badge-important';
|
||||
|
||||
next();
|
||||
next(null, read);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
next(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
function get_teaser(next) {
|
||||
Topics.get_teaser(tid, function(teaser) {
|
||||
topicData.teaser_text = teaser.text;
|
||||
topicData.teaser_username = teaser.username;
|
||||
|
||||
next();
|
||||
function getTeaser(next) {
|
||||
Topics.getTeaser(tid, function(teaser) {
|
||||
next(null, teaser);
|
||||
});
|
||||
}
|
||||
|
||||
async.parallel([get_topic_data, get_read_status, get_teaser], function(err) {
|
||||
async.parallel([getTopicData, getReadStatus, getTeaser], function(err, results) {
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
|
||||
var topicData = results[0],
|
||||
hasRead = results[1],
|
||||
teaser = results[2];
|
||||
|
||||
topicData.relativeTime = utils.relativeTime(topicData.timestamp);
|
||||
topicData.badgeclass = hasRead ? '' : 'badge-important';
|
||||
topicData.teaser_text = teaser.text;
|
||||
topicData.teaser_username = teaser.username;
|
||||
topicData.teaser_timestamp = utils.relativeTime(teaser.timestamp);
|
||||
|
||||
topicData.tid = tid;
|
||||
callback(topicData);
|
||||
});
|
||||
}
|
||||
@@ -175,7 +201,7 @@ marked.setOptions({
|
||||
tids.sort(function(a, b) { return b - a; });
|
||||
|
||||
async.each(tids, function(tid, next) {
|
||||
Topics.get_topic(tid, 0, function(topicData) {
|
||||
Topics.getTopicDataWithUsername(tid, function(topicData) {
|
||||
topics.push(topicData);
|
||||
next();
|
||||
});
|
||||
@@ -185,35 +211,11 @@ marked.setOptions({
|
||||
});
|
||||
}
|
||||
|
||||
Topics.get_cid_by_tid = function(tid, callback) {
|
||||
RDB.get(schema.topics(tid).cid, function(err, cid) {
|
||||
if (cid && parseInt(cid) > 0) {
|
||||
callback(cid);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Topics.getTitle = function(tid, callback) {
|
||||
RDB.get('tid:' + tid + ':title', function(err, title) {
|
||||
callback(title);
|
||||
});
|
||||
}
|
||||
|
||||
Topics.getSlug = function(tid, callback) {
|
||||
RDB.get('tid:' + tid + ':slug', function(err, slug) {
|
||||
callback(slug);
|
||||
});
|
||||
}
|
||||
|
||||
Topics.getTitleByPid = function(pid, callback) {
|
||||
RDB.get('pid:' + pid + ':tid', function(err, tid) {
|
||||
if (!err) {
|
||||
Topics.getTitle(tid, function(title) {
|
||||
callback(title);
|
||||
});
|
||||
} else callback('Could not grab title');
|
||||
posts.getPostField(pid, 'tid', function(tid) {
|
||||
Topics.getTopicField(tid, 'title', function(title) {
|
||||
callback(title);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -221,7 +223,7 @@ marked.setOptions({
|
||||
|
||||
RDB.sadd(schema.topics(tid).read_by_uid, uid);
|
||||
|
||||
Topics.get_cid_by_tid(tid, function(cid) {
|
||||
Topics.getTopicField(tid, 'cid', function(cid) {
|
||||
|
||||
categories.isTopicsRead(cid, uid, function(read) {
|
||||
if(read) {
|
||||
@@ -243,13 +245,13 @@ marked.setOptions({
|
||||
});
|
||||
}
|
||||
|
||||
Topics.get_teasers = function(tids, callback) {
|
||||
Topics.getTeasers = function(tids, callback) {
|
||||
var requests = [];
|
||||
if (Array.isArray(tids)) {
|
||||
for(x=0,numTids=tids.length;x<numTids;x++) {
|
||||
(function(tid) {
|
||||
requests.push(function(next) {
|
||||
Topics.get_teaser(tid, function(teaser_info) {
|
||||
Topics.getTeaser(tid, function(teaser_info) {
|
||||
next(null, teaser_info);
|
||||
});
|
||||
});
|
||||
@@ -263,42 +265,37 @@ marked.setOptions({
|
||||
}
|
||||
}
|
||||
|
||||
// start: probably should be moved into posts
|
||||
|
||||
Topics.get_latest_undeleted_pid = function(tid, callback) {
|
||||
RDB.lrange(schema.topics(tid).posts, 0, -1, function(err, pids) {
|
||||
var pidKeys = [],
|
||||
numPids = pids.length;
|
||||
|
||||
if (numPids === 0) return callback(null);
|
||||
posts.getPostsByTid(tid, 0, -1, function(posts) {
|
||||
|
||||
for(var x=0,numPids=pids.length;x<numPids;x++) {
|
||||
pidKeys.push('pid:' + pids[x] + ':deleted');
|
||||
}
|
||||
RDB.mget(pidKeys, function(err, posts) {
|
||||
var numPosts = posts.length;
|
||||
while(numPosts--) {
|
||||
if (posts[numPosts] !== '1') {
|
||||
callback(pids[numPosts]);
|
||||
break;
|
||||
}
|
||||
var numPosts = posts.length;
|
||||
if(!numPosts)
|
||||
callback(null);
|
||||
|
||||
while(numPosts--) {
|
||||
if(posts[numPosts].deleted !== '1') {
|
||||
callback(posts[numPosts].pid);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Topics.get_teaser = function(tid, callback) {
|
||||
Topics.getTeaser = function(tid, callback) {
|
||||
Topics.get_latest_undeleted_pid(tid, function(pid) {
|
||||
if (pid !== null) {
|
||||
RDB.mget([
|
||||
'pid:' + pid + ':content',
|
||||
'pid:' + pid + ':uid',
|
||||
'pid:' + pid + ':timestamp'
|
||||
], function(err, content) {
|
||||
user.getUserField(content[1], 'username', function(username) {
|
||||
var stripped = content[0],
|
||||
timestamp = content[2];
|
||||
if(content[0])
|
||||
stripped = utils.strip_tags(marked(content[0]));
|
||||
|
||||
posts.getPostFields(pid, ['content', 'uid', 'timestamp'], function(postData) {
|
||||
|
||||
user.getUserField(postData.uid, 'username', function(username) {
|
||||
var stripped = postData.content,
|
||||
timestamp = postData.timestamp;
|
||||
|
||||
if(postData.content)
|
||||
stripped = utils.strip_tags(marked(postData.content));
|
||||
|
||||
callback({
|
||||
"text": stripped,
|
||||
"username": username,
|
||||
@@ -309,10 +306,10 @@ marked.setOptions({
|
||||
}
|
||||
});
|
||||
}
|
||||
// end: probably should be moved into posts
|
||||
|
||||
Topics.post = function(socket, uid, title, content, category_id) {
|
||||
if (!category_id) throw new Error('Attempted to post without a category_id');
|
||||
if (!category_id)
|
||||
throw new Error('Attempted to post without a category_id');
|
||||
|
||||
if (uid === 0) {
|
||||
socket.emit('event:alert', {
|
||||
@@ -352,16 +349,24 @@ marked.setOptions({
|
||||
}
|
||||
|
||||
var slug = tid + '/' + utils.slugify(title);
|
||||
var timestamp = Date.now();
|
||||
|
||||
// Topic Info
|
||||
RDB.set(schema.topics(tid).title, title);
|
||||
RDB.set(schema.topics(tid).uid, uid);
|
||||
RDB.set(schema.topics(tid).slug, slug);
|
||||
RDB.set(schema.topics(tid).timestamp, Date.now());
|
||||
RDB.hmset('topic:' + tid, {
|
||||
'tid': tid,
|
||||
'uid': uid,
|
||||
'cid': category_id,
|
||||
'title': title,
|
||||
'slug': slug,
|
||||
'timestamp': timestamp,
|
||||
'lastposttime': 0,
|
||||
'postcount': 0,
|
||||
'locked': 0,
|
||||
'deleted': 0,
|
||||
'pinned': 0
|
||||
});
|
||||
|
||||
RDB.set('topic:slug:' + slug + ':tid', tid);
|
||||
RDB.set('topicslug:' + slug + ':tid', tid);
|
||||
|
||||
// Posts
|
||||
posts.create(uid, tid, content, function(pid) {
|
||||
if (pid > 0) {
|
||||
RDB.lpush(schema.topics(tid).posts, pid);
|
||||
@@ -370,7 +375,7 @@ marked.setOptions({
|
||||
threadTools.toggleFollow(tid, uid);
|
||||
|
||||
// Notify any users looking at the category that a new topic has arrived
|
||||
Topics.get_topic(tid, uid, function(topicData) {
|
||||
Topics.getTopicForCategoryView(tid, uid, function(topicData) {
|
||||
io.sockets.in('category_' + category_id).emit('event:new_topic', topicData);
|
||||
io.sockets.in('recent_posts').emit('event:new_topic', topicData);
|
||||
});
|
||||
@@ -379,8 +384,26 @@ marked.setOptions({
|
||||
}
|
||||
});
|
||||
|
||||
// User Details - move this out later
|
||||
RDB.lpush('uid:' + uid + ':topics', tid);
|
||||
user.addTopicIdToUser(uid, tid);
|
||||
|
||||
// let everyone know that there is an unread topic in this category
|
||||
RDB.del('cid:' + category_id + ':read_by_uid', function(err, data) {
|
||||
Topics.markAsRead(tid, uid);
|
||||
});
|
||||
|
||||
|
||||
// in future it may be possible to add topics to several categories, so leaving the door open here.
|
||||
RDB.sadd('categories:' + category_id + ':tid', tid);
|
||||
|
||||
categories.getCategories([category_id], function(data) {
|
||||
Topics.setTopicField(tid, 'category_name', data.categories[0].name);
|
||||
Topics.setTopicField(tid, 'category_slug', data.categories[0].slug);
|
||||
});
|
||||
|
||||
RDB.hincrby('category:' + category_id, 'topic_count', 1);
|
||||
RDB.incr('totaltopiccount');
|
||||
|
||||
feed.updateCategory(category_id);
|
||||
|
||||
socket.emit('event:alert', {
|
||||
title: 'Thank you for posting',
|
||||
@@ -388,31 +411,35 @@ marked.setOptions({
|
||||
type: 'notify',
|
||||
timeout: 2000
|
||||
});
|
||||
|
||||
// let everyone know that there is an unread topic in this category
|
||||
RDB.del('cid:' + category_id + ':read_by_uid', function(err, data) {
|
||||
Topics.markAsRead(tid, uid);
|
||||
});
|
||||
|
||||
|
||||
RDB.zadd(schema.topics().recent, Date.now(), tid);
|
||||
//RDB.zadd('topics:active', tid);
|
||||
|
||||
// in future it may be possible to add topics to several categories, so leaving the door open here.
|
||||
RDB.sadd('categories:' + category_id + ':tid', tid);
|
||||
RDB.set(schema.topics(tid).cid, category_id);
|
||||
categories.getCategories([category_id], function(data) {
|
||||
RDB.set(schema.topics(tid).category_name, data.categories[0].name);
|
||||
RDB.set(schema.topics(tid).category_slug, data.categories[0].slug);
|
||||
});
|
||||
|
||||
RDB.incr('cid:' + category_id + ':topiccount');
|
||||
RDB.incr('totaltopiccount');
|
||||
|
||||
feed.updateCategory(category_id);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Topics.getTopicField = function(tid, field, callback) {
|
||||
RDB.hget('topic:' + tid, field, function(err, data) {
|
||||
if(err === null)
|
||||
callback(data);
|
||||
else
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
Topics.setTopicField = function(tid, field, value) {
|
||||
RDB.hset('topic:' + tid, field, value);
|
||||
}
|
||||
|
||||
Topics.increasePostCount = function(tid) {
|
||||
RDB.hincrby('topic:' + tid, 'postcount', 1);
|
||||
}
|
||||
|
||||
Topics.isLocked = function(tid, callback) {
|
||||
Topics.getTopicField(tid, 'locked', function(locked) {
|
||||
callback(locked);
|
||||
});
|
||||
}
|
||||
|
||||
Topics.addToRecent = function(tid, timestamp) {
|
||||
RDB.zadd(schema.topics().recent, timestamp, tid);
|
||||
}
|
||||
|
||||
}(exports));
|
||||
54
src/user.js
54
src/user.js
@@ -11,7 +11,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
|
||||
(function(User) {
|
||||
User.getUserField = function(uid, field, callback) {
|
||||
RDB.hget('user:'+uid, field, function(err, data) {
|
||||
RDB.hget('user:' + uid, field, function(err, data) {
|
||||
if(err === null)
|
||||
callback(data);
|
||||
else
|
||||
@@ -20,7 +20,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
}
|
||||
|
||||
User.getUserFields = function(uid, fields, callback) {
|
||||
RDB.hmget('user:'+uid, fields, function(err, data) {
|
||||
RDB.hmget('user:' + uid, fields, function(err, data) {
|
||||
if(err === null) {
|
||||
var returnData = {};
|
||||
|
||||
@@ -55,13 +55,13 @@ var utils = require('./../public/src/utils.js'),
|
||||
loaded ++;
|
||||
if (loaded == uuids.length) callback(data);
|
||||
});
|
||||
}(uuids[i]))
|
||||
}(uuids[i]));
|
||||
}
|
||||
}
|
||||
|
||||
User.getUserData = function(uid, callback) {
|
||||
|
||||
RDB.hgetall('user:'+uid, function(err, data) {
|
||||
RDB.hgetall('user:' + uid, function(err, data) {
|
||||
if(err === null) {
|
||||
if(data) {
|
||||
if(data['password'])
|
||||
@@ -107,11 +107,11 @@ var utils = require('./../public/src/utils.js'),
|
||||
}
|
||||
|
||||
User.setUserField = function(uid, field, value) {
|
||||
RDB.hset('user:'+uid, field, value);
|
||||
RDB.hset('user:' + uid, field, value);
|
||||
}
|
||||
|
||||
User.incrementUserFieldBy = function(uid, field, value) {
|
||||
RDB.hincrby('user:'+uid, field, value);
|
||||
RDB.hincrby('user:' + uid, field, value);
|
||||
}
|
||||
|
||||
User.getUserList = function(callback) {
|
||||
@@ -129,7 +129,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
|
||||
User.getUserData(uid, function(userData) {
|
||||
data.push(userData);
|
||||
if(data.length == userkeys.length)
|
||||
if(data.length === userkeys.length)
|
||||
callback(data);
|
||||
});
|
||||
}
|
||||
@@ -221,13 +221,13 @@ var utils = require('./../public/src/utils.js'),
|
||||
RDB.lpush('userlist', username);
|
||||
io.sockets.emit('user.latest', {userslug: userslug, username: username});
|
||||
|
||||
callback(null, uid);
|
||||
|
||||
if (password) {
|
||||
User.hashPassword(password, function(hash) {
|
||||
RDB.hset('user:'+uid, 'password', hash);
|
||||
User.setUserField(uid, 'password', hash);
|
||||
});
|
||||
}
|
||||
|
||||
callback(null, uid);
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -276,6 +276,38 @@ var utils = require('./../public/src/utils.js'),
|
||||
});
|
||||
}
|
||||
|
||||
User.onNewPostMade = function(uid, tid, pid, timestamp) {
|
||||
User.addPostIdToUser(uid, pid)
|
||||
|
||||
User.incrementUserFieldBy(uid, 'postcount', 1);
|
||||
User.setUserField(uid, 'lastposttime', timestamp);
|
||||
|
||||
User.sendPostNotificationToFollowers(uid, tid, pid);
|
||||
}
|
||||
|
||||
User.addPostIdToUser = function(uid, pid) {
|
||||
RDB.lpush('uid:' + uid + ':posts', pid);
|
||||
}
|
||||
|
||||
User.addTopicIdToUser = function(uid, tid) {
|
||||
RDB.lpush('uid:' + uid + ':topics', tid);
|
||||
}
|
||||
|
||||
User.getPostIds = function(uid, start, end, callback) {
|
||||
RDB.lrange('uid:' + uid + ':posts', start, end, function(err, pids) {
|
||||
if(err === null) {
|
||||
if(pids && pids.length)
|
||||
callback(pids);
|
||||
else
|
||||
callback([]);
|
||||
}
|
||||
else {
|
||||
console.log(err);
|
||||
callback([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
User.sendConfirmationEmail = function (email) {
|
||||
if (global.config['email:host'] && global.config['email:port'] && global.config['email:from']) {
|
||||
var confirm_code = utils.generateUUID(),
|
||||
@@ -397,7 +429,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
User.getUserField(uid, 'username', function(username) {
|
||||
RDB.smembers('followers:'+uid, function(err, followers) {
|
||||
|
||||
topics.getSlug(tid, function(slug) {
|
||||
topics.getTopicField(tid, 'slug', function(slug) {
|
||||
|
||||
var message = username + ' made a new post';
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ var express = require('express'),
|
||||
|
||||
|
||||
var topic_url = tid + (req.params.slug ? '/' + req.params.slug : '');
|
||||
topics.getTopicById(tid, ((req.user) ? req.user.uid : 0), function(topic) {
|
||||
topics.getTopicWithPosts(tid, ((req.user) ? req.user.uid : 0), function(topic) {
|
||||
res.send(
|
||||
app.build_header(res) +
|
||||
'\n\t<noscript>\n' + templates['noscript/header'] + templates['noscript/topic'].parse(topic) + '\n\t</noscript>' +
|
||||
@@ -241,7 +241,7 @@ var express = require('express'),
|
||||
res.json(data);
|
||||
break;
|
||||
case 'topic' :
|
||||
topics.getTopicById(req.params.id, uid, function(data) {
|
||||
topics.getTopicWithPosts(req.params.id, uid, function(data) {
|
||||
res.json(data);
|
||||
});
|
||||
break;
|
||||
@@ -294,8 +294,30 @@ var express = require('express'),
|
||||
app.get('/api/:method/:id/:section?', api_method);
|
||||
app.get('/api/:method/:id*', api_method);
|
||||
|
||||
app.get('/tid/:tid', function(req, res) {
|
||||
topics.getTopicData(req.params.tid, function(data){
|
||||
if(data)
|
||||
res.send(data);
|
||||
else
|
||||
res.send("Topic doesn't exist!");
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/pid/:pid', function(req, res) {
|
||||
posts.getPostData(req.params.pid, function(data){
|
||||
if(data)
|
||||
res.send(data);
|
||||
else
|
||||
res.send("Post doesn't exist!");
|
||||
});
|
||||
});
|
||||
|
||||
app.all('/test', function(req, res) {
|
||||
res.send();
|
||||
|
||||
categories.getCategoryById(1,1, function(data) {
|
||||
res.send(data);
|
||||
},1);
|
||||
|
||||
});
|
||||
|
||||
//START TODO: MOVE TO GRAPH.JS
|
||||
|
||||
@@ -247,7 +247,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
});
|
||||
|
||||
socket.on('api:posts.getRawPost', function(data) {
|
||||
posts.getRawContent(data.pid, function(raw) {
|
||||
posts.getPostField(data.pid, 'content', function(raw) {
|
||||
socket.emit('api:posts.getRawPost', { post: raw });
|
||||
});
|
||||
});
|
||||
@@ -332,10 +332,16 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
socket.on('api:composer.push', function(data) {
|
||||
if (uid > 0) {
|
||||
if (parseInt(data.tid) > 0) {
|
||||
topics.get_topic(data.tid, uid, function(topicData) {
|
||||
topicData.tid = data.tid;
|
||||
if (data.body) topicData.body = data.body;
|
||||
socket.emit('api:composer.push', topicData);
|
||||
topics.getTopicData(data.tid, function(topicData) {
|
||||
|
||||
if (data.body)
|
||||
topicData.body = data.body;
|
||||
|
||||
socket.emit('api:composer.push', {
|
||||
tid: data.tid,
|
||||
title: topicData.title,
|
||||
body: topicData.body
|
||||
});
|
||||
});
|
||||
} else if (parseInt(data.cid) > 0) {
|
||||
user.getUserField(uid, 'username', function(username) {
|
||||
@@ -349,7 +355,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
} else if (parseInt(data.pid) > 0) {
|
||||
async.parallel([
|
||||
function(next) {
|
||||
posts.getRawContent(data.pid, function(raw) {
|
||||
posts.getPostField(data.pid, 'content', function(raw) {
|
||||
next(null, raw);
|
||||
});
|
||||
},
|
||||
@@ -374,7 +380,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
});
|
||||
|
||||
socket.on('api:composer.editCheck', function(pid) {
|
||||
posts.get_tid_by_pid(pid, function(tid) {
|
||||
posts.getPostField(pid, 'tid', function(tid) {
|
||||
postTools.isMain(pid, tid, function(isMain) {
|
||||
socket.emit('api:composer.editCheck', {
|
||||
titleEditable: isMain
|
||||
@@ -413,14 +419,10 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
var start = data.after,
|
||||
end = start + 10;
|
||||
|
||||
posts.getPostsByTid(data.tid, uid, start, end, function(posts){
|
||||
if (!posts.error) {
|
||||
postTools.constructPostObject(posts, data.tid, uid, null, function(postObj) {
|
||||
io.sockets.in('topic_' + data.tid).emit('event:new_post', {
|
||||
posts: postObj
|
||||
});
|
||||
});
|
||||
}
|
||||
topics.getTopicPosts(data.tid, start, end, uid, function(posts) {
|
||||
io.sockets.in('topic_' + data.tid).emit('event:new_post', {
|
||||
posts: posts
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user