mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-02-26 16:41:21 +01:00
refactor: migrate posts.getReplies to write API
This commit is contained in:
@@ -164,6 +164,8 @@ paths:
|
|||||||
$ref: 'write/posts/pid/diffs/since.yaml'
|
$ref: 'write/posts/pid/diffs/since.yaml'
|
||||||
/posts/{pid}/diffs/{timestamp}:
|
/posts/{pid}/diffs/{timestamp}:
|
||||||
$ref: 'write/posts/pid/diffs/timestamp.yaml'
|
$ref: 'write/posts/pid/diffs/timestamp.yaml'
|
||||||
|
/posts/{pid}/replies:
|
||||||
|
$ref: 'write/posts/pid/replies.yaml'
|
||||||
/chats/:
|
/chats/:
|
||||||
$ref: 'write/chats.yaml'
|
$ref: 'write/chats.yaml'
|
||||||
/chats/{roomId}:
|
/chats/{roomId}:
|
||||||
|
|||||||
234
public/openapi/write/posts/pid/replies.yaml
Normal file
234
public/openapi/write/posts/pid/replies.yaml
Normal file
@@ -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);
|
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 }));
|
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, 'put', '/:pid/diffs/:since', middlewares, controllers.write.posts.restoreDiff);
|
||||||
setupApiRoute(router, 'delete', '/:pid/diffs/:timestamp', middlewares, controllers.write.posts.deleteDiff);
|
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
|
// Shorthand route to access post routes by topic index
|
||||||
router.all('/+byIndex/:index*?', [middleware.checkRequired.bind(null, ['tid'])], controllers.write.posts.redirectByIndex);
|
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 plugins = require('../plugins');
|
||||||
const meta = require('../meta');
|
const meta = require('../meta');
|
||||||
const topics = require('../topics');
|
const topics = require('../topics');
|
||||||
const user = require('../user');
|
|
||||||
const notifications = require('../notifications');
|
const notifications = require('../notifications');
|
||||||
const utils = require('../utils');
|
const utils = require('../utils');
|
||||||
const events = require('../events');
|
const events = require('../events');
|
||||||
@@ -91,21 +90,13 @@ SocketPosts.getPidIndex = async function (socket, data) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
SocketPosts.getReplies = async function (socket, pid) {
|
SocketPosts.getReplies = async function (socket, pid) {
|
||||||
|
sockets.warnDeprecated(socket, 'GET /api/v3/posts/:pid/replies');
|
||||||
|
|
||||||
if (!utils.isNumber(pid)) {
|
if (!utils.isNumber(pid)) {
|
||||||
throw new Error('[[error:invalid-data]]');
|
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([
|
return await api.posts.getReplies(socket, { pid });
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketPosts.accept = async function (socket, data) {
|
SocketPosts.accept = async function (socket, data) {
|
||||||
|
|||||||
Reference in New Issue
Block a user