diff --git a/src/categories/topics.js b/src/categories/topics.js index 00addbe02..8e2427133 100644 --- a/src/categories/topics.js +++ b/src/categories/topics.js @@ -1,49 +1,50 @@ -'use strict'; - +"use strict"; +// plugins.d.ts const db = require('../database'); const topics = require('../topics'); const plugins = require('../plugins'); const meta = require('../meta'); const privileges = require('../privileges'); const user = require('../user'); - module.exports = function (Categories) { + async function filterScheduledTids(tids) { + const scores = await db.sortedSetScores('topics:scheduled', tids); + const now = Date.now(); + return tids.filter((tid, index) => tid && (!scores[index] || scores[index] <= now)); + } Categories.getCategoryTopics = async function (data) { let results = await plugins.hooks.fire('filter:category.topics.prepare', data); const tids = await Categories.getTopicIds(results); let topicsData = await topics.getTopicsByTids(tids, data.uid); topicsData = await user.blocks.filter(data.uid, topicsData); - if (!topicsData.length) { return { topics: [], uid: data.uid }; } topics.calculateTopicIndices(topicsData, data.start); - - results = await plugins.hooks.fire('filter:category.topics.get', { cid: data.cid, topics: topicsData, uid: data.uid }); + results = await plugins.hooks.fire('filter:category.topics.get', { + cid: data.cid, + topics: topicsData, + uid: data.uid, + }); return { topics: results.topics, nextStart: data.stop + 1 }; }; - Categories.getTopicIds = async function (data) { - const dataForPinned = { ...data }; + const dataForPinned = Object.assign({}, data); dataForPinned.start = 0; dataForPinned.stop = -1; - const [pinnedTids, set, direction] = await Promise.all([ Categories.getPinnedTids(dataForPinned), Categories.buildTopicsSortedSet(data), Categories.getSortedSetRangeDirection(data.sort), ]); - const totalPinnedCount = pinnedTids.length; const pinnedTidsOnPage = pinnedTids.slice(data.start, data.stop !== -1 ? data.stop + 1 : undefined); const pinnedCountOnPage = pinnedTidsOnPage.length; const topicsPerPage = data.stop - data.start + 1; const normalTidsToGet = Math.max(0, topicsPerPage - pinnedCountOnPage); - if (!normalTidsToGet && data.stop !== -1) { return pinnedTidsOnPage; } - if (plugins.hooks.hasListeners('filter:categories.getTopicIds')) { const result = await plugins.hooks.fire('filter:categories.getTopicIds', { tids: [], @@ -55,25 +56,23 @@ module.exports = function (Categories) { }); return result && result.tids; } - let { start } = data; if (start > 0 && totalPinnedCount) { start -= totalPinnedCount - pinnedCountOnPage; } - const stop = data.stop === -1 ? data.stop : start + normalTidsToGet - 1; let normalTids; const reverse = direction === 'highest-to-lowest'; if (Array.isArray(set)) { const weights = set.map((s, index) => (index ? 0 : 1)); normalTids = await db[reverse ? 'getSortedSetRevIntersect' : 'getSortedSetIntersect']({ sets: set, start: start, stop: stop, weights: weights }); - } else { + } + else { normalTids = await db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, stop); } - normalTids = normalTids.filter(tid => !pinnedTids.includes(tid)); + normalTids = normalTids.filter(tid => pinnedTids.indexOf(tid) === -1); return pinnedTidsOnPage.concat(normalTids); }; - Categories.getTopicCount = async function (data) { if (plugins.hooks.hasListeners('filter:categories.getTopicCount')) { const result = await plugins.hooks.fire('filter:categories.getTopicCount', { @@ -85,58 +84,67 @@ module.exports = function (Categories) { const set = await Categories.buildTopicsSortedSet(data); if (Array.isArray(set)) { return await db.sortedSetIntersectCard(set); - } else if (data.targetUid && set) { + } + else if (data.targetUid && set) { return await db.sortedSetCard(set); } return data.category.topic_count; }; - Categories.buildTopicsSortedSet = async function (data) { const { cid } = data; let set = `cid:${cid}:tids`; - const sort = data.sort || (data.settings && data.settings.categoryTopicSort) || meta.config.categoryTopicSort || 'newest_to_oldest'; - + const sort = data.sort || + (data.settings && data.settings.categoryTopicSort) || + meta.config.categoryTopicSort || + 'newest_to_oldest'; if (sort === 'most_posts') { set = `cid:${cid}:tids:posts`; - } else if (sort === 'most_votes') { + } + else if (sort === 'most_votes') { set = `cid:${cid}:tids:votes`; - } else if (sort === 'most_views') { + } + else if (sort === 'most_views') { set = `cid:${cid}:tids:views`; } - if (data.tag) { if (Array.isArray(data.tag)) { set = [set].concat(data.tag.map(tag => `tag:${tag}:topics`)); - } else { + } + else { set = [set, `tag:${data.tag}:topics`]; } } - if (data.targetUid) { - set = (Array.isArray(set) ? set : [set]).concat([`cid:${cid}:uid:${data.targetUid}:tids`]); + set = (Array.isArray(set) ? set : [set]).concat([ + `cid:${cid}:uid:${data.targetUid}:tids`, + ]); } - const result = await plugins.hooks.fire('filter:categories.buildTopicsSortedSet', { set: set, data: data, }); return result && result.set; }; - Categories.getSortedSetRangeDirection = async function (sort) { sort = sort || 'newest_to_oldest'; - const direction = ['newest_to_oldest', 'most_posts', 'most_votes', 'most_views'].includes(sort) ? 'highest-to-lowest' : 'lowest-to-highest'; + const directionOptions = [ + 'newest_to_oldest', + 'most_posts', + 'most_votes', + 'most_views', + ]; + const direction = directionOptions.indexOf(sort) !== -1 ? + 'highest-to-lowest' : + 'lowest-to-highest'; const result = await plugins.hooks.fire('filter:categories.getSortedSetRangeDirection', { sort: sort, direction: direction, }); return result && result.direction; }; - Categories.getAllTopicIds = async function (cid, start, stop) { return await db.getSortedSetRange([`cid:${cid}:tids:pinned`, `cid:${cid}:tids`], start, stop); }; - Categories.getPinnedTids = async function (data) { if (plugins.hooks.hasListeners('filter:categories.getPinnedTids')) { const result = await plugins.hooks.fire('filter:categories.getPinnedTids', { @@ -149,16 +157,15 @@ module.exports = function (Categories) { db.getSortedSetRevRange(`cid:${data.cid}:tids:pinned`, data.start, data.stop), privileges.categories.can('topics:schedule', data.cid, data.uid), ]); - const pinnedTids = canSchedule ? allPinnedTids : await filterScheduledTids(allPinnedTids); - + const pinnedTids = canSchedule ? + allPinnedTids : + await filterScheduledTids(allPinnedTids); return await topics.tools.checkPinExpiry(pinnedTids); }; - Categories.modifyTopicsByPrivilege = function (topics, privileges) { if (!Array.isArray(topics) || !topics.length || privileges.view_deleted) { return; } - topics.forEach((topic) => { if (!topic.scheduled && topic.deleted && !topic.isOwner) { topic.title = '[[topic:topic_is_deleted]]'; @@ -172,7 +179,6 @@ module.exports = function (Categories) { } }); }; - Categories.onNewPostMade = async function (cid, pinned, postData) { if (!cid || !postData) { return; @@ -187,10 +193,4 @@ module.exports = function (Categories) { await Promise.all(promises); await Categories.updateRecentTidForCid(cid); }; - - async function filterScheduledTids(tids) { - const scores = await db.sortedSetScores('topics:scheduled', tids); - const now = Date.now(); - return tids.filter((tid, index) => tid && (!scores[index] || scores[index] <= now)); - } }; diff --git a/src/categories/topics.ts b/src/categories/topics.ts new file mode 100644 index 000000000..dd882ee1b --- /dev/null +++ b/src/categories/topics.ts @@ -0,0 +1,385 @@ + + +declare function require(name: string); +// plugins.d.ts + +const db = require('../database') as unknown as DB; +const topics = require('../topics') as unknown as Topics; +const plugins = require('../plugins') as unknown as Plugins; +const meta = require('../meta') as unknown as Meta; +const privileges = require('../privileges') as unknown as Privileges; +const user = require('../user') as unknown as User; + +interface DB { + sortedSetIntersectCard: (a: string | string[]) => Promise; + sortedSetCard: (set: string | string[]) => Promise; + getSortedSetRange: ( + a: string[] | string, + b: number, + c: number + ) => Promise; + getSortedSetRevRange: (a: string, b: number, c: number) => Promise; + sortedSetAdd: (a: string, b: number, c: number) => Promise; + sortedSetIncrBy: (a: string, b: number, c: number) => Promise; + incrObjectField: (a: string, b: string) => Promise; + sortedSetScores: (a: string, b: number[]) => Promise; + getSortedSetRevIntersect: (obj: { + sets: string[]; + start: number; + stop: number; + weights: (1 | 0)[]; + }) => Promise; + getSortedSetIntersect: (obj: { + sets: string[]; + start: number; + weights: (1 | 0)[]; + }) => Promise; +} + +interface Meta { + config: { + categoryTopicSort: string; + }; +} + +interface User { + blocks: { + filter: (a: number, b: TopicsData[]) => Promise; + }; +} + +interface Privileges { + categories: { + can: (a: string, b: number, c: number) => Promise; + }; +} + +interface Topics { + tid: number; + title: string; + tools: { + checkPinExpiry: (a: number[]) => Promise; + }; + getTopicsByTids: (a: number[], b: number) => Promise; + calculateTopicIndices: (a: TopicsData[], b: number) => void; +} +interface Plugins { + hooks: { + fire: (hookName: string, data: CategoryData) => Promise; + hasListeners: (a: string) => boolean; + }; +} +interface CategoryData { + cid?: number; + uid?: number; + start?: number; + stop?: number; + sort?: string; + tag?: string | string[]; + settings?: { categoryTopicSort: string }; + category?: { topic_count: number }; + targetUid?: number; + topics?: TopicsData[]; + set?: string[] | string; + topicCount?: number; + data?: CategoryData; + pinnedTids?: number[]; + direction?: 'highest-to-lowest' | 'lowest-to-highest'; + tids?: number[]; + allPinnedTids?: number[]; + totalPinnedCount?: number; + normalTidsToGet?: number; +} + +interface TopicsData { + tid: number; + scheduled: boolean; + deleted: boolean; + isOwner: boolean; + title: string; + titleRaw?: string; + slug: number; + teaser: string | null; + noAnchor: boolean; + tags: string[]; +} + +interface PostData { + timestamp: number; + pid: number; + tid: number; +} + +interface privilegesData { + view_deleted: boolean; +} + +interface getCategoryTopicsResponse { + topics: TopicsData[]; + nextStart?: number; + uuid?: number; +} + +export = function (Categories: { + getPinnedTids: (data: CategoryData) => Promise; + buildTopicsSortedSet: (data: CategoryData) => Promise; + getSortedSetRangeDirection: (sort: string) => Promise; + getCategoryTopics: (data: CategoryData) => Promise; + getTopicIds: (data: CategoryData) => Promise; + getTopicCount: (data: CategoryData) => Promise; + getAllTopicIds: ( + cid: number, + start: number, + stop: number + ) => Promise; + modifyTopicsByPrivilege: ( + topics: TopicsData[], + privileges: privilegesData + ) => void; + onNewPostMade: ( + cid: number, + pinned: boolean, + postData: PostData + ) => Promise; + updateRecentTidForCid: (cid: number) => Promise; +}) { + async function filterScheduledTids(tids: number[]): Promise { + const scores = await db.sortedSetScores('topics:scheduled', tids); + const now = Date.now(); + return tids.filter( + (tid, index) => tid && (!scores[index] || scores[index] <= now) + ); + } + Categories.getCategoryTopics = async function (data) { + let results = await plugins.hooks.fire( + 'filter:category.topics.prepare', + data + ); + const tids = await Categories.getTopicIds(results); + let topicsData = await topics.getTopicsByTids(tids, data.uid); + topicsData = await user.blocks.filter(data.uid, topicsData); + + if (!topicsData.length) { + return { topics: [], uid: data.uid }; + } + topics.calculateTopicIndices(topicsData, data.start); + + results = await plugins.hooks.fire('filter:category.topics.get', { + cid: data.cid, + topics: topicsData, + uid: data.uid, + }); + return { topics: results.topics, nextStart: data.stop + 1 }; + }; + + Categories.getTopicIds = async function (data) { + const dataForPinned = { ...data }; + dataForPinned.start = 0; + dataForPinned.stop = -1; + + const [pinnedTids, set, direction] = await Promise.all([ + Categories.getPinnedTids(dataForPinned), + Categories.buildTopicsSortedSet(data), + Categories.getSortedSetRangeDirection(data.sort), + ]); + + const totalPinnedCount = pinnedTids.length; + const pinnedTidsOnPage = pinnedTids.slice( + data.start, + data.stop !== -1 ? data.stop + 1 : undefined + ); + const pinnedCountOnPage = pinnedTidsOnPage.length; + const topicsPerPage = data.stop - data.start + 1; + const normalTidsToGet = Math.max(0, topicsPerPage - pinnedCountOnPage); + + if (!normalTidsToGet && data.stop !== -1) { + return pinnedTidsOnPage; + } + + if (plugins.hooks.hasListeners('filter:categories.getTopicIds')) { + const result = await plugins.hooks.fire('filter:categories.getTopicIds', { + tids: [], + data: data, + pinnedTids: pinnedTidsOnPage, + allPinnedTids: pinnedTids, + totalPinnedCount: totalPinnedCount, + normalTidsToGet: normalTidsToGet, + }); + return result && result.tids; + } + + let { start } = data; + if (start > 0 && totalPinnedCount) { + start -= totalPinnedCount - pinnedCountOnPage; + } + + const stop = data.stop === -1 ? data.stop : start + normalTidsToGet - 1; + let normalTids: number[] | undefined; + const reverse = direction === 'highest-to-lowest'; + if (Array.isArray(set)) { + const weights = set.map((s, index) => (index ? 0 : 1)); + normalTids = await db[ + reverse ? 'getSortedSetRevIntersect' : 'getSortedSetIntersect' + ]({ sets: set, start: start, stop: stop, weights: weights }); + } else { + normalTids = await db[ + reverse ? 'getSortedSetRevRange' : 'getSortedSetRange' + ](set, start, stop); + } + normalTids = normalTids.filter(tid => pinnedTids.indexOf(tid) === -1); + return pinnedTidsOnPage.concat(normalTids); + }; + + Categories.getTopicCount = async function (data) { + if (plugins.hooks.hasListeners('filter:categories.getTopicCount')) { + const result = await plugins.hooks.fire( + 'filter:categories.getTopicCount', + { + topicCount: data.category.topic_count, + data: data, + } + ); + return result && result.topicCount; + } + const set = await Categories.buildTopicsSortedSet(data); + if (Array.isArray(set)) { + return await db.sortedSetIntersectCard(set); + } else if (data.targetUid && set) { + return await db.sortedSetCard(set); + } + return data.category.topic_count; + }; + + Categories.buildTopicsSortedSet = async function (data) { + const { cid } = data; + let set: string[] | string = `cid:${cid}:tids`; + const sort = + data.sort || + (data.settings && data.settings.categoryTopicSort) || + meta.config.categoryTopicSort || + 'newest_to_oldest'; + + if (sort === 'most_posts') { + set = `cid:${cid}:tids:posts`; + } else if (sort === 'most_votes') { + set = `cid:${cid}:tids:votes`; + } else if (sort === 'most_views') { + set = `cid:${cid}:tids:views`; + } + + if (data.tag) { + if (Array.isArray(data.tag)) { + set = [set].concat(data.tag.map(tag => `tag:${tag}:topics`)); + } else { + set = [set, `tag:${data.tag}:topics`]; + } + } + + if (data.targetUid) { + set = (Array.isArray(set) ? set : [set]).concat([ + `cid:${cid}:uid:${data.targetUid}:tids`, + ]); + } + + const result = await plugins.hooks.fire( + 'filter:categories.buildTopicsSortedSet', + { + set: set, + data: data, + } + ); + return result && result.set; + }; + + Categories.getSortedSetRangeDirection = async function (sort) { + sort = sort || 'newest_to_oldest'; + const directionOptions = [ + 'newest_to_oldest', + 'most_posts', + 'most_votes', + 'most_views', + ]; + const direction = + directionOptions.indexOf(sort) !== -1 ? + 'highest-to-lowest' : + 'lowest-to-highest'; + const result = await plugins.hooks.fire( + 'filter:categories.getSortedSetRangeDirection', + { + sort: sort, + direction: direction, + } + ); + return result && result.direction; + }; + + Categories.getAllTopicIds = async function (cid, start, stop) { + return await db.getSortedSetRange( + [`cid:${cid}:tids:pinned`, `cid:${cid}:tids`], + start, + stop + ); + }; + + Categories.getPinnedTids = async function (data) { + if (plugins.hooks.hasListeners('filter:categories.getPinnedTids')) { + const result = await plugins.hooks.fire( + 'filter:categories.getPinnedTids', + { + pinnedTids: [], + data: data, + } + ); + return result && result.pinnedTids; + } + const [allPinnedTids, canSchedule] = await Promise.all([ + db.getSortedSetRevRange( + `cid:${data.cid}:tids:pinned`, + data.start, + data.stop + ), + privileges.categories.can('topics:schedule', data.cid, data.uid), + ]); + const pinnedTids = canSchedule ? + allPinnedTids : + await filterScheduledTids(allPinnedTids); + + return await topics.tools.checkPinExpiry(pinnedTids); + }; + + Categories.modifyTopicsByPrivilege = function (topics, privileges) { + if (!Array.isArray(topics) || !topics.length || privileges.view_deleted) { + return; + } + + topics.forEach((topic) => { + if (!topic.scheduled && topic.deleted && !topic.isOwner) { + topic.title = '[[topic:topic_is_deleted]]'; + if (topic.hasOwnProperty('titleRaw')) { + topic.titleRaw = '[[topic:topic_is_deleted]]'; + } + topic.slug = topic.tid; + topic.teaser = null; + topic.noAnchor = true; + topic.tags = []; + } + }); + }; + + Categories.onNewPostMade = async function (cid, pinned, postData) { + if (!cid || !postData) { + return; + } + const promises = [ + db.sortedSetAdd(`cid:${cid}:pids`, postData.timestamp, postData.pid), + db.incrObjectField(`category:${cid}`, 'post_count'), + ]; + if (!pinned) { + promises.push( + db.sortedSetIncrBy(`cid:${cid}:tids:posts`, 1, postData.tid) + ); + } + await Promise.all(promises); + await Categories.updateRecentTidForCid(cid); + }; +}; diff --git a/src/controllers/composer.js b/src/controllers/composer.js index ab7f52b79..b9a62a715 100644 --- a/src/controllers/composer.js +++ b/src/controllers/composer.js @@ -1,15 +1,6 @@ "use strict"; // This is one of the two example TypeScript files included with the NodeBB repository // It is meant to serve as an example to assist you with your HW1 translation -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -21,92 +12,86 @@ const plugins_1 = __importDefault(require("../plugins")); const topics_1 = __importDefault(require("../topics")); const posts_1 = __importDefault(require("../posts")); const helpers_1 = __importDefault(require("./helpers")); -function get(req, res, callback) { - return __awaiter(this, void 0, void 0, function* () { - res.locals.metaTags = Object.assign(Object.assign({}, res.locals.metaTags), { name: 'robots', content: 'noindex' }); - const data = yield plugins_1.default.hooks.fire('filter:composer.build', { - req: req, - res: res, - next: callback, - templateData: {}, +async function get(req, res, callback) { + res.locals.metaTags = Object.assign(Object.assign({}, res.locals.metaTags), { name: 'robots', content: 'noindex' }); + const data = await plugins_1.default.hooks.fire('filter:composer.build', { + req: req, + res: res, + next: callback, + templateData: {}, + }); + if (res.headersSent) { + return; + } + if (!data || !data.templateData) { + return callback(new Error('[[error:invalid-data]]')); + } + if (data.templateData.disabled) { + res.render('', { + title: '[[modules:composer.compose]]', }); - if (res.headersSent) { - return; + } + else { + data.templateData.title = '[[modules:composer.compose]]'; + res.render('compose', data.templateData); + } +} +exports.get = get; +async function post(req, res) { + const { body } = req; + const data = { + uid: req.uid, + req: req, + timestamp: Date.now(), + content: body.content, + fromQueue: false, + }; + req.body.noscript = 'true'; + if (!data.content) { + return await helpers_1.default.noScriptErrors(req, res, '[[error:invalid-data]]', 400); + } + async function queueOrPost(postFn, data) { + // The next line calls a function in a module that has not been updated to TS yet + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const shouldQueue = await posts_1.default.shouldQueue(req.uid, data); + if (shouldQueue) { + delete data.req; + // The next line calls a function in a module that has not been updated to TS yet + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return await posts_1.default.addToQueue(data); } - if (!data || !data.templateData) { - return callback(new Error('[[error:invalid-data]]')); + return await postFn(data); + } + try { + let result; + if (body.tid) { + data.tid = body.tid; + result = await queueOrPost(topics_1.default.reply, data); } - if (data.templateData.disabled) { - res.render('', { - title: '[[modules:composer.compose]]', - }); + else if (body.cid) { + data.cid = body.cid; + data.title = body.title; + data.tags = []; + data.thumb = ''; + result = await queueOrPost(topics_1.default.post, data); } else { - data.templateData.title = '[[modules:composer.compose]]'; - res.render('compose', data.templateData); + throw new Error('[[error:invalid-data]]'); } - }); -} -exports.get = get; -function post(req, res) { - return __awaiter(this, void 0, void 0, function* () { - const { body } = req; - const data = { - uid: req.uid, - req: req, - timestamp: Date.now(), - content: body.content, - fromQueue: false, - }; - req.body.noscript = 'true'; - if (!data.content) { - return yield helpers_1.default.noScriptErrors(req, res, '[[error:invalid-data]]', 400); + if (result.queued) { + return res.redirect(`${nconf_1.default.get('relative_path') || '/'}?noScriptMessage=[[success:post-queued]]`); } - function queueOrPost(postFn, data) { - return __awaiter(this, void 0, void 0, function* () { - // The next line calls a function in a module that has not been updated to TS yet - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const shouldQueue = yield posts_1.default.shouldQueue(req.uid, data); - if (shouldQueue) { - delete data.req; - // The next line calls a function in a module that has not been updated to TS yet - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return yield posts_1.default.addToQueue(data); - } - return yield postFn(data); - }); + const uid = result.uid ? result.uid : result.topicData.uid; + // The next line calls a function in a module that has not been updated to TS yet + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + user_1.default.updateOnlineUsers(uid); + const path = result.pid ? `/post/${result.pid}` : `/topic/${result.topicData.slug}`; + res.redirect(nconf_1.default.get('relative_path') + path); + } + catch (err) { + if (err instanceof Error) { + await helpers_1.default.noScriptErrors(req, res, err.message, 400); } - try { - let result; - if (body.tid) { - data.tid = body.tid; - result = yield queueOrPost(topics_1.default.reply, data); - } - else if (body.cid) { - data.cid = body.cid; - data.title = body.title; - data.tags = []; - data.thumb = ''; - result = yield queueOrPost(topics_1.default.post, data); - } - else { - throw new Error('[[error:invalid-data]]'); - } - if (result.queued) { - return res.redirect(`${nconf_1.default.get('relative_path') || '/'}?noScriptMessage=[[success:post-queued]]`); - } - const uid = result.uid ? result.uid : result.topicData.uid; - // The next line calls a function in a module that has not been updated to TS yet - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - user_1.default.updateOnlineUsers(uid); - const path = result.pid ? `/post/${result.pid}` : `/topic/${result.topicData.slug}`; - res.redirect(nconf_1.default.get('relative_path') + path); - } - catch (err) { - if (err instanceof Error) { - yield helpers_1.default.noScriptErrors(req, res, err.message, 400); - } - } - }); + } } exports.post = post; diff --git a/src/social.js b/src/social.js index e1caaeb66..b84898a5e 100644 --- a/src/social.js +++ b/src/social.js @@ -1,15 +1,6 @@ "use strict"; // This is one of the two example TypeScript files included with the NodeBB repository // It is meant to serve as an example to assist you with your HW1 translation -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -19,56 +10,50 @@ const lodash_1 = __importDefault(require("lodash")); const plugins_1 = __importDefault(require("./plugins")); const database_1 = __importDefault(require("./database")); let postSharing = null; -function getPostSharing() { - return __awaiter(this, void 0, void 0, function* () { - if (postSharing) { - return lodash_1.default.cloneDeep(postSharing); - } - let networks = [ - { - id: 'facebook', - name: 'Facebook', - class: 'fa-facebook', - activated: null, - }, - { - id: 'twitter', - name: 'Twitter', - class: 'fa-twitter', - activated: null, - }, - ]; - networks = (yield plugins_1.default.hooks.fire('filter:social.posts', networks)); - // The next line calls a function in a module that has not been updated to TS yet - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const activated = yield database_1.default.getSetMembers('social:posts.activated'); - networks.forEach((network) => { - network.activated = activated.includes(network.id); - }); - postSharing = networks; - return lodash_1.default.cloneDeep(networks); +async function getPostSharing() { + if (postSharing) { + return lodash_1.default.cloneDeep(postSharing); + } + let networks = [ + { + id: 'facebook', + name: 'Facebook', + class: 'fa-facebook', + activated: null, + }, + { + id: 'twitter', + name: 'Twitter', + class: 'fa-twitter', + activated: null, + }, + ]; + networks = await plugins_1.default.hooks.fire('filter:social.posts', networks); + // The next line calls a function in a module that has not been updated to TS yet + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const activated = await database_1.default.getSetMembers('social:posts.activated'); + networks.forEach((network) => { + network.activated = activated.includes(network.id); }); + postSharing = networks; + return lodash_1.default.cloneDeep(networks); } exports.getPostSharing = getPostSharing; -function getActivePostSharing() { - return __awaiter(this, void 0, void 0, function* () { - const networks = yield getPostSharing(); - return networks.filter(network => network && network.activated); - }); +async function getActivePostSharing() { + const networks = await getPostSharing(); + return networks.filter(network => network && network.activated); } exports.getActivePostSharing = getActivePostSharing; -function setActivePostSharingNetworks(networkIDs) { - return __awaiter(this, void 0, void 0, function* () { - postSharing = null; - // The next line calls a function in a module that has not been updated to TS yet - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - yield database_1.default.delete('social:posts.activated'); - if (!networkIDs.length) { - return; - } - // The next line calls a function in a module that has not been updated to TS yet - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - yield database_1.default.setAdd('social:posts.activated', networkIDs); - }); +async function setActivePostSharingNetworks(networkIDs) { + postSharing = null; + // The next line calls a function in a module that has not been updated to TS yet + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + await database_1.default.delete('social:posts.activated'); + if (!networkIDs.length) { + return; + } + // The next line calls a function in a module that has not been updated to TS yet + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + await database_1.default.setAdd('social:posts.activated', networkIDs); } exports.setActivePostSharingNetworks = setActivePostSharingNetworks; diff --git a/tsconfig.json b/tsconfig.json index 10aeeef7e..c15cb3771 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "allowJs": false, - "target": "es6", + "target": "es2017", "module": "commonjs", "moduleResolution": "node", "esModuleInterop": true,