refactor: migrate `posts.getReplies` to write API

isekai-main
Julian Lam 2 years ago
parent ee9f53f1ff
commit 69b409385d

@ -164,6 +164,8 @@ paths:
$ref: 'write/posts/pid/diffs/since.yaml'
/posts/{pid}/diffs/{timestamp}:
$ref: 'write/posts/pid/diffs/timestamp.yaml'
/posts/{pid}/replies:
$ref: 'write/posts/pid/replies.yaml'
/chats/:
$ref: 'write/chats.yaml'
/chats/{roomId}:

@ -0,0 +1,234 @@
get:
tags:
- posts
summary: get post replies
description: This operation retrieves a post's direct replies
parameters:
- in: path
name: pid
schema:
type: string
required: true
description: a valid post id
example: 2
responses:
'200':
description: Post replies successfully retrieved.
content:
application/json:
schema:
type: object
properties:
status:
$ref: ../../../components/schemas/Status.yaml#/Status
response:
type: object
properties:
replies:
type: array
items:
type: object
properties:
pid:
type: number
uid:
type: number
description: A user identifier
tid:
type: number
description: A topic identifier
content:
type: string
timestamp:
type: number
votes:
type: number
deleted:
type: number
upvotes:
type: number
downvotes:
type: number
bookmarks:
type: number
deleterUid:
type: number
edited:
type: number
timestampISO:
type: string
description: An ISO 8601 formatted date string (complementing `timestamp`)
editedISO:
type: string
index:
type: number
user:
type: object
properties:
uid:
type: number
description: A user identifier
username:
type: string
description: A friendly name for a given user account
displayname:
type: string
description: This is either username or fullname depending on forum and user settings
userslug:
type: string
description: An URL-safe variant of the username (i.e. lower-cased, spaces
removed, etc.)
reputation:
type: number
postcount:
type: number
topiccount:
type: number
picture:
type: string
nullable: true
signature:
type: string
banned:
type: number
banned:expire:
type: number
status:
type: string
lastonline:
type: number
groupTitle:
nullable: true
type: string
groupTitleArray:
type: array
items:
type: string
muted:
type: boolean
description: Whether or not the user has been muted.
mutedUntil:
type: number
description: A UNIX timestamp representing the moment a muted state will be lifted.
nullable: true
icon:text:
type: string
description: A single-letter representation of a username. This is used in the
auto-generated icon given to users without
an avatar
icon:bgColor:
type: string
description: A six-character hexadecimal colour code assigned to the user. This
value is used in conjunction with
`icon:text` for the user's auto-generated
icon
example: "#f44336"
lastonlineISO:
type: string
banned_until:
type: number
banned_until_readable:
type: string
selectedGroups:
type: array
items:
type: object
properties:
name:
type: string
slug:
type: string
labelColor:
type: string
textColor:
type: string
icon:
type: string
userTitle:
type: string
custom_profile_info:
type: array
items:
type: object
properties:
content:
type: string
description: HTML that is injected into `topic.tpl` of themes that support custom profile info
editor:
nullable: true
bookmarked:
type: boolean
upvoted:
type: boolean
downvoted:
type: boolean
replies:
type: object
properties:
hasMore:
type: boolean
users:
type: array
items:
type: object
properties:
username:
type: string
description: A friendly name for a given user account
userslug:
type: string
description: An URL-safe variant of the username (i.e. lower-cased, spaces
removed, etc.)
picture:
type: string
uid:
type: number
description: A user identifier
icon:text:
type: string
description: A single-letter representation of a username. This is used in the
auto-generated icon given to users without
an avatar
icon:bgColor:
type: string
description: A six-character hexadecimal colour code assigned to the user. This
value is used in conjunction with
`icon:text` for the user's auto-generated
icon
example: "#f44336"
administrator:
type: boolean
text:
type: string
count:
type: number
selfPost:
type: boolean
events:
type: array
items:
type: object
properties:
type:
type: string
id:
type: number
timestamp:
type: number
timestampISO:
type: string
topicOwnerPost:
type: boolean
display_edit_tools:
type: boolean
display_delete_tools:
type: boolean
display_moderator_tools:
type: boolean
display_move_tools:
type: boolean
display_post_menu:
type: boolean
flagId:
type: number
description: The flag identifier, if this particular post has been flagged before

@ -386,3 +386,25 @@ postsAPI.deleteDiff = async (caller, { pid, timestamp }) => {
await posts.diffs.delete(pid, timestamp, caller.uid);
};
postsAPI.getReplies = async (caller, { pid }) => {
const { uid } = caller;
const canRead = await privileges.posts.can('topics:read', pid, caller.uid);
if (!canRead) {
return null;
}
const { topicPostSort } = await user.getSettings(uid);
const pids = await posts.getPidsFromSet(`pid:${pid}:replies`, 0, -1, topicPostSort === 'newest_to_oldest');
let [postData, postPrivileges] = await Promise.all([
posts.getPostsByPids(pids, uid),
privileges.posts.get(pids, uid),
]);
postData = await topics.addPostData(postData, uid);
postData.forEach((postData, index) => posts.modifyPostByPrivilege(postData, postPrivileges[index]));
postData = postData.filter((postData, index) => postData && postPrivileges[index].read);
postData = await user.blocks.filter(uid, postData);
return postData;
};

@ -160,3 +160,12 @@ Posts.deleteDiff = async (req, res) => {
helpers.formatApiResponse(200, res, await api.posts.getDiffs(req, { ...req.params }));
};
Posts.getReplies = async (req, res) => {
const replies = await api.posts.getReplies(req, { ...req.params });
if (replies === null) {
return helpers.formatApiResponse(404, res, new Error('[[error:no-post]]'));
}
helpers.formatApiResponse(200, res, { replies });
};

@ -35,6 +35,8 @@ module.exports = function () {
setupApiRoute(router, 'put', '/:pid/diffs/:since', middlewares, controllers.write.posts.restoreDiff);
setupApiRoute(router, 'delete', '/:pid/diffs/:timestamp', middlewares, controllers.write.posts.deleteDiff);
setupApiRoute(router, 'get', '/:pid/replies', [middleware.assert.post], controllers.write.posts.getReplies);
// Shorthand route to access post routes by topic index
router.all('/+byIndex/:index*?', [middleware.checkRequired.bind(null, ['tid'])], controllers.write.posts.redirectByIndex);

@ -8,7 +8,6 @@ const privileges = require('../privileges');
const plugins = require('../plugins');
const meta = require('../meta');
const topics = require('../topics');
const user = require('../user');
const notifications = require('../notifications');
const utils = require('../utils');
const events = require('../events');
@ -91,21 +90,13 @@ SocketPosts.getPidIndex = async function (socket, data) {
};
SocketPosts.getReplies = async function (socket, pid) {
sockets.warnDeprecated(socket, 'GET /api/v3/posts/:pid/replies');
if (!utils.isNumber(pid)) {
throw new Error('[[error:invalid-data]]');
}
const { topicPostSort } = await user.getSettings(socket.uid);
const pids = await posts.getPidsFromSet(`pid:${pid}:replies`, 0, -1, topicPostSort === 'newest_to_oldest');
let [postData, postPrivileges] = await Promise.all([
posts.getPostsByPids(pids, socket.uid),
privileges.posts.get(pids, socket.uid),
]);
postData = await topics.addPostData(postData, socket.uid);
postData.forEach((postData, index) => posts.modifyPostByPrivilege(postData, postPrivileges[index]));
postData = postData.filter((postData, index) => postData && postPrivileges[index].read);
postData = await user.blocks.filter(socket.uid, postData);
return postData;
return await api.posts.getReplies(socket, { pid });
};
SocketPosts.accept = async function (socket, data) {

Loading…
Cancel
Save