diff --git a/src/activitypub/helpers.js b/src/activitypub/helpers.js index 1721ce40a7..17dd233228 100644 --- a/src/activitypub/helpers.js +++ b/src/activitypub/helpers.js @@ -355,3 +355,52 @@ Helpers.remoteAnchorToLocalProfile = async (content) => { // eslint-disable-next-line max-len Helpers.makeSet = (object, properties) => new Set(properties.reduce((memo, property) => memo.concat(Array.isArray(object[property]) ? object[property] : [object[property]]), [])); + +Helpers.generateCollection = async ({ set, method, page, perPage, url }) => { + if (!method) { + method = db.getSortedSetRange; + } + const count = await db.sortedSetCard(set); + // const { cid, titleRaw: name, mainPid, slug, postcount: count } = await topics.getTopicFields(req.params.tid, ['cid', 'title', 'mainPid', 'slug', 'postcount']); + const pageCount = Math.max(1, Math.ceil(count / perPage)); + let items; + let paginate = true; + + if (!page && pageCount === 1) { + page = 1; + paginate = false; + } + + if (page) { + const invalidPagination = page < 1 || page > pageCount; + if (invalidPagination) { + throw new Error('[[error:invalid-data]]'); + } + + const start = Math.max(0, ((page - 1) * perPage) - 1); + const stop = Math.max(0, start + perPage - 1); + items = await method(set, start, stop); + } + + const object = { + type: paginate && items ? 'OrderedCollectionPage' : 'OrderedCollection', + totalItems: count, + }; + + if (items) { + object.orderedItems = items; + + if (paginate) { + object.partOf = url; + object.next = page < pageCount ? `${url}?page=${page + 1}` : null; + object.prev = page > 1 ? `${url}?page=${page - 1}` : null; + } + } + + if (paginate) { + object.first = `${url}?page=1`; + object.last = `${url}?page=${pageCount}`; + } + + return object; +}; diff --git a/src/controllers/activitypub/actors.js b/src/controllers/activitypub/actors.js index dd562140b2..f173fda30b 100644 --- a/src/controllers/activitypub/actors.js +++ b/src/controllers/activitypub/actors.js @@ -68,59 +68,36 @@ Actors.topic = async function (req, res, next) { return res.sendStatus(404); } - let page = parseInt(req.query.page, 10); - const { cid, titleRaw: name, mainPid, slug, postcount } = await topics.getTopicFields(req.params.tid, ['cid', 'title', 'mainPid', 'slug', 'postcount']); - const pageCount = Math.max(1, Math.ceil(postcount / meta.config.postsPerPage)); - let items; - let paginate = true; + const page = parseInt(req.query.page, 10); + const perPage = meta.config.postsPerPage; + const { cid, titleRaw: name, mainPid, slug } = await topics.getTopicFields(req.params.tid, ['cid', 'title', 'mainPid', 'slug']); + const collection = await activitypub.helpers.generateCollection({ + set: `tid:${req.params.tid}:posts`, + method: posts.getPidsFromSet, + page, + perPage, + url: `${nconf.get('url')}/topic/${req.params.tid}`, + }); - if (!page && pageCount === 1) { - page = 1; - paginate = false; - } - - if (page) { - const invalidPagination = page < 1 || page > pageCount; - if (invalidPagination) { - return next(); - } - - const start = Math.max(0, ((page - 1) * meta.config.postsPerPage) - 1); - const stop = Math.max(0, start + meta.config.postsPerPage - 1); - const pids = await posts.getPidsFromSet(`tid:${req.params.tid}:posts`, start, stop); + // Convert pids to urls + if (collection.orderedItems) { if (page === 1) { - pids.unshift(mainPid); - pids.length = Math.min(pids.length, meta.config.postsPerPage); + collection.orderedItems.unshift(mainPid); + collection.orderedItems.length = Math.min(collection.orderedItems.length, meta.config.postsPerPage); } - items = pids.map(pid => (utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid)); + collection.orderedItems = collection.orderedItems.map(pid => (utils.isNumber(pid) ? `${nconf.get('url')}/post/${pid}` : pid)); } const object = { '@context': 'https://www.w3.org/ns/activitystreams', - id: `${nconf.get('url')}/topic/${req.params.tid}${paginate && page ? `?page=${page}` : ''}`, + id: `${nconf.get('url')}/topic/${req.params.tid}${collection.orderedItems && page ? `?page=${page}` : ''}`, url: `${nconf.get('url')}/topic/${slug}`, name, - type: paginate && items ? 'OrderedCollectionPage' : 'OrderedCollection', attributedTo: `${nconf.get('url')}/category/${cid}`, audience: cid !== -1 ? `${nconf.get('url')}/category/${cid}/followers` : undefined, - totalItems: postcount, + ...collection, }; - if (items) { - object.orderedItems = items; - - if (paginate) { - object.partOf = `${nconf.get('url')}/topic/${req.params.tid}`; - object.next = page < pageCount ? `${nconf.get('url')}/topic/${req.params.tid}?page=${page + 1}` : null; - object.prev = page > 1 ? `${nconf.get('url')}/topic/${req.params.tid}?page=${page - 1}` : null; - } - } - - if (paginate) { - object.first = `${nconf.get('url')}/topic/${req.params.tid}?page=1`; - object.last = `${nconf.get('url')}/topic/${req.params.tid}?page=${pageCount}`; - } - res.status(200).json(object); };