mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-12 00:45:47 +01:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -25,7 +25,6 @@
|
|||||||
"passport-facebook": "0.1.5",
|
"passport-facebook": "0.1.5",
|
||||||
"less-middleware": "0.1.12",
|
"less-middleware": "0.1.12",
|
||||||
"marked": "0.2.8",
|
"marked": "0.2.8",
|
||||||
"bcrypt": "0.7.5",
|
|
||||||
"async": "~0.2.8",
|
"async": "~0.2.8",
|
||||||
"node-imagemagick": "0.1.8",
|
"node-imagemagick": "0.1.8",
|
||||||
"gravatar": "1.0.6",
|
"gravatar": "1.0.6",
|
||||||
@@ -47,7 +46,8 @@
|
|||||||
"semver": "~2.2.1",
|
"semver": "~2.2.1",
|
||||||
"string": "~1.7.0",
|
"string": "~1.7.0",
|
||||||
"xregexp": "~2.0.0",
|
"xregexp": "~2.0.0",
|
||||||
"socket.io-wildcard": "~0.1.1"
|
"socket.io-wildcard": "~0.1.1",
|
||||||
|
"bcryptjs": "~0.7.10"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"redis": "0.8.3",
|
"redis": "0.8.3",
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
"header.recent": "Recent",
|
"header.recent": "Recent",
|
||||||
"header.unread": "Unread",
|
"header.unread": "Unread",
|
||||||
"header.users": "Users",
|
"header.users": "Users",
|
||||||
|
"header.chats": "Chats",
|
||||||
|
"header.notifications": "Notifications",
|
||||||
"header.search": "Search",
|
"header.search": "Search",
|
||||||
"header.profile": "Profile",
|
"header.profile": "Profile",
|
||||||
|
|
||||||
|
|||||||
14
public/language/pt_br/category.json
Normal file
14
public/language/pt_br/category.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"new_topic_button": "New Topic",
|
||||||
|
"no_topics": "<strong>There are no topics in this category.</strong><br />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"
|
||||||
|
}
|
||||||
7
public/language/pt_br/footer.json
Normal file
7
public/language/pt_br/footer.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"stats.online": "Online",
|
||||||
|
"stats.users": "Testers",
|
||||||
|
"stats.topics": "Tópicos",
|
||||||
|
"stats.posts": "Posts",
|
||||||
|
"success": "Sucesso"
|
||||||
|
}
|
||||||
40
public/language/pt_br/global.json
Normal file
40
public/language/pt_br/global.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"home": "Home",
|
||||||
|
"search": "Procurar",
|
||||||
|
"buttons.close": "Fechar",
|
||||||
|
"403.title": "Acesso Negado",
|
||||||
|
"403.message": "Parece que voc<6F> não tem acesso a essa página. talvez voc<6F> devesse <a href='/login'>tentar logar...</a>?",
|
||||||
|
"404.title": "Not Found",
|
||||||
|
"404.message": "Essa página não existe... volte para <a href='/'>página principal</a>.",
|
||||||
|
"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;"
|
||||||
|
}
|
||||||
4
public/language/pt_br/language.json
Normal file
4
public/language/pt_br/language.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"name": "Português Brasileiro",
|
||||||
|
"code": "pt_br"
|
||||||
|
}
|
||||||
10
public/language/pt_br/login.json
Normal file
10
public/language/pt_br/login.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"login": "Login",
|
||||||
|
"username": "Usuário",
|
||||||
|
"password": "Senha",
|
||||||
|
"remember_me": "Lembrar?",
|
||||||
|
"forgot_password": "Esqueceu a Senha?",
|
||||||
|
"alternative_logins": "Voc<6F> pode logar usando também...",
|
||||||
|
"failed_login_attempt": "Falha no login, por favor tente novamente.",
|
||||||
|
"login_successful": "Voc<6F> logou com sucesso!"
|
||||||
|
}
|
||||||
6
public/language/pt_br/modules.json
Normal file
6
public/language/pt_br/modules.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"chat.chatting_with": "Conversar com <span id=\"chat-with-name\"></span>",
|
||||||
|
"chat.placeholder": "Digite sua mensagem aqui e pressione 'enter' para enviar",
|
||||||
|
"chat.send": "Enviar",
|
||||||
|
"chat.no_active": "Voc<6F> não tem chats ativos."
|
||||||
|
}
|
||||||
8
public/language/pt_br/notifications.json
Normal file
8
public/language/pt_br/notifications.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"title": "Notificações",
|
||||||
|
"back_to_home": "voltar para home",
|
||||||
|
"outgoing_link": "Link Externo",
|
||||||
|
"outgoing_link_message": "Voc<6F> está saindo do agiletesters com um link externo",
|
||||||
|
"continue_to": "Continuar para",
|
||||||
|
"return_to": "Voltar para"
|
||||||
|
}
|
||||||
5
public/language/pt_br/recent.json
Normal file
5
public/language/pt_br/recent.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"day": "Dia",
|
||||||
|
"week": "Semana",
|
||||||
|
"month": "M<>s"
|
||||||
|
}
|
||||||
16
public/language/pt_br/register.json
Normal file
16
public/language/pt_br/register.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"register": "Cadastrar",
|
||||||
|
"help.email": "Por padrão, seu email não ficará visivel.",
|
||||||
|
"help.username_restrictions": "Um usuário <20>nico com %1 e %2 caracteres. Outros poderão te mencionar digitando @<span id='yourUsername'>usuário</span>.",
|
||||||
|
"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<6F> pode usar essas outras formas de cadastro"
|
||||||
|
}
|
||||||
13
public/language/pt_br/reset_password.json
Normal file
13
public/language/pt_br/reset_password.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"reset_Senha": "Resetar Senha",
|
||||||
|
"update_Senha": "Alterar Senha",
|
||||||
|
"Senha_changed.title": "Senha Alterada",
|
||||||
|
"Senha_changed.message": "<p>Senha resetada com sucesso, por favor <a href=\"/login\">logue novamente</a>.",
|
||||||
|
"wrong_reset_code.title": "Código De Reset Incorreto",
|
||||||
|
"wrong_reset_code.message": "Codigo de Reset Incorreto. Tente novamente, ou <a href=\"/reset\">peça um novo</a>.",
|
||||||
|
"new_Senha": "Nova Senha",
|
||||||
|
"repeat_Senha": "Confirmar Senha",
|
||||||
|
"enter_email": "Por digite seu <strong>email</strong> nós enviaremos para voc<6F> as instruções de como resetar sua senha.",
|
||||||
|
"Senha_reset_sent": "Reset de Senha Enviado",
|
||||||
|
"invalid_email": "Email inválido!"
|
||||||
|
}
|
||||||
53
public/language/pt_br/topic.json
Normal file
53
public/language/pt_br/topic.json
Normal file
@@ -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<6F> 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<6F> fazer o fork",
|
||||||
|
"fork_no_pids": "Nenhum Tópico selecionado",
|
||||||
|
"fork_success": "Fork realizado com sucesso!",
|
||||||
|
|
||||||
|
"reputation": "Reputação",
|
||||||
|
"posts": "Posts"
|
||||||
|
}
|
||||||
5
public/language/pt_br/unread.json
Normal file
5
public/language/pt_br/unread.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"no_unread_topics": "Todos os topicos lidos.",
|
||||||
|
"mark_all_read": "Marcar como Lido",
|
||||||
|
"load_more": "Carregar"
|
||||||
|
}
|
||||||
41
public/language/pt_br/user.json
Normal file
41
public/language/pt_br/user.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
9
public/language/pt_br/users.json
Normal file
9
public/language/pt_br/users.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
@@ -537,12 +537,28 @@ var socket,
|
|||||||
app.alternatingTitle('');
|
app.alternatingTitle('');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createHeaderTooltips();
|
||||||
|
|
||||||
templates.setGlobal('relative_path', RELATIVE_PATH);
|
templates.setGlobal('relative_path', RELATIVE_PATH);
|
||||||
templates.setGlobal('usePagination', config.usePagination);
|
templates.setGlobal('usePagination', config.usePagination);
|
||||||
templates.setGlobal('topicsPerPage', config.topicsPerPage);
|
templates.setGlobal('topicsPerPage', config.topicsPerPage);
|
||||||
templates.setGlobal('postsPerPage', config.postsPerPage);
|
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;
|
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
|
||||||
|
|
||||||
app.loadConfig();
|
app.loadConfig();
|
||||||
|
|||||||
@@ -178,13 +178,13 @@ define(['uploader'], function(uploader) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Permissions modal
|
// Permissions modal
|
||||||
$('.permissions').on('click', function() {
|
$('.admin-categories').on('click', '.permissions', function() {
|
||||||
var cid = $(this).parents('li[data-cid]').attr('data-cid');
|
var cid = $(this).parents('li[data-cid]').attr('data-cid');
|
||||||
Categories.launchPermissionsModal(cid);
|
Categories.launchPermissionsModal(cid);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$('.upload-button').on('click', function() {
|
$('.admin-categories').on('click', '.upload-button', function() {
|
||||||
var inputEl = this;
|
var inputEl = this;
|
||||||
var cid = $(this).parents('li[data-cid]').attr('data-cid');
|
var cid = $(this).parents('li[data-cid]').attr('data-cid');
|
||||||
uploader.open(RELATIVE_PATH + '/admin/category/uploadpicture', {cid:cid}, function(imageUrlOnServer) {
|
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]'),
|
var parent = $(this).parents('li[data-cid]'),
|
||||||
inputEl = parent.find('.upload-button'),
|
inputEl = parent.find('.upload-button'),
|
||||||
preview = parent.find('.preview-box'),
|
preview = parent.find('.preview-box'),
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ define(function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Admin.updateRoomUsage = function(err, data) {
|
Admin.updateRoomUsage = function(err, data) {
|
||||||
|
|
||||||
function getUserCountIn(room) {
|
function getUserCountIn(room) {
|
||||||
var count = 0;
|
var count = 0;
|
||||||
for(var user in data[room]) {
|
for(var user in data[room]) {
|
||||||
@@ -25,27 +26,36 @@ define(function() {
|
|||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
var active_users = $('#active_users'),
|
|
||||||
|
var active_users = $('#active_users').html(''),
|
||||||
total = 0;
|
total = 0;
|
||||||
|
|
||||||
if(!active_users.length) {
|
if(!active_users.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
active_users.html('');
|
|
||||||
|
|
||||||
var usersHtml = '';
|
var sortedData = [];
|
||||||
|
|
||||||
for (var room in data) {
|
for (var room in data) {
|
||||||
if (room !== '') {
|
if (room !== '') {
|
||||||
var count = getUserCountIn(room);
|
sortedData.push({room: room, count: data[room].length});
|
||||||
total += count;
|
total += data[room].length;
|
||||||
usersHtml += "<div class='alert alert-success'><strong>" + room + "</strong> " + count + " active user" + (count > 1 ? "s" : "") + "</div>";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sortedData.sort(function(a, b) {
|
||||||
|
return parseInt(b.count, 10) - parseInt(a.count, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
var usersHtml = '';
|
||||||
|
for(var i=0; i<sortedData.length; ++i) {
|
||||||
|
usersHtml += "<div class='alert alert-success'><strong>" + sortedData[i].room + "</strong> " +
|
||||||
|
sortedData[i].count + " active user" + (sortedData[i].count > 1 ? "s" : "") + "</div>";
|
||||||
|
}
|
||||||
|
|
||||||
active_users.html(usersHtml);
|
active_users.html(usersHtml);
|
||||||
document.getElementById('connections').innerHTML = total;
|
$('#connections').html(total);
|
||||||
};
|
};
|
||||||
|
|
||||||
return Admin;
|
return Admin;
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
|
|||||||
loadingMoreTopics = true;
|
loadingMoreTopics = true;
|
||||||
socket.emit('categories.loadMore', {
|
socket.emit('categories.loadMore', {
|
||||||
cid: cid,
|
cid: cid,
|
||||||
after: $('#topics-container').children('.category-item').length
|
after: $('#topics-container').attr('data-nextstart')
|
||||||
}, function (err, data) {
|
}, function (err, data) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return app.alertError(err.message);
|
return app.alertError(err.message);
|
||||||
@@ -153,6 +153,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
|
|||||||
|
|
||||||
if (data && data.topics.length) {
|
if (data && data.topics.length) {
|
||||||
Category.onTopicsLoaded(data.topics);
|
Category.onTopicsLoaded(data.topics);
|
||||||
|
$('#topics-container').attr('data-nextstart', data.nextStart);
|
||||||
}
|
}
|
||||||
loadingMoreTopics = false;
|
loadingMoreTopics = false;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ define(function() {
|
|||||||
Recent.loadMoreTopics = function() {
|
Recent.loadMoreTopics = function() {
|
||||||
loadingMoreTopics = true;
|
loadingMoreTopics = true;
|
||||||
socket.emit('topics.loadMoreRecentTopics', {
|
socket.emit('topics.loadMoreRecentTopics', {
|
||||||
after: $('#topics-container').children('li').length,
|
after: $('#topics-container').attr('data-nextstart'),
|
||||||
term: active
|
term: active
|
||||||
}, function(err, data) {
|
}, function(err, data) {
|
||||||
if(err) {
|
if(err) {
|
||||||
@@ -95,6 +95,7 @@ define(function() {
|
|||||||
|
|
||||||
if (data.topics && data.topics.length) {
|
if (data.topics && data.topics.length) {
|
||||||
Recent.onTopicsLoaded('recent', data.topics);
|
Recent.onTopicsLoaded('recent', data.topics);
|
||||||
|
$('#topics-container').attr('data-nextstart', data.nextStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingMoreTopics = false;
|
loadingMoreTopics = false;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ define(function() {
|
|||||||
var Search = {};
|
var Search = {};
|
||||||
|
|
||||||
Search.init = function() {
|
Search.init = function() {
|
||||||
var searchQuery = $('#topics-container').attr('data-search-query');
|
var searchQuery = $('#topic-results').attr('data-search-query');
|
||||||
|
console.log(searchQuery);
|
||||||
$('.search-result-text').each(function() {
|
$('.search-result-text').children().each(function() {
|
||||||
var text = $(this).html();
|
var text = $(this).html();
|
||||||
var regex = new RegExp(searchQuery, 'gi');
|
var regex = new RegExp(searchQuery, 'gi');
|
||||||
text = text.replace(regex, '<span class="label label-success">' + searchQuery + '</span>');
|
text = text.replace(regex, '<span class="label label-success">' + searchQuery + '</span>');
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ define(['forum/recent'], function(recent) {
|
|||||||
function loadMoreTopics() {
|
function loadMoreTopics() {
|
||||||
loadingMoreTopics = true;
|
loadingMoreTopics = true;
|
||||||
socket.emit('topics.loadMoreUnreadTopics', {
|
socket.emit('topics.loadMoreUnreadTopics', {
|
||||||
after: parseInt($('#topics-container').attr('data-next-start'), 10)
|
after: $('#topics-container').attr('data-nextstart')
|
||||||
}, function(err, data) {
|
}, function(err, data) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return app.alertError(err.message);
|
return app.alertError(err.message);
|
||||||
@@ -54,7 +54,7 @@ define(['forum/recent'], function(recent) {
|
|||||||
|
|
||||||
if (data.topics && data.topics.length) {
|
if (data.topics && data.topics.length) {
|
||||||
recent.onTopicsLoaded('unread', data.topics);
|
recent.onTopicsLoaded('unread', data.topics);
|
||||||
$('#topics-container').attr('data-next-start', data.nextStart);
|
$('#topics-container').attr('data-nextstart', data.nextStart);
|
||||||
} else {
|
} else {
|
||||||
$('#load-more-btn').hide();
|
$('#load-more-btn').hide();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ define(function() {
|
|||||||
var notifContainer = document.getElementsByClassName('notifications')[0],
|
var notifContainer = document.getElementsByClassName('notifications')[0],
|
||||||
notifTrigger = notifContainer.querySelector('a'),
|
notifTrigger = notifContainer.querySelector('a'),
|
||||||
notifList = document.getElementById('notif-list'),
|
notifList = document.getElementById('notif-list'),
|
||||||
notifIcon = $('.notifications a');
|
notifIcon = $('.notifications a i');
|
||||||
|
|
||||||
notifTrigger.addEventListener('click', function(e) {
|
notifTrigger.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -46,14 +46,14 @@ define(function() {
|
|||||||
notifList.appendChild(notifFrag);
|
notifList.appendChild(notifFrag);
|
||||||
|
|
||||||
if (data.unread.length > 0) {
|
if (data.unread.length > 0) {
|
||||||
notifIcon.toggleClass('active', true);
|
notifIcon.removeClass('fa-bell-o').addClass('fa-bell');
|
||||||
} else {
|
} else {
|
||||||
notifIcon.toggleClass('active', false);
|
notifIcon.removeClass('fa-bell').addClass('fa-bell-o');
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.emit('modules.notifications.mark_all_read', null, function(err) {
|
socket.emit('modules.notifications.mark_all_read', null, function(err) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
notifIcon.toggleClass('active', false);
|
notifIcon.removeClass('fa-bell').addClass('fa-bell-o');
|
||||||
app.refreshTitle();
|
app.refreshTitle();
|
||||||
|
|
||||||
// Update favicon + local count
|
// Update favicon + local count
|
||||||
@@ -87,9 +87,9 @@ define(function() {
|
|||||||
var updateNotifCount = function(count) {
|
var updateNotifCount = function(count) {
|
||||||
// Update notification icon, if necessary
|
// Update notification icon, if necessary
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
notifIcon.toggleClass('active', true);
|
notifIcon.removeClass('fa-bell-o').addClass('fa-bell');
|
||||||
} else {
|
} else {
|
||||||
notifIcon.toggleClass('active', false);
|
notifIcon.removeClass('fa-bell').addClass('fa-bell-o');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the favicon + saved local count
|
// Update the favicon + saved local count
|
||||||
@@ -106,7 +106,9 @@ define(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on('event:new_notification', function() {
|
socket.on('event:new_notification', function() {
|
||||||
notifIcon.toggleClass('active', true);
|
|
||||||
|
notifIcon.removeClass('fa-bell-o').addClass('fa-bell');
|
||||||
|
|
||||||
app.alert({
|
app.alert({
|
||||||
alert_id: 'new_notif',
|
alert_id: 'new_notif',
|
||||||
title: 'New notification',
|
title: 'New notification',
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
collapseWhitespace : /\s+/g,
|
collapseWhitespace : /\s+/g,
|
||||||
collapseDash : /-+/g,
|
collapseDash : /-+/g,
|
||||||
trimTrailingDash : /-$/g,
|
trimTrailingDash : /-$/g,
|
||||||
|
trimLeadingDash : /^-/g,
|
||||||
isLatin : /^[\w]+$/,
|
isLatin : /^[\w]+$/,
|
||||||
|
|
||||||
//http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/
|
//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.collapseWhitespace, '-')
|
||||||
str = str.replace(utils.collapseDash, '-');
|
str = str.replace(utils.collapseDash, '-');
|
||||||
str = str.replace(utils.trimTrailingDash, '');
|
str = str.replace(utils.trimTrailingDash, '');
|
||||||
|
str = str.replace(utils.trimLeadingDash, '');
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
<h1><i class="fa fa-facebook-square"></i> Facebook Social Authentication</h1>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<div class="alert alert-warning">
|
|
||||||
<p>
|
|
||||||
Create a <strong>Facebook Application</strong> via the
|
|
||||||
<a href="https://developers.facebook.com/">Facebook Developers Page</a> and
|
|
||||||
then paste your application details here.
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<input type="text" data-field="social:facebook:app_id" title="Application ID" class="form-control input-lg" placeholder="App ID"><br />
|
|
||||||
<input type="text" data-field="social:facebook:secret" title="Application Secret" class="form-control input-md" placeholder="App Secret"><br />
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
require(['forum/admin/settings'], function(Settings) {
|
|
||||||
Settings.prepare();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<h1><i class="fa fa-google-plus-square"></i> Google Accounts Social Authentication</h1>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<div class="alert alert-warning">
|
|
||||||
<p>
|
|
||||||
Create a <strong>Google Application</strong> via the
|
|
||||||
<a href="https://code.google.com/apis/console/">API Console</a> and then paste
|
|
||||||
your application details here.
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<input type="text" data-field="social:google:id" title="Client ID" class="form-control input-lg" placeholder="Client ID"><br />
|
|
||||||
<input type="text" data-field="social:google:secret" title="Client Secret" class="form-control" placeholder="Client Secret"><br />
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
require(['forum/admin/settings'], function(Settings) {
|
|
||||||
Settings.prepare();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -115,9 +115,6 @@
|
|||||||
<div class="well sidebar-nav">
|
<div class="well sidebar-nav">
|
||||||
<ul class="nav nav-list">
|
<ul class="nav nav-list">
|
||||||
<li class="nav-header">Social Authentication</li>
|
<li class="nav-header">Social Authentication</li>
|
||||||
<li><a href="{relative_path}/admin/twitter"><i class="fa fa-fw fa-twitter-square"></i> Twitter</a></li>
|
|
||||||
<li><a href="{relative_path}/admin/facebook"><i class="fa fa-fw fa-facebook-square"></i> Facebook</a></li>
|
|
||||||
<li><a href="{relative_path}/admin/gplus"><i class="fa fa-fw fa-google-plus-square"></i> Google+</a></li>
|
|
||||||
<!-- BEGIN authentication -->
|
<!-- BEGIN authentication -->
|
||||||
<li>
|
<li>
|
||||||
<a href="{relative_path}/admin{authentication.route}"><i class="fa fa-fw {authentication.icon}"></i> {authentication.name}</a>
|
<a href="{relative_path}/admin{authentication.route}"><i class="fa fa-fw {authentication.icon}"></i> {authentication.name}</a>
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
<h1><i class="fa fa-twitter-square"></i> Twitter Social Authentication</h1>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<div class="alert alert-warning">
|
|
||||||
<p>
|
|
||||||
Create a <strong>Twitter Application</strong> via the
|
|
||||||
<a href="https://dev.twitter.com/">Twitter Developers Page</a> and then
|
|
||||||
paste your application details here.
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<input type="text" data-field="social:twitter:key" title="Consumer Key" class="form-control input-lg" placeholder="Consumer Key"><br />
|
|
||||||
<input type="text" data-field="social:twitter:secret" title="Consumer Secret" class="form-control input-md" placeholder="Consumer Secret">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
require(['forum/admin/settings'], function(Settings) {
|
|
||||||
Settings.prepare();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
<div class="category row">
|
<div class="category row">
|
||||||
<div class="{topic_row_size}">
|
<div class="{topic_row_size}">
|
||||||
<ul id="topics-container" itemscope itemtype="http://www.schema.org/ItemList">
|
<ul id="topics-container" itemscope itemtype="http://www.schema.org/ItemList" data-nextstart="{nextStart}">
|
||||||
<meta itemprop="itemListOrder" content="descending">
|
<meta itemprop="itemListOrder" content="descending">
|
||||||
<!-- BEGIN topics -->
|
<!-- BEGIN topics -->
|
||||||
<li class="category-item {topics.deleted-class}" itemprop="itemListElement">
|
<li class="category-item {topics.deleted-class}" itemprop="itemListElement">
|
||||||
|
|||||||
@@ -11,10 +11,7 @@
|
|||||||
"^admin/plugins/?$": "admin/plugins",
|
"^admin/plugins/?$": "admin/plugins",
|
||||||
"^admin/languages/?$": "admin/languages",
|
"^admin/languages/?$": "admin/languages",
|
||||||
"^admin/settings.*": "admin/settings",
|
"^admin/settings.*": "admin/settings",
|
||||||
"^admin/twitter.*": "admin/twitter",
|
|
||||||
"^admin/facebook.*": "admin/facebook",
|
|
||||||
"^admin/logger.*": "admin/logger",
|
"^admin/logger.*": "admin/logger",
|
||||||
"^admin/gplus.*": "admin/gplus",
|
|
||||||
"^admin/motd/?$": "admin/motd",
|
"^admin/motd/?$": "admin/motd",
|
||||||
"^admin/groups/?$": "admin/groups",
|
"^admin/groups/?$": "admin/groups",
|
||||||
"^users/sort-posts": "users",
|
"^users/sort-posts": "users",
|
||||||
|
|||||||
@@ -92,7 +92,7 @@
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="notifications dropdown text-center hidden-xs">
|
<li class="notifications dropdown text-center hidden-xs">
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"></a>
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"><i class="fa fa-bell-o" title="[[global:header.notifications]]"></i></a>
|
||||||
<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown">
|
<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown">
|
||||||
<li>
|
<li>
|
||||||
<a href="#"><i class="fa fa-refresh fa-spin"></i> [[global:notifications.loading]]</a>
|
<a href="#"><i class="fa fa-refresh fa-spin"></i> [[global:notifications.loading]]</a>
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="chats dropdown text-center hidden-xs">
|
<li class="chats dropdown text-center hidden-xs">
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="chat_dropdown"><i class="fa fa-comment-o"></i></a>
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="chat_dropdown"><i class="fa fa-comment-o" title="[[global:header.chats]]"></i></a>
|
||||||
<ul id="chat-list" class="dropdown-menu" aria-labelledby="chat_dropdown">
|
<ul id="chat-list" class="dropdown-menu" aria-labelledby="chat_dropdown">
|
||||||
<li>
|
<li>
|
||||||
<a href="#"><i class="fa fa-refresh fa-spin"></i> [[global:chats.loading]]</a>
|
<a href="#"><i class="fa fa-refresh fa-spin"></i> [[global:chats.loading]]</a>
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li id="user_label" class="dropdown">
|
<li id="user_label" class="dropdown">
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="user_dropdown">
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="user_dropdown" title="[[global:header.profile]]">
|
||||||
<img src=""/>
|
<img src=""/>
|
||||||
</a>
|
</a>
|
||||||
<ul id="user-control-list" class="dropdown-menu" aria-labelledby="user_dropdown">
|
<ul id="user-control-list" class="dropdown-menu" aria-labelledby="user_dropdown">
|
||||||
@@ -152,7 +152,7 @@
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="hidden-xs">
|
<li class="hidden-xs">
|
||||||
<a href="#" id="search-button" class="hide"><i class="fa fa-search"></i></a>
|
<a href="#" id="search-button" class="hide"><i class="fa fa-search" title="[[global:header.search]]"></i></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<div class="category row">
|
<div class="category row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<ul id="topics-container">
|
<ul id="topics-container" data-nextstart="{nextStart}">
|
||||||
<!-- BEGIN topics -->
|
<!-- BEGIN topics -->
|
||||||
<li class="category-item {topics.deleted-class}">
|
<li class="category-item {topics.deleted-class}">
|
||||||
<div class="col-md-12 col-xs-12 panel panel-default topic-row">
|
<div class="col-md-12 col-xs-12 panel panel-default topic-row">
|
||||||
|
|||||||
@@ -13,8 +13,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="category search">
|
<div class="search favourites well">
|
||||||
<div class="{show_results}">
|
<div class="{show_results} row">
|
||||||
|
|
||||||
|
<div id="topic-results" class="col-md-12" data-search-query="{search_query}">
|
||||||
|
|
||||||
<h3>[[topic:topics]]</h3>
|
<h3>[[topic:topics]]</h3>
|
||||||
|
|
||||||
<!-- IF topic_matches -->
|
<!-- IF topic_matches -->
|
||||||
@@ -22,47 +25,74 @@
|
|||||||
<!-- ENDIF topic_matches -->
|
<!-- ENDIF topic_matches -->
|
||||||
<div class="alert alert-info {show_no_topics}">[[topic:no_topics_found]]</div>
|
<div class="alert alert-info {show_no_topics}">[[topic:no_topics_found]]</div>
|
||||||
|
|
||||||
<ul id="topics-container" data-search-query="{search_query}">
|
|
||||||
|
|
||||||
<!-- BEGIN topics -->
|
<!-- BEGIN topics -->
|
||||||
<li class="category-item">
|
<div class="topic-row panel panel-default clearfix">
|
||||||
<a href="{relative_path}/topic/{topics.slug}" id="tid-{topics.tid}">
|
<div class="panel-body">
|
||||||
<div>
|
<a href="../../user/{topics.userslug}">
|
||||||
<div class="col-md-12 img-thumbnail">
|
<img title="{topics.username}" class="img-rounded user-img" src="{topics.picture}">
|
||||||
<div class="search-result-post">
|
|
||||||
<img src="{topics.teaser_userpicture}" />
|
|
||||||
<strong>{topics.teaser_username}</strong>: <span class="search-result-text">{topics.title}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
|
||||||
<!-- END topics -->
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
<a href="../../user/{topics.userslug}">
|
||||||
|
<strong><span>{topics.username}</span></strong>
|
||||||
|
</a>
|
||||||
|
<span class="search-result-text">
|
||||||
|
<p>{topics.title}</p>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<small>
|
||||||
|
<span class="pull-right">
|
||||||
|
<a href="../../topic/{topics.slug}">posted</a>
|
||||||
|
in
|
||||||
|
<a href="../../category/{topics.categorySlug}">
|
||||||
|
<i class="fa {topics.categoryIcon}"></i> {topics.categoryName}
|
||||||
|
</a>
|
||||||
|
<span class="timeago" title="{topics.relativeTime}"></span>
|
||||||
|
</span>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- END topics -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="post-results" class="col-md-12" data-search-query="{search_query}">
|
||||||
<h3>Posts</h3>
|
<h3>Posts</h3>
|
||||||
|
|
||||||
<!-- IF post_matches -->
|
<!-- IF post_matches -->
|
||||||
<small>{post_matches} result(s) matching "{search_query}"</small>
|
<small>{post_matches} result(s) matching "{search_query}"</small>
|
||||||
<!-- ENDIF post_matches -->
|
<!-- ENDIF post_matches -->
|
||||||
<div class="alert alert-info {show_no_posts}">No posts found!</div>
|
<div class="alert alert-info {show_no_posts}">No posts found!</div>
|
||||||
|
|
||||||
<ul id="topics-container" data-search-query="{search_query}">
|
|
||||||
<!-- BEGIN posts -->
|
<!-- BEGIN posts -->
|
||||||
<li class="category-item">
|
<div class="topic-row panel panel-default clearfix">
|
||||||
<a href="{relative_path}/topic/{posts.topicSlug}#{posts.pid}" id="tid-{posts.tid}">
|
<div class="panel-body">
|
||||||
<div>
|
<a href="../../user/{posts.userslug}">
|
||||||
<div class="col-md-12 img-thumbnail">
|
<img title="{posts.username}" class="img-rounded user-img" src="{posts.picture}">
|
||||||
<div class="search-result-post">
|
|
||||||
<img src="{posts.picture}" />
|
|
||||||
<strong>{posts.username}</strong>: <span class="search-result-text">{posts.content}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
|
||||||
|
<a href="../../user/{posts.userslug}">
|
||||||
|
<strong><span>{posts.username}</span></strong>
|
||||||
|
</a>
|
||||||
|
<span class="search-result-text">
|
||||||
|
{posts.content}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<small>
|
||||||
|
<span class="pull-right">
|
||||||
|
<a href="../../topic/{posts.topicSlug}#{posts.pid}">posted</a>
|
||||||
|
in
|
||||||
|
<a href="../../category/{posts.categorySlug}">
|
||||||
|
<i class="fa {posts.categoryIcon}"></i> {posts.categoryName}
|
||||||
|
</a>
|
||||||
|
<span class="timeago" title="{posts.relativeTime}"></span>
|
||||||
|
</span>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- END posts -->
|
<!-- END posts -->
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<div class="category row">
|
<div class="category row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<ul id="topics-container" data-next-start="{nextStart}">
|
<ul id="topics-container" data-nextstart="{nextStart}">
|
||||||
<!-- BEGIN topics -->
|
<!-- BEGIN topics -->
|
||||||
<li class="category-item {topics.deleted-class}">
|
<li class="category-item {topics.deleted-class}">
|
||||||
<div class="col-md-12 col-xs-12 panel panel-default topic-row">
|
<div class="col-md-12 col-xs-12 panel panel-default topic-row">
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
var db = require('./database.js'),
|
var db = require('./database'),
|
||||||
posts = require('./posts.js'),
|
posts = require('./posts'),
|
||||||
utils = require('./../public/src/utils.js'),
|
utils = require('./../public/src/utils'),
|
||||||
user = require('./user.js'),
|
user = require('./user'),
|
||||||
topics = require('./topics.js'),
|
topics = require('./topics'),
|
||||||
plugins = require('./plugins'),
|
plugins = require('./plugins'),
|
||||||
CategoryTools = require('./categoryTools'),
|
CategoryTools = require('./categoryTools'),
|
||||||
meta = require('./meta'),
|
meta = require('./meta'),
|
||||||
@@ -52,8 +52,8 @@ var db = require('./database.js'),
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTopicIds(next) {
|
function getTopics(next) {
|
||||||
Categories.getTopicIds(category_id, start, end, next);
|
Categories.getCategoryTopics(category_id, start, end, current_user, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActiveUsers(next) {
|
function getActiveUsers(next) {
|
||||||
@@ -70,9 +70,12 @@ var db = require('./database.js'),
|
|||||||
Categories.getPageCount(category_id, next);
|
Categories.getPageCount(category_id, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
async.parallel([getTopicIds, getActiveUsers, getSidebars, getPageCount], function(err, results) {
|
async.parallel([getTopics, getActiveUsers, getSidebars, getPageCount], function(err, results) {
|
||||||
var tids = results[0],
|
if(err) {
|
||||||
active_users = results[1],
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var active_users = results[1],
|
||||||
sidebars = results[2],
|
sidebars = results[2],
|
||||||
pageCount = results[3];
|
pageCount = results[3];
|
||||||
|
|
||||||
@@ -87,27 +90,22 @@ var db = require('./database.js'),
|
|||||||
'topic_row_size': 'col-md-9',
|
'topic_row_size': 'col-md-9',
|
||||||
'category_id': category_id,
|
'category_id': category_id,
|
||||||
'active_users': [],
|
'active_users': [],
|
||||||
'topics': [],
|
'topics': results[0].topics,
|
||||||
|
'nextStart': results[0].nextStart,
|
||||||
'pageCount': pageCount,
|
'pageCount': pageCount,
|
||||||
'disableSocialButtons': meta.config.disableSocialButtons !== undefined ? parseInt(meta.config.disableSocialButtons, 10) !== 0 : false,
|
'disableSocialButtons': meta.config.disableSocialButtons !== undefined ? parseInt(meta.config.disableSocialButtons, 10) !== 0 : false,
|
||||||
'sidebars': sidebars
|
'sidebars': sidebars
|
||||||
};
|
};
|
||||||
|
|
||||||
function getTopics(next) {
|
|
||||||
topics.getTopicsByTids(tids, category_id, current_user, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getModerators(next) {
|
function getModerators(next) {
|
||||||
Categories.getModerators(category_id, next);
|
Categories.getModerators(category_id, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActiveUsers(next) {
|
function getActiveUsers(next) {
|
||||||
user.getMultipleUserFields(active_users, ['uid', 'username', 'userslug', 'picture'], function(err, users) {
|
user.getMultipleUserFields(active_users, ['uid', 'username', 'userslug', 'picture'], next);
|
||||||
next(err, users);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tids.length === 0) {
|
if (!category.topics.length) {
|
||||||
getModerators(function(err, moderators) {
|
getModerators(function(err, moderators) {
|
||||||
category.moderator_block_class = moderators.length > 0 ? '' : 'none';
|
category.moderator_block_class = moderators.length > 0 ? '' : 'none';
|
||||||
category.moderators = moderators;
|
category.moderators = moderators;
|
||||||
@@ -116,11 +114,10 @@ var db = require('./database.js'),
|
|||||||
callback(null, category);
|
callback(null, category);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
async.parallel([getTopics, getModerators, getActiveUsers], function(err, results) {
|
async.parallel([getModerators, getActiveUsers], function(err, results) {
|
||||||
category.topics = results[0];
|
category.moderator_block_class = results[0].length > 0 ? '' : 'none';
|
||||||
category.moderator_block_class = results[1].length > 0 ? '' : 'none';
|
category.moderators = results[0];
|
||||||
category.moderators = results[1];
|
category.active_users = results[1];
|
||||||
category.active_users = results[2];
|
|
||||||
category.show_sidebar = category.topics.length > 0 ? 'show' : 'hidden';
|
category.show_sidebar = category.topics.length > 0 ? 'show' : 'hidden';
|
||||||
callback(null, category);
|
callback(null, category);
|
||||||
});
|
});
|
||||||
@@ -131,13 +128,26 @@ var db = require('./database.js'),
|
|||||||
};
|
};
|
||||||
|
|
||||||
Categories.getCategoryTopics = function(cid, start, stop, uid, callback) {
|
Categories.getCategoryTopics = function(cid, start, stop, uid, callback) {
|
||||||
Categories.getTopicIds(cid, start, stop, function(err, tids) {
|
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) {
|
if(err) {
|
||||||
return callback(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) {
|
Categories.getTopicIds = function(cid, start, stop, callback) {
|
||||||
|
|||||||
@@ -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) {
|
module.sortedSetScore = function(key, value, callback) {
|
||||||
if(value !== null && value !== undefined) {
|
if(value !== null && value !== undefined) {
|
||||||
value = value.toString();
|
value = value.toString();
|
||||||
|
|||||||
@@ -382,6 +382,10 @@
|
|||||||
redisClient.zrank(key, value, callback);
|
redisClient.zrank(key, value, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.sortedSetRevRank = function(key, value, callback) {
|
||||||
|
redisClient.zrevrank(key, value, callback);
|
||||||
|
}
|
||||||
|
|
||||||
module.sortedSetScore = function(key, value, callback) {
|
module.sortedSetScore = function(key, value, callback) {
|
||||||
redisClient.zscore(key, value, callback);
|
redisClient.zscore(key, value, callback);
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/feed.js
10
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({
|
var feed = new rss({
|
||||||
title: topicData.topic_name,
|
title: topicData.topic_name,
|
||||||
description: topicData.posts[0].content,
|
description: description,
|
||||||
feed_url: Feed.defaults.baseUrl + '/topics/' + tid + '.rss',
|
feed_url: Feed.defaults.baseUrl + '/topics/' + tid + '.rss',
|
||||||
site_url: nconf.get('url') + '/topic/' + topicData.slug,
|
site_url: nconf.get('url') + '/topic/' + topicData.slug,
|
||||||
image_url: topicData.posts[0].picture,
|
image_url: image_url,
|
||||||
author: topicData.posts[0].username,
|
author: author,
|
||||||
ttl: Feed.defaults.ttl
|
ttl: Feed.defaults.ttl
|
||||||
}),
|
}),
|
||||||
dateStamp;
|
dateStamp;
|
||||||
|
|||||||
127
src/login.js
127
src/login.js
@@ -1,5 +1,5 @@
|
|||||||
var user = require('./user'),
|
var user = require('./user'),
|
||||||
bcrypt = require('bcrypt'),
|
bcrypt = require('bcryptjs'),
|
||||||
db = require('./database'),
|
db = require('./database'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
winston = require('winston'),
|
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));
|
}(exports));
|
||||||
|
|||||||
@@ -56,13 +56,16 @@ var db = require('./database'),
|
|||||||
|
|
||||||
var messages = [];
|
var messages = [];
|
||||||
|
|
||||||
|
userData[0].uid = touid;
|
||||||
|
userData[1].uid = fromuid;
|
||||||
|
|
||||||
function getMessage(mid, next) {
|
function getMessage(mid, next) {
|
||||||
db.getObject('message:' + mid, function(err, message) {
|
db.getObject('message:' + mid, function(err, message) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(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;
|
message.content = result;
|
||||||
messages.push(message);
|
messages.push(message);
|
||||||
next(null);
|
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) {
|
plugins.fireHook('filter:post.parse', message, function(err, parsed) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(message);
|
return callback(message);
|
||||||
@@ -104,6 +107,7 @@ var db = require('./database'),
|
|||||||
myuid: myuid,
|
myuid: myuid,
|
||||||
toUserData: toUserData,
|
toUserData: toUserData,
|
||||||
myUserData: myUserData,
|
myUserData: myUserData,
|
||||||
|
isNew: isNew,
|
||||||
parsedMessage: picture + username + parsed
|
parsedMessage: picture + username + parsed
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -58,8 +58,7 @@ var nconf = require('nconf'),
|
|||||||
(function () {
|
(function () {
|
||||||
var routes = [
|
var routes = [
|
||||||
'categories/active', 'categories/disabled', 'users', 'topics', 'settings', 'themes',
|
'categories/active', 'categories/disabled', 'users', 'topics', 'settings', 'themes',
|
||||||
'twitter', 'facebook', 'gplus', 'database', 'events', 'motd', 'groups', 'plugins',
|
'database', 'events', 'motd', 'groups', 'plugins', 'languages', 'logger',
|
||||||
'languages', 'logger',
|
|
||||||
'users/latest', 'users/sort-posts', 'users/sort-reputation', 'users/search'
|
'users/latest', 'users/sort-posts', 'users/sort-reputation', 'users/search'
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -409,18 +408,6 @@ var nconf = require('nconf'),
|
|||||||
res.json(200, {});
|
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) {
|
app.get('/testing/categories', function (req, res) {
|
||||||
res.json(200, {});
|
res.json(200, {});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
(function(Auth) {
|
(function(Auth) {
|
||||||
var passport = require('passport'),
|
var passport = require('passport'),
|
||||||
passportLocal = require('passport-local').Strategy,
|
passportLocal = require('passport-local').Strategy,
|
||||||
passportTwitter = require('passport-twitter').Strategy,
|
|
||||||
passportGoogle = require('passport-google-oauth').OAuth2Strategy,
|
|
||||||
passportFacebook = require('passport-facebook').Strategy,
|
|
||||||
login_strategies = [],
|
login_strategies = [],
|
||||||
nconf = require('nconf'),
|
nconf = require('nconf'),
|
||||||
meta = require('../meta'),
|
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) {
|
passport.serializeUser(function(user, done) {
|
||||||
done(null, user.uid);
|
done(null, user.uid);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -75,12 +75,12 @@ var DebugRoute = function(app) {
|
|||||||
|
|
||||||
app.get('/test', function(req, res) {
|
app.get('/test', function(req, res) {
|
||||||
|
|
||||||
/*topics.getTopicPosts2(2, 0, 10, 5, function(err, data) {
|
var db = require('./../database');
|
||||||
res.json(data);
|
|
||||||
})*/
|
db.getSortedSetRevRange('topics:recent', 0 , -1, function(err, tids) {
|
||||||
topics.getTopicWithPosts(2, 1, 0, -1, true, function (err, topicData) {
|
res.json(tids);
|
||||||
res.json(topicData);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,14 +18,10 @@ SocketCategories.loadMore = function(socket, data, callback) {
|
|||||||
|
|
||||||
var topicsPerPage = parseInt(meta.config.topicsPerPage, 10) || 20;
|
var topicsPerPage = parseInt(meta.config.topicsPerPage, 10) || 20;
|
||||||
|
|
||||||
var start = data.after,
|
var start = parseInt(data.after, 10),
|
||||||
end = start + topicsPerPage - 1;
|
end = start + topicsPerPage - 1;
|
||||||
|
|
||||||
categories.getCategoryTopics(data.cid, start, end, socket.uid, function(err, topics) {
|
categories.getCategoryTopics(data.cid, start, end, socket.uid, callback);
|
||||||
callback(err, {
|
|
||||||
topics: topics
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketCategories.getPageCount = function(socket, cid, callback) {
|
SocketCategories.getPageCount = function(socket, cid, callback) {
|
||||||
|
|||||||
@@ -22,12 +22,11 @@ var SocketIO = require('socket.io'),
|
|||||||
|
|
||||||
/* === */
|
/* === */
|
||||||
|
|
||||||
var users = {},
|
|
||||||
io;
|
var io;
|
||||||
|
|
||||||
|
|
||||||
Sockets.userSockets = {};
|
Sockets.userSockets = {};
|
||||||
Sockets.rooms = {};
|
|
||||||
|
|
||||||
|
|
||||||
Sockets.init = function(server) {
|
Sockets.init = function(server) {
|
||||||
@@ -59,9 +58,9 @@ Sockets.init = function(server) {
|
|||||||
sessionID = socket.handshake.signedCookies["express.sid"];
|
sessionID = socket.handshake.signedCookies["express.sid"];
|
||||||
db.sessionStore.get(sessionID, function(err, sessionData) {
|
db.sessionStore.get(sessionID, function(err, sessionData) {
|
||||||
if (!err && sessionData && sessionData.passport && sessionData.passport.user) {
|
if (!err && sessionData && sessionData.passport && sessionData.passport.user) {
|
||||||
uid = users[sessionID] = sessionData.passport.user;
|
uid = sessionData.passport.user;
|
||||||
} else {
|
} else {
|
||||||
uid = users[sessionID] = 0;
|
uid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.uid = parseInt(uid, 10);
|
socket.uid = parseInt(uid, 10);
|
||||||
@@ -110,8 +109,8 @@ Sockets.init = function(server) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Sockets.userSockets[uid] && Sockets.userSockets[uid].length === 0) {
|
if (Sockets.userSockets[uid] && Sockets.userSockets[uid].length === 0) {
|
||||||
delete users[sessionID];
|
|
||||||
delete Sockets.userSockets[uid];
|
delete Sockets.userSockets[uid];
|
||||||
|
|
||||||
if (uid) {
|
if (uid) {
|
||||||
db.sortedSetRemove('users:online', uid, function(err, data) {
|
db.sortedSetRemove('users:online', uid, function(err, data) {
|
||||||
});
|
});
|
||||||
@@ -126,17 +125,10 @@ Sockets.init = function(server) {
|
|||||||
|
|
||||||
emitOnlineUserCount();
|
emitOnlineUserCount();
|
||||||
|
|
||||||
for (var roomName in Sockets.rooms) {
|
for(var roomName in io.sockets.manager.roomClients[socket.id]) {
|
||||||
if (Sockets.rooms.hasOwnProperty(roomName)) {
|
updateRoomBrowsingText(roomName.slice(1));
|
||||||
socket.leave(roomName);
|
|
||||||
|
|
||||||
if (Sockets.rooms[roomName][socket.id]) {
|
|
||||||
delete Sockets.rooms[roomName][socket.id];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRoomBrowsingText(roomName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('*', function(payload, callback) {
|
socket.on('*', function(payload, callback) {
|
||||||
@@ -222,9 +214,10 @@ function updateRoomBrowsingText(roomName) {
|
|||||||
|
|
||||||
function getUidsInRoom(room) {
|
function getUidsInRoom(room) {
|
||||||
var uids = [];
|
var uids = [];
|
||||||
for (var socketId in room) {
|
var clients = io.sockets.clients(roomName);
|
||||||
if (uids.indexOf(room[socketId]) === -1) {
|
for(var i=0; i<clients.length; ++i) {
|
||||||
uids.push(room[socketId]);
|
if (uids.indexOf(clients[i].uid) === -1 && clients[i].uid !== 0) {
|
||||||
|
uids.push(clients[i].uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return uids;
|
return uids;
|
||||||
@@ -235,15 +228,14 @@ function updateRoomBrowsingText(roomName) {
|
|||||||
var anonCount = 0;
|
var anonCount = 0;
|
||||||
|
|
||||||
for (var i = 0; i < clients.length; ++i) {
|
for (var i = 0; i < clients.length; ++i) {
|
||||||
var hs = clients[i].handshake;
|
if(clients[i].uid === 0) {
|
||||||
if (hs && clients[i].state && clients[i].state.user.uid === 0) {
|
|
||||||
++anonCount;
|
++anonCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return anonCount;
|
return anonCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
var uids = getUidsInRoom(Sockets.rooms[roomName]),
|
var uids = getUidsInRoom(roomName),
|
||||||
anonymousCount = getAnonymousCount(roomName);
|
anonymousCount = getAnonymousCount(roomName);
|
||||||
|
|
||||||
user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], function(err, users) {
|
user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], function(err, users) {
|
||||||
|
|||||||
@@ -84,18 +84,6 @@ SocketMeta.rooms.enter = function(socket, data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
socket.join(data.enter);
|
socket.join(data.enter);
|
||||||
server.rooms[data.enter] = server.rooms[data.enter] || {};
|
|
||||||
|
|
||||||
if (socket.uid) {
|
|
||||||
server.rooms[data.enter][socket.id] = socket.uid;
|
|
||||||
|
|
||||||
if (data.leave && server.rooms[data.leave] && server.rooms[data.leave][socket.id] && data.enter !== data.leave) {
|
|
||||||
delete server.rooms[data.leave][socket.id];
|
|
||||||
if(!Object.keys(server.rooms[data.leave]).length) {
|
|
||||||
delete server.rooms[data.leave];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.leave) {
|
if (data.leave) {
|
||||||
module.parent.exports.updateRoomBrowsingText(data.leave);
|
module.parent.exports.updateRoomBrowsingText(data.leave);
|
||||||
@@ -104,12 +92,12 @@ SocketMeta.rooms.enter = function(socket, data) {
|
|||||||
module.parent.exports.updateRoomBrowsingText(data.enter);
|
module.parent.exports.updateRoomBrowsingText(data.enter);
|
||||||
|
|
||||||
if (data.enter != 'admin') {
|
if (data.enter != 'admin') {
|
||||||
server.in('admin').emit('event:meta.rooms.update', null, server.rooms);
|
server.in('admin').emit('event:meta.rooms.update', null, server.server.sockets.manager.rooms);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketMeta.rooms.getAll = function(socket, data, callback) {
|
SocketMeta.rooms.getAll = function(socket, data, callback) {
|
||||||
callback(null, server.rooms);
|
callback(null, server.server.sockets.manager.rooms);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Exports */
|
/* Exports */
|
||||||
|
|||||||
@@ -109,7 +109,11 @@ SocketModules.chats.send = function(socket, data) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Messaging.parse(msg, socket.uid, socket.uid, usersData[1], usersData[0], function(parsed) {
|
|
||||||
|
usersData[0].uid = socket.uid;
|
||||||
|
usersData[1].uid = touid;
|
||||||
|
|
||||||
|
Messaging.parse(msg, socket.uid, socket.uid, usersData[1], usersData[0], true, function(parsed) {
|
||||||
Messaging.addMessage(socket.uid, touid, msg, function(err, message) {
|
Messaging.addMessage(socket.uid, touid, msg, function(err, message) {
|
||||||
var numSockets = 0,
|
var numSockets = 0,
|
||||||
x;
|
x;
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ SocketTopics.loadMore = function(socket, data, callback) {
|
|||||||
var postsPerPage = parseInt(meta.config.postsPerPage, 10);
|
var postsPerPage = parseInt(meta.config.postsPerPage, 10);
|
||||||
postsPerPage = postsPerPage ? postsPerPage : 20;
|
postsPerPage = postsPerPage ? postsPerPage : 20;
|
||||||
|
|
||||||
var start = data.after,
|
var start = parseInt(data.after, 10),
|
||||||
end = start + postsPerPage - 1;
|
end = start + postsPerPage - 1;
|
||||||
|
|
||||||
async.parallel({
|
async.parallel({
|
||||||
@@ -256,14 +256,14 @@ SocketTopics.loadMoreRecentTopics = function(socket, data, callback) {
|
|||||||
return callback(new Error('invalid data'));
|
return callback(new Error('invalid data'));
|
||||||
}
|
}
|
||||||
|
|
||||||
var start = data.after,
|
var start = parseInt(data.after, 10),
|
||||||
end = start + 9;
|
end = start + 9;
|
||||||
|
|
||||||
topics.getLatestTopics(socket.uid, start, end, data.term, callback);
|
topics.getLatestTopics(socket.uid, start, end, data.term, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketTopics.loadMoreUnreadTopics = function(socket, data, callback) {
|
SocketTopics.loadMoreUnreadTopics = function(socket, data, callback) {
|
||||||
var start = data.after,
|
var start = parseInt(data.after, 10),
|
||||||
end = start + 9;
|
end = start + 9;
|
||||||
|
|
||||||
topics.getUnreadTopics(socket.uid, start, end, callback);
|
topics.getUnreadTopics(socket.uid, start, end, callback);
|
||||||
|
|||||||
@@ -426,8 +426,9 @@ var async = require('async'),
|
|||||||
};
|
};
|
||||||
|
|
||||||
var since = terms['day'];
|
var since = terms['day'];
|
||||||
if(terms[term])
|
if(terms[term]) {
|
||||||
since = terms[term];
|
since = terms[term];
|
||||||
|
}
|
||||||
|
|
||||||
var args = ['topics:recent', '+inf', timestamp - since, 'LIMIT', start, end - start + 1];
|
var args = ['topics:recent', '+inf', timestamp - since, 'LIMIT', start, end - start + 1];
|
||||||
db.getSortedSetRevRangeByScore(args, function(err, tids) {
|
db.getSortedSetRevRangeByScore(args, function(err, tids) {
|
||||||
@@ -442,23 +443,29 @@ var async = require('async'),
|
|||||||
|
|
||||||
if (!tids || !tids.length) {
|
if (!tids || !tids.length) {
|
||||||
latestTopics.no_topics_message = 'show';
|
latestTopics.no_topics_message = 'show';
|
||||||
callback(err, latestTopics);
|
return callback(null, latestTopics);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter out topics that belong to categories that this user cannot access
|
|
||||||
async.filter(tids, function(tid, next) {
|
async.filter(tids, function(tid, next) {
|
||||||
threadTools.privileges(tid, current_user, function(err, privileges) {
|
threadTools.privileges(tid, current_user, function(err, privileges) {
|
||||||
if (!err && privileges.read) {
|
next(!err && privileges.read);
|
||||||
next(true);
|
|
||||||
} else {
|
|
||||||
next(false);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, function(tids) {
|
}, function(tids) {
|
||||||
Topics.getTopicsByTids(tids, 0, current_user, function(err, topicData) {
|
Topics.getTopicsByTids(tids, 0, current_user, function(err, topicData) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!topicData || !topicData.length) {
|
||||||
|
latestTopics.no_topics_message = 'show';
|
||||||
|
return callback(null, latestTopics);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.sortedSetRevRank('topics:recent', topicData[topicData.length - 1].tid, function(err, rank) {
|
||||||
|
latestTopics.nextStart = parseInt(rank,10) + 1;
|
||||||
latestTopics.topics = topicData;
|
latestTopics.topics = topicData;
|
||||||
callback(err, latestTopics);
|
callback(null, latestTopics);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -538,7 +545,7 @@ var async = require('async'),
|
|||||||
return parseInt(read[index], 10) === 0;
|
return parseInt(read[index], 10) === 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Filter out topics that belong to categories that this user cannot access
|
|
||||||
async.filter(newtids, function(tid, next) {
|
async.filter(newtids, function(tid, next) {
|
||||||
threadTools.privileges(tid, uid, function(err, privileges) {
|
threadTools.privileges(tid, uid, function(err, privileges) {
|
||||||
if (!err && privileges.read) {
|
if (!err && privileges.read) {
|
||||||
@@ -588,8 +595,14 @@ var async = require('async'),
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.sortedSetRevRank('topics:recent', topicData[topicData.length - 1].tid, function(err, rank) {
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
unreadTopics.topics = topicData;
|
unreadTopics.topics = topicData;
|
||||||
unreadTopics.nextStart = stop + 1;
|
unreadTopics.nextStart = parseInt(rank, 10) + 1;
|
||||||
|
|
||||||
if (!topicData || topicData.length === 0) {
|
if (!topicData || topicData.length === 0) {
|
||||||
unreadTopics.no_topics_message = 'show';
|
unreadTopics.no_topics_message = 'show';
|
||||||
}
|
}
|
||||||
@@ -599,6 +612,7 @@ var async = require('async'),
|
|||||||
|
|
||||||
callback(null, unreadTopics);
|
callback(null, unreadTopics);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Topics.getUnreadTids(uid, start, stop, function(err, unreadTids) {
|
Topics.getUnreadTids(uid, start, stop, function(err, unreadTids) {
|
||||||
@@ -700,6 +714,7 @@ var async = require('async'),
|
|||||||
|
|
||||||
function isTopicVisible(topicData, topicInfo) {
|
function isTopicVisible(topicData, topicInfo) {
|
||||||
var deleted = parseInt(topicData.deleted, 10) !== 0;
|
var deleted = parseInt(topicData.deleted, 10) !== 0;
|
||||||
|
|
||||||
return !deleted || (deleted && topicInfo.privileges.view_deleted) || topicData.uid === current_user;
|
return !deleted || (deleted && topicInfo.privileges.view_deleted) || topicData.uid === current_user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
src/user.js
37
src/user.js
@@ -1,4 +1,4 @@
|
|||||||
var bcrypt = require('bcrypt'),
|
var bcrypt = require('bcryptjs'),
|
||||||
async = require('async'),
|
async = require('async'),
|
||||||
nconf = require('nconf'),
|
nconf = require('nconf'),
|
||||||
winston = require('winston'),
|
winston = require('winston'),
|
||||||
@@ -742,33 +742,6 @@ var bcrypt = require('bcrypt'),
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
User.getUidByTwitterId = function(twid, callback) {
|
|
||||||
db.getObjectField('twid:uid', twid, function(err, uid) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
callback(null, uid);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
User.getUidByGoogleId = function(gplusid, callback) {
|
|
||||||
db.getObjectField('gplusid:uid', gplusid, function(err, uid) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
callback(null, uid);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
User.getUidByFbid = function(fbid, callback) {
|
|
||||||
db.getObjectField('fbid:uid', fbid, function(err, uid) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
callback(null, uid);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
User.isModerator = function(uid, cid, callback) {
|
User.isModerator = function(uid, cid, callback) {
|
||||||
db.isSetMember('cid:' + cid + ':moderators', uid, function(err, exists) {
|
db.isSetMember('cid:' + cid + ':moderators', uid, function(err, exists) {
|
||||||
if(err) {
|
if(err) {
|
||||||
@@ -926,11 +899,12 @@ var bcrypt = require('bcrypt'),
|
|||||||
confirm: function(code, callback) {
|
confirm: function(code, callback) {
|
||||||
db.getObject('confirm:' + code, function(err, confirmObj) {
|
db.getObject('confirm:' + code, function(err, confirmObj) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback({
|
return callback({
|
||||||
status:'error'
|
status:'error'
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
if (confirmObj.uid && confirmObj.email) {
|
|
||||||
|
if (confirmObj && confirmObj.uid && confirmObj.email) {
|
||||||
db.setObjectField('email:confirmed', confirmObj.email, '1', function() {
|
db.setObjectField('email:confirmed', confirmObj.email, '1', function() {
|
||||||
callback({
|
callback({
|
||||||
status: 'ok'
|
status: 'ok'
|
||||||
@@ -941,7 +915,6 @@ var bcrypt = require('bcrypt'),
|
|||||||
status: 'not_ok'
|
status: 'not_ok'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ describe('Categories', function() {
|
|||||||
|
|
||||||
describe('.getCategoryTopics', function() {
|
describe('.getCategoryTopics', function() {
|
||||||
it('should return a list of topics', function(done) {
|
it('should return a list of topics', function(done) {
|
||||||
Categories.getCategoryTopics(categoryObj.cid, 0, 10, 0, function(err, topics) {
|
Categories.getCategoryTopics(categoryObj.cid, 0, 10, 0, function(err, result) {
|
||||||
assert(Array.isArray(topics));
|
assert(Array.isArray(result.topics));
|
||||||
assert(topics.every(function(topic) {
|
assert(result.topics.every(function(topic) {
|
||||||
return topic instanceof Object;
|
return topic instanceof Object;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user