diff --git a/package.json b/package.json index bbc04c94ac..8534d01908 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,6 @@ "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", @@ -47,7 +46,8 @@ "semver": "~2.2.1", "string": "~1.7.0", "xregexp": "~2.0.0", - "socket.io-wildcard": "~0.1.1" + "socket.io-wildcard": "~0.1.1", + "bcryptjs": "~0.7.10" }, "optionalDependencies": { "redis": "0.8.3", diff --git a/public/language/en/global.json b/public/language/en/global.json index 99fd8c74dc..210486f0a9 100644 --- a/public/language/en/global.json +++ b/public/language/en/global.json @@ -23,6 +23,8 @@ "header.recent": "Recent", "header.unread": "Unread", "header.users": "Users", + "header.chats": "Chats", + "header.notifications": "Notifications", "header.search": "Search", "header.profile": "Profile", diff --git a/public/language/pt_br/category.json b/public/language/pt_br/category.json new file mode 100644 index 0000000000..d29e23eb95 --- /dev/null +++ b/public/language/pt_br/category.json @@ -0,0 +1,14 @@ +{ + "new_topic_button": "New Topic", + "no_topics": "There are no topics in this category.
Why don't you try posting one?", + "sidebar.recent_replies": "Recent Replies", + "sidebar.active_participants": "Active Participants", + "sidebar.moderators": "Moderators", + "posts": "posts", + "views": "views", + "posted": "posted", + "browsing": "browsing", + "no_replies": "No one has replied", + "replied": "replied", + "last_edited_by": "last edited by" +} diff --git a/public/language/pt_br/footer.json b/public/language/pt_br/footer.json new file mode 100644 index 0000000000..06c7f43b74 --- /dev/null +++ b/public/language/pt_br/footer.json @@ -0,0 +1,7 @@ +{ + "stats.online": "Online", + "stats.users": "Testers", + "stats.topics": "Tópicos", + "stats.posts": "Posts", + "success": "Sucesso" +} diff --git a/public/language/pt_br/global.json b/public/language/pt_br/global.json new file mode 100644 index 0000000000..b10075d10d --- /dev/null +++ b/public/language/pt_br/global.json @@ -0,0 +1,40 @@ +{ + "home": "Home", + "search": "Procurar", + "buttons.close": "Fechar", + "403.title": "Acesso Negado", + "403.message": "Parece que você não tem acesso a essa página. talvez você devesse tentar logar...?", + "404.title": "Not Found", + "404.message": "Essa página não existe... volte para página principal.", + "500.title": "Erro Interno.", + "500.message": "Oops! deu algo errado!", + + "register": "Cadastrar", + "login": "Logar", + + "logout": "Logout", + "logout.title": "Logout com sucesso.", + "logout.message": "Logado com Sucesso!", + + "save_changes": "Salvar Alterações", + "close": "Fechar", + + "header.admin": "Admin", + "header.recent": "Recente", + "header.unread": "Não Lido", + "header.users": "Usuários", + "header.search": "Procurar", + "header.profile": "Profile", + + "notifications.loading": "Carregando Notificações", + "chats.loading": "Carregando Bate-Papo", + + "motd.welcome": "Welcome to NodeBB, the discussion platform of the future.", + "motd.get": "Get NodeBB", + "motd.fork": "Fork", + "motd.like": "Like", + "motd.follow": "Seguir", + + "previouspage": "Página Anterior", + "nextpage": "Próxima pagina;" +} diff --git a/public/language/pt_br/language.json b/public/language/pt_br/language.json new file mode 100644 index 0000000000..611dd6491d --- /dev/null +++ b/public/language/pt_br/language.json @@ -0,0 +1,4 @@ +{ + "name": "Português Brasileiro", + "code": "pt_br" +} \ No newline at end of file diff --git a/public/language/pt_br/login.json b/public/language/pt_br/login.json new file mode 100644 index 0000000000..10ccb32227 --- /dev/null +++ b/public/language/pt_br/login.json @@ -0,0 +1,10 @@ +{ + "login": "Login", + "username": "Usuário", + "password": "Senha", + "remember_me": "Lembrar?", + "forgot_password": "Esqueceu a Senha?", + "alternative_logins": "Você pode logar usando também...", + "failed_login_attempt": "Falha no login, por favor tente novamente.", + "login_successful": "Você logou com sucesso!" +} diff --git a/public/language/pt_br/modules.json b/public/language/pt_br/modules.json new file mode 100644 index 0000000000..1ce45f5ff5 --- /dev/null +++ b/public/language/pt_br/modules.json @@ -0,0 +1,6 @@ +{ + "chat.chatting_with": "Conversar com ", + "chat.placeholder": "Digite sua mensagem aqui e pressione 'enter' para enviar", + "chat.send": "Enviar", + "chat.no_active": "Você não tem chats ativos." +} \ No newline at end of file diff --git a/public/language/pt_br/notifications.json b/public/language/pt_br/notifications.json new file mode 100644 index 0000000000..007e836d84 --- /dev/null +++ b/public/language/pt_br/notifications.json @@ -0,0 +1,8 @@ +{ + "title": "Notificações", + "back_to_home": "voltar para home", + "outgoing_link": "Link Externo", + "outgoing_link_message": "Você está saindo do agiletesters com um link externo", + "continue_to": "Continuar para", + "return_to": "Voltar para" +} diff --git a/public/language/pt_br/recent.json b/public/language/pt_br/recent.json new file mode 100644 index 0000000000..92ea088ba7 --- /dev/null +++ b/public/language/pt_br/recent.json @@ -0,0 +1,5 @@ +{ + "day": "Dia", + "week": "Semana", + "month": "Mês" +} \ No newline at end of file diff --git a/public/language/pt_br/register.json b/public/language/pt_br/register.json new file mode 100644 index 0000000000..2bc244c900 --- /dev/null +++ b/public/language/pt_br/register.json @@ -0,0 +1,16 @@ +{ + "register": "Cadastrar", + "help.email": "Por padrão, seu email não ficará visivel.", + "help.username_restrictions": "Um usuário único com %1 e %2 caracteres. Outros poderão te mencionar digitando @usuário.", + "help.minimum_password_length": "Sua senha tem que ter no mínimo %1 caracteres.", + "email_address": "Email", + "email_address_placeholder": "Digite seu Email", + "username": "Usuário", + "username_placeholder": "Digiter Usuário", + "password": "Senha", + "password_placeholder": "Digitar Senha", + "confirm_password": "Confirmar Senha", + "confirm_password_placeholder": "Confirmar Senha", + "register_now_button": "Cadastrar Agora", + "alternative_registration": "Você pode usar essas outras formas de cadastro" +} \ No newline at end of file diff --git a/public/language/pt_br/reset_password.json b/public/language/pt_br/reset_password.json new file mode 100644 index 0000000000..d277772c14 --- /dev/null +++ b/public/language/pt_br/reset_password.json @@ -0,0 +1,13 @@ +{ + "reset_Senha": "Resetar Senha", + "update_Senha": "Alterar Senha", + "Senha_changed.title": "Senha Alterada", + "Senha_changed.message": "

Senha resetada com sucesso, por favor logue novamente.", + "wrong_reset_code.title": "Código De Reset Incorreto", + "wrong_reset_code.message": "Codigo de Reset Incorreto. Tente novamente, ou peça um novo.", + "new_Senha": "Nova Senha", + "repeat_Senha": "Confirmar Senha", + "enter_email": "Por digite seu email nós enviaremos para você as instruções de como resetar sua senha.", + "Senha_reset_sent": "Reset de Senha Enviado", + "invalid_email": "Email inválido!" +} diff --git a/public/language/pt_br/topic.json b/public/language/pt_br/topic.json new file mode 100644 index 0000000000..d72097afe6 --- /dev/null +++ b/public/language/pt_br/topic.json @@ -0,0 +1,53 @@ +{ + "topic": "Tópico", + "topics": "Tópicos", + + "no_topics_found": "Nenhum tópico encontrado!", + + "profile": "Profile", + "posted_by": "Postado por", + "chat": "Chat", + "notify_me": "Ser notificado a cada nova resposta", + "quote": "Citar", + "reply": "Esponder", + "edit": "Editar", + "delete": "Deletar", + "move": "Mover", + "fork": "Fork", + "banned": "Banido", + "link": "Link", + "share": "Compartilho", + "tools": "Ferramentas", + + "thread_tools.title": "Ferramentas da Thread", + "thread_tools.markAsUnreadForAll": "Marcar como não lido", + "thread_tools.pin": "Fixar Thread", + "thread_tools.lock": "Travar Thread", + "thread_tools.move": "Mover Thread", + "thread_tools.fork": "Fork Thread", + "thread_tools.delete": "Deletar Thread", + + "load_categories": "Carregando Categorias", + "disabled_categories_note": "Categorias desabilitadas estão em cinza", + "confirm_move": "Mover", + "confirm_fork": "Fork", + + "favourite": "Favoritar", + "favourites": "Favoritos", + "favourites.not_logged_in.title": "Não Logado", + "favourites.not_logged_in.message": "Por Favor logar para favoritar o tópico", + "favourites.has_no_favourites": "Você não tem nenhum item favoritado!", + + "posted_by": "postado por", + "loading_more_posts": "Carregando mais posts", + "move_topic": "Mover Tópico", + "move_post": "Mover Post", + "fork_topic": "Fork Tópico", + "topic_will_be_moved_to": "Este tópico será movido para categoria", + "fork_topic_instruction": "Clique nos postas que você fazer o fork", + "fork_no_pids": "Nenhum Tópico selecionado", + "fork_success": "Fork realizado com sucesso!", + + "reputation": "Reputação", + "posts": "Posts" +} diff --git a/public/language/pt_br/unread.json b/public/language/pt_br/unread.json new file mode 100644 index 0000000000..b75d15c994 --- /dev/null +++ b/public/language/pt_br/unread.json @@ -0,0 +1,5 @@ +{ + "no_unread_topics": "Todos os topicos lidos.", + "mark_all_read": "Marcar como Lido", + "load_more": "Carregar" +} \ No newline at end of file diff --git a/public/language/pt_br/user.json b/public/language/pt_br/user.json new file mode 100644 index 0000000000..187c823028 --- /dev/null +++ b/public/language/pt_br/user.json @@ -0,0 +1,41 @@ +{ + "banned": "Banido", + "offline": "Offline", + "username": "Usuário", + "email": "Email", + "fullname": "Nome Completo", + "website": "Website", + "location": "Localização", + "age": "Idade", + "joined": "Cadastrou", + "lastonline": "Visto á", + "profile_views": "Visualizações de Profile", + "reputation": "Reputação", + "posts": "Posts", + "followers": "Seguidores", + "following": "Seguindo", + "signature": "Assinatura", + "gravatar": "Gravatar", + "birthday": "Aniversário", + + "change_picture": "Alterar Foto", + "edit": "Editar", + "uploaded_picture": "Foto Carregada", + "upload_new_picture": "Carregar novo Foto", + "change_password": "Alterar Senha", + "confirm_password": "Confirmar Senha", + "password": "Senha", + + "upload_picture": "Carregar Foto", + "upload_a_picture": "Carregar Foto", + "image_spec": "Somente arquivos jpg, png e gif com no maximo 256kb.", + + "settings": "Configurações", + "show_email": "Mostrar meu email", + + "has_no_follower": "Ninguém está seguindo esse usuário...", + "follows_no_one": "Este usuário não está seguindo ninguem...", + + "email_hidden": "Email Escondido", + "hidden": "Escondido" +} diff --git a/public/language/pt_br/users.json b/public/language/pt_br/users.json new file mode 100644 index 0000000000..0fa4005679 --- /dev/null +++ b/public/language/pt_br/users.json @@ -0,0 +1,9 @@ +{ + "latest_users": "Usuários Recentes", + "top_posters": "Top Posters", + "most_reputation": "Com Mais Reputação", + "online": "Online", + "search": "Procurar", + "enter_username": "Digite um usuário para buscar", + "load_more": "Carregar mais" +} \ No newline at end of file diff --git a/public/src/app.js b/public/src/app.js index 21c0c72c86..77d55bd3ef 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -537,12 +537,28 @@ var socket, app.alternatingTitle(''); }); + createHeaderTooltips(); + templates.setGlobal('relative_path', RELATIVE_PATH); templates.setGlobal('usePagination', config.usePagination); templates.setGlobal('topicsPerPage', config.topicsPerPage); templates.setGlobal('postsPerPage', config.postsPerPage); }); + function createHeaderTooltips() { + $('#header-menu li i[title]').each(function() { + $(this).parents('li').tooltip({ + placement: 'bottom', + title: $(this).attr('title') + }); + }); + + $('#user_label').tooltip({ + placement: 'bottom', + title: $('#user_dropdown').attr('title') + }); + } + showWelcomeMessage = location.href.indexOf('loggedin') !== -1; app.loadConfig(); diff --git a/public/src/forum/admin/categories.js b/public/src/forum/admin/categories.js index 327e29968f..6142cafb24 100644 --- a/public/src/forum/admin/categories.js +++ b/public/src/forum/admin/categories.js @@ -178,13 +178,13 @@ define(['uploader'], function(uploader) { }); // Permissions modal - $('.permissions').on('click', function() { + $('.admin-categories').on('click', '.permissions', function() { var cid = $(this).parents('li[data-cid]').attr('data-cid'); Categories.launchPermissionsModal(cid); }); - $('.upload-button').on('click', function() { + $('.admin-categories').on('click', '.upload-button', function() { var inputEl = this; var cid = $(this).parents('li[data-cid]').attr('data-cid'); uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', {cid:cid}, function(imageUrlOnServer) { @@ -196,7 +196,7 @@ define(['uploader'], function(uploader) { }); }); - $('.admin-categories').delegate('.delete-image', 'click', function() { + $('.admin-categories').on('click', '.delete-image', function() { var parent = $(this).parents('li[data-cid]'), inputEl = parent.find('.upload-button'), preview = parent.find('.preview-box'), diff --git a/public/src/forum/admin/index.js b/public/src/forum/admin/index.js index c0806106dd..c99dd43cb9 100644 --- a/public/src/forum/admin/index.js +++ b/public/src/forum/admin/index.js @@ -18,6 +18,7 @@ define(function() { }; Admin.updateRoomUsage = function(err, data) { + function getUserCountIn(room) { var count = 0; for(var user in data[room]) { @@ -25,27 +26,36 @@ define(function() { } return count; } - var active_users = $('#active_users'), + + var active_users = $('#active_users').html(''), total = 0; if(!active_users.length) { return; } - active_users.html(''); - var usersHtml = ''; + var sortedData = []; for (var room in data) { if (room !== '') { - var count = getUserCountIn(room); - total += count; - usersHtml += "

" + room + " " + count + " active user" + (count > 1 ? "s" : "") + "
"; + sortedData.push({room: room, count: data[room].length}); + total += data[room].length; } } + sortedData.sort(function(a, b) { + return parseInt(b.count, 10) - parseInt(a.count, 10); + }); + + var usersHtml = ''; + for(var i=0; i " + + sortedData[i].count + " active user" + (sortedData[i].count > 1 ? "s" : "") + ""; + } + active_users.html(usersHtml); - document.getElementById('connections').innerHTML = total; + $('#connections').html(total); }; return Admin; diff --git a/public/src/forum/category.js b/public/src/forum/category.js index 29dcffa269..e61443337b 100644 --- a/public/src/forum/category.js +++ b/public/src/forum/category.js @@ -145,7 +145,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { loadingMoreTopics = true; socket.emit('categories.loadMore', { cid: cid, - after: $('#topics-container').children('.category-item').length + after: $('#topics-container').attr('data-nextstart') }, function (err, data) { if(err) { return app.alertError(err.message); @@ -153,6 +153,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { if (data && data.topics.length) { Category.onTopicsLoaded(data.topics); + $('#topics-container').attr('data-nextstart', data.nextStart); } loadingMoreTopics = false; }); diff --git a/public/src/forum/recent.js b/public/src/forum/recent.js index 966ce0058d..17d4602403 100644 --- a/public/src/forum/recent.js +++ b/public/src/forum/recent.js @@ -86,7 +86,7 @@ define(function() { Recent.loadMoreTopics = function() { loadingMoreTopics = true; socket.emit('topics.loadMoreRecentTopics', { - after: $('#topics-container').children('li').length, + after: $('#topics-container').attr('data-nextstart'), term: active }, function(err, data) { if(err) { @@ -95,6 +95,7 @@ define(function() { if (data.topics && data.topics.length) { Recent.onTopicsLoaded('recent', data.topics); + $('#topics-container').attr('data-nextstart', data.nextStart); } loadingMoreTopics = false; diff --git a/public/src/forum/search.js b/public/src/forum/search.js index 17c65866a6..9ae2543b28 100644 --- a/public/src/forum/search.js +++ b/public/src/forum/search.js @@ -2,9 +2,9 @@ define(function() { var Search = {}; Search.init = function() { - var searchQuery = $('#topics-container').attr('data-search-query'); - - $('.search-result-text').each(function() { + var searchQuery = $('#topic-results').attr('data-search-query'); +console.log(searchQuery); + $('.search-result-text').children().each(function() { var text = $(this).html(); var regex = new RegExp(searchQuery, 'gi'); text = text.replace(regex, '' + searchQuery + ''); diff --git a/public/src/forum/unread.js b/public/src/forum/unread.js index b562ce1502..4f3024fbab 100644 --- a/public/src/forum/unread.js +++ b/public/src/forum/unread.js @@ -46,7 +46,7 @@ define(['forum/recent'], function(recent) { function loadMoreTopics() { loadingMoreTopics = true; socket.emit('topics.loadMoreUnreadTopics', { - after: parseInt($('#topics-container').attr('data-next-start'), 10) + after: $('#topics-container').attr('data-nextstart') }, function(err, data) { if(err) { return app.alertError(err.message); @@ -54,7 +54,7 @@ define(['forum/recent'], function(recent) { if (data.topics && data.topics.length) { recent.onTopicsLoaded('unread', data.topics); - $('#topics-container').attr('data-next-start', data.nextStart); + $('#topics-container').attr('data-nextstart', data.nextStart); } else { $('#load-more-btn').hide(); } diff --git a/public/src/modules/notifications.js b/public/src/modules/notifications.js index 2fff715165..c862facd15 100644 --- a/public/src/modules/notifications.js +++ b/public/src/modules/notifications.js @@ -6,7 +6,7 @@ define(function() { var notifContainer = document.getElementsByClassName('notifications')[0], notifTrigger = notifContainer.querySelector('a'), notifList = document.getElementById('notif-list'), - notifIcon = $('.notifications a'); + notifIcon = $('.notifications a i'); notifTrigger.addEventListener('click', function(e) { e.preventDefault(); @@ -46,14 +46,14 @@ define(function() { notifList.appendChild(notifFrag); if (data.unread.length > 0) { - notifIcon.toggleClass('active', true); + notifIcon.removeClass('fa-bell-o').addClass('fa-bell'); } else { - notifIcon.toggleClass('active', false); + notifIcon.removeClass('fa-bell').addClass('fa-bell-o'); } socket.emit('modules.notifications.mark_all_read', null, function(err) { if (!err) { - notifIcon.toggleClass('active', false); + notifIcon.removeClass('fa-bell').addClass('fa-bell-o'); app.refreshTitle(); // Update favicon + local count @@ -87,9 +87,9 @@ define(function() { var updateNotifCount = function(count) { // Update notification icon, if necessary if (count > 0) { - notifIcon.toggleClass('active', true); + notifIcon.removeClass('fa-bell-o').addClass('fa-bell'); } else { - notifIcon.toggleClass('active', false); + notifIcon.removeClass('fa-bell').addClass('fa-bell-o'); } // Update the favicon + saved local count @@ -106,7 +106,9 @@ define(function() { }); socket.on('event:new_notification', function() { - notifIcon.toggleClass('active', true); + + notifIcon.removeClass('fa-bell-o').addClass('fa-bell'); + app.alert({ alert_id: 'new_notif', title: 'New notification', diff --git a/public/src/utils.js b/public/src/utils.js index e7916ef5f6..988253f3c1 100644 --- a/public/src/utils.js +++ b/public/src/utils.js @@ -106,6 +106,7 @@ collapseWhitespace : /\s+/g, collapseDash : /-+/g, trimTrailingDash : /-$/g, + trimLeadingDash : /^-/g, isLatin : /^[\w]+$/, //http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/ @@ -120,6 +121,7 @@ str = str.replace(utils.collapseWhitespace, '-') str = str.replace(utils.collapseDash, '-'); str = str.replace(utils.trimTrailingDash, ''); + str = str.replace(utils.trimLeadingDash, ''); return str; }, diff --git a/public/templates/admin/facebook.tpl b/public/templates/admin/facebook.tpl deleted file mode 100644 index 19137f8500..0000000000 --- a/public/templates/admin/facebook.tpl +++ /dev/null @@ -1,23 +0,0 @@ -

Facebook Social Authentication

-
- -
-
-

- Create a Facebook Application via the - Facebook Developers Page and - then paste your application details here. -

-
-
-
-
-
- - - - \ No newline at end of file diff --git a/public/templates/admin/gplus.tpl b/public/templates/admin/gplus.tpl deleted file mode 100644 index d44041adee..0000000000 --- a/public/templates/admin/gplus.tpl +++ /dev/null @@ -1,23 +0,0 @@ -

Google Accounts Social Authentication

-
- -
-
-

- Create a Google Application via the - API Console and then paste - your application details here. -

-
-
-
-
-
- - - - \ No newline at end of file diff --git a/public/templates/admin/header.tpl b/public/templates/admin/header.tpl index 2baa221059..9e3dc7f839 100644 --- a/public/templates/admin/header.tpl +++ b/public/templates/admin/header.tpl @@ -115,9 +115,6 @@ diff --git a/public/templates/unread.tpl b/public/templates/unread.tpl index 114e8cba83..36874fd2b8 100644 --- a/public/templates/unread.tpl +++ b/public/templates/unread.tpl @@ -16,7 +16,7 @@
-
    +
    • diff --git a/src/categories.js b/src/categories.js index a2aee70091..31e425c27b 100644 --- a/src/categories.js +++ b/src/categories.js @@ -1,8 +1,8 @@ -var db = require('./database.js'), - posts = require('./posts.js'), - utils = require('./../public/src/utils.js'), - user = require('./user.js'), - topics = require('./topics.js'), +var db = require('./database'), + posts = require('./posts'), + utils = require('./../public/src/utils'), + user = require('./user'), + topics = require('./topics'), plugins = require('./plugins'), CategoryTools = require('./categoryTools'), meta = require('./meta'), @@ -52,8 +52,8 @@ var db = require('./database.js'), return callback(err); } - function getTopicIds(next) { - Categories.getTopicIds(category_id, start, end, next); + function getTopics(next) { + Categories.getCategoryTopics(category_id, start, end, current_user, next); } function getActiveUsers(next) { @@ -70,9 +70,12 @@ var db = require('./database.js'), Categories.getPageCount(category_id, next); } - async.parallel([getTopicIds, getActiveUsers, getSidebars, getPageCount], function(err, results) { - var tids = results[0], - active_users = results[1], + async.parallel([getTopics, getActiveUsers, getSidebars, getPageCount], function(err, results) { + if(err) { + return callback(err); + } + + var active_users = results[1], sidebars = results[2], pageCount = results[3]; @@ -87,27 +90,22 @@ var db = require('./database.js'), 'topic_row_size': 'col-md-9', 'category_id': category_id, 'active_users': [], - 'topics': [], + 'topics': results[0].topics, + 'nextStart': results[0].nextStart, 'pageCount': pageCount, 'disableSocialButtons': meta.config.disableSocialButtons !== undefined ? parseInt(meta.config.disableSocialButtons, 10) !== 0 : false, 'sidebars': sidebars }; - function getTopics(next) { - topics.getTopicsByTids(tids, category_id, current_user, next); - } - function getModerators(next) { Categories.getModerators(category_id, next); } function getActiveUsers(next) { - user.getMultipleUserFields(active_users, ['uid', 'username', 'userslug', 'picture'], function(err, users) { - next(err, users); - }); + user.getMultipleUserFields(active_users, ['uid', 'username', 'userslug', 'picture'], next); } - if (tids.length === 0) { + if (!category.topics.length) { getModerators(function(err, moderators) { category.moderator_block_class = moderators.length > 0 ? '' : 'none'; category.moderators = moderators; @@ -116,11 +114,10 @@ var db = require('./database.js'), callback(null, category); }); } else { - async.parallel([getTopics, getModerators, getActiveUsers], function(err, results) { - category.topics = results[0]; - category.moderator_block_class = results[1].length > 0 ? '' : 'none'; - category.moderators = results[1]; - category.active_users = results[2]; + async.parallel([getModerators, getActiveUsers], function(err, results) { + category.moderator_block_class = results[0].length > 0 ? '' : 'none'; + category.moderators = results[0]; + category.active_users = results[1]; category.show_sidebar = category.topics.length > 0 ? 'show' : 'hidden'; callback(null, category); }); @@ -131,13 +128,26 @@ var db = require('./database.js'), }; Categories.getCategoryTopics = function(cid, start, stop, uid, callback) { - Categories.getTopicIds(cid, start, stop, function(err, tids) { - if(err) { - return callback(err); - } + async.waterfall([ + function(next) { + Categories.getTopicIds(cid, start, stop, next); + }, + function(tids, next) { + topics.getTopicsByTids(tids, cid, uid, next); + }, + function(topics, next) { + db.sortedSetRevRank('categories:' + cid + ':tid', topics[topics.length - 1].tid, function(err, rank) { + if(err) { + return next(err); + } - topics.getTopicsByTids(tids, cid, uid, callback); - }); + return next(null, { + topics: topics, + nextStart: parseInt(rank, 10) + 1 + }); + }); + } + ], callback); }; Categories.getTopicIds = function(cid, start, stop, callback) { diff --git a/src/database/mongo.js b/src/database/mongo.js index 59fbc41b5a..9ebc45bd33 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -656,6 +656,23 @@ }); } + module.sortedSetRevRank = function(key, value, callback) { + if(value !== null && value !== undefined) { + value = value.toString(); + } + module.getSortedSetRange(key, 0, -1, function(err, result) { + if(err) { + return callback(err); + } + var rank = result.indexOf(value); + if(rank === -1) { + return callback(null, null); + } + + callback(null, result.length - rank - 1); + }); + } + module.sortedSetScore = function(key, value, callback) { if(value !== null && value !== undefined) { value = value.toString(); diff --git a/src/database/redis.js b/src/database/redis.js index de4802456c..b4e67b836b 100644 --- a/src/database/redis.js +++ b/src/database/redis.js @@ -382,6 +382,10 @@ redisClient.zrank(key, value, callback); } + module.sortedSetRevRank = function(key, value, callback) { + redisClient.zrevrank(key, value, callback); + } + module.sortedSetScore = function(key, value, callback) { redisClient.zscore(key, value, callback); } diff --git a/src/feed.js b/src/feed.js index 89828328e1..0b8fe46f49 100644 --- a/src/feed.js +++ b/src/feed.js @@ -38,13 +38,17 @@ } } + var description = topicData.posts.length ? topicData.posts[0].content : ''; + var image_url = topicData.posts.length ? topicData.posts[0].picture : ''; + var author = topicData.posts.length ? topicData.posts[0].username : ''; + var feed = new rss({ title: topicData.topic_name, - description: topicData.posts[0].content, + description: description, feed_url: Feed.defaults.baseUrl + '/topics/' + tid + '.rss', site_url: nconf.get('url') + '/topic/' + topicData.slug, - image_url: topicData.posts[0].picture, - author: topicData.posts[0].username, + image_url: image_url, + author: author, ttl: Feed.defaults.ttl }), dateStamp; diff --git a/src/login.js b/src/login.js index 50ce805b21..acd3498cfa 100644 --- a/src/login.js +++ b/src/login.js @@ -1,5 +1,5 @@ var user = require('./user'), - bcrypt = require('bcrypt'), + bcrypt = require('bcryptjs'), db = require('./database'), path = require('path'), winston = require('winston'), @@ -56,129 +56,4 @@ var user = require('./user'), }); } } - - Login.loginViaTwitter = function(twid, handle, photos, callback) { - user.getUidByTwitterId(twid, function(err, uid) { - if(err) { - return callback(err); - } - - if (uid !== null) { - // Existing User - callback(null, { - uid: uid - }); - } else { - // New User - user.create({username: handle}, function(err, uid) { - if(err) { - return callback(err); - } - - // Save twitter-specific information to the user - user.setUserField(uid, 'twid', twid); - db.setObjectField('twid:uid', twid, uid); - - // Save their photo, if present - if (photos && photos.length > 0) { - var photoUrl = photos[0].value; - photoUrl = path.dirname(photoUrl) + '/' + path.basename(photoUrl, path.extname(photoUrl)).slice(0, -6) + 'bigger' + path.extname(photoUrl); - user.setUserField(uid, 'uploadedpicture', photoUrl); - user.setUserField(uid, 'picture', photoUrl); - } - - callback(null, { - uid: uid - }); - }); - } - }); - }; - - Login.loginViaGoogle = function(gplusid, handle, email, callback) { - user.getUidByGoogleId(gplusid, function(err, uid) { - if(err) { - return callback(err); - } - - if (uid !== null) { - // Existing User - callback(null, { - uid: uid - }); - } else { - // New User - var success = function(uid) { - // Save google-specific information to the user - user.setUserField(uid, 'gplusid', gplusid); - db.setObjectField('gplusid:uid', gplusid, uid); - callback(null, { - uid: uid - }); - }; - - user.getUidByEmail(email, function(err, uid) { - if(err) { - return callback(err); - } - - if (!uid) { - user.create({username: handle, email: email}, function(err, uid) { - if(err) { - return callback(err); - } - - success(uid); - }); - } else { - success(uid); // Existing account -- merge - } - }); - } - }); - }; - - Login.loginViaFacebook = function(fbid, name, email, callback) { - user.getUidByFbid(fbid, function(err, uid) { - if(err) { - return callback(err); - } - - if (uid !== null) { - // Existing User - callback(null, { - uid: uid - }); - } else { - // New User - var success = function(uid) { - // Save facebook-specific information to the user - user.setUserField(uid, 'fbid', fbid); - db.setObjectField('fbid:uid', fbid, uid); - callback(null, { - uid: uid - }); - }; - - user.getUidByEmail(email, function(err, uid) { - if(err) { - return callback(err); - } - - if (!uid) { - user.create({username: name, email: email}, function(err, uid) { - if(err) { - return callback(err); - } - - success(uid); - }); - } else { - success(uid); // Existing account -- merge - } - }); - } - }); - } - }(exports)); diff --git a/src/messaging.js b/src/messaging.js index f6cc6671c0..6f2c54de28 100644 --- a/src/messaging.js +++ b/src/messaging.js @@ -56,13 +56,16 @@ var db = require('./database'), var messages = []; + userData[0].uid = touid; + userData[1].uid = fromuid; + function getMessage(mid, next) { db.getObject('message:' + mid, function(err, message) { if (err) { return next(err); } - Messaging.parse(message.content, message.fromuid, fromuid, userData[1], userData[0], function(result) { + Messaging.parse(message.content, message.fromuid, fromuid, userData[1], userData[0], false, function(result) { message.content = result; messages.push(message); next(null); @@ -81,7 +84,7 @@ var db = require('./database'), }); }; - Messaging.parse = function (message, fromuid, myuid, toUserData, myUserData, callback) { + Messaging.parse = function (message, fromuid, myuid, toUserData, myUserData, isNew, callback) { plugins.fireHook('filter:post.parse', message, function(err, parsed) { if (err) { return callback(message); @@ -104,6 +107,7 @@ var db = require('./database'), myuid: myuid, toUserData: toUserData, myUserData: myUserData, + isNew: isNew, parsedMessage: picture + username + parsed }; diff --git a/src/routes/admin.js b/src/routes/admin.js index 0cdac99a9a..d94983eed0 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -58,8 +58,7 @@ var nconf = require('nconf'), (function () { var routes = [ 'categories/active', 'categories/disabled', 'users', 'topics', 'settings', 'themes', - 'twitter', 'facebook', 'gplus', 'database', 'events', 'motd', 'groups', 'plugins', - 'languages', 'logger', + 'database', 'events', 'motd', 'groups', 'plugins', 'languages', 'logger', 'users/latest', 'users/sort-posts', 'users/sort-reputation', 'users/search' ]; @@ -409,18 +408,6 @@ var nconf = require('nconf'), res.json(200, {}); }); - app.get('/twitter', function (req, res) { - res.json(200, {}); - }); - - app.get('/facebook', function (req, res) { - res.json(200, {}); - }); - - app.get('/gplus', function (req, res) { - res.json(200, {}); - }); - app.get('/testing/categories', function (req, res) { res.json(200, {}); }); diff --git a/src/routes/authentication.js b/src/routes/authentication.js index 8b1bc8b4af..e3336b27a8 100644 --- a/src/routes/authentication.js +++ b/src/routes/authentication.js @@ -1,9 +1,6 @@ (function(Auth) { var passport = require('passport'), passportLocal = require('passport-local').Strategy, - passportTwitter = require('passport-twitter').Strategy, - passportGoogle = require('passport-google-oauth').OAuth2Strategy, - passportFacebook = require('passport-facebook').Strategy, login_strategies = [], nconf = require('nconf'), meta = require('../meta'), @@ -32,75 +29,6 @@ }); }); - if (meta.config['social:twitter:key'] && meta.config['social:twitter:secret']) { - passport.use(new passportTwitter({ - consumerKey: meta.config['social:twitter:key'], - consumerSecret: meta.config['social:twitter:secret'], - callbackURL: nconf.get('url') + '/auth/twitter/callback' - }, function(token, tokenSecret, profile, done) { - login_module.loginViaTwitter(profile.id, profile.username, profile.photos, function(err, user) { - if (err) { - return done(err); - } - done(null, user); - }); - })); - - login_strategies.push({ - name: 'twitter', - url: '/auth/twitter', - callbackURL: '/auth/twitter/callback', - icon: 'twitter', - scope: '' - }); - } - - if (meta.config['social:google:id'] && meta.config['social:google:secret']) { - passport.use(new passportGoogle({ - clientID: meta.config['social:google:id'], - clientSecret: meta.config['social:google:secret'], - callbackURL: nconf.get('url') + '/auth/google/callback' - }, function(accessToken, refreshToken, profile, done) { - login_module.loginViaGoogle(profile.id, profile.displayName, profile.emails[0].value, function(err, user) { - if (err) { - return done(err); - } - done(null, user); - }); - })); - - login_strategies.push({ - name: 'google', - url: '/auth/google', - callbackURL: '/auth/google/callback', - icon: 'google-plus', - scope: 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email' - }); - } - - if (meta.config['social:facebook:app_id'] && meta.config['social:facebook:secret']) { - passport.use(new passportFacebook({ - clientID: meta.config['social:facebook:app_id'], - clientSecret: meta.config['social:facebook:secret'], - callbackURL: nconf.get('url') + '/auth/facebook/callback' - }, function(accessToken, refreshToken, profile, done) { - login_module.loginViaFacebook(profile.id, profile.displayName, profile.emails[0].value, function(err, user) { - if (err) { - return done(err); - } - done(null, user); - }); - })); - - login_strategies.push({ - name: 'facebook', - url: '/auth/facebook', - callbackURL: '/auth/facebook/callback', - icon: 'facebook', - scope: 'email' - }); - } - passport.serializeUser(function(user, done) { done(null, user.uid); }); diff --git a/src/routes/debug.js b/src/routes/debug.js index b2a6e5c335..b25d00a894 100644 --- a/src/routes/debug.js +++ b/src/routes/debug.js @@ -75,12 +75,12 @@ var DebugRoute = function(app) { app.get('/test', function(req, res) { - /*topics.getTopicPosts2(2, 0, 10, 5, function(err, data) { - res.json(data); - })*/ - topics.getTopicWithPosts(2, 1, 0, -1, true, function (err, topicData) { - res.json(topicData); + var db = require('./../database'); + + db.getSortedSetRevRange('topics:recent', 0 , -1, function(err, tids) { + res.json(tids); }); + }); }); diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js index eaac85b4ac..ddea33d2f3 100644 --- a/src/socket.io/categories.js +++ b/src/socket.io/categories.js @@ -18,14 +18,10 @@ SocketCategories.loadMore = function(socket, data, callback) { var topicsPerPage = parseInt(meta.config.topicsPerPage, 10) || 20; - var start = data.after, + var start = parseInt(data.after, 10), end = start + topicsPerPage - 1; - categories.getCategoryTopics(data.cid, start, end, socket.uid, function(err, topics) { - callback(err, { - topics: topics - }); - }); + categories.getCategoryTopics(data.cid, start, end, socket.uid, callback); }; SocketCategories.getPageCount = function(socket, cid, callback) { diff --git a/src/socket.io/index.js b/src/socket.io/index.js index 90ff00d7f3..a0d89bc102 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -22,12 +22,11 @@ var SocketIO = require('socket.io'), /* === */ -var users = {}, - io; + +var io; Sockets.userSockets = {}; -Sockets.rooms = {}; Sockets.init = function(server) { @@ -59,9 +58,9 @@ Sockets.init = function(server) { sessionID = socket.handshake.signedCookies["express.sid"]; db.sessionStore.get(sessionID, function(err, sessionData) { if (!err && sessionData && sessionData.passport && sessionData.passport.user) { - uid = users[sessionID] = sessionData.passport.user; + uid = sessionData.passport.user; } else { - uid = users[sessionID] = 0; + uid = 0; } socket.uid = parseInt(uid, 10); @@ -110,8 +109,8 @@ Sockets.init = function(server) { } if (Sockets.userSockets[uid] && Sockets.userSockets[uid].length === 0) { - delete users[sessionID]; delete Sockets.userSockets[uid]; + if (uid) { db.sortedSetRemove('users:online', uid, function(err, data) { }); @@ -126,17 +125,10 @@ Sockets.init = function(server) { emitOnlineUserCount(); - for (var roomName in Sockets.rooms) { - if (Sockets.rooms.hasOwnProperty(roomName)) { - socket.leave(roomName); - - if (Sockets.rooms[roomName][socket.id]) { - delete Sockets.rooms[roomName][socket.id]; - } - - updateRoomBrowsingText(roomName); - } + for(var roomName in io.sockets.manager.roomClients[socket.id]) { + updateRoomBrowsingText(roomName.slice(1)); } + }); socket.on('*', function(payload, callback) { @@ -222,9 +214,10 @@ function updateRoomBrowsingText(roomName) { function getUidsInRoom(room) { var uids = []; - for (var socketId in room) { - if (uids.indexOf(room[socketId]) === -1) { - uids.push(room[socketId]); + var clients = io.sockets.clients(roomName); + for(var i=0; i