mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-03-05 12:01:17 +01:00
Merge branch 'master' into optimize-22-09-2013
Conflicts: package.json
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,6 +6,7 @@ npm-debug.log
|
||||
node_modules/
|
||||
sftp-config.json
|
||||
config.json
|
||||
public/src/nodebb.min.js
|
||||
public/config.json
|
||||
public/css/*.css
|
||||
public/themes/*
|
||||
@@ -15,4 +16,4 @@ public/themes/*
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
plugins/*
|
||||
.project
|
||||
.project
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
Please support NodeBB development! Check out our IndieGoGo campaign and like, share, and follow us :)
|
||||
[NodeBB Homepage](http://www.nodebb.org/ "NodeBB") # [Follow on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter") # [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")
|
||||
|
||||
# NodeBB
|
||||
**NodeBB** is a robust Node.js driven forum built on a redis database. It is powered by web sockets, and is compatible down to IE8.
|
||||
|
||||
* [NodeBB Homepage](http://www.nodebb.org/ "NodeBB")
|
||||
* [Follow on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter")
|
||||
* [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")
|
||||
* [Join us on IRC](https://kiwiirc.com/client/irc.freenode.net/nodebb) - #nodebb on Freenode
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
58
app.js
58
app.js
@@ -24,8 +24,11 @@
|
||||
nconf.argv().env();
|
||||
|
||||
var fs = require('fs'),
|
||||
async = require('async'),
|
||||
winston = require('winston'),
|
||||
pkg = require('./package.json'),
|
||||
path = require('path'),
|
||||
uglifyjs = require('uglify-js'),
|
||||
meta;
|
||||
|
||||
// Runtime environment
|
||||
@@ -69,6 +72,61 @@
|
||||
winston.info('Base Configuration OK.');
|
||||
}
|
||||
|
||||
// Minify JS
|
||||
var toMinify = [
|
||||
'/vendor/jquery/js/jquery.js',
|
||||
'/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js',
|
||||
'/vendor/jquery/js/jquery.timeago.js',
|
||||
'/vendor/bootstrap/js/bootstrap.min.js',
|
||||
'/src/app.js',
|
||||
'/vendor/requirejs/require.js',
|
||||
'/vendor/bootbox/bootbox.min.js',
|
||||
'/src/templates.js',
|
||||
'/src/ajaxify.js',
|
||||
'/src/jquery.form.js',
|
||||
'/src/utils.js'
|
||||
],
|
||||
minified, mtime;
|
||||
toMinify = toMinify.map(function (jsPath) {
|
||||
return path.join(__dirname + '/public', jsPath);
|
||||
});
|
||||
async.parallel({
|
||||
mtime: function (next) {
|
||||
async.map(toMinify, fs.stat, function (err, stats) {
|
||||
async.reduce(stats, 0, function (memo, item, callback) {
|
||||
mtime = +new Date(item.mtime);
|
||||
callback(null, mtime > memo ? mtime : memo);
|
||||
}, next);
|
||||
});
|
||||
},
|
||||
minFile: function (next) {
|
||||
var minFile = path.join(__dirname, 'public/src/nodebb.min.js');
|
||||
if (!fs.existsSync(minFile)) {
|
||||
winston.warn('No minified client-side library found');
|
||||
return next(null, 0);
|
||||
}
|
||||
|
||||
fs.stat(minFile, function (err, stat) {
|
||||
next(err, +new Date(stat.mtime));
|
||||
});
|
||||
}
|
||||
}, function (err, results) {
|
||||
if (results.minFile > results.mtime) {
|
||||
winston.info('No changes to client-side libraries -- skipping minification');
|
||||
} else {
|
||||
winston.info('Minifying client-side libraries');
|
||||
minified = uglifyjs.minify(toMinify);
|
||||
fs.writeFile(path.join(__dirname, '/public/src', 'nodebb.min.js'), minified.code, function (err) {
|
||||
if (!err) {
|
||||
winston.info('Minified client-side libraries');
|
||||
} else {
|
||||
winston.error('Problem minifying client-side libraries, exiting.');
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
meta.configs.init(function () {
|
||||
// Initial setup for Redis & Reds
|
||||
var reds = require('reds'),
|
||||
|
||||
129
package.json
129
package.json
@@ -1,69 +1,64 @@
|
||||
{
|
||||
"name": "nodebb",
|
||||
"license": "GPLv3 or later",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "0.0.6",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/designcreateplay/NodeBB/"
|
||||
},
|
||||
"main": "app.js",
|
||||
"dependencies": {
|
||||
"socket.io": "~0.9.16",
|
||||
"redis": "0.8.3",
|
||||
"express": "3.2.0",
|
||||
"express-namespace": "0.1.1",
|
||||
"emailjs": "0.3.4",
|
||||
"cookie": "0.0.6",
|
||||
"connect-redis": "1.4.5",
|
||||
"passport": "0.1.17",
|
||||
"passport-local": "0.1.6",
|
||||
"passport-twitter": "0.1.5",
|
||||
"passport-google-oauth": "0.1.5",
|
||||
"passport-facebook": "0.1.5",
|
||||
"less-middleware": "0.1.12",
|
||||
"marked": "0.2.8",
|
||||
"bcrypt": "0.7.5",
|
||||
"async": "0.2.8",
|
||||
"node-imagemagick": "0.1.8",
|
||||
"gravatar": "1.0.6",
|
||||
"nconf": "~0.6.7",
|
||||
"sitemap": "~0.6.0",
|
||||
"request": "~2.25.0",
|
||||
"reds": "~0.2.4",
|
||||
"winston": "~0.7.2",
|
||||
"nodebb-plugin-mentions": "~0.1.0",
|
||||
"nodebb-plugin-markdown": "~0.1.0",
|
||||
"rss": "~0.2.0",
|
||||
"prompt": "~0.2.11"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Andrew Rodrigues",
|
||||
"email": "andrew@designcreateplay.com"
|
||||
},
|
||||
{
|
||||
"name": "Julian Lam",
|
||||
"email": "julian@designcreateplay.com"
|
||||
},
|
||||
{
|
||||
"name": "Barış Soner Uşaklı",
|
||||
"email": "baris@designcreateplay.com"
|
||||
},
|
||||
{
|
||||
"name": "Damian Bushong",
|
||||
"url": "https://github.com/damianb"
|
||||
},
|
||||
{
|
||||
"name": "Matt Smith",
|
||||
"url": "https://github.com/soimafreak"
|
||||
}
|
||||
]
|
||||
"name": "nodebb",
|
||||
"license": "GPLv3 or later",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "0.0.6",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/designcreateplay/NodeBB/"
|
||||
},
|
||||
"main": "app.js",
|
||||
"dependencies": {
|
||||
"socket.io": "~0.9.16",
|
||||
"redis": "0.8.3",
|
||||
"express": "3.2.0",
|
||||
"express-namespace": "0.1.1",
|
||||
"emailjs": "0.3.4",
|
||||
"cookie": "0.0.6",
|
||||
"connect-redis": "1.4.5",
|
||||
"passport": "0.1.17",
|
||||
"passport-local": "0.1.6",
|
||||
"passport-twitter": "0.1.5",
|
||||
"passport-google-oauth": "0.1.5",
|
||||
"passport-facebook": "0.1.5",
|
||||
"less-middleware": "0.1.12",
|
||||
"marked": "0.2.8",
|
||||
"bcrypt": "0.7.5",
|
||||
"async": "0.2.8",
|
||||
"node-imagemagick": "0.1.8",
|
||||
"gravatar": "1.0.6",
|
||||
"nconf": "~0.6.7",
|
||||
"sitemap": "~0.6.0",
|
||||
"request": "~2.25.0",
|
||||
"reds": "~0.2.4",
|
||||
"winston": "~0.7.2",
|
||||
"nodebb-plugin-mentions": "~0.1.0",
|
||||
"nodebb-plugin-markdown": "~0.1.0",
|
||||
"rss": "~0.2.0",
|
||||
"prompt": "~0.2.11",
|
||||
"uglify-js": "~2.4.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
},
|
||||
"contributors": [{
|
||||
"name": "Andrew Rodrigues",
|
||||
"email": "andrew@designcreateplay.com"
|
||||
}, {
|
||||
"name": "Julian Lam",
|
||||
"email": "julian@designcreateplay.com"
|
||||
}, {
|
||||
"name": "Barış Soner Uşaklı",
|
||||
"email": "baris@designcreateplay.com"
|
||||
}, {
|
||||
"name": "Damian Bushong",
|
||||
"url": "https://github.com/damianb"
|
||||
}, {
|
||||
"name": "Matt Smith",
|
||||
"url": "https://github.com/soimafreak"
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ var socket,
|
||||
if (active) {
|
||||
jQuery('#main-nav li a').each(function() {
|
||||
var href = this.getAttribute('href');
|
||||
if (active == "sort-posts" || active == "sort-reputation" || active == "search" || active== "latest")
|
||||
if (active == "sort-posts" || active == "sort-reputation" || active == "search" || active == "latest" || active == "online")
|
||||
active = 'users';
|
||||
if (href && href.match(active)) {
|
||||
jQuery(this.parentNode).addClass('active');
|
||||
@@ -286,6 +286,7 @@ var socket,
|
||||
|
||||
$('span.timeago').timeago();
|
||||
|
||||
|
||||
setTimeout(function() {
|
||||
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
|
||||
}, 100);
|
||||
@@ -432,12 +433,11 @@ var socket,
|
||||
ajaxify.go("search/" + input.val(), null, "search");
|
||||
input.val('');
|
||||
return false;
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
|
||||
|
||||
loadConfig();
|
||||
|
||||
|
||||
}());
|
||||
@@ -26,7 +26,6 @@
|
||||
fields: ['username', 'picture', 'userslug']
|
||||
});
|
||||
socket.on('api:updateHeader', function(data) {
|
||||
|
||||
jQuery('#search-button').on('click', function() {
|
||||
jQuery('#search-fields').removeClass('hide').show();
|
||||
jQuery(this).hide();
|
||||
@@ -67,7 +66,16 @@
|
||||
</li>');
|
||||
rightMenu.append(userli);
|
||||
|
||||
var logoutli = $('<li><a href="' + RELATIVE_PATH + '/logout">Log out</a></li>');
|
||||
var logoutli = $('<li><a href="#">Log out</a></li>');
|
||||
logoutli.on('click', function() {
|
||||
var csrf_token = $('#csrf_token').val();
|
||||
|
||||
$.post(RELATIVE_PATH + '/logout', {
|
||||
_csrf: csrf_token
|
||||
}, function() {
|
||||
window.location = RELATIVE_PATH + '/';
|
||||
});
|
||||
});
|
||||
rightMenu.append(logoutli);
|
||||
}
|
||||
} else {
|
||||
@@ -86,6 +94,11 @@
|
||||
right_menu.appendChild(registerEl);
|
||||
right_menu.appendChild(loginEl);
|
||||
}
|
||||
|
||||
$('#main-nav a,#right-menu a').off('click').on('click', function() {
|
||||
if($('.navbar .navbar-collapse').hasClass('in'))
|
||||
$('.navbar-header button').click();
|
||||
});
|
||||
});
|
||||
|
||||
// Notifications dropdown
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
|
||||
|
||||
$('#search-form input').val(searchQuery);
|
||||
|
||||
$('#mobile-search-form').off('submit').on('submit', function() {
|
||||
var input = $(this).find('input');
|
||||
ajaxify.go("search/" + input.val(), null, "search");
|
||||
input.val('');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -223,6 +223,15 @@
|
||||
}
|
||||
});
|
||||
|
||||
var bookmark = localStorage.getItem('topic:' + tid + ':bookmark');
|
||||
|
||||
if(bookmark) {
|
||||
// need to find out why it doesnt work without setTimeout -baris
|
||||
setTimeout(function() {
|
||||
app.scrollToPost(parseInt(bookmark, 10));
|
||||
}, 300);
|
||||
}
|
||||
|
||||
$('#post-container').on('click', '.deleted', function(ev) {
|
||||
$(this).toggleClass('deleted-expanded');
|
||||
});
|
||||
@@ -659,6 +668,7 @@
|
||||
var scrollBottom = scrollTop + windowHeight;
|
||||
|
||||
if (scrollTop < 50 && postcount > 1) {
|
||||
localStorage.removeItem("topic:" + tid + ":bookmark");
|
||||
postAuthorImage.src = (jQuery('.main-post .avatar img').attr('src'));
|
||||
mobileAuthorOverlay.innerHTML = 'Posted by ' + jQuery('.main-post').attr('data-username') + ', ' + jQuery('.main-post').find('.relativeTimeAgo').html();
|
||||
pagination.innerHTML = '0 out of ' + postcount;
|
||||
@@ -666,7 +676,7 @@
|
||||
}
|
||||
|
||||
|
||||
var count = 0;
|
||||
var count = 0, smallestNonNegative = 0;
|
||||
|
||||
jQuery('.sub-posts').each(function() {
|
||||
count++;
|
||||
@@ -682,6 +692,11 @@
|
||||
|
||||
|
||||
if (inView) {
|
||||
if(elTop - scrollTop > smallestNonNegative) {
|
||||
localStorage.setItem("topic:" + tid + ":bookmark", el.attr('data-pid'));
|
||||
smallestNonNegative = Number.MAX_VALUE;
|
||||
}
|
||||
|
||||
pagination.innerHTML = this.postnumber + ' out of ' + postcount;
|
||||
postAuthorImage.src = (jQuery(this).find('.profile-image-block img').attr('src'));
|
||||
mobileAuthorOverlay.innerHTML = 'Posted by ' + jQuery(this).attr('data-username') + ', ' + jQuery(this).find('.relativeTimeAgo').html();
|
||||
|
||||
@@ -74,7 +74,12 @@
|
||||
|
||||
});
|
||||
|
||||
|
||||
socket.on('api:user.isOnline', function(data) {
|
||||
if(active == 'online' && !loadingMoreUsers) {
|
||||
$('#users-container').empty();
|
||||
startLoading('users:online', 0);
|
||||
}
|
||||
});
|
||||
|
||||
function onUsersLoaded(users) {
|
||||
var html = templates.prepare(templates['users'].blocks['users']).parse({
|
||||
@@ -91,24 +96,32 @@
|
||||
set = 'users:postcount';
|
||||
} else if (active === 'sort-reputation') {
|
||||
set = 'users:reputation';
|
||||
} else if (active === 'online') {
|
||||
set = 'users:online';
|
||||
}
|
||||
|
||||
if (set) {
|
||||
loadingMoreUsers = true;
|
||||
socket.emit('api:users.loadMore', {
|
||||
set: set,
|
||||
after: $('#users-container').children().length
|
||||
}, function(data) {
|
||||
if (data.users.length) {
|
||||
onUsersLoaded(data.users);
|
||||
} else {
|
||||
$('#load-more-users-btn').addClass('disabled');
|
||||
}
|
||||
loadingMoreUsers = false;
|
||||
});
|
||||
startLoading(set, $('#users-container').children().length);
|
||||
}
|
||||
}
|
||||
|
||||
function startLoading(set, after) {
|
||||
loadingMoreUsers = true;
|
||||
socket.emit('api:users.loadMore', {
|
||||
set: set,
|
||||
after: after
|
||||
}, function(data) {
|
||||
if (data.users.length) {
|
||||
onUsersLoaded(data.users);
|
||||
$('#load-more-users-btn').removeClass('disabled');
|
||||
} else {
|
||||
$('#load-more-users-btn').addClass('disabled');
|
||||
}
|
||||
loadingMoreUsers = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$('#load-more-users-btn').on('click', loadMoreUsers);
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
|
||||
@@ -8,27 +8,16 @@
|
||||
<script>
|
||||
var RELATIVE_PATH = "{relative_path}";
|
||||
</script>
|
||||
<script src="http://code.jquery.com/jquery.js"></script>
|
||||
<script src="{relative_path}/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js"></script>
|
||||
<script src="{relative_path}/vendor/jquery/js/jquery.timeago.js"></script>
|
||||
<script src="{relative_path}/vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="{relative_path}/socket.io/socket.io.js"></script>
|
||||
<script src="{relative_path}/src/app.js"></script>
|
||||
<script src="{relative_path}/vendor/requirejs/require.js"></script>
|
||||
<script src="{relative_path}/vendor/bootbox/bootbox.min.js"></script>
|
||||
<script src="{relative_path}/src/nodebb.min.js"></script>
|
||||
<script>
|
||||
require.config({
|
||||
baseUrl: "{relative_path}/src/modules",
|
||||
waitSeconds: 3
|
||||
});
|
||||
</script>
|
||||
<script src="{relative_path}/src/templates.js"></script>
|
||||
<script src="{relative_path}/src/ajaxify.js"></script>
|
||||
<script src="{relative_path}/src/jquery.form.js"></script>
|
||||
<script src="{relative_path}/src/utils.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/nodebb.css" />
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -54,9 +43,9 @@
|
||||
<li>
|
||||
<a href="/users">Users</a>
|
||||
</li>
|
||||
<!--Enable when /search form is completed <li class="visible-xs">
|
||||
<li class="visible-xs">
|
||||
<a href="/search">Search</a>
|
||||
</li>-->
|
||||
</li>
|
||||
<li>
|
||||
<a href="/"></a>
|
||||
</li>
|
||||
|
||||
@@ -3,8 +3,18 @@
|
||||
<li class="active">Search</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<form id="mobile-search-form" class="navbar-form navbar-right visible-xs" role="search" method="GET" action="">
|
||||
<div class="" id="search-fields">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Search" name="query" value="">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default hide">Search</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="category search">
|
||||
<div class="">
|
||||
<div class="{show_results}">
|
||||
<ul id="topics-container" data-search-query="{search_query}">
|
||||
<h3>Topics</h3>
|
||||
<div class="alert alert-info {show_no_topics}">No topics found!</div>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<li class=''><a href='/users/latest'>Latest Users</a></li>
|
||||
<li class=''><a href='/users/sort-posts'>Top Posters</a></li>
|
||||
<li class=''><a href='/users/sort-reputation'>Most Reputation</a></li>
|
||||
<li class=''><a href='/users/online'>Online</a></li>
|
||||
<li class=''><a href='/users/search'>Search</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -105,6 +105,8 @@
|
||||
width: 70%;
|
||||
margin-left: 10px;
|
||||
overflow: hidden;
|
||||
max-height: 33px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9921
public/vendor/jquery/js/jquery.js
vendored
Normal file
9921
public/vendor/jquery/js/jquery.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -137,7 +137,7 @@ var fs = require('fs'),
|
||||
hookList = this.loadedHooks[hook];
|
||||
|
||||
if (hookList && Array.isArray(hookList)) {
|
||||
if (global.env === 'development') winston.info('[plugins] Firing hook: \'' + hook + '\'');
|
||||
//if (global.env === 'development') winston.info('[plugins] Firing hook: \'' + hook + '\'');
|
||||
var hookType = hook.split(':')[0];
|
||||
switch (hookType) {
|
||||
case 'filter':
|
||||
|
||||
@@ -70,7 +70,7 @@ var RDB = require('./redis.js'),
|
||||
Posts.getPostFields(pid, ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'], function(postData) {
|
||||
if (postData.deleted === '1') return callback(null);
|
||||
else {
|
||||
postData.relativeTime = new Date(parseInt(postData.timestamp, 10)).toISOString();
|
||||
postData.relativeTime = new Date(parseInt(postData.timestamp || 0, 10)).toISOString();
|
||||
next(null, postData);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -186,6 +186,7 @@ var user = require('./../user.js'),
|
||||
return res.json({
|
||||
show_no_topics: 'hide',
|
||||
show_no_posts: 'hide',
|
||||
show_results: 'hide',
|
||||
search_query: '',
|
||||
posts: [],
|
||||
topics: []
|
||||
@@ -235,6 +236,7 @@ var user = require('./../user.js'),
|
||||
return res.json({
|
||||
show_no_topics: results[1].length ? 'hide' : '',
|
||||
show_no_posts: results[0].length ? 'hide' : '',
|
||||
show_results: '',
|
||||
search_query: req.params.term,
|
||||
posts: results[0],
|
||||
topics: results[1]
|
||||
|
||||
@@ -90,19 +90,14 @@
|
||||
}
|
||||
|
||||
Auth.create_routes = function(app) {
|
||||
|
||||
app.get('/logout', function(req, res) {
|
||||
app.post('/logout', function(req, res) {
|
||||
if (req.user && req.user.uid > 0) {
|
||||
winston.info('[Auth] Session ' + req.sessionID + ' logout (uid: ' + req.user.uid + ')');
|
||||
|
||||
req.logout();
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res
|
||||
}, function(err, header) {
|
||||
res.send(header + templates['logout'] + templates['footer']);
|
||||
});
|
||||
} else res.redirect('/');
|
||||
}
|
||||
|
||||
res.send(200)
|
||||
});
|
||||
|
||||
if (login_strategies.indexOf('twitter') !== -1) {
|
||||
|
||||
@@ -25,7 +25,6 @@ var user = require('./../user.js'),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
app.get('/users', function(req, res) {
|
||||
@@ -64,6 +63,15 @@ var user = require('./../user.js'),
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/users/online', function(req, res) {
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res
|
||||
}, function(err, header) {
|
||||
res.send(header + app.create_route("users/online", "users") + templates['footer']);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/users/search', function(req, res) {
|
||||
app.build_header({
|
||||
req: req,
|
||||
@@ -136,7 +144,7 @@ var user = require('./../user.js'),
|
||||
app.post('/user/uploadpicture', function(req, res) {
|
||||
if (!req.user)
|
||||
return res.redirect('/403');
|
||||
|
||||
|
||||
var uploadSize = meta.config.maximumProfileImageSize || 256;
|
||||
|
||||
if (req.files.userPhoto.size > uploadSize * 1024) {
|
||||
@@ -342,7 +350,7 @@ var user = require('./../user.js'),
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
user.getUserFields(uid, ['username', 'userslug', 'showemail'], function(err, userData) {
|
||||
if (err)
|
||||
return next(err);
|
||||
@@ -436,6 +444,7 @@ var user = require('./../user.js'),
|
||||
app.get('/api/users/sort-posts', getUsersSortedByPosts);
|
||||
app.get('/api/users/sort-reputation', getUsersSortedByReputation);
|
||||
app.get('/api/users/latest', getUsersSortedByJoinDate);
|
||||
app.get('/api/users/online', getOnlineUsers);
|
||||
app.get('/api/users/search', getUsersForSearch);
|
||||
|
||||
|
||||
@@ -469,6 +478,16 @@ var user = require('./../user.js'),
|
||||
});
|
||||
}
|
||||
|
||||
function getOnlineUsers(req, res) {
|
||||
user.getUsers('users:online', 0, 49, function(err, data) {
|
||||
res.json({
|
||||
search_display: 'none',
|
||||
loadmore_display: 'block',
|
||||
users: data
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getUsersForSearch(req, res) {
|
||||
res.json({
|
||||
search_display: 'block',
|
||||
|
||||
143
src/webserver.js
143
src/webserver.js
@@ -24,14 +24,14 @@ var express = require('express'),
|
||||
plugins = require('./plugins'),
|
||||
nconf = require('nconf');
|
||||
|
||||
(function(app) {
|
||||
(function (app) {
|
||||
var templates = null;
|
||||
|
||||
/**
|
||||
* `options` object requires: req, res
|
||||
* accepts: metaTags
|
||||
*/
|
||||
app.build_header = function(options, callback) {
|
||||
app.build_header = function (options, callback) {
|
||||
var defaultMetaTags = [{
|
||||
name: 'viewport',
|
||||
content: 'width=device-width, initial-scale=1.0'
|
||||
@@ -48,33 +48,28 @@ var express = require('express'),
|
||||
metaString = utils.buildMetaTags(defaultMetaTags.concat(options.metaTags || [])),
|
||||
templateValues = {
|
||||
cssSrc: meta.config['theme:src'] || nconf.get('relative_path') + '/vendor/bootstrap/css/bootstrap.min.css',
|
||||
title: meta.config['title'] || 'NodeBB',
|
||||
browserTitle: meta.config['title'] || 'NodeBB',
|
||||
title: meta.config.title || 'NodeBB',
|
||||
browserTitle: meta.config.title || 'NodeBB',
|
||||
csrf: options.res.locals.csrf_token,
|
||||
relative_path: nconf.get('relative_path'),
|
||||
meta_tags: metaString
|
||||
};
|
||||
|
||||
// meta.build_title(options.title, (options.req.user ? options.req.user.uid : 0), function(err, title) {
|
||||
// if (!err) templateValues.browserTitle = title;
|
||||
|
||||
// callback(null, templates['header'].parse(templateValues));
|
||||
// });
|
||||
|
||||
callback(null, templates['header'].parse(templateValues));
|
||||
callback(null, templates.header.parse(templateValues));
|
||||
};
|
||||
|
||||
// Middlewares
|
||||
app.use(express.compress());
|
||||
app.use(express.favicon(path.join(__dirname, '../', 'public', 'favicon.ico')));
|
||||
app.use(require('less-middleware')({
|
||||
src: path.join(__dirname, '../', 'public'),
|
||||
prefix: nconf.get('relative_path')
|
||||
prefix: nconf.get('relative_path'),
|
||||
yuicompress: true
|
||||
}));
|
||||
app.use(nconf.get('relative_path'), express.static(path.join(__dirname, '../', 'public')));
|
||||
app.use(express.bodyParser()); // Puts POST vars in request.body
|
||||
|
||||
app.use(express.cookieParser()); // If you want to parse cookies (res.cookies)
|
||||
app.use(express.compress());
|
||||
app.use(express.session({
|
||||
store: new RedisStore({
|
||||
client: RDB,
|
||||
@@ -87,16 +82,16 @@ var express = require('express'),
|
||||
}
|
||||
}));
|
||||
app.use(express.csrf());
|
||||
app.use(function(req, res, next) {
|
||||
app.use(function (req, res, next) {
|
||||
res.locals.csrf_token = req.session._csrf;
|
||||
next();
|
||||
});
|
||||
|
||||
// Static Directories for NodeBB Plugins
|
||||
app.configure(function() {
|
||||
app.configure(function () {
|
||||
var tailMiddlewares = [];
|
||||
|
||||
plugins.ready(function() {
|
||||
plugins.ready(function () {
|
||||
// Remove some middlewares until the router is gone
|
||||
// This is not recommended behaviour: http://stackoverflow.com/a/13691542/122353
|
||||
// Also: https://www.exratione.com/2013/03/nodejs-abusing-express-3-to-enable-late-addition-of-middleware/
|
||||
@@ -115,14 +110,14 @@ var express = require('express'),
|
||||
});
|
||||
});
|
||||
|
||||
module.exports.init = function() {
|
||||
module.exports.init = function () {
|
||||
templates = global.templates;
|
||||
server.listen(nconf.get('PORT') || nconf.get('port'));
|
||||
}
|
||||
|
||||
auth.initialize(app);
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
app.use(function (req, res, next) {
|
||||
|
||||
nconf.set('https', req.secure);
|
||||
|
||||
@@ -131,7 +126,7 @@ var express = require('express'),
|
||||
|
||||
app.use(app.router);
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
app.use(function (req, res, next) {
|
||||
res.status(404);
|
||||
|
||||
// respond with html page
|
||||
@@ -153,7 +148,7 @@ var express = require('express'),
|
||||
res.type('txt').send('Not found');
|
||||
});
|
||||
|
||||
app.use(function(err, req, res, next) {
|
||||
app.use(function (err, req, res, next) {
|
||||
|
||||
// we may use properties of the error object
|
||||
// here and next(err) appropriately, or if
|
||||
@@ -168,12 +163,12 @@ var express = require('express'),
|
||||
});
|
||||
|
||||
|
||||
app.create_route = function(url, tpl) { // to remove
|
||||
app.create_route = function (url, tpl) { // to remove
|
||||
return '<script>templates.ready(function(){ajaxify.go("' + url + '", null, "' + tpl + '");});</script>';
|
||||
};
|
||||
|
||||
|
||||
app.namespace(nconf.get('relative_path'), function() {
|
||||
app.namespace(nconf.get('relative_path'), function () {
|
||||
|
||||
auth.create_routes(app);
|
||||
admin.create_routes(app);
|
||||
@@ -183,16 +178,16 @@ var express = require('express'),
|
||||
|
||||
|
||||
// Basic Routes (entirely client-side parsed, goal is to move the rest of the crap in this file into this one section)
|
||||
(function() {
|
||||
(function () {
|
||||
var routes = ['login', 'register', 'account', 'recent', 'unread', 'popular', 'active', '403', '404'];
|
||||
|
||||
for (var i = 0, ii = routes.length; i < ii; i++) {
|
||||
(function(route) {
|
||||
(function (route) {
|
||||
|
||||
app.get('/' + route, function(req, res) {
|
||||
app.get('/' + route, function (req, res) {
|
||||
if ((route === 'login' || route === 'register') && (req.user && req.user.uid > 0)) {
|
||||
|
||||
user.getUserField(req.user.uid, 'userslug', function(err, userslug) {
|
||||
user.getUserField(req.user.uid, 'userslug', function (err, userslug) {
|
||||
res.redirect('/user/' + userslug);
|
||||
});
|
||||
return;
|
||||
@@ -201,7 +196,7 @@ var express = require('express'),
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res
|
||||
}, function(err, header) {
|
||||
}, function (err, header) {
|
||||
res.send(header + app.create_route(route) + templates['footer']);
|
||||
});
|
||||
});
|
||||
@@ -210,9 +205,9 @@ var express = require('express'),
|
||||
}());
|
||||
|
||||
|
||||
app.get('/', function(req, res) {
|
||||
app.get('/', function (req, res) {
|
||||
async.parallel({
|
||||
"header": function(next) {
|
||||
"header": function (next) {
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res,
|
||||
@@ -231,17 +226,17 @@ var express = require('express'),
|
||||
}]
|
||||
}, next);
|
||||
},
|
||||
"categories": function(next) {
|
||||
categories.getAllCategories(function(returnData) {
|
||||
returnData.categories = returnData.categories.filter(function(category) {
|
||||
"categories": function (next) {
|
||||
categories.getAllCategories(function (returnData) {
|
||||
returnData.categories = returnData.categories.filter(function (category) {
|
||||
if (category.disabled !== '1') return true;
|
||||
else return false;
|
||||
else return false;
|
||||
});
|
||||
|
||||
next(null, returnData);
|
||||
}, 0);
|
||||
}
|
||||
}, function(err, data) {
|
||||
}, function (err, data) {
|
||||
res.send(
|
||||
data.header +
|
||||
'\n\t<noscript>\n' + templates['noscript/header'] + templates['noscript/home'].parse(data.categories) + '\n\t</noscript>' +
|
||||
@@ -252,14 +247,14 @@ var express = require('express'),
|
||||
});
|
||||
|
||||
|
||||
app.get('/topic/:topic_id/:slug?', function(req, res) {
|
||||
app.get('/topic/:topic_id/:slug?', function (req, res) {
|
||||
var tid = req.params.topic_id;
|
||||
|
||||
if (tid.match(/^\d+\.rss$/)) {
|
||||
tid = tid.slice(0, -4);
|
||||
var rssPath = path.join(__dirname, '../', 'feeds/topics', tid + '.rss'),
|
||||
loadFeed = function() {
|
||||
fs.readFile(rssPath, function(err, data) {
|
||||
loadFeed = function () {
|
||||
fs.readFile(rssPath, function (err, data) {
|
||||
if (err) res.type('text').send(404, "Unable to locate an rss feed at this location.");
|
||||
else res.type('xml').set('Content-Length', data.length).send(data);
|
||||
});
|
||||
@@ -267,7 +262,7 @@ var express = require('express'),
|
||||
};
|
||||
|
||||
if (!fs.existsSync(rssPath)) {
|
||||
feed.updateTopic(tid, function(err) {
|
||||
feed.updateTopic(tid, function (err) {
|
||||
if (err) res.redirect('/404');
|
||||
else loadFeed();
|
||||
});
|
||||
@@ -277,8 +272,8 @@ var express = require('express'),
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
topics.getTopicWithPosts(tid, ((req.user) ? req.user.uid : 0), 0, -1, function(err, topicData) {
|
||||
function (next) {
|
||||
topics.getTopicWithPosts(tid, ((req.user) ? req.user.uid : 0), 0, -1, function (err, topicData) {
|
||||
if (topicData) {
|
||||
if (topicData.deleted === '1' && topicData.expose_tools === 0)
|
||||
return next(new Error('Topic deleted'), null);
|
||||
@@ -287,7 +282,7 @@ var express = require('express'),
|
||||
next(err, topicData);
|
||||
});
|
||||
},
|
||||
function(topicData, next) {
|
||||
function (topicData, next) {
|
||||
var lastMod = 0,
|
||||
timestamp;
|
||||
|
||||
@@ -324,14 +319,14 @@ var express = require('express'),
|
||||
property: 'article:section',
|
||||
content: topicData.category_name
|
||||
}]
|
||||
}, function(err, header) {
|
||||
}, function (err, header) {
|
||||
next(err, {
|
||||
header: header,
|
||||
topics: topicData
|
||||
});
|
||||
});
|
||||
},
|
||||
], function(err, data) {
|
||||
], function (err, data) {
|
||||
if (err) return res.redirect('404');
|
||||
var topic_url = tid + (req.params.slug ? '/' + req.params.slug : '');
|
||||
|
||||
@@ -344,14 +339,14 @@ var express = require('express'),
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/category/:category_id/:slug?', function(req, res) {
|
||||
app.get('/category/:category_id/:slug?', function (req, res) {
|
||||
var cid = req.params.category_id;
|
||||
|
||||
if (cid.match(/^\d+\.rss$/)) {
|
||||
cid = cid.slice(0, -4);
|
||||
var rssPath = path.join(__dirname, '../', 'feeds/categories', cid + '.rss'),
|
||||
loadFeed = function() {
|
||||
fs.readFile(rssPath, function(err, data) {
|
||||
loadFeed = function () {
|
||||
fs.readFile(rssPath, function (err, data) {
|
||||
if (err) res.type('text').send(404, "Unable to locate an rss feed at this location.");
|
||||
else res.type('xml').set('Content-Length', data.length).send(data);
|
||||
});
|
||||
@@ -359,7 +354,7 @@ var express = require('express'),
|
||||
};
|
||||
|
||||
if (!fs.existsSync(rssPath)) {
|
||||
feed.updateCategory(cid, function(err) {
|
||||
feed.updateCategory(cid, function (err) {
|
||||
if (err) res.redirect('/404');
|
||||
else loadFeed();
|
||||
});
|
||||
@@ -369,8 +364,8 @@ var express = require('express'),
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
categories.getCategoryById(cid, 0, function(err, categoryData) {
|
||||
function (next) {
|
||||
categories.getCategoryById(cid, 0, function (err, categoryData) {
|
||||
|
||||
if (categoryData) {
|
||||
if (categoryData.disabled === '1')
|
||||
@@ -379,7 +374,7 @@ var express = require('express'),
|
||||
next(err, categoryData);
|
||||
});
|
||||
},
|
||||
function(categoryData, next) {
|
||||
function (categoryData, next) {
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res,
|
||||
@@ -393,14 +388,14 @@ var express = require('express'),
|
||||
property: "og:type",
|
||||
content: 'website'
|
||||
}]
|
||||
}, function(err, header) {
|
||||
}, function (err, header) {
|
||||
next(err, {
|
||||
header: header,
|
||||
categories: categoryData
|
||||
});
|
||||
});
|
||||
}
|
||||
], function(err, data) {
|
||||
], function (err, data) {
|
||||
if (err) return res.redirect('404');
|
||||
var category_url = cid + (req.params.slug ? '/' + req.params.slug : '');
|
||||
|
||||
@@ -413,24 +408,24 @@ var express = require('express'),
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/confirm/:code', function(req, res) {
|
||||
app.get('/confirm/:code', function (req, res) {
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res
|
||||
}, function(err, header) {
|
||||
}, function (err, header) {
|
||||
res.send(header + '<script>templates.ready(function(){ajaxify.go("confirm/' + req.params.code + '");});</script>' + templates['footer']);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/sitemap.xml', function(req, res) {
|
||||
app.get('/sitemap.xml', function (req, res) {
|
||||
var sitemap = require('./sitemap.js');
|
||||
|
||||
sitemap.render(function(xml) {
|
||||
sitemap.render(function (xml) {
|
||||
res.type('xml').set('Content-Length', xml.length).send(xml);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/robots.txt', function(req, res) {
|
||||
app.get('/robots.txt', function (req, res) {
|
||||
res.set('Content-Type', 'text/plain');
|
||||
res.send("User-agent: *\n" +
|
||||
"Disallow: \n" +
|
||||
@@ -438,8 +433,8 @@ var express = require('express'),
|
||||
"Sitemap: " + nconf.get('url') + "sitemap.xml");
|
||||
});
|
||||
|
||||
app.get('/cid/:cid', function(req, res) {
|
||||
categories.getCategoryData(req.params.cid, function(err, data) {
|
||||
app.get('/cid/:cid', function (req, res) {
|
||||
categories.getCategoryData(req.params.cid, function (err, data) {
|
||||
if (data)
|
||||
res.send(data);
|
||||
else
|
||||
@@ -447,8 +442,8 @@ var express = require('express'),
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/tid/:tid', function(req, res) {
|
||||
topics.getTopicData(req.params.tid, function(data) {
|
||||
app.get('/tid/:tid', function (req, res) {
|
||||
topics.getTopicData(req.params.tid, function (data) {
|
||||
if (data)
|
||||
res.send(data);
|
||||
else
|
||||
@@ -456,8 +451,8 @@ var express = require('express'),
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/pid/:pid', function(req, res) {
|
||||
posts.getPostData(req.params.pid, function(data) {
|
||||
app.get('/pid/:pid', function (req, res) {
|
||||
posts.getPostData(req.params.pid, function (data) {
|
||||
if (data)
|
||||
res.send(data);
|
||||
else
|
||||
@@ -465,13 +460,13 @@ var express = require('express'),
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/outgoing', function(req, res) {
|
||||
app.get('/outgoing', function (req, res) {
|
||||
if (!req.query.url) return res.redirect('/404');
|
||||
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res
|
||||
}, function(err, header) {
|
||||
}, function (err, header) {
|
||||
res.send(
|
||||
header +
|
||||
'\n\t<script>templates.ready(function(){ajaxify.go("outgoing?url=' + encodeURIComponent(req.query.url) + '", null, null, true);});</script>' +
|
||||
@@ -480,31 +475,35 @@ var express = require('express'),
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/search', function(req, res) {
|
||||
app.get('/search', function (req, res) {
|
||||
if (!req.user)
|
||||
return res.redirect('/403');
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res
|
||||
}, function(err, header) {
|
||||
}, function (err, header) {
|
||||
res.send(header + app.create_route("search", null, "search") + templates['footer']);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/search/:term', function(req, res) {
|
||||
app.get('/search/:term', function (req, res) {
|
||||
if (!req.user)
|
||||
return res.redirect('/403');
|
||||
app.build_header({
|
||||
req: req,
|
||||
res: res
|
||||
}, function(err, header) {
|
||||
}, function (err, header) {
|
||||
res.send(header + app.create_route("search/" + req.params.term, null, "search") + templates['footer']);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/reindex', function(req, res) {
|
||||
topics.reIndexAll(function(err) {
|
||||
app.get('/reindex', function (req, res) {
|
||||
topics.reIndexAll(function (err) {
|
||||
if (err) {
|
||||
return res.json(err);
|
||||
}
|
||||
|
||||
user.reIndexAll(function(err) {
|
||||
user.reIndexAll(function (err) {
|
||||
if (err) {
|
||||
return res.json(err);
|
||||
} else {
|
||||
|
||||
@@ -23,6 +23,7 @@ var SocketIO = require('socket.io').listen(global.server, {
|
||||
client: RDB,
|
||||
ttl: 60 * 60 * 24 * 14
|
||||
}),
|
||||
nconf = require('nconf'),
|
||||
socketCookieParser = express.cookieParser(nconf.get('secret')),
|
||||
admin = {
|
||||
'categories': require('./admin/categories.js'),
|
||||
@@ -53,14 +54,17 @@ var SocketIO = require('socket.io').listen(global.server, {
|
||||
userSockets[uid].push(socket);
|
||||
|
||||
if (uid) {
|
||||
socket.join('uid_' + uid);
|
||||
io.sockets. in ('global').emit('api:user.isOnline', isUserOnline(uid));
|
||||
|
||||
user.getUserField(uid, 'username', function(err, username) {
|
||||
socket.emit('event:connect', {
|
||||
status: 1,
|
||||
username: username,
|
||||
uid: uid
|
||||
RDB.zadd('users:online', Date.now(), uid, function(err, data) {
|
||||
socket.join('uid_' + uid);
|
||||
io.sockets. in ('global').emit('api:user.isOnline', isUserOnline(uid));
|
||||
|
||||
user.getUserField(uid, 'username', function(err, username) {
|
||||
socket.emit('event:connect', {
|
||||
status: 1,
|
||||
username: username,
|
||||
uid: uid
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -80,7 +84,9 @@ var SocketIO = require('socket.io').listen(global.server, {
|
||||
delete users[sessionID];
|
||||
delete userSockets[uid];
|
||||
if (uid) {
|
||||
io.sockets. in ('global').emit('api:user.isOnline', isUserOnline(uid));
|
||||
RDB.zrem('users:online', uid, function(err, data) {
|
||||
io.sockets. in ('global').emit('api:user.isOnline', isUserOnline(uid));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +106,7 @@ var SocketIO = require('socket.io').listen(global.server, {
|
||||
|
||||
socket.on('api:get_all_rooms', function(data) {
|
||||
socket.emit('api:get_all_rooms', io.sockets.manager.rooms);
|
||||
})
|
||||
});
|
||||
|
||||
function updateRoomBrowsingText(roomName) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user