refactor(response-modifier): rewrite modifiers with Typescript
Bug: twpowertools:230
Change-Id: Ibedccb24445098aae87fdbca94b0868bdcfccd41
diff --git a/src/xhrInterceptor/responseModifiers/loadMoreThread.ts b/src/xhrInterceptor/responseModifiers/loadMoreThread.ts
new file mode 100644
index 0000000..06613d5
--- /dev/null
+++ b/src/xhrInterceptor/responseModifiers/loadMoreThread.ts
@@ -0,0 +1,132 @@
+import { CCApi } from '../../common/api.js';
+import { getAuthUser } from '../../common/communityConsoleUtils.js';
+import { ProtobufNumber } from '../../common/protojs.types.js';
+import GapModel from '../../models/Gap.js';
+import MessageModel from '../../models/Message';
+import ThreadModel from '../../models/Thread';
+import { Modifier } from './types.js';
+
+const authuser = getAuthUser();
+
+const loadMoreThread: Modifier = {
+ urlRegex: /api\/ViewThread/i,
+ featureGated: true,
+ features: ['flattenthreads', 'flattenthreads_switch_enabled'],
+ isEnabled(options) {
+ return (
+ options['flattenthreads'] && options['flattenthreads_switch_enabled']
+ );
+ },
+ async interceptor(response, url) {
+ if (!response[1]?.[40]) return response;
+
+ const thread = new ThreadModel(response[1]);
+
+ if (!thread.getForumId() || !thread.getId()) {
+ console.error(
+ "[loadMoreThread] Couldn't find forum id and thread id for:",
+ url,
+ );
+ return response;
+ }
+
+ const mogs = thread.getMessageOrGapModels();
+ thread.setRawCommentsAndGaps(
+ await loadGaps(thread.getForumId(), thread.getId(), mogs, 0),
+ );
+
+ response[1] = thread.toRawThread();
+ return response;
+ },
+};
+
+function loadGaps(
+ forumId: ProtobufNumber,
+ threadId: ProtobufNumber,
+ mogs: Array<MessageModel | GapModel>,
+ it: number,
+): Promise<Array<MessageModel | GapModel>> {
+ if (it >= 10) {
+ return Promise.reject(
+ new Error(
+ 'loadGaps has been called for more than 10 times, ' +
+ "which means we've entered an infinite loop.",
+ ),
+ );
+ }
+
+ const messageOrGapPromises = [];
+ messageOrGapPromises.push(
+ Promise.resolve(mogs.filter((mog) => mog !== undefined)),
+ );
+ mogs.forEach((mog) => {
+ if (mog instanceof GapModel) {
+ messageOrGapPromises.push(loadGap(forumId, threadId, mog));
+ }
+ if (mog instanceof MessageModel) {
+ mog.getCommentsAndGaps().forEach((cog) => {
+ if (cog instanceof GapModel) {
+ messageOrGapPromises.push(loadGap(forumId, threadId, cog));
+ }
+ });
+ }
+ });
+
+ return Promise.all(messageOrGapPromises).then((res) => {
+ // #!if !production
+ console.time('mergeMessages');
+ // #!endif
+ const mogs = ThreadModel.mergeMessageOrGapsMultiarray(res);
+ // #!if !production
+ console.timeEnd('mergeMessages');
+ // #!endif
+
+ if (
+ mogs.some((mog) => {
+ return (
+ mog instanceof GapModel ||
+ mog.getCommentsAndGaps().some((cog) => cog instanceof GapModel)
+ );
+ })
+ ) {
+ return loadGaps(forumId, threadId, mogs, it + 1);
+ }
+ return mogs.map((message) => message.toRawMessageOrGap());
+ });
+}
+
+async function loadGap(
+ forumId: ProtobufNumber,
+ threadId: ProtobufNumber,
+ gap: GapModel,
+): Promise<Array<MessageModel | GapModel>> {
+ return CCApi(
+ 'ViewThread',
+ {
+ 1: forumId,
+ 2: threadId,
+ 3: {
+ // options
+ 1: {
+ // pagination
+ 2: gap.getCount(), // maxNum
+ 7: {
+ // targetRange
+ 1: gap.getStartMicroseconds(), // startMicroseconds
+ 2: gap.getEndMicroseconds(), // endMicroseconds
+ 3: gap.getParentId(), // parentId
+ },
+ },
+ 5: true, // withUserProfile
+ 10: true, // withPromotedMessages
+ },
+ },
+ /* authenticated = */ true,
+ authuser,
+ ).then((res) => {
+ const thread = new ThreadModel(res[1]);
+ return thread.getMessageOrGapModels();
+ });
+}
+
+export default loadMoreThread;