refactor: posts api

v1.18.x
Barış Soner Uşaklı 4 years ago
parent 272e73da53
commit d9a16855d0

@ -8,15 +8,6 @@ define('forum/topic/votes', [
Votes.addVoteHandler = function () { Votes.addVoteHandler = function () {
components.get('topic').on('mouseenter', '[data-pid] [component="post/vote-count"]', loadDataAndCreateTooltip); components.get('topic').on('mouseenter', '[data-pid] [component="post/vote-count"]', loadDataAndCreateTooltip);
components.get('topic').on('mouseout', '[data-pid] [component="post/vote-count"]', function () {
var el = $(this).parent();
el.on('shown.bs.tooltip', function () {
$('.tooltip').tooltip('destroy');
el.off('shown.bs.tooltip');
});
$('.tooltip').tooltip('destroy');
});
}; };
function loadDataAndCreateTooltip(e) { function loadDataAndCreateTooltip(e) {
@ -26,18 +17,14 @@ define('forum/topic/votes', [
var el = $this.parent(); var el = $this.parent();
var pid = el.parents('[data-pid]').attr('data-pid'); var pid = el.parents('[data-pid]').attr('data-pid');
$('.tooltip').tooltip('destroy');
$this.off('mouseenter', loadDataAndCreateTooltip);
socket.emit('posts.getUpvoters', [pid], function (err, data) { socket.emit('posts.getUpvoters', [pid], function (err, data) {
if (err) { if (err) {
return app.alertError(err.message); return app.alertError(err.message);
} }
if (data.length) { if (data.length) {
createTooltip(el, data[0]); createTooltip($this, data[0]);
} }
$this.off('mouseenter').on('mouseenter', loadDataAndCreateTooltip);
}); });
return false; return false;
} }
@ -46,7 +33,8 @@ define('forum/topic/votes', [
function doCreateTooltip(title) { function doCreateTooltip(title) {
el.attr('title', title).tooltip('fixTitle').tooltip('show'); el.attr('title', title).tooltip('fixTitle').tooltip('show');
} }
var usernames = data.usernames; var usernames = data.usernames
.filter(name => name !== '[[global:former_user]]');
if (!usernames.length) { if (!usernames.length) {
return; return;
} }
@ -70,10 +58,10 @@ define('forum/topic/votes', [
const method = currentState ? 'del' : 'put'; const method = currentState ? 'del' : 'put';
api[method](`/posts/${post.attr('data-pid')}/vote`, { api[method](`/posts/${post.attr('data-pid')}/vote`, {
delta: delta, delta: delta,
}, undefined, (err) => { }).catch((err) => {
app.alertError(err.status.message); app.alertError(err.message);
if (err.status.message === '[[error:not-logged-in]]') { if (err.message === '[[error:not-logged-in]]') {
ajaxify.go('login'); ajaxify.go('login');
} }
}); });

@ -22,13 +22,7 @@ define('api', () => {
ev.responseJSON.status.message : ev.responseJSON.status.message :
ev.responseJSON.error; ev.responseJSON.error;
const error = new Error(errMessage || ev.statusText); cb(new Error(errMessage || ev.statusText));
if (!utils.hasLanguageKey(error.message)) {
app.alertError(error.message);
}
cb(error);
}); });
} }

@ -3,8 +3,11 @@
const url = require('url'); const url = require('url');
const user = require('../user'); const user = require('../user');
const topics = require('../topics'); const topics = require('../topics');
const posts = require('../posts');
const privileges = require('../privileges'); const privileges = require('../privileges');
const plugins = require('../plugins');
const socketHelpers = require('../socket.io/helpers'); const socketHelpers = require('../socket.io/helpers');
const websockets = require('../socket.io');
const events = require('../events'); const events = require('../events');
// creates a slimmed down version of the request object // creates a slimmed down version of the request object
@ -34,7 +37,6 @@ exports.buildReqObject = (req, payload) => {
}; };
}; };
exports.doTopicAction = async function (action, event, caller, { tids }) { exports.doTopicAction = async function (action, event, caller, { tids }) {
if (!Array.isArray(tids)) { if (!Array.isArray(tids)) {
throw new Error('[[error:invalid-tid]]'); throw new Error('[[error:invalid-tid]]');
@ -73,3 +75,59 @@ async function logTopicAction(action, req, tid, title) {
title: String(title), title: String(title),
}); });
} }
exports.postCommand = async function (caller, command, eventName, notification, data) {
if (!caller.uid) {
throw new Error('[[error:not-logged-in]]');
}
if (!data || !data.pid) {
throw new Error('[[error:invalid-data]]');
}
if (!data.room_id) {
throw new Error('[[error:invalid-room-id, ' + data.room_id + ' ]]');
}
const [exists, deleted] = await Promise.all([
posts.exists(data.pid),
posts.getPostField(data.pid, 'deleted'),
]);
if (!exists) {
throw new Error('[[error:invalid-pid]]');
}
if (deleted) {
throw new Error('[[error:post-deleted]]');
}
/*
hooks:
filter:post.upvote
filter:post.downvote
filter:post.unvote
filter:post.bookmark
filter:post.unbookmark
*/
const filteredData = await plugins.fireHook('filter:post.' + command, {
data: data,
uid: caller.uid,
});
return await executeCommand(caller, command, eventName, notification, filteredData.data);
};
async function executeCommand(caller, command, eventName, notification, data) {
const result = await posts[command](data.pid, caller.uid);
if (result && eventName) {
websockets.in('uid_' + caller.uid).emit('posts.' + command, result);
websockets.in(data.room_id).emit('event:' + eventName, result);
}
if (result && command === 'upvote') {
socketHelpers.upvote(result, notification);
} else if (result && notification) {
socketHelpers.sendNotificationToPostOwner(data.pid, caller.uid, command, notification);
} else if (result && command === 'unvote') {
socketHelpers.rescindUpvoteNotification(data.pid, caller.uid);
}
return result;
}

@ -165,3 +165,22 @@ async function isMainAndLastPost(pid) {
}; };
} }
postsAPI.upvote = async function (caller, data) {
return await apiHelpers.postCommand(caller, 'upvote', 'voted', 'notifications:upvoted_your_post_in', data);
};
postsAPI.downvote = async function (caller, data) {
return await apiHelpers.postCommand(caller, 'downvote', 'voted', '', data);
};
postsAPI.unvote = async function (caller, data) {
return await apiHelpers.postCommand(caller, 'unvote', 'voted', '', data);
};
postsAPI.bookmark = async function (caller, data) {
return await apiHelpers.postCommand(caller, 'bookmark', 'bookmarked', '', data);
};
postsAPI.unbookmark = async function (caller, data) {
return await apiHelpers.postCommand(caller, 'unbookmark', 'bookmarked', '', data);
};

@ -11,9 +11,7 @@ const categories = require('../categories');
const plugins = require('../plugins'); const plugins = require('../plugins');
const meta = require('../meta'); const meta = require('../meta');
const middleware = require('../middleware'); const middleware = require('../middleware');
const translator = require('../translator');
const isLanguageKey = /^\[\[[\w.\-_:]+]]$/;
const helpers = module.exports; const helpers = module.exports;
helpers.noScriptErrors = async function (req, res, error, httpStatus) { helpers.noScriptErrors = async function (req, res, error, httpStatus) {
@ -349,12 +347,7 @@ helpers.formatApiResponse = async (statusCode, res, payload) => {
response: payload || {}, response: payload || {},
}); });
} else if (payload instanceof Error) { } else if (payload instanceof Error) {
let message = ''; const message = payload.message;
if (isLanguageKey.test(payload.message)) {
message = await translator.translate(payload.message, 'en-GB');
} else {
message = payload.message;
}
// Update status code based on some common error codes // Update status code based on some common error codes
switch (payload.message) { switch (payload.message) {

@ -5,7 +5,6 @@ const posts = require('../../posts');
const api = require('../../api'); const api = require('../../api');
const helpers = require('../helpers'); const helpers = require('../helpers');
const apiHelpers = require('../../api/helpers'); const apiHelpers = require('../../api/helpers');
const socketPostHelpers = require('../../socket.io/posts/helpers'); // eehhh...
const Posts = module.exports; const Posts = module.exports;
@ -37,43 +36,36 @@ Posts.delete = async (req, res) => {
async function mock(req) { async function mock(req) {
const tid = await posts.getPostField(req.params.pid, 'tid'); const tid = await posts.getPostField(req.params.pid, 'tid');
const data = { pid: req.params.pid, room_id: `topic_${tid}` }; return { pid: req.params.pid, room_id: `topic_${tid}` };
const socketMock = { uid: req.user.uid };
return { data, socketMock };
} }
Posts.vote = async (req, res) => { Posts.vote = async (req, res) => {
const { data, socketMock } = await mock(req); const data = await mock(req);
if (req.body.delta > 0) { if (req.body.delta > 0) {
await socketPostHelpers.postCommand(socketMock, 'upvote', 'voted', 'notifications:upvoted_your_post_in', data); await api.posts.upvote(req, data);
} else if (req.body.delta < 0) { } else if (req.body.delta < 0) {
await socketPostHelpers.postCommand(socketMock, 'downvote', 'voted', '', data); await api.posts.downvote(req, data);
} else { } else {
await socketPostHelpers.postCommand(socketMock, 'unvote', 'voted', '', data); await api.posts.unvote(req, data);
} }
helpers.formatApiResponse(200, res); helpers.formatApiResponse(200, res);
}; };
Posts.unvote = async (req, res) => { Posts.unvote = async (req, res) => {
const { data, socketMock } = await mock(req); const data = await mock(req);
await api.posts.unvote(req, data);
await socketPostHelpers.postCommand(socketMock, 'unvote', 'voted', '', data);
helpers.formatApiResponse(200, res); helpers.formatApiResponse(200, res);
}; };
Posts.bookmark = async (req, res) => { Posts.bookmark = async (req, res) => {
const { data, socketMock } = await mock(req); const data = await mock(req);
await api.posts.bookmark(req, data);
await socketPostHelpers.postCommand(socketMock, 'bookmark', 'bookmarked', '', data);
helpers.formatApiResponse(200, res); helpers.formatApiResponse(200, res);
}; };
Posts.unbookmark = async (req, res) => { Posts.unbookmark = async (req, res) => {
const { data, socketMock } = await mock(req); const data = await mock(req);
await api.posts.unbookmark(req, data);
await socketPostHelpers.postCommand(socketMock, 'unbookmark', 'bookmarked', '', data);
helpers.formatApiResponse(200, res); helpers.formatApiResponse(200, res);
}; };

@ -1,17 +1,16 @@
'use strict'; 'use strict';
const helpers = require('./helpers');
const sockets = require('..'); const sockets = require('..');
const api = require('../../api');
module.exports = function (SocketPosts) { module.exports = function (SocketPosts) {
SocketPosts.bookmark = async function (socket, data) { SocketPosts.bookmark = async function (socket, data) {
sockets.warnDeprecated(socket, 'PUT /api/v3/posts/:pid/bookmark'); sockets.warnDeprecated(socket, 'PUT /api/v3/posts/:pid/bookmark');
return await helpers.postCommand(socket, 'bookmark', 'bookmarked', '', data); return await api.posts.bookmark(socket, data);
}; };
SocketPosts.unbookmark = async function (socket, data) { SocketPosts.unbookmark = async function (socket, data) {
sockets.warnDeprecated(socket, 'DELETE /api/v3/posts/:pid/bookmark'); sockets.warnDeprecated(socket, 'DELETE /api/v3/posts/:pid/bookmark');
return await helpers.postCommand(socket, 'unbookmark', 'bookmarked', '', data); return await api.posts.unbookmark(socket, data);
}; };
}; };

@ -1,62 +0,0 @@
'use strict';
const posts = require('../../posts');
const plugins = require('../../plugins');
const websockets = require('../index');
const socketHelpers = require('../helpers');
const helpers = module.exports;
helpers.postCommand = async function (socket, command, eventName, notification, data) {
if (!socket.uid) {
throw new Error('[[error:not-logged-in]]');
}
if (!data || !data.pid) {
throw new Error('[[error:invalid-data]]');
}
if (!data.room_id) {
throw new Error('[[error:invalid-room-id, ' + data.room_id + ' ]]');
}
const [exists, deleted] = await Promise.all([
posts.exists(data.pid),
posts.getPostField(data.pid, 'deleted'),
]);
if (!exists) {
throw new Error('[[error:invalid-pid]]');
}
if (deleted) {
throw new Error('[[error:post-deleted]]');
}
/*
hooks:
filter:post.upvote
filter:post.downvote
filter:post.unvote
filter:post.bookmark
filter:post.unbookmark
*/
const filteredData = await plugins.fireHook('filter:post.' + command, { data: data, uid: socket.uid });
return await executeCommand(socket, command, eventName, notification, filteredData.data);
};
async function executeCommand(socket, command, eventName, notification, data) {
const result = await posts[command](data.pid, socket.uid);
if (result && eventName) {
websockets.in('uid_' + socket.uid).emit('posts.' + command, result);
websockets.in(data.room_id).emit('event:' + eventName, result);
}
if (result && command === 'upvote') {
socketHelpers.upvote(result, notification);
} else if (result && notification) {
socketHelpers.sendNotificationToPostOwner(data.pid, socket.uid, command, notification);
} else if (result && command === 'unvote') {
socketHelpers.rescindUpvoteNotification(data.pid, socket.uid);
}
return result;
}

@ -5,7 +5,7 @@ const user = require('../../user');
const posts = require('../../posts'); const posts = require('../../posts');
const privileges = require('../../privileges'); const privileges = require('../../privileges');
const meta = require('../../meta'); const meta = require('../../meta');
const helpers = require('./helpers'); const api = require('../../api');
const sockets = require('..'); const sockets = require('..');
@ -64,16 +64,16 @@ module.exports = function (SocketPosts) {
SocketPosts.upvote = async function (socket, data) { SocketPosts.upvote = async function (socket, data) {
sockets.warnDeprecated(socket, 'PUT /api/v3/posts/:pid/vote'); sockets.warnDeprecated(socket, 'PUT /api/v3/posts/:pid/vote');
return await helpers.postCommand(socket, 'upvote', 'voted', 'notifications:upvoted_your_post_in', data); return await api.posts.upvote(socket, data);
}; };
SocketPosts.downvote = async function (socket, data) { SocketPosts.downvote = async function (socket, data) {
sockets.warnDeprecated(socket, 'PUT /api/v3/posts/:pid/vote'); sockets.warnDeprecated(socket, 'PUT /api/v3/posts/:pid/vote');
return await helpers.postCommand(socket, 'downvote', 'voted', '', data); return await api.posts.downvote(socket, data);
}; };
SocketPosts.unvote = async function (socket, data) { SocketPosts.unvote = async function (socket, data) {
sockets.warnDeprecated(socket, 'DELETE /api/v3/posts/:pid/vote'); sockets.warnDeprecated(socket, 'DELETE /api/v3/posts/:pid/vote');
return await helpers.postCommand(socket, 'unvote', 'voted', '', data); return await api.posts.unvote(socket, data);
}; };
}; };

Loading…
Cancel
Save