diff --git a/loader.js b/loader.js index e0bfac6258..20f9d49f88 100644 --- a/loader.js +++ b/loader.js @@ -6,6 +6,18 @@ var nconf = require('nconf'), start = function() { var fork = require('child_process').fork, nbb_start = function() { + if (timesStarted > 3) { + console.log('\n[loader] Experienced three start attempts in 10 seconds, most likely am error on startup. Halting.'); + process.exit(); + return; + } + + timesStarted++; + if (startTimer) { + clearTimeout(startTimer); + } + startTimer = setTimeout(resetTimer, 1000*10); + nbb = fork('./app', process.argv.slice(2), { env: { 'NODE_ENV': process.env.NODE_ENV @@ -29,6 +41,10 @@ var nconf = require('nconf'), }); }, nbb_stop = function() { + if (startTimer) { + clearTimeout(startTimer); + } + nbb.kill(); if (fs.existsSync(pidFilePath)) { var pid = parseInt(fs.readFileSync(pidFilePath, { encoding: 'utf-8' }), 10); @@ -42,7 +58,13 @@ var nconf = require('nconf'), nbb_start(); }); nbb.kill(); - }; + }, + resetTimer = function() { + clearTimeout(startTimer); + timesStarted = 0; + }, + timesStarted = 0, + startTimer; process.on('SIGINT', nbb_stop); process.on('SIGTERM', nbb_stop); diff --git a/public/language/ar/unread.json b/public/language/ar/unread.json index 0c763e2d90..3a973748af 100644 --- a/public/language/ar/unread.json +++ b/public/language/ar/unread.json @@ -1,6 +1,9 @@ { "title": "Unread", "no_unread_topics": "ليس هناك أي موضوع غير مقروء", - "mark_all_read": "إجعل كل المواضيع مقرؤة", - "load_more": "حمل المزيد" + "load_more": "حمل المزيد", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/cs/unread.json b/public/language/cs/unread.json index 88f2fd2255..e3e5bc1ce5 100644 --- a/public/language/cs/unread.json +++ b/public/language/cs/unread.json @@ -1,6 +1,9 @@ { "title": "Unread", "no_unread_topics": "Nejsou zde žádné nepřečtené témata.", - "mark_all_read": "Označit vše jako přečtené", - "load_more": "Načíst další" + "load_more": "Načíst další", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/de/category.json b/public/language/de/category.json index b0a4cd36a5..85e6c3da99 100644 --- a/public/language/de/category.json +++ b/public/language/de/category.json @@ -7,6 +7,6 @@ "browsing": "Aktiv", "no_replies": "Niemand hat geantwortet", "replied": "geantwortet", - "last_edited_by": "zuletzt editiert durch", - "share_this_category": "Share this category" + "last_edited_by": "zuletzt editiert von", + "share_this_category": "Teile diese Kategorie" } \ No newline at end of file diff --git a/public/language/de/unread.json b/public/language/de/unread.json index 0ca36e3266..3362e0dee9 100644 --- a/public/language/de/unread.json +++ b/public/language/de/unread.json @@ -1,6 +1,9 @@ { "title": "Ungelesen", "no_unread_topics": "Es gibt keine ungelesenen Themen.", - "mark_all_read": "alle als gelesen markieren", - "load_more": "mehr laden" + "load_more": "mehr laden", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/en@pirate/unread.json b/public/language/en@pirate/unread.json index a4bb2fd315..17e7089fdf 100644 --- a/public/language/en@pirate/unread.json +++ b/public/language/en@pirate/unread.json @@ -1,6 +1,9 @@ { "title": "Unread", "no_unread_topics": "There be no unread topics.", - "mark_all_read": "I seen 'em all!", - "load_more": "Giv'er more" + "load_more": "Giv'er more", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/en_GB/error.json b/public/language/en_GB/error.json index dcab1f9288..584a472327 100644 --- a/public/language/en_GB/error.json +++ b/public/language/en_GB/error.json @@ -5,11 +5,32 @@ "invalid-cid": "Invalid Category ID", "invalid-tid": "Invalid Topic ID", + "invalid-pid": "Invalid Post ID", + "invalid-uid": "Invalid User ID", + + "invalid-username": "Invalid Username", + "invalid-email": "Invalid Email", + "invalid-title": "Invalid title", + "invalid-user-data": "Invalid User Data", + "invalid-password": "Invalid Password", + + "invalid-pagination-value": "Invalid pagination value", + + "username-taken": "Username taken", + "email-taken": "Email taken", + + "user-banned": "User banned", "no-category": "Category doesn't exist", "no-topic": "Topic doesn't exist", + "no-post": "Post doesn't exist", + "no-group": "Group doesn't exist", + "no-user": "User doesn't exist", + "no-teaser": "Teaser doesn't exist", "no-privileges": "You don't have enough privileges for this action.", + "category-disabled": "Category disabled", + "topic-locked": "Topic Locked", "still-uploading" : "Please wait for uploads to complete.", @@ -17,5 +38,32 @@ "title-too-short" : "Please enter a longer title. At least %1 characters.", "title-too-long" : "Please enter a shorter title. Titles can't be longer than %1 characters.", "too-many-posts" : "You can only post every %1 seconds.'", - "file-too-big" : "Maximum allowed file size is %1 kbs" -} \ No newline at end of file + "file-too-big" : "Maximum allowed file size is %1 kbs", + + "cant-vote-self-post": "You cannot vote for your own post", + "already-favourited": "You already favourited this post", + "already-unfavourited": "You alread unfavourited this post", + + "cant-ban-other-admins": "You can't ban other admins!", + + "invalid-image-type": "Invalid image type", + + "group-name-too-short": "Group name too short", + "group-already-exists": "Group already exists", + "group-name-change-not-allowed": "Group name change not allowed", + + "post-already-deleted": "Post already deleted", + "post-already-restored": "Post already restored", + + "topic-already-deleted": "Topic already deleted", + "topic-already-restored": "Topic already restored", + + + "topic-thumbnails-are-disabled": "Topic thumbnails are disabled.", + "invalid-file": "Invalid File", + "uploads-are-disabled": "Uploads are disabled", + + "signature-too-long" : "Signature can't be longer than %1 characters!", + + "cant-chat-with-yourself": "You can't chat with yourself!" +} diff --git a/public/language/en_GB/success.json b/public/language/en_GB/success.json index 397b857c38..d38b90c6fa 100644 --- a/public/language/en_GB/success.json +++ b/public/language/en_GB/success.json @@ -1,4 +1,5 @@ { - "topic-post": "You have successfully posted." + "topic-post": "You have successfully posted.", + "authentication-successful": "Authentication Successful" } \ No newline at end of file diff --git a/public/language/en_GB/topic.json b/public/language/en_GB/topic.json index 1a38c9f776..a11a3b941a 100644 --- a/public/language/en_GB/topic.json +++ b/public/language/en_GB/topic.json @@ -69,15 +69,8 @@ "favourite": "Favourite", "favourites": "Favourites", - "favourites.not_logged_in.title": "Not Logged In", - "favourites.not_logged_in.message": "Please log in in order to favourite this post", "favourites.has_no_favourites": "You don't have any favourites, favourite some posts to see them here!", - "vote.not_logged_in.title": "Not Logged In", - "vote.not_logged_in.message": "Please log in in order to vote", - "vote.cant_vote_self.title": "Invalid Vote", - "vote.cant_vote_self.message": "You cannot vote for your own post", - "loading_more_posts": "Loading More Posts", "move_topic": "Move Topic", "move_post": "Move Post", diff --git a/public/language/en_GB/user.json b/public/language/en_GB/user.json index d7f2d83b2d..110dd9698e 100644 --- a/public/language/en_GB/user.json +++ b/public/language/en_GB/user.json @@ -23,6 +23,7 @@ "follow": "Follow", "unfollow": "Unfollow", + "profile_update_success": "Profile has been updated successfully!", "change_picture": "Change Picture", "edit": "Edit", "uploaded_picture": "Uploaded Picture", diff --git a/public/language/es/unread.json b/public/language/es/unread.json index b06f14f687..29f15be5f2 100644 --- a/public/language/es/unread.json +++ b/public/language/es/unread.json @@ -1,6 +1,9 @@ { "title": "No leído", "no_unread_topics": "No hay temas nuevos para leer.", - "mark_all_read": "Marcar todo como leído", - "load_more": "Cargar más" + "load_more": "Cargar más", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/et/unread.json b/public/language/et/unread.json index a8de01c463..606ffe7fcd 100644 --- a/public/language/et/unread.json +++ b/public/language/et/unread.json @@ -1,6 +1,9 @@ { "title": "Lugemata", "no_unread_topics": "Siin ei ole lugemata teemasi.", - "mark_all_read": "Märgi kõik loetuks", - "load_more": "Lae rohkem" + "load_more": "Lae rohkem", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/fa_IR/unread.json b/public/language/fa_IR/unread.json index fcfe933e92..b65f56a41f 100644 --- a/public/language/fa_IR/unread.json +++ b/public/language/fa_IR/unread.json @@ -1,6 +1,9 @@ { "title": "نخواندهها", "no_unread_topics": "جستار خوانده نشدهای وجود ندارد.", - "mark_all_read": "همه را خوانده شده بگیر", - "load_more": "بارگذاری بیشتر" + "load_more": "بارگذاری بیشتر", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/fi/unread.json b/public/language/fi/unread.json index 928290c7ce..f6f1990845 100644 --- a/public/language/fi/unread.json +++ b/public/language/fi/unread.json @@ -1,6 +1,9 @@ { "title": "Lukematon", "no_unread_topics": "Ei lukemattomia aiheita.", - "mark_all_read": "Merkitse kaikki luetuiksi", - "load_more": "Lataa lisää" + "load_more": "Lataa lisää", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/fr/unread.json b/public/language/fr/unread.json index 69c70b8de9..f48f6def05 100644 --- a/public/language/fr/unread.json +++ b/public/language/fr/unread.json @@ -1,6 +1,9 @@ { "title": "Non Lu", "no_unread_topics": "Aucun sujet non lu.", - "mark_all_read": "Marquer tout comme lu", - "load_more": "Charger la suite" + "load_more": "Charger la suite", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/he/unread.json b/public/language/he/unread.json index e191fbf760..1b4cd01f78 100644 --- a/public/language/he/unread.json +++ b/public/language/he/unread.json @@ -1,6 +1,9 @@ { "title": "לא נקרא", "no_unread_topics": "אין נושאים שלא נקראו", - "mark_all_read": "סמן הכל כנקרא", - "load_more": "טען עוד" + "load_more": "טען עוד", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/hu/unread.json b/public/language/hu/unread.json index 8c3a6a1887..e120ac3948 100644 --- a/public/language/hu/unread.json +++ b/public/language/hu/unread.json @@ -1,6 +1,9 @@ { "title": "Olvasatlan", "no_unread_topics": "Nincsenek olvasatlan topikok.", - "mark_all_read": "Az összes olvasottként jelölése", - "load_more": "Több betöltése" + "load_more": "Több betöltése", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/it/unread.json b/public/language/it/unread.json index 362b11e8f5..bb6af18556 100644 --- a/public/language/it/unread.json +++ b/public/language/it/unread.json @@ -1,6 +1,9 @@ { "title": "Non letto", "no_unread_topics": "Non ci sono discussioni non lette.", - "mark_all_read": "Segna tutto come già letto", - "load_more": "Carica Altro" + "load_more": "Carica Altro", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/nb/unread.json b/public/language/nb/unread.json index 3e3150d7f1..f3a501649c 100644 --- a/public/language/nb/unread.json +++ b/public/language/nb/unread.json @@ -1,6 +1,9 @@ { "title": "Uleste", "no_unread_topics": "Det er ingen uleste emner.", - "mark_all_read": "Marker alle som lest", - "load_more": "Last mer" + "load_more": "Last mer", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/nl/unread.json b/public/language/nl/unread.json index ce0b9a43e9..efee7eb23c 100644 --- a/public/language/nl/unread.json +++ b/public/language/nl/unread.json @@ -1,6 +1,9 @@ { "title": "Ongelezen", "no_unread_topics": "Er zijn geen ongelezen onderwerpen", - "mark_all_read": "Alles markeren als Gelezen", - "load_more": "Meer Laden" + "load_more": "Meer Laden", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/pl/unread.json b/public/language/pl/unread.json index a69a8570a7..74197b2f5a 100644 --- a/public/language/pl/unread.json +++ b/public/language/pl/unread.json @@ -1,6 +1,9 @@ { "title": "Nieprzeczytane", "no_unread_topics": "Nie masz żadnych nieprzeczytanych wątków.", - "mark_all_read": "Oznacz wszystkie jako przeczytane", - "load_more": "Więcej" + "load_more": "Więcej", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/pt_BR/unread.json b/public/language/pt_BR/unread.json index e5f60bcefa..b053b20a6f 100644 --- a/public/language/pt_BR/unread.json +++ b/public/language/pt_BR/unread.json @@ -1,6 +1,9 @@ { "title": "Não Lido", "no_unread_topics": "Todos os tópicos lidos.", - "mark_all_read": "Marcar todos como Lido", - "load_more": "Carregar" + "load_more": "Carregar", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/ru/unread.json b/public/language/ru/unread.json index d1184cb5c8..1f7a121182 100644 --- a/public/language/ru/unread.json +++ b/public/language/ru/unread.json @@ -1,6 +1,9 @@ { "title": "Непрочитанные темы", "no_unread_topics": "Нет непрочитанных тем.", - "mark_all_read": "Отметить все темы как прочитанные", - "load_more": "Загрузить еще" + "load_more": "Загрузить еще", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/sc/unread.json b/public/language/sc/unread.json index 6e0664abfc..db7e78b8c9 100644 --- a/public/language/sc/unread.json +++ b/public/language/sc/unread.json @@ -1,6 +1,9 @@ { "title": "De Lèghere", "no_unread_topics": "Non bi sunt arresonadas de lèghere.", - "mark_all_read": "Signala comente Lèghidos", - "load_more": "Càrriga de Prus" + "load_more": "Càrriga de Prus", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/sk/unread.json b/public/language/sk/unread.json index 252ab9d3e4..99a9b42acf 100644 --- a/public/language/sk/unread.json +++ b/public/language/sk/unread.json @@ -1,6 +1,9 @@ { "title": "Neprečítané", "no_unread_topics": "Nie sú tu žiadne neprečítané témy.", - "mark_all_read": "Označit všetko ako prečítané", - "load_more": "Načítať dalšie" + "load_more": "Načítať dalšie", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/sv/unread.json b/public/language/sv/unread.json index 12701bdde5..4bc578abc8 100644 --- a/public/language/sv/unread.json +++ b/public/language/sv/unread.json @@ -1,6 +1,9 @@ { "title": "Olästa", "no_unread_topics": "Det finns inga ilästa ämnen.", - "mark_all_read": "Markera alla som lästa", - "load_more": "Ladda fler" + "load_more": "Ladda fler", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/th/unread.json b/public/language/th/unread.json index f0d186b444..37451a65ba 100644 --- a/public/language/th/unread.json +++ b/public/language/th/unread.json @@ -1,6 +1,9 @@ { "title": "ไม่ได้อ่าน", "no_unread_topics": "ไม่มีกระทู้ที่ยังไม่ได้อ่านเป็น", - "mark_all_read": "มาร์คทั้งหมดเป็นอ่าน", - "load_more": "โหลดเพิ่มเติม" + "load_more": "โหลดเพิ่มเติม", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/tr/unread.json b/public/language/tr/unread.json index feabfb6e03..0473f2dd3a 100644 --- a/public/language/tr/unread.json +++ b/public/language/tr/unread.json @@ -1,6 +1,9 @@ { "title": "Okunmadı", "no_unread_topics": "Okunmamış başlık mevcut değil.", - "mark_all_read": "Hepsini Okundu Olarak İşaretle", - "load_more": "Daha Fazla" + "load_more": "Daha Fazla", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/zh_CN/unread.json b/public/language/zh_CN/unread.json index b5107e3b47..296a432e01 100644 --- a/public/language/zh_CN/unread.json +++ b/public/language/zh_CN/unread.json @@ -1,6 +1,9 @@ { "title": "未读", "no_unread_topics": "没有未读主题。", - "mark_all_read": "标记全部为已读", - "load_more": "载入更多" + "load_more": "载入更多", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/language/zh_TW/unread.json b/public/language/zh_TW/unread.json index 050c12403d..7f8beef22f 100644 --- a/public/language/zh_TW/unread.json +++ b/public/language/zh_TW/unread.json @@ -1,6 +1,9 @@ { "title": "未讀", "no_unread_topics": "沒有未讀主題。", - "mark_all_read": "標記全部為已讀", - "load_more": "載入更多" + "load_more": "載入更多", + "mark_as_read": "Mark as Read", + "selected": "Selected", + "all": "All", + "topics_marked_as_read.success": "Topics marked as read!" } \ No newline at end of file diff --git a/public/src/app.js b/public/src/app.js index 86e6033c45..108635da2e 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -320,25 +320,11 @@ var socket, app.openChat = function (username, touid) { if (username === app.username) { - app.alert({ - type: 'warning', - title: 'Invalid Chat', - message: "You can't chat with yourself!", - timeout: 5000 - }); - - return; + return app.alertError('[[error:cant-chat-with-yourself]]'); } if (!app.uid) { - app.alert({ - type: 'danger', - title: 'Not Logged In', - message: 'Please log in to chat with <strong>' + username + '</strong>', - timeout: 5000 - }); - - return; + return app.alertError('[[error:not-logged-in]]'); } require(['chat'], function (chat) { diff --git a/public/src/forum/accountedit.js b/public/src/forum/accountedit.js index 701c97ff74..071cb31a3a 100644 --- a/public/src/forum/accountedit.js +++ b/public/src/forum/accountedit.js @@ -1,82 +1,82 @@ +'use strict'; + +/* globals define, ajaxify, socket, app, config, utils, translator */ + define(['forum/accountheader', 'uploader'], function(header, uploader) { var AccountEdit = {}, gravatarPicture = '', - uploadedPicture = ''; + uploadedPicture = '', + selectedImageType = ''; AccountEdit.init = function() { - header.init(); - gravatarPicture = ajaxify.variables.get('gravatarpicture'); uploadedPicture = ajaxify.variables.get('uploadedpicture'); - var selectedImageType = ''; - - $('#submitBtn').on('click', function() { + header.init(); - var userData = { - uid: $('#inputUID').val(), - username: $('#inputUsername').val(), - email: $('#inputEmail').val(), - fullname: $('#inputFullname').val(), - website: $('#inputWebsite').val(), - birthday: $('#inputBirthday').val(), - location: $('#inputLocation').val(), - signature: $('#inputSignature').val() - }; + $('#submitBtn').on('click', updateProfile); - socket.emit('user.updateProfile', userData, function(err, data) { - if(err) { - return app.alertError(err.message); - } + handleImageChange(); + handleImageUpload(); + handlePasswordChange(); + updateSignature(); + }; - if (!data) { - return app.alertError('There was an error updating the profile!'); - } + function updateProfile() { + var userData = { + uid: $('#inputUID').val(), + username: $('#inputUsername').val(), + email: $('#inputEmail').val(), + fullname: $('#inputFullname').val(), + website: $('#inputWebsite').val(), + birthday: $('#inputBirthday').val(), + location: $('#inputLocation').val(), + signature: $('#inputSignature').val() + }; - app.alertSuccess('Profile has been updated successfully!'); - if (data.picture) { - $('#user-current-picture').attr('src', data.picture); - $('#user_label img').attr('src', data.picture); - } + socket.emit('user.updateProfile', userData, function(err, data) { + if (err) { + return app.alertError(err.message); + } - if (data.gravatarpicture) { - $('#user-gravatar-picture').attr('src', data.gravatarpicture); - gravatarPicture = data.gravatarpicture; - } + app.alertSuccess('[[user:profile_update_success]]'); - if(data.userslug) { - var oldslug = $('.account-username-box').attr('data-userslug'); - $('.account-username-box a').each(function(index) { - $(this).attr('href', $(this).attr('href').replace(oldslug, data.userslug)); - }); + if (data.picture) { + $('#user-current-picture').attr('src', data.picture); + $('#user_label img').attr('src', data.picture); + } - $('.account-username-box').attr('data-userslug', data.userslug); + if (data.gravatarpicture) { + $('#user-gravatar-picture').attr('src', data.gravatarpicture); + gravatarPicture = data.gravatarpicture; + } - $('#user-profile-link').attr('href', config.relative_path + '/user/' + data.userslug); - $('#user-profile-link span').html(' ' + userData.username); - } - }); - return false; - }); + if (data.userslug) { + var oldslug = $('.account-username-box').attr('data-userslug'); + $('.account-username-box a').each(function(index) { + $(this).attr('href', $(this).attr('href').replace(oldslug, data.userslug)); + }); + $('.account-username-box').attr('data-userslug', data.userslug); - function getSignatureCharsLeft() { - if($('#inputSignature').length) { - return '(' + $('#inputSignature').val().length + '/' + config.maximumSignatureLength + ')'; - } else { - return ''; + $('#user-profile-link').attr('href', config.relative_path + '/user/' + data.userslug); + $('#user-profile-link span').html(' ' + userData.username); } - } + }); - $('#signatureCharCountLeft').html(getSignatureCharsLeft()); + return false; + } - $('#inputSignature').on('keyup change', function(ev) { - $('#signatureCharCountLeft').html(getSignatureCharsLeft()); - }); + function handleImageChange() { + function selectImageType(type) { + $('#gravatar-box .fa-check').toggle(type === 'gravatar'); + $('#uploaded-box .fa-check').toggle(type === 'uploaded'); + selectedImageType = type; + } $('#changePictureBtn').on('click', function() { selectedImageType = ''; - AccountEdit.updateImages(); + updateImages(); $('#change-picture-modal').modal('show'); $('#change-picture-modal').removeClass('hide'); @@ -85,31 +85,29 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) { }); $('#gravatar-box').on('click', function() { - $('#gravatar-box .fa-check').show(); - $('#uploaded-box .fa-check').hide(); - selectedImageType = 'gravatar'; + selectImageType('gravatar'); }); $('#uploaded-box').on('click', function() { - $('#gravatar-box .fa-check').hide(); - $('#uploaded-box .fa-check').show(); - selectedImageType = 'uploaded'; + selectImageType('uploaded'); }); $('#savePictureChangesBtn').on('click', function() { $('#change-picture-modal').modal('hide'); if (selectedImageType) { - AccountEdit.changeUserPicture(selectedImageType); + changeUserPicture(selectedImageType); - if (selectedImageType == 'gravatar') + if (selectedImageType === 'gravatar') { $('#user-current-picture').attr('src', gravatarPicture); - else if (selectedImageType == 'uploaded') + } else if (selectedImageType === 'uploaded') { $('#user-current-picture').attr('src', uploadedPicture); + } } - }); + } + function handleImageUpload() { $('#upload-picture-modal').on('hide', function() { $('#userPhotoInput').val(''); }); @@ -117,7 +115,7 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) { $('#uploadPictureBtn').on('click', function() { $('#change-picture-modal').modal('hide'); - uploader.open(RELATIVE_PATH + '/user/uploadpicture', {uid: ajaxify.variables.get('theirid')}, config.maximumProfileImageSize, function(imageUrlOnServer) { + uploader.open(config.relative_path + '/user/uploadpicture', {uid: ajaxify.variables.get('theirid')}, config.maximumProfileImageSize, function(imageUrlOnServer) { imageUrlOnServer = imageUrlOnServer + '?' + new Date().getTime(); $('#user-current-picture').attr('src', imageUrlOnServer); @@ -130,137 +128,129 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) { }, app.updateHeader); }); - return false; }); + } - function showError(element, msg) { - translator.translate(msg, function(msg) { - element.html(msg); - element.parent() - .removeClass('alert-success') - .addClass('alert-danger'); - element.show(); - validationError = true; - }); - } - - function showSuccess(element, msg) { - translator.translate(msg, function(msg) { - element.html(msg); - element.parent() - .removeClass('alert-danger') - .addClass('alert-success'); - element.show(); - }); + function handlePasswordChange() { + var currentPassword = $('#inputCurrentPassword'); + var password_notify = $('#password-notify'); + var password_confirm_notify = $('#password-confirm-notify'); + var password = $('#inputNewPassword'); + var password_confirm = $('#inputNewPasswordAgain'); + var passwordvalid = false; + var passwordsmatch = false; + var successIcon = '<i class="fa fa-check"></i>'; + + function onPasswordChanged() { + passwordvalid = utils.isPasswordValid(password.val()); + if (password.val().length < config.minimumPasswordLength) { + showError(password_notify, '[[user:change_password_error_length]]'); + } else if (!passwordvalid) { + showError(password_notify, '[[user:change_password_error]]'); + } else { + showSuccess(password_notify, successIcon); + } } - (function handlePasswordChange() { - var currentPassword = $('#inputCurrentPassword'); - var password_notify = $('#password-notify'); - var password_confirm_notify = $('#password-confirm-notify'); - var password = $('#inputNewPassword'); - var password_confirm = $('#inputNewPasswordAgain'); - var passwordvalid = false; - var passwordsmatch = false; - var successIcon = '<i class="fa fa-check"></i>'; - - - function onPasswordChanged() { - passwordvalid = utils.isPasswordValid(password.val()); - if (password.val().length < config.minimumPasswordLength) { - showError(password_notify, '[[user:change_password_error_length]]'); - } else if (!passwordvalid) { - showError(password_notify, '[[user:change_password_error]]'); + function onPasswordConfirmChanged() { + if(password.val()) { + if (password.val() !== password_confirm.val()) { + showError(password_confirm_notify, '[[user:change_password_error_match]]'); + passwordsmatch = false; } else { - showSuccess(password_notify, successIcon); + showSuccess(password_confirm_notify, successIcon); + passwordsmatch = true; } } + } - function onPasswordConfirmChanged() { - if(password.val()) { - if (password.val() !== password_confirm.val()) { - showError(password_confirm_notify, '[[user:change_password_error_match]]') - passwordsmatch = false; - } else { - showSuccess(password_confirm_notify, successIcon); - passwordsmatch = true; + password.on('blur', onPasswordChanged); + password_confirm.on('blur', onPasswordConfirmChanged); + + $('#changePasswordBtn').on('click', function() { + if ((passwordvalid && passwordsmatch) || app.isAdmin) { + socket.emit('user.changePassword', { + 'currentPassword': currentPassword.val(), + 'newPassword': password.val(), + 'uid': ajaxify.variables.get('theirid') + }, function(err) { + currentPassword.val(''); + password.val(''); + password_confirm.val(''); + passwordsmatch = false; + passwordvalid = false; + + if (err) { + return app.alertError(err.message); } - } - } - - password.on('blur', onPasswordChanged); - password_confirm.on('blur', onPasswordConfirmChanged); - - $('#changePasswordBtn').on('click', function() { - if ((passwordvalid && passwordsmatch) || app.isAdmin) { - socket.emit('user.changePassword', { - 'currentPassword': currentPassword.val(), - 'newPassword': password.val(), - 'uid': ajaxify.variables.get('theirid') - }, function(err) { - currentPassword.val(''); - password.val(''); - password_confirm.val(''); - passwordsmatch = false; - passwordvalid = false; - - if (err) { - return app.alertError(err.message); - } - - app.alertSuccess('[[user:change_password_success]]'); - }); - } - return false; - }); - - }()); - }; + app.alertSuccess('[[user:change_password_success]]'); + }); + } + return false; + }); + } - AccountEdit.changeUserPicture = function(type) { - var userData = { + function changeUserPicture(type) { + socket.emit('user.changePicture', { type: type, uid: ajaxify.variables.get('theirid') - }; - - socket.emit('user.changePicture', userData, function(err) { + }, function(err) { if(err) { app.alertError(err.message); } }); } - AccountEdit.updateImages = function() { + function updateImages() { var currentPicture = $('#user-current-picture').attr('src'); if (gravatarPicture) { $('#user-gravatar-picture').attr('src', gravatarPicture); - $('#gravatar-box').show(); - } else { - $('#gravatar-box').hide(); } if (uploadedPicture) { $('#user-uploaded-picture').attr('src', uploadedPicture); - $('#uploaded-box').show(); - } else { - $('#uploaded-box').hide(); } + $('#gravatar-box').toggle(!!gravatarPicture); + $('#uploaded-box').toggle(!!uploadedPicture); - if (currentPicture == gravatarPicture) { - $('#gravatar-box .fa-check').show(); - } else { - $('#gravatar-box .fa-check').hide(); - } + $('#gravatar-box .fa-check').toggle(currentPicture === gravatarPicture); + $('#uploaded-box .fa-check').toggle(currentPicture === uploadedPicture); + } - if (currentPicture == uploadedPicture) { - $('#uploaded-box .fa-check').show(); - } else { - $('#uploaded-box .fa-check').hide(); + function updateSignature() { + function getSignatureCharsLeft() { + return $('#inputSignature').length ? '(' + $('#inputSignature').val().length + '/' + config.maximumSignatureLength + ')' : ''; } + + $('#signatureCharCountLeft').html(getSignatureCharsLeft()); + + $('#inputSignature').on('keyup change', function(ev) { + $('#signatureCharCountLeft').html(getSignatureCharsLeft()); + }); + } + + function showError(element, msg) { + translator.translate(msg, function(msg) { + element.html(msg); + element.parent() + .removeClass('alert-success') + .addClass('alert-danger'); + element.show(); + }); + } + + function showSuccess(element, msg) { + translator.translate(msg, function(msg) { + element.html(msg); + element.parent() + .removeClass('alert-danger') + .addClass('alert-success'); + element.show(); + }); } return AccountEdit; diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 6df80606ea..ab9eb9d7ad 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -143,7 +143,7 @@ define(['forum/pagination', 'forum/topic/threadTools', 'forum/topic/postTools', ajaxify.register_events([ - 'event:rep_up', 'event:rep_down', 'event:favourited', 'event:unfavourited', 'event:new_post', 'get_users_in_room', + 'event:voted', 'event:favourited', 'event:new_post', 'get_users_in_room', 'event:topic_deleted', 'event:topic_restored', 'event:topic:locked', 'event:topic_unlocked', 'event:topic_pinned', 'event:topic_unpinned', 'event:topic_moved', 'event:post_edited', 'event:post_deleted', 'event:post_restored', @@ -241,20 +241,12 @@ define(['forum/pagination', 'forum/topic/threadTools', 'forum/topic/postTools', app.populateOnlineUsers(); }); - socket.on('event:rep_up', function(data) { - adjust_rep(1, data.pid, data.uid); - }); - - socket.on('event:rep_down', function(data) { - adjust_rep(-1, data.pid, data.uid); + socket.on('event:voted', function(data) { + updatePostVotesAndUserReputation(data); }); socket.on('event:favourited', function(data) { - adjust_favourites(1, data.pid, data.uid); - }); - - socket.on('event:unfavourited', function(data) { - adjust_favourites(-1, data.pid, data.uid); + updateFavouriteCount(data.post.pid, data.post.reputation); }); socket.on('event:new_post', function(data) { @@ -338,37 +330,31 @@ define(['forum/pagination', 'forum/topic/threadTools', 'forum/topic/postTools', }); }); - socket.on('posts.upvote', function(data) { - if (data && data.pid) { - $('li[data-pid="' + data.pid + '"] .upvote').addClass('btn-primary upvoted'); - } + socket.on('posts.upvote', function(pid) { + toggleUpvoteDownvote(pid, true, false); }); - socket.on('posts.downvote', function(data) { - if (data && data.pid) { - $('li[data-pid="' + data.pid + '"] .downvote').addClass('btn-primary downvoted'); - } + socket.on('posts.downvote', function(pid) { + toggleUpvoteDownvote(pid, false, true); }); - socket.on('posts.unvote', function(data) { - if (data && data.pid) { - var post = $('li[data-pid="' + data.pid + '"]'); - - post.find('.upvote').removeClass('btn-primary upvoted'); - post.find('.downvote').removeClass('btn-primary downvoted'); - } + socket.on('posts.unvote', function(pid) { + toggleUpvoteDownvote(pid, false, false); }); - socket.on('posts.favourite', function(data) { - if (data && data.pid) { - toggleFavourite(data.pid, true); - } + function toggleUpvoteDownvote(pid, upvote, downvote) { + var post = $('li[data-pid="' + pid + '"]'); + + post.find('.upvote').toggleClass('btn-primary upvoted', upvote); + post.find('.downvote').toggleClass('btn-primary downvoted', downvote); + } + + socket.on('posts.favourite', function(pid) { + toggleFavourite(pid, true); }); - socket.on('posts.unfavourite', function(data) { - if (data && data.pid) { - toggleFavourite(data.pid, false); - } + socket.on('posts.unfavourite', function(pid) { + toggleFavourite(pid, false); }); function toggleFavourite(pid, isFavourited) { @@ -406,26 +392,16 @@ define(['forum/pagination', 'forum/topic/threadTools', 'forum/topic/postTools', $('.thread_active_users [data-uid="' + uid + '"]').removeClass('replying'); }); - function adjust_rep(value, pid, uid) { - var votes = $('li[data-pid="' + pid + '"] .votes'), - reputationElements = $('.reputation[data-uid="' + uid + '"]'), - currentVotes = parseInt(votes.attr('data-votes'), 10), - reputation = parseInt(reputationElements.attr('data-reputation'), 10); - - currentVotes += value; - reputation += value; + function updatePostVotesAndUserReputation(data) { + var votes = $('li[data-pid="' + data.post.pid + '"] .votes'), + reputationElements = $('.reputation[data-uid="' + data.post.uid + '"]'); - votes.html(currentVotes).attr('data-votes', currentVotes); - reputationElements.html(reputation).attr('data-reputation', reputation); + votes.html(data.post.votes).attr('data-votes', data.post.votes); + reputationElements.html(data.user.reputation).attr('data-reputation', data.user.reputation); } - function adjust_favourites(value, pid, uid) { - var favourites = $('li[data-pid="' + pid + '"] .favouriteCount'), - currentFavourites = parseInt(favourites.attr('data-favourites'), 10); - - currentFavourites += value; - - favourites.html(currentFavourites).attr('data-favourites', currentFavourites); + function updateFavouriteCount(pid, value) { + $('li[data-pid="' + pid + '"] .favouriteCount').html(value).attr('data-favourites', value); } function set_locked_state(locked, alert) { diff --git a/public/src/forum/topic/postTools.js b/public/src/forum/topic/postTools.js index 36243dad79..bbe9a109ca 100644 --- a/public/src/forum/topic/postTools.js +++ b/public/src/forum/topic/postTools.js @@ -111,6 +111,10 @@ define(['composer', 'share'], function(composer, share) { socket.emit(method, { pid: pid, room_id: app.currentRoom + }, function(err) { + if (err) { + app.alertError(err.message); + } }); return false; @@ -123,6 +127,10 @@ define(['composer', 'share'], function(composer, share) { socket.emit(currentState ? 'posts.unvote' : method , { pid: post.attr('data-pid'), room_id: app.currentRoom + }, function(err) { + if (err) { + app.alertError(err.message); + } }); return false; diff --git a/src/categories.js b/src/categories.js index 809c77c8e5..409e8e7aeb 100644 --- a/src/categories.js +++ b/src/categories.js @@ -64,7 +64,7 @@ var db = require('./database'), Categories.getCategoryById = function(cid, start, end, uid, callback) { Categories.getCategoryData(cid, function(err, category) { if(err || !category) { - return callback(err || new Error('category-not-found [' + cid + ']')); + return callback(err || new Error('[[error:invalid-cid]]')); } if(parseInt(uid, 10)) { @@ -278,7 +278,7 @@ var db = require('./database'), Categories.getCategories = function(cids, uid, callback) { if (!Array.isArray(cids) || cids.length === 0) { - return callback(new Error('invalid-cids')); + return callback(new Error('[[error:invalid-cid]]')); } async.parallel({ diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index 369449e9aa..518c170445 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -33,7 +33,7 @@ function userNotAllowed(res) { function getUserDataByUserSlug(userslug, callerUID, callback) { user.getUidByUserslug(userslug, function(err, uid) { if(err || !uid) { - return callback(err || new Error('invalid-user')); + return callback(err || new Error('[[error:invalid-uid]]')); } async.parallel({ @@ -54,7 +54,7 @@ function getUserDataByUserSlug(userslug, callerUID, callback) { } }, function(err, results) { if(err || !results.userData) { - return callback(err || new Error('invalid-user')); + return callback(err || new Error('[[error:invalid-uid]]')); } var userData = results.userData; diff --git a/src/controllers/categories.js b/src/controllers/categories.js index 93112a2524..f30dcc13b3 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -70,7 +70,7 @@ categoriesController.get = function(req, res, next) { categoryTools.privileges(cid, uid, function(err, categoryPrivileges) { if (!err) { if (!categoryPrivileges.read) { - next(new Error('not-enough-privileges')); + next(new Error('[[error:no-privileges]]')); } else { next(null, categoryPrivileges); } @@ -95,7 +95,7 @@ categoriesController.get = function(req, res, next) { if (categoryData) { if (parseInt(categoryData.disabled, 10) === 1) { - return next(new Error('Category disabled'), null); + return next(new Error('[[error:category-disabled]]')); } } diff --git a/src/controllers/topics.js b/src/controllers/topics.js index aa5488295d..5fdf606d47 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -26,7 +26,7 @@ topicsController.get = function(req, res, next) { } if (!userPrivileges.read) { - return next(new Error('not-enough-privileges')); + return next(new Error('[[error:no-privileges]]')); } privileges = userPrivileges; @@ -45,7 +45,7 @@ topicsController.get = function(req, res, next) { topics.getTopicWithPosts(tid, uid, start, end, function (err, topicData) { if (topicData) { if (parseInt(topicData.deleted, 10) === 1 && parseInt(topicData.expose_tools, 10) === 0) { - return next(new Error('Topic deleted')); + return next(new Error('[[error:no-topic]]')); } topicData.currentPage = page; } diff --git a/src/database/mongo.js b/src/database/mongo.js index aaf161ee42..e792d41b1a 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -538,21 +538,15 @@ getSortedSetRange(key, start, stop, -1, callback); }; - module.getSortedSetRangeByScore = function(args, callback) { - getSortedSetRangeByScore(args, 1, callback); + module.getSortedSetRangeByScore = function(key, start, count, min, max, callback) { + getSortedSetRangeByScore(key, start, count, min, max, 1, callback); }; - module.getSortedSetRevRangeByScore = function(args, callback) { - getSortedSetRangeByScore(args, -1, callback); + module.getSortedSetRevRangeByScore = function(key, start, count, max, min, callback) { + getSortedSetRangeByScore(key, start, count, min, max, -1, callback); }; - function getSortedSetRangeByScore(args, sort, callback) { - var key = args[0], - max = (args[1] === '+inf') ? Number.MAX_VALUE : args[1], - min = args[2], - start = args[4], - count = args[5]; - + function getSortedSetRangeByScore(key, start, count, min, max, sort, callback) { if(parseInt(count, 10) === -1) { count = 0; } diff --git a/src/database/redis.js b/src/database/redis.js index 90daed3e74..f14863a83b 100644 --- a/src/database/redis.js +++ b/src/database/redis.js @@ -359,12 +359,12 @@ redisClient.zrevrange(key, start, stop, callback); }; - module.getSortedSetRangeByScore = function(args, callback) { - redisClient.zrangebyscore(args, callback); + module.getSortedSetRangeByScore = function(key, start, count, min, max, callback) { + redisClient.zrangebyscore([key, min, max, 'LIMIT', start, count], callback); }; - module.getSortedSetRevRangeByScore = function(args, callback) { - redisClient.zrevrangebyscore(args, callback); + module.getSortedSetRevRangeByScore = function(key, start, count, max, min, callback) { + redisClient.zrevrangebyscore([key, max, min, 'LIMIT', start, count], callback); }; module.sortedSetCount = function(key, min, max, callback) { diff --git a/src/favourites.js b/src/favourites.js index 67c52b8d8c..30ef254cfb 100644 --- a/src/favourites.js +++ b/src/favourites.js @@ -8,67 +8,50 @@ var async = require('async'), (function (Favourites) { "use strict"; - function vote(type, unvote, pid, room_id, uid, socket, callback) { - var websockets = require('./socket.io'); + function vote(type, unvote, pid, uid, callback) { + uid = parseInt(uid, 10); if (uid === 0) { - return socket.emit('event:alert', { - alert_id: 'post_vote', - title: '[[topic:vote.not_logged_in.title]]', - message: '[[topic:vote.not_logged_in.message]]', - type: 'danger', - timeout: 5000 - }); + return callback(new Error('[[error:not-logged-in]]')); } - posts.getPostFields(pid, ['uid', 'timestamp'], function (err, postData) { - if (uid === parseInt(postData.uid, 10)) { - socket.emit('event:alert', { - alert_id: 'post_vote', - title: '[[topic:vote.cant_vote_self.title]]', - message: '[[topic:vote.cant_vote_self.message]]', - type: 'danger', - timeout: 5000 - }); - - if (callback) { - callback(false); - } + posts.getPostFields(pid, ['pid', 'uid', 'timestamp'], function (err, postData) { + if (err) { + return callback(err); + } - return false; + if (uid === parseInt(postData.uid, 10)) { + return callback(new Error('[[error:cant-vote-self-post]]')); } - if(type === 'upvote' || !unvote) { - db.sortedSetAdd('uid: ' + uid + ':upvote', postData.timestamp, pid); + if(type === 'upvote' && !unvote) { + db.sortedSetAdd('uid:' + uid + ':upvote', postData.timestamp, pid); } else { - db.sortedSetRemove('uid: ' + uid + ':upvote', pid); + db.sortedSetRemove('uid:' + uid + ':upvote', pid); } if(type === 'upvote' || unvote) { - db.sortedSetRemove('uid: ' + uid + ':downvote', pid); + db.sortedSetRemove('uid:' + uid + ':downvote', pid); } else { - db.sortedSetAdd('uid: ' + uid + ':downvote', postData.timestamp, pid); + db.sortedSetAdd('uid:' + uid + ':downvote', postData.timestamp, pid); } user[type === 'upvote' ? 'incrementUserFieldBy' : 'decrementUserFieldBy'](postData.uid, 'reputation', 1, function (err, newreputation) { + if (err) { + return callback(err); + } + db.sortedSetAdd('users:reputation', newreputation, postData.uid); - }); - if (room_id) { - websockets.in(room_id).emit('event:' + (type === 'upvote' ? 'rep_up' : 'rep_down'), { - uid: postData.uid, - pid: pid + adjustPostVotes(pid, uid, type, unvote, function(err, votes) { + postData.votes = votes; + callback(err, { + user: { + reputation: newreputation + }, + post: postData + }); }); - } - - socket.emit('posts.' + (unvote ? 'unvote' : type), { - pid: pid - }); - - adjustPostVotes(pid, uid, type, unvote, function() { - if (callback) { - callback(); - } }); }); } @@ -79,21 +62,19 @@ var async = require('async'), async.series([ function(next) { if (unvote) { - db.setRemove('pid:' + pid + ':' + type, uid, function(err) { - next(err); - }); + db.setRemove('pid:' + pid + ':' + type, uid, next); } else { - db.setAdd('pid:' + pid + ':' + type, uid, function(err) { - next(err); - }); + db.setAdd('pid:' + pid + ':' + type, uid, next); } }, function(next) { - db.setRemove('pid:' + pid + ':' + notType, uid, function(err) { - next(err); - }); + db.setRemove('pid:' + pid + ':' + notType, uid, next); } ], function(err) { + if (err) { + return callback(err); + } + async.parallel({ upvotes: function(next) { db.setCount('pid:' + pid + ':upvote', next); @@ -102,48 +83,46 @@ var async = require('async'), db.setCount('pid:' + pid + ':downvote', next); } }, function(err, results) { - posts.setPostField(pid, 'votes', parseInt(results.upvotes, 10) - parseInt(results.downvotes, 10)); + if (err) { + return callback(err); + } + var voteCount = parseInt(results.upvotes, 10) - parseInt(results.downvotes, 10); + posts.setPostField(pid, 'votes', voteCount, function(err) { + callback(err, voteCount); + }); }); - - if (callback) { - callback(); - } }); } - Favourites.upvote = function(pid, room_id, uid, socket) { - toggleVote('upvote', pid, room_id, uid, socket); + Favourites.upvote = function(pid, uid, callback) { + toggleVote('upvote', pid, uid, callback); }; - Favourites.downvote = function(pid, room_id, uid, socket) { - toggleVote('downvote', pid, room_id, uid, socket); + Favourites.downvote = function(pid, uid, callback) { + toggleVote('downvote', pid, uid, callback); }; - function toggleVote(type, pid, room_id, uid, socket) { - Favourites.unvote(pid, room_id, uid, socket, function(err) { - vote(type, false, pid, room_id, uid, socket); + function toggleVote(type, pid, uid, callback) { + Favourites.unvote(pid, uid, function(err) { + if (err) { + return callback(err); + } + + vote(type, false, pid, uid, callback); }); } - Favourites.unvote = function(pid, room_id, uid, socket, callback) { - var websockets = require('./socket.io'); - + Favourites.unvote = function(pid, uid, callback) { Favourites.hasVoted(pid, uid, function(err, voteStatus) { - if (voteStatus.upvoted || voteStatus.downvoted) { - socket.emit('posts.unvote', { - pid: pid - }); - - return vote(voteStatus.upvoted ? 'downvote' : 'upvote', true, pid, room_id, uid, socket, function() { - if (callback) { - callback(err); - } - }); + if (err) { + return callback(err); } - if (callback) { - callback(err); + if (!voteStatus || (!voteStatus.upvoted && !voteStatus.downvoted)) { + return callback(); } + + vote(voteStatus.upvoted ? 'downvote' : 'upvote', true, pid, uid, callback); }); }; @@ -164,77 +143,64 @@ var async = require('async'), }, callback); }; - Favourites.favourite = function (pid, room_id, uid, socket) { - var websockets = require('./socket.io'); + Favourites.favourite = function (pid, uid, callback) { + toggleFavourite('favourite', pid, uid, callback); + }; + + Favourites.unfavourite = function(pid, uid, callback) { + toggleFavourite('unfavourite', pid, uid, callback); + }; + function toggleFavourite(type, pid, uid, callback) { if (uid === 0) { - return socket.emit('event:alert', { - alert_id: 'post_favourite', - title: '[[topic:favourites.not_logged_in.title]]', - message: '[[topic:favourites.not_logged_in.message]]', - type: 'danger', - timeout: 5000 - }); + return callback(new Error('[[error:not-logged-in]]')); } - posts.getPostFields(pid, ['uid', 'timestamp'], function (err, postData) { - Favourites.hasFavourited(pid, uid, function (err, hasFavourited) { - if (!hasFavourited) { - db.sortedSetAdd('uid:' + uid + ':favourites', postData.timestamp, pid); - db.setAdd('pid:' + pid + ':users_favourited', uid, function(err) { - db.setCount('pid:' + pid + ':users_favourited', function(err, count) { - posts.setPostField(pid, 'reputation', count); - }); - }); - - if (room_id) { - websockets.in(room_id).emit('event:favourited', { - uid: uid !== postData.uid ? postData.uid : 0, - pid: pid - }); - } + posts.getPostFields(pid, ['pid', 'uid', 'timestamp'], function (err, postData) { + if (err) { + return callback(err); + } - socket.emit('posts.favourite', { - pid: pid - }); + Favourites.hasFavourited(pid, uid, function (err, hasFavourited) { + if (err) { + return callback(err); } - }); - }); - }; - Favourites.unfavourite = function(pid, room_id, uid, socket) { - var websockets = require('./socket.io'); + if (type === 'favourite' && hasFavourited) { + return callback(new Error('[[error:already-favourited]]')); + } - if (uid === 0) { - return; - } + if (type === 'unfavourite' && !hasFavourited) { + return callback(new Error('[[error:alrady-unfavourited]]')); + } - posts.getPostField(pid, 'uid', function (err, uid_of_poster) { - Favourites.hasFavourited(pid, uid, function (err, hasFavourited) { - if (hasFavourited) { + if (type === 'favourite') { + db.sortedSetAdd('uid:' + uid + ':favourites', postData.timestamp, pid); + } else { db.sortedSetRemove('uid:' + uid + ':favourites', pid); - db.setRemove('pid:' + pid + ':users_favourited', uid, function(err) { - db.setCount('pid:' + pid + ':users_favourited', function(err, count) { - posts.setPostField(pid, 'reputation', count); - }); - }); + } - if (room_id) { - websockets.in(room_id).emit('event:unfavourited', { - uid: uid !== uid_of_poster ? uid_of_poster : 0, - pid: pid - }); + + db[type === 'favourite' ? 'setAdd' : 'setRemove']('pid:' + pid + ':users_favourited', uid, function(err) { + if (err) { + return callback(err); } - if (socket) { - socket.emit('posts.unfavourite', { - pid: pid + db.setCount('pid:' + pid + ':users_favourited', function(err, count) { + if (err) { + return callback(err); + } + postData.reputation = count; + posts.setPostField(pid, 'reputation', count, function(err) { + callback(err, { + post: postData + }); }); - } - } + }); + }); }); }); - }; + } Favourites.hasFavourited = function(pid, uid, callback) { db.isSetMember('pid:' + pid + ':users_favourited', uid, callback); diff --git a/src/groups.js b/src/groups.js index 24894ff7fb..6501b3dc66 100644 --- a/src/groups.js +++ b/src/groups.js @@ -137,7 +137,7 @@ Groups.create = function(name, description, callback) { if (name.length === 0) { - return callback(new Error('name-too-short')); + return callback(new Error('[[error:group-name-too-short]]')); } if (name === 'administrators' || name === 'registered-users') { @@ -145,28 +145,32 @@ } Groups.exists(name, function (err, exists) { - if (!exists) { - var groupData = { - name: name, - description: description, - deleted: '0', - hidden: '0', - system: system ? '1' : '0' - }; + if (err) { + return callback(err); + } - async.parallel([ - function(next) { - db.setAdd('groups', name, next); - }, - function(next) { - db.setObject('group:' + name, groupData, function(err) { - Groups.get(name, {}, next); - }); - } - ], callback); - } else { - callback(new Error('group-exists')); + if (exists) { + return callback(new Error('[[error:group-already-exists]]')); } + + var groupData = { + name: name, + description: description, + deleted: '0', + hidden: '0', + system: system ? '1' : '0' + }; + + async.parallel([ + function(next) { + db.setAdd('groups', name, next); + }, + function(next) { + db.setObject('group:' + name, groupData, function(err) { + Groups.get(name, {}, next); + }); + } + ], callback); }); }; @@ -184,12 +188,12 @@ db.setObject('group:' + groupName, values, callback); } else { if (callback) { - callback(new Error('name-change-not-allowed')); + callback(new Error('[[error:group-name-change-not-allowed]]')); } } } else { if (callback) { - callback(new Error('gid-not-found')); + callback(new Error('[[error:no-group]]')); } } }); diff --git a/src/postTools.js b/src/postTools.js index 7ecf7387ba..3cb73e2282 100644 --- a/src/postTools.js +++ b/src/postTools.js @@ -120,7 +120,7 @@ var winston = require('winston'), PostTools.privileges(pid, uid, function(err, privileges) { if (err || !privileges.editable) { - return callback(err || new Error('not-privileges-to-edit')); + return callback(err || new Error('[[error:no-privileges]]')); } posts.getPostData(pid, function(err, postData) { @@ -155,15 +155,15 @@ var winston = require('winston'), }, function(deleted, next) { if(parseInt(deleted, 10) === 1 && isDelete) { - return next(new Error('Post already deleted')); + return next(new Error('[[error:post-already-deleted]]')); } else if(parseInt(deleted, 10) !== 1 && !isDelete) { - return next(new Error('Post already restored')); + return next(new Error('[[error:post-already-restored]]')); } PostTools.privileges(pid, uid, next); }, function(privileges, next) { if (!privileges || !privileges.editable) { - return next(new Error('no privileges')); + return next(new Error('[[error:no-privileges]]')); } next(); } diff --git a/src/posts.js b/src/posts.js index 08603611ea..d35cd12e5d 100644 --- a/src/posts.js +++ b/src/posts.js @@ -30,7 +30,7 @@ var db = require('./database'), toPid = data.toPid; if (uid === null) { - return callback(new Error('invalid-user')); + return callback(new Error('[[error:invalid-uid]]')); } var timestamp = Date.now(), @@ -210,7 +210,7 @@ var db = require('./database'), var count = parseInt(stop, 10) === -1 ? stop : stop - start + 1; - db.getSortedSetRevRangeByScore(['posts:pid', '+inf', Date.now() - since, 'LIMIT', start, count], function(err, pids) { + db.getSortedSetRevRangeByScore('posts:pid', start, count, Infinity, Date.now() - since, function(err, pids) { if(err) { return callback(err); } @@ -420,7 +420,7 @@ var db = require('./database'), topics.getTopicField(tid, 'cid', function(err, cid) { if(err || !cid) { - return callback(err || new Error('invalid-category-id')); + return callback(err || new Error('[[error:invalid-cid]]')); } callback(null, cid); }); @@ -458,7 +458,7 @@ var db = require('./database'), Posts.getPidPage = function(pid, uid, callback) { if(!pid) { - return callback(new Error('invalid-pid')); + return callback(new Error('[[error:invalid-pid]]')); } var index = 0; diff --git a/src/routes/api.js b/src/routes/api.js index 909f142863..54c72e3e45 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -63,14 +63,14 @@ function uploadPost(req, res, next) { function uploadThumb(req, res, next) { if (!meta.config.allowTopicsThumbnail) { deleteTempFiles(req.files.files); - return callback(new Error('Topic Thumbnails are disabled!')); + return callback(new Error('[[error:topic-thumbnails-are-disabled]]')); } upload(req, res, function(file, next) { if(file.type.match(/image./)) { uploadImage(file, next); } else { - next(new Error('Invalid File')); + next(new Error('[[error:invalid-file]]')); } }, next); } @@ -85,7 +85,7 @@ function uploadImage(image, callback) { if (meta.config.allowFileUploads) { uploadFile(image, callback); } else { - callback(new Error('Uploads are disabled!')); + callback(new Error('[[error:uploads-are-disabled]]')); } } } @@ -97,15 +97,15 @@ function uploadFile(file, callback) { } else { if(!meta.config.allowFileUploads) { - return callback(new Error('File uploads are not allowed')); + return callback(new Error('[[error:uploads-are-disabled]]')); } if(!file) { - return callback(new Error('invalid file')); + return callback(new Error('[[error:invalid-file]]')); } if(file.size > parseInt(meta.config.maximumFileSize, 10) * 1024) { - return callback(new Error('File too big')); + return callback(new Error('[[error:file-too-big, ' + meta.config.maximumFileSize + ']]')); } var filename = 'upload-' + utils.generateUUID() + path.extname(file.name); diff --git a/src/routes/authentication.js b/src/routes/authentication.js index a2d9f66e44..2728f58116 100644 --- a/src/routes/authentication.js +++ b/src/routes/authentication.js @@ -158,7 +158,7 @@ Auth.login = function(username, password, next) { if (!username || !password) { - return next(new Error('invalid-user')); + return next(new Error('[[error:invalid-user-data]]')); } var userslug = utils.slugify(username); @@ -170,7 +170,7 @@ if(!uid) { // Even if a user doesn't exist, compare passwords anyway, so we don't immediately return - return next(null, false, 'user doesn\'t exist'); + return next(null, false, '[[error:no-user]]'); } user.getUserFields(uid, ['password', 'banned'], function(err, userData) { @@ -179,11 +179,11 @@ } if (!userData || !userData.password) { - return next(new Error('invalid userdata or password')); + return next(new Error('[[error:invalid-user-data]]')); } if (userData.banned && parseInt(userData.banned, 10) === 1) { - return next(null, false, 'User banned'); + return next(null, false, '[[error:user-banned]]'); } bcrypt.compare(password, userData.password, function(err, res) { @@ -192,12 +192,12 @@ } if (!res) { - return next(null, false, 'invalid-password'); + return next(null, false, '[[error:invalid-password]]'); } next(null, { uid: uid - }, 'Authentication successful'); + }, '[[success:authentication-successful]]'); }); }); }); diff --git a/src/socket.io/admin.js b/src/socket.io/admin.js index 5888fd636d..dc0b248ae9 100644 --- a/src/socket.io/admin.js +++ b/src/socket.io/admin.js @@ -79,7 +79,7 @@ SocketAdmin.user.removeAdmin = function(socket, theirid, callback) { SocketAdmin.user.createUser = function(socket, userData, callback) { if (!userData) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } user.create(userData, callback); }; @@ -87,7 +87,7 @@ SocketAdmin.user.createUser = function(socket, userData, callback) { SocketAdmin.user.banUser = function(socket, theirid, callback) { user.isAdministrator(theirid, function(err, isAdmin) { if (err || isAdmin) { - return callback(err || new Error('You can\'t ban other admins!')); + return callback(err || new Error('[[error:cant-ban-other-admins]]')); } user.ban(theirid, function(err) { @@ -137,6 +137,10 @@ SocketAdmin.user.search = function(socket, username, callback) { }); } + if (err) { + return callback(err); + } + async.each(data.users, isAdmin, function(err) { callback(err, data); }); @@ -146,7 +150,7 @@ SocketAdmin.user.search = function(socket, username, callback) { /* Categories */ SocketAdmin.categories.create = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } categories.create(data, callback); @@ -154,7 +158,7 @@ SocketAdmin.categories.create = function(socket, data, callback) { SocketAdmin.categories.update = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } categories.update(data, callback); @@ -162,7 +166,7 @@ SocketAdmin.categories.update = function(socket, data, callback) { SocketAdmin.categories.search = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } var username = data.username, @@ -184,7 +188,7 @@ SocketAdmin.categories.search = function(socket, data, callback) { SocketAdmin.categories.setPrivilege = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } var cid = data.cid, @@ -248,15 +252,14 @@ SocketAdmin.categories.getPrivilegeSettings = function(socket, cid, callback) { callback(null, { "+r": data['+r'].members, "+w": data['+w'].members, - "mods": data['mods'].members + "mods": data.mods.members }); }); }; SocketAdmin.categories.setGroupPrivilege = function(socket, data, callback) { - if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } if (data.set) { @@ -295,7 +298,7 @@ SocketAdmin.themes.getInstalled = function(socket, data, callback) { SocketAdmin.themes.set = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } widgets.reset(function(err) { @@ -315,7 +318,7 @@ SocketAdmin.plugins.toggle = function(socket, plugin_id) { SocketAdmin.widgets.set = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } widgets.setArea(data, callback); @@ -328,7 +331,7 @@ SocketAdmin.config.get = function(socket, data, callback) { SocketAdmin.config.set = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } meta.configs.set(data.key, data.value, function(err) { @@ -354,7 +357,7 @@ SocketAdmin.config.remove = function(socket, key) { /* Groups */ SocketAdmin.groups.create = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } groups.create(data.name, data.description, function(err, groupObj) { @@ -376,7 +379,7 @@ SocketAdmin.groups.get = function(socket, groupName, callback) { SocketAdmin.groups.join = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } groups.join(data.groupName, data.uid, callback); @@ -384,7 +387,7 @@ SocketAdmin.groups.join = function(socket, data, callback) { SocketAdmin.groups.leave = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } groups.leave(data.groupName, data.uid, callback); @@ -392,7 +395,7 @@ SocketAdmin.groups.leave = function(socket, data, callback) { SocketAdmin.groups.update = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } groups.update(data.groupName, data.values, function(err) { diff --git a/src/socket.io/categories.js b/src/socket.io/categories.js index 0dd546ef16..eaa6eb0966 100644 --- a/src/socket.io/categories.js +++ b/src/socket.io/categories.js @@ -13,7 +13,7 @@ SocketCategories.getRecentReplies = function(socket, cid, callback) { return callback(err); } - if (privileges && !privileges.read) { + if (!privileges || !privileges.read) { return callback(null, []); } @@ -27,7 +27,7 @@ SocketCategories.get = function(socket, data, callback) { SocketCategories.loadMore = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } user.getSettings(socket.uid, function(err, settings) { diff --git a/src/socket.io/meta.js b/src/socket.io/meta.js index 08415ab260..e2733e33a7 100644 --- a/src/socket.io/meta.js +++ b/src/socket.io/meta.js @@ -37,7 +37,7 @@ SocketMeta.buildTitle = function(socket, text, callback) { SocketMeta.updateHeader = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } if (socket.uid) { @@ -76,7 +76,7 @@ SocketMeta.getUsageStats = function(socket, data, callback) { SocketMeta.rooms.enter = function(socket, data) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } if (data.leave !== null) { diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js index 115bcf17b8..7dea871b32 100644 --- a/src/socket.io/modules.js +++ b/src/socket.io/modules.js @@ -49,35 +49,36 @@ var stopTracking = function(replyObj) { }; SocketModules.composer.push = function(socket, pid, callback) { - if (socket.uid || parseInt(meta.config.allowGuestPosting, 10)) { - if (parseInt(pid, 10) > 0) { - - async.parallel([ - function(next) { - posts.getPostFields(pid, ['content'], next); - }, - function(next) { - topics.getTopicDataByPid(pid, next); - }, - function(next) { - posts.getPidIndex(pid, next); - } - ], function(err, results) { - if(err) { - return callback(err); - } - callback(null, { - pid: pid, - body: results[0].content, - title: results[1].title, - topic_thumb: results[1].thumb, - index: results[2] - }); - }); - } - } else { - callback(new Error('no-uid')); + if(!socket.uid && parseInt(meta.config.allowGuestPosting, 10) !== 1) { + return callback(new Error('[[error:not-logged-in]]')); } + + posts.getPostFields(pid, ['content'], function(err, postData) { + if(err || (!postData && !postData.content)) { + return callback(err || new Error('[[error:invalid-pid]]')); + } + + async.parallel({ + topic: function(next) { + topics.getTopicDataByPid(pid, next); + }, + index: function(next) { + posts.getPidIndex(pid, next); + } + }, function(err, results) { + if(err) { + return callback(err); + } + + callback(null, { + pid: pid, + body: postData.content, + title: results.topic.title, + topic_thumb: results.topic.thumb, + index: results.index + }); + }); + }); }; SocketModules.composer.editCheck = function(socket, pid, callback) { @@ -150,7 +151,7 @@ SocketModules.composer.getUsersByTid = function(socket, tid, callback) { SocketModules.chats.get = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } Messaging.getMessages(socket.uid, data.touid, false, callback); @@ -158,7 +159,7 @@ SocketModules.chats.get = function(socket, data, callback) { SocketModules.chats.send = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } var touid = data.touid; diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index 71bc1ab030..8383f58f82 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -11,7 +11,7 @@ var async = require('async'), notifications = require('../notifications'), groups = require('../groups'), user = require('../user'), - index = require('./index'), + websockets = require('./index'), SocketPosts = {}; @@ -40,38 +40,50 @@ SocketPosts.reply = function(socket, data, callback) { posts: [postData] }; - index.server.sockets.emit('event:new_post', socketData); + websockets.server.sockets.emit('event:new_post', socketData); callback(); } }); }; -SocketPosts.upvote = function(socket, data) { - favouriteCommand('upvote', socket, data); +SocketPosts.upvote = function(socket, data, callback) { + favouriteCommand('upvote', 'voted', socket, data, callback); sendNotificationToPostOwner(data, socket.uid, 'has upvoted your post'); }; -SocketPosts.downvote = function(socket, data) { - favouriteCommand('downvote', socket, data); +SocketPosts.downvote = function(socket, data, callback) { + favouriteCommand('downvote', 'voted', socket, data, callback); }; -SocketPosts.unvote = function(socket, data) { - favouriteCommand('unvote', socket, data); +SocketPosts.unvote = function(socket, data, callback) { + favouriteCommand('unvote', 'voted', socket, data, callback); }; -SocketPosts.favourite = function(socket, data) { - favouriteCommand('favourite', socket, data); +SocketPosts.favourite = function(socket, data, callback) { + favouriteCommand('favourite', 'favourited', socket, data, callback); sendNotificationToPostOwner(data, socket.uid, 'has favourited your post'); }; -SocketPosts.unfavourite = function(socket, data) { - favouriteCommand('unfavourite', socket, data); +SocketPosts.unfavourite = function(socket, data, callback) { + favouriteCommand('unfavourite', 'favourited', socket, data, callback); }; -function favouriteCommand(command, socket, data) { +function favouriteCommand(command, eventName, socket, data, callback) { + if(data && data.pid && data.room_id) { - favourites[command](data.pid, data.room_id, socket.uid, socket); + favourites[command](data.pid, socket.uid, function(err, result) { + if (err) { + return callback(err); + } + + socket.emit('posts.' + command, data.pid); + + if(data.room_id && result && eventName) { + websockets.in(data.room_id).emit('event:' + eventName, result); + } + callback(); + }); } } @@ -116,8 +128,8 @@ SocketPosts.getRawPost = function(socket, pid, callback) { return callback(err); } - if(data.deleted === '1') { - return callback(new Error('This post no longer exists')); + if(parseInt(data.deleted, 10) === 1) { + return callback(new Error('[[error:no-post]]')); } callback(null, data.content); @@ -140,7 +152,7 @@ SocketPosts.edit = function(socket, data, callback) { return callback(err); } - index.server.sockets.in('topic_' + results.topic.tid).emit('event:post_edited', { + websockets.server.sockets.in('topic_' + results.topic.tid).emit('event:post_edited', { pid: data.pid, title: results.topic.title, isMainPost: results.topic.isMainPost, @@ -161,7 +173,7 @@ SocketPosts.restore = function(socket, data, callback) { function deleteOrRestore(command, socket, data, callback) { if(!data) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } postTools[command](socket.uid, data.pid, function(err) { @@ -172,7 +184,7 @@ function deleteOrRestore(command, socket, data, callback) { module.parent.exports.emitTopicPostStats(); var eventName = command === 'restore' ? 'event:post_restored' : 'event:post_deleted'; - index.server.sockets.in('topic_' + data.tid).emit(eventName, { + websockets.server.sockets.in('topic_' + data.tid).emit(eventName, { pid: data.pid }); @@ -235,7 +247,7 @@ SocketPosts.getPidIndex = function(socket, pid, callback) { SocketPosts.flag = function(socket, pid, callback) { if (!socket.uid) { - return callback(new Error('not-logged-in')); + return callback(new Error('[[error:not-logged-in]]')); } var message = '', @@ -273,7 +285,7 @@ SocketPosts.flag = function(socket, pid, callback) { SocketPosts.loadMoreFavourites = function(socket, data, callback) { if(!data || !data.after) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } var start = parseInt(data.after, 10), @@ -284,7 +296,7 @@ SocketPosts.loadMoreFavourites = function(socket, data, callback) { SocketPosts.loadMoreUserPosts = function(socket, data, callback) { if(!data || !data.after || !data.uid) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } var start = parseInt(data.after, 10), @@ -296,7 +308,7 @@ SocketPosts.loadMoreUserPosts = function(socket, data, callback) { SocketPosts.getRecentPosts = function(socket, data, callback) { if(!data || !data.count) { - return callback(new Error('invalid data')); + return callback(new Error('[[error:invalid-data]]')); } posts.getRecentPosts(socket.uid, 0, data.count - 1, data.term, callback); diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 4dee39f4be..ce78fe9976 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -60,7 +60,7 @@ SocketUser.changePassword = function(socket, data, callback) { SocketUser.updateProfile = function(socket, data, callback) { if(!data || !data.uid) { - return callback(new Error('invalid-data')); + return callback(new Error('[[error:invalid-data]]')); } if(socket.uid === parseInt(data.uid, 10)) { @@ -73,7 +73,7 @@ SocketUser.updateProfile = function(socket, data, callback) { } if(!isAdmin) { - return callback(new Error('not allowed!')); + return callback(new Error('[[error:no-privileges]]')); } user.updateProfile(data.uid, data, callback); @@ -82,7 +82,7 @@ SocketUser.updateProfile = function(socket, data, callback) { SocketUser.changePicture = function(socket, data, callback) { if(!data) { - return callback(new Error('invalid-data')); + return callback(new Error('[[error:invalid-data]]')); } var type = data.type; @@ -117,7 +117,7 @@ SocketUser.changePicture = function(socket, data, callback) { } else if (type === 'uploaded') { type = 'uploadedpicture'; } else { - return callback(new Error('invalid-image-type')); + return callback(new Error('[[error:invalid-image-type]]')); } if(socket.uid === parseInt(data.uid, 10)) { @@ -136,7 +136,7 @@ SocketUser.changePicture = function(socket, data, callback) { } if(!isAdmin) { - return callback(new Error('not-allowed')); + return callback(new Error('[[error:no-privileges]]')); } changePicture(data.uid, callback); @@ -170,7 +170,7 @@ SocketUser.saveSettings = function(socket, data, callback) { SocketUser.getOnlineUsers = function(socket, data, callback) { var returnData = {}; if(!data) { - return callback(new Error('invalid-data')); + return callback(new Error('[[error:invalid-data]]')); } function getUserStatus(uid, next) { @@ -202,11 +202,11 @@ SocketUser.getActiveUsers = function(socket, data, callback) { SocketUser.loadMore = function(socket, data, callback) { if(!data || !data.set || parseInt(data.after, 10) < 0) { - return callback(new Error('invalid-data')); + return callback(new Error('[[error:invalid-data]]')); } if (!socket.uid && !!parseInt(meta.config.privateUserInfo, 10)) { - return callback(new Error('not-allowed')); + return callback(new Error('[[error:no-privileges]]')); } var start = data.after, diff --git a/src/threadTools.js b/src/threadTools.js index 27f2da6fe2..7e7c8e509b 100644 --- a/src/threadTools.js +++ b/src/threadTools.js @@ -69,9 +69,9 @@ var winston = require('winston'), } if (parseInt(deleted, 10) && isDelete) { - return callback(new Error('topic-already-deleted')); + return callback(new Error('[[error:topic-already-deleted]]')); } else if (!parseInt(deleted, 10) && !isDelete) { - return callback(new Error('topic-already-restored')); + return callback(new Error('[[error:topic-already-restored]]')); } topics[isDelete ? 'delete' : 'restore'](tid, function(err) { diff --git a/src/topics.js b/src/topics.js index 2da58b7245..a5cbd0b69b 100644 --- a/src/topics.js +++ b/src/topics.js @@ -58,7 +58,7 @@ var async = require('async'), Topics.getTopicDataWithUser = function(tid, callback) { Topics.getTopicData(tid, function(err, topic) { if (err || !topic) { - return callback(err || new Error('topic doesn\'t exist')); + return callback(err || new Error('[[error:no-topic]]')); } user.getUserFields(topic.uid, ['username', 'userslug', 'picture'] , function(err, userData) { @@ -101,7 +101,7 @@ var async = require('async'), Topics.getTidPage = function(tid, uid, callback) { if(!tid) { - return callback(new Error('invalid-tid')); + return callback(new Error('[[error:invalid-tid]]')); } async.parallel({ @@ -270,7 +270,7 @@ var async = require('async'), Topics.getTopicWithPosts = function(tid, uid, start, end, callback) { Topics.getTopicData(tid, function(err, topicData) { if (err || !topicData) { - return callback(err || new Error('Topic tid \'' + tid + '\' not found')); + return callback(err || new Error('[[error:no-topic]]')); } async.parallel({ @@ -328,8 +328,8 @@ var async = require('async'), posts.getPostFields(pid, ['pid', 'uid', 'timestamp'], function(err, postData) { if (err) { return callback(err); - } else if(!postData) { - return callback(new Error('no-teaser-found')); + } else if(!postData || !postData.uid) { + return callback(new Error('[[error:no-teaser]]')); } user.getUserFields(postData.uid, ['username', 'userslug', 'picture'], function(err, userData) { diff --git a/src/topics/fork.js b/src/topics/fork.js index 6cda238973..005b137058 100644 --- a/src/topics/fork.js +++ b/src/topics/fork.js @@ -19,11 +19,11 @@ module.exports = function(Topics) { } if(!title) { - return callback(new Error('invalid-title')); + return callback(new Error('[[error:invalid-title]]')); } if(!pids || !pids.length) { - return callback(new Error('invalid-pids')); + return callback(new Error('[[error:invalid-pid]]')); } pids.sort(); @@ -71,7 +71,7 @@ module.exports = function(Topics) { Topics.movePostToTopic = function(pid, tid, callback) { threadTools.exists(tid, function(err, exists) { if(err || !exists) { - return callback(err || new Error('Topic doesn\'t exist')); + return callback(err || new Error('[[error:no-topic]]')); } posts.getPostFields(pid, ['deleted', 'tid', 'timestamp'], function(err, postData) { @@ -79,8 +79,8 @@ module.exports = function(Topics) { return callback(err); } - if(!postData) { - return callback(new Error('Post doesn\'t exist')); + if(!postData || !postData.tid) { + return callback(new Error('[[error:no-post]]')); } Topics.removePostFromTopic(postData.tid, pid, function(err) { diff --git a/src/topics/recent.js b/src/topics/recent.js index bb51800785..255c65a388 100644 --- a/src/topics/recent.js +++ b/src/topics/recent.js @@ -30,7 +30,7 @@ module.exports = function(Topics) { var count = parseInt(end, 10) === -1 ? end : end - start + 1; - db.getSortedSetRevRangeByScore(['topics:recent', '+inf', Date.now() - since, 'LIMIT', start, count], callback); + db.getSortedSetRevRangeByScore('topics:recent', start, count, Infinity, Date.now() - since, callback); }; }; diff --git a/src/user.js b/src/user.js index 93805a567b..a06219b957 100644 --- a/src/user.js +++ b/src/user.js @@ -126,11 +126,11 @@ var bcrypt = require('bcryptjs'), } if (parseInt(results.banned, 10) === 1) { - return callback(new Error('user-banned')); + return callback(new Error('[[error:user-banned]]')); } if (!results.exists) { - return callback(new Error('invalid-user')); + return callback(new Error('[[error:no-user]]')); } var lastposttime = results.lastposttime; diff --git a/src/user/create.js b/src/user/create.js index 33d7a5fd8c..f8f95b0878 100644 --- a/src/user/create.js +++ b/src/user/create.js @@ -25,17 +25,17 @@ module.exports = function(User) { async.parallel([ function(next) { if (userData.email) { - next(!utils.isEmailValid(userData.email) ? new Error('Invalid Email!') : null); + next(!utils.isEmailValid(userData.email) ? new Error('[[error:invalid-email]]') : null); } else { next(); } }, function(next) { - next((!utils.isUserNameValid(userData.username) || !userData.userslug) ? new Error('Invalid Username!') : null); + next((!utils.isUserNameValid(userData.username) || !userData.userslug) ? new Error('[[error:invalid-username]]') : null); }, function(next) { if (userData.password) { - next(!utils.isPasswordValid(userData.password) ? new Error('Invalid Password!') : null); + next(!utils.isPasswordValid(userData.password) ? new Error('[[error:invalid-password]]') : null); } else { next(); } @@ -45,7 +45,7 @@ module.exports = function(User) { if (err) { return next(err); } - next(exists ? new Error('Username taken!') : null); + next(exists ? new Error('[[error:username-taken]]') : null); }); }, function(next) { @@ -54,7 +54,7 @@ module.exports = function(User) { if (err) { return next(err); } - next(!available ? new Error('Email taken!') : null); + next(!available ? new Error('[[error:email-taken]]') : null); }); } else { next(); diff --git a/src/user/notifications.js b/src/user/notifications.js index df3096b8e8..3b4542a787 100644 --- a/src/user/notifications.js +++ b/src/user/notifications.js @@ -114,7 +114,7 @@ var async = require('async'), UserNotifications.getDailyUnread = function(uid, callback) { var now = Date.now(), yesterday = now - (1000*60*60*24); // Approximate, can be more or less depending on time changes, makes no difference really. - db.getSortedSetRangeByScore(['uid:' + uid + ':notifications:unread', yesterday, now], function(err, nids) { + db.getSortedSetRangeByScore('uid:' + uid + ':notifications:unread', 0, 20, yesterday, now, function(err, nids) { async.map(nids, function(nid, next) { notifications.get(nid, uid, function(notif_data) { next(null, notif_data); diff --git a/src/user/profile.js b/src/user/profile.js index 50a33112e5..8620dde36e 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -18,7 +18,7 @@ module.exports = function(User) { function isSignatureValid(next) { if (data.signature !== undefined && data.signature.length > meta.config.maximumSignatureLength) { - next(new Error('Signature can\'t be longer than ' + meta.config.maximumSignatureLength + ' characters!')); + next(new Error('[[error:signature-too-long, ' + meta.config.maximumSignatureLength + ']]')); } else { next(); } @@ -39,7 +39,7 @@ module.exports = function(User) { return next(err); } - next(!available ? new Error('Email not available!') : null); + next(!available ? new Error('[[error:email-taken]]') : null); }); }); @@ -55,7 +55,7 @@ module.exports = function(User) { } if(!utils.isUserNameValid(data.username) || !userslug) { - return next(new Error('Invalid Username!')); + return next(new Error('[[error:invalid-username]]')); } User.exists(userslug, function(err, exists) { @@ -63,7 +63,7 @@ module.exports = function(User) { return next(err); } - next(exists ? new Error('Username not available!') : null); + next(exists ? new Error('[[error:username-taken]]') : null); }); }); } @@ -196,7 +196,7 @@ module.exports = function(User) { User.changePassword = function(uid, data, callback) { if(!data || !data.uid) { - return callback(new Error('invalid-uid')); + return callback(new Error('[[error:invalid-uid]]')); } function hashAndSetPassword(callback) { diff --git a/src/user/reset.js b/src/user/reset.js index 330f49c843..7e3b2d75c8 100644 --- a/src/user/reset.js +++ b/src/user/reset.js @@ -40,7 +40,7 @@ var async = require('async'), UserReset.send = function(socket, email, callback) { user.getUidByEmail(email, function(err, uid) { if(err || !uid) { - return callback(err || new Error('invalid-email')); + return callback(err || new Error('[[error:invalid-email]]')); } // Generate a new reset code diff --git a/src/user/settings.js b/src/user/settings.js index bc28622960..7e9665d9f0 100644 --- a/src/user/settings.js +++ b/src/user/settings.js @@ -37,7 +37,7 @@ module.exports = function(User) { User.saveSettings = function(uid, data, callback) { if(!data.topicsPerPage || !data.postsPerPage || parseInt(data.topicsPerPage, 10) <= 0 || parseInt(data.postsPerPage, 10) <= 0) { - return callback(new Error('Invalid pagination value!')); + return callback(new Error('[[error:invalid-pagination-value]]')); } plugins.fireHook('action:user.saveSettings', {uid: uid, settings: data}); diff --git a/tests/database.js b/tests/database.js index 8ca9a8f390..eaa8bc667a 100644 --- a/tests/database.js +++ b/tests/database.js @@ -349,4 +349,4 @@ describe('Test database', function() { }); }); -}); \ No newline at end of file +}); diff --git a/tests/topics.js b/tests/topics.js index a028c1b274..c28456fdbc 100644 --- a/tests/topics.js +++ b/tests/topics.js @@ -43,7 +43,7 @@ describe('Topic\'s', function() { it('should fail to create new topic with wrong parameters', function(done) { topics.post({uid: null, title: topic.title, content: topic.content, cid: topic.categoryId}, function(err, result) { - assert.equal(err.message, 'invalid-user'); + assert.equal(err.message, '[[error:no-user]]'); done(); }); });