@pkcprotocol/pkc-js 0.0.19 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/clients/base-client-manager.d.ts +6 -0
- package/dist/browser/clients/base-client-manager.js +37 -3
- package/dist/browser/clients/base-client-manager.js.map +1 -1
- package/dist/browser/community/community-client-manager.js +2 -2
- package/dist/browser/community/community-client-manager.js.map +1 -1
- package/dist/browser/generated-version.d.ts +1 -1
- package/dist/browser/generated-version.js +1 -1
- package/dist/browser/pages/pages-client-manager.d.ts +16 -3
- package/dist/browser/pages/pages-client-manager.js +32 -14
- package/dist/browser/pages/pages-client-manager.js.map +1 -1
- package/dist/browser/pages/pages.d.ts +5 -1
- package/dist/browser/pages/pages.js +16 -8
- package/dist/browser/pages/pages.js.map +1 -1
- package/dist/browser/pages/schema-util.js +2 -2
- package/dist/browser/pages/schema-util.js.map +1 -1
- package/dist/browser/pages/schema.d.ts +1 -1
- package/dist/browser/pages/schema.js +1 -1
- package/dist/browser/pages/schema.js.map +1 -1
- package/dist/browser/pages/types.d.ts +5 -2
- package/dist/browser/pages/util.js +2 -2
- package/dist/browser/pages/util.js.map +1 -1
- package/dist/browser/pkc/pkc.d.ts +2 -0
- package/dist/browser/pkc/pkc.js +8 -0
- package/dist/browser/pkc/pkc.js.map +1 -1
- package/dist/browser/publications/comment/comment-client-manager.d.ts +3 -0
- package/dist/browser/publications/comment/comment-client-manager.js +33 -3
- package/dist/browser/publications/comment/comment-client-manager.js.map +1 -1
- package/dist/browser/publications/comment/comment.js +4 -4
- package/dist/browser/publications/comment/comment.js.map +1 -1
- package/dist/browser/publications/comment/schema.d.ts +16 -190
- package/dist/browser/publications/comment/schema.js +10 -1
- package/dist/browser/publications/comment/schema.js.map +1 -1
- package/dist/browser/publications/comment/types.d.ts +4 -1
- package/dist/browser/publications/publication-author.d.ts +1 -2
- package/dist/browser/publications/publication-author.js +2 -6
- package/dist/browser/publications/publication-author.js.map +1 -1
- package/dist/browser/publications/publication.js +21 -1
- package/dist/browser/publications/publication.js.map +1 -1
- package/dist/browser/runtime/node/community/db-handler-types.d.ts +3 -3
- package/dist/browser/runtime/node/community/db-handler.d.ts +19 -4
- package/dist/browser/runtime/node/community/db-handler.js +367 -78
- package/dist/browser/runtime/node/community/db-handler.js.map +1 -1
- package/dist/browser/runtime/node/community/local-community.d.ts +1 -0
- package/dist/browser/runtime/node/community/local-community.js +108 -33
- package/dist/browser/runtime/node/community/local-community.js.map +1 -1
- package/dist/browser/runtime/node/community/page-generator.d.ts +11 -5
- package/dist/browser/runtime/node/community/page-generator.js +13 -8
- package/dist/browser/runtime/node/community/page-generator.js.map +1 -1
- package/dist/browser/runtime/node/util.d.ts +13 -1
- package/dist/browser/runtime/node/util.js +126 -14
- package/dist/browser/runtime/node/util.js.map +1 -1
- package/dist/browser/schema.d.ts +0 -1
- package/dist/browser/schema.js.map +1 -1
- package/dist/browser/signer/encryption.js +8 -4
- package/dist/browser/signer/encryption.js.map +1 -1
- package/dist/browser/signer/signatures.d.ts +1 -1
- package/dist/browser/signer/signatures.js +3 -3
- package/dist/browser/signer/signatures.js.map +1 -1
- package/dist/browser/signer/util.js +4 -4
- package/dist/browser/signer/util.js.map +1 -1
- package/dist/browser/test/test-util.d.ts +0 -1
- package/dist/browser/test/test-util.js.map +1 -1
- package/dist/browser/util.d.ts +11 -0
- package/dist/browser/util.js +43 -1
- package/dist/browser/util.js.map +1 -1
- package/dist/browser/version.js +1 -1
- package/dist/node/clients/base-client-manager.d.ts +6 -0
- package/dist/node/clients/base-client-manager.js +37 -3
- package/dist/node/clients/base-client-manager.js.map +1 -1
- package/dist/node/community/community-client-manager.js +2 -2
- package/dist/node/community/community-client-manager.js.map +1 -1
- package/dist/node/generated-version.d.ts +1 -1
- package/dist/node/generated-version.js +1 -1
- package/dist/node/pages/pages-client-manager.d.ts +16 -3
- package/dist/node/pages/pages-client-manager.js +32 -14
- package/dist/node/pages/pages-client-manager.js.map +1 -1
- package/dist/node/pages/pages.d.ts +5 -1
- package/dist/node/pages/pages.js +16 -8
- package/dist/node/pages/pages.js.map +1 -1
- package/dist/node/pages/schema-util.js +2 -2
- package/dist/node/pages/schema-util.js.map +1 -1
- package/dist/node/pages/schema.d.ts +1 -1
- package/dist/node/pages/schema.js +1 -1
- package/dist/node/pages/schema.js.map +1 -1
- package/dist/node/pages/types.d.ts +5 -2
- package/dist/node/pages/util.js +2 -2
- package/dist/node/pages/util.js.map +1 -1
- package/dist/node/pkc/pkc.d.ts +2 -0
- package/dist/node/pkc/pkc.js +8 -0
- package/dist/node/pkc/pkc.js.map +1 -1
- package/dist/node/publications/comment/comment-client-manager.d.ts +3 -0
- package/dist/node/publications/comment/comment-client-manager.js +33 -3
- package/dist/node/publications/comment/comment-client-manager.js.map +1 -1
- package/dist/node/publications/comment/comment.js +4 -4
- package/dist/node/publications/comment/comment.js.map +1 -1
- package/dist/node/publications/comment/schema.d.ts +16 -190
- package/dist/node/publications/comment/schema.js +10 -1
- package/dist/node/publications/comment/schema.js.map +1 -1
- package/dist/node/publications/comment/types.d.ts +4 -1
- package/dist/node/publications/publication-author.d.ts +1 -2
- package/dist/node/publications/publication-author.js +2 -6
- package/dist/node/publications/publication-author.js.map +1 -1
- package/dist/node/publications/publication.js +21 -1
- package/dist/node/publications/publication.js.map +1 -1
- package/dist/node/runtime/node/community/db-handler-types.d.ts +3 -3
- package/dist/node/runtime/node/community/db-handler.d.ts +19 -4
- package/dist/node/runtime/node/community/db-handler.js +367 -78
- package/dist/node/runtime/node/community/db-handler.js.map +1 -1
- package/dist/node/runtime/node/community/local-community.d.ts +1 -0
- package/dist/node/runtime/node/community/local-community.js +108 -33
- package/dist/node/runtime/node/community/local-community.js.map +1 -1
- package/dist/node/runtime/node/community/page-generator.d.ts +11 -5
- package/dist/node/runtime/node/community/page-generator.js +13 -8
- package/dist/node/runtime/node/community/page-generator.js.map +1 -1
- package/dist/node/runtime/node/util.d.ts +13 -1
- package/dist/node/runtime/node/util.js +126 -14
- package/dist/node/runtime/node/util.js.map +1 -1
- package/dist/node/schema.d.ts +0 -1
- package/dist/node/schema.js.map +1 -1
- package/dist/node/signer/encryption.js +8 -4
- package/dist/node/signer/encryption.js.map +1 -1
- package/dist/node/signer/signatures.d.ts +1 -1
- package/dist/node/signer/signatures.js +3 -3
- package/dist/node/signer/signatures.js.map +1 -1
- package/dist/node/signer/util.js +4 -4
- package/dist/node/signer/util.js.map +1 -1
- package/dist/node/test/test-util.d.ts +0 -1
- package/dist/node/test/test-util.js.map +1 -1
- package/dist/node/util.d.ts +11 -0
- package/dist/node/util.js +43 -1
- package/dist/node/util.js.map +1 -1
- package/dist/node/version.js +1 -1
- package/package.json +21 -22
|
@@ -23,7 +23,7 @@ import { TIMEFRAMES_TO_SECONDS } from "../../../pages/util.js";
|
|
|
23
23
|
import { parseCommentEditsRow, parseCommentUpdateRow, parseCommentsTableRow, parsePrefixedComment, parseVoteRow } from "./db-row-parser.js";
|
|
24
24
|
import { ZodError } from "zod";
|
|
25
25
|
import { messages } from "../../../errors.js";
|
|
26
|
-
import {
|
|
26
|
+
import { getAuthorNameFromWire } from "../../../publications/publication-author.js";
|
|
27
27
|
const TABLES = Object.freeze({
|
|
28
28
|
COMMENTS: "comments",
|
|
29
29
|
COMMENT_UPDATES: "commentUpdates",
|
|
@@ -332,8 +332,8 @@ export class DbHandler {
|
|
|
332
332
|
CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
333
333
|
commentCid TEXT NOT NULL PRIMARY KEY UNIQUE REFERENCES ${TABLES.COMMENTS}(cid) ON DELETE CASCADE,
|
|
334
334
|
aliasPrivateKey TEXT NOT NULL,
|
|
335
|
-
|
|
336
|
-
|
|
335
|
+
originalAuthorPublicKey TEXT NOT NULL,
|
|
336
|
+
originalAuthorName TEXT NULLABLE, -- the original author's name (e.g., user.eth) if they used one
|
|
337
337
|
mode TEXT NOT NULL CHECK(mode IN ('per-post', 'per-reply', 'per-author')),
|
|
338
338
|
insertedAt INTEGER NOT NULL
|
|
339
339
|
)
|
|
@@ -489,7 +489,7 @@ export class DbHandler {
|
|
|
489
489
|
const moderationsToUpdate = this._db
|
|
490
490
|
.prepare(`
|
|
491
491
|
SELECT cm.rowid, cm.commentCid, c.authorSignerAddress,
|
|
492
|
-
pa.
|
|
492
|
+
pa.originalAuthorPublicKey
|
|
493
493
|
FROM ${TABLES.COMMENT_MODERATIONS} cm
|
|
494
494
|
LEFT JOIN ${TABLES.COMMENTS} c ON cm.commentCid = c.cid
|
|
495
495
|
LEFT JOIN ${TABLES.PSEUDONYMITY_ALIASES} pa ON cm.commentCid = pa.commentCid
|
|
@@ -504,9 +504,9 @@ export class DbHandler {
|
|
|
504
504
|
for (const mod of items) {
|
|
505
505
|
let targetAddress = null;
|
|
506
506
|
// If the comment was published with pseudonymity, use the original author's address
|
|
507
|
-
if (mod.
|
|
507
|
+
if (mod.originalAuthorPublicKey) {
|
|
508
508
|
try {
|
|
509
|
-
targetAddress = getPKCAddressFromPublicKeySync(mod.
|
|
509
|
+
targetAddress = getPKCAddressFromPublicKeySync(mod.originalAuthorPublicKey);
|
|
510
510
|
}
|
|
511
511
|
catch {
|
|
512
512
|
// If we can't derive the address from the public key, fall back to authorSignerAddress
|
|
@@ -531,7 +531,7 @@ export class DbHandler {
|
|
|
531
531
|
const moderationsToUpdate = this._db
|
|
532
532
|
.prepare(`
|
|
533
533
|
SELECT cm.rowid, c.author as commentAuthor,
|
|
534
|
-
pa.
|
|
534
|
+
pa.originalAuthorName
|
|
535
535
|
FROM ${TABLES.COMMENT_MODERATIONS} cm
|
|
536
536
|
LEFT JOIN ${TABLES.COMMENTS} c ON cm.commentCid = c.cid
|
|
537
537
|
LEFT JOIN ${TABLES.PSEUDONYMITY_ALIASES} pa ON cm.commentCid = pa.commentCid
|
|
@@ -547,13 +547,13 @@ export class DbHandler {
|
|
|
547
547
|
for (const mod of items) {
|
|
548
548
|
let targetDomain = null;
|
|
549
549
|
// If the comment was published with pseudonymity, use the original author's domain
|
|
550
|
-
if (mod.
|
|
551
|
-
targetDomain = mod.
|
|
550
|
+
if (mod.originalAuthorName) {
|
|
551
|
+
targetDomain = mod.originalAuthorName;
|
|
552
552
|
}
|
|
553
553
|
else if (mod.commentAuthor) {
|
|
554
554
|
try {
|
|
555
555
|
const author = JSON.parse(mod.commentAuthor);
|
|
556
|
-
targetDomain =
|
|
556
|
+
targetDomain = getAuthorNameFromWire(author) || null;
|
|
557
557
|
}
|
|
558
558
|
catch {
|
|
559
559
|
// Ignore parse errors
|
|
@@ -622,6 +622,17 @@ export class DbHandler {
|
|
|
622
622
|
srcRecord.extraProps = { ...existingExtra, subplebbitAddress: addr };
|
|
623
623
|
delete srcRecord["subplebbitAddress"];
|
|
624
624
|
}
|
|
625
|
+
// Rename pseudonymityAliases columns (v38 → v39)
|
|
626
|
+
if (currentDbVersion < 39 && srcTable === TABLES.PSEUDONYMITY_ALIASES) {
|
|
627
|
+
if (srcRecord["originalAuthorSignerPublicKey"] !== undefined) {
|
|
628
|
+
srcRecord["originalAuthorPublicKey"] = srcRecord["originalAuthorSignerPublicKey"];
|
|
629
|
+
delete srcRecord["originalAuthorSignerPublicKey"];
|
|
630
|
+
}
|
|
631
|
+
if (srcRecord["originalAuthorDomain"] !== undefined) {
|
|
632
|
+
srcRecord["originalAuthorName"] = srcRecord["originalAuthorDomain"];
|
|
633
|
+
delete srcRecord["originalAuthorDomain"];
|
|
634
|
+
}
|
|
635
|
+
}
|
|
625
636
|
// Prepare record for insertion (stringify JSONs, convert booleans)
|
|
626
637
|
const processedRecord = this._processRecordsForDbBeforeInsert([srcRecord])[0];
|
|
627
638
|
// Map values including rowid (preserve the original rowid value)
|
|
@@ -857,8 +868,8 @@ export class DbHandler {
|
|
|
857
868
|
const processedAliases = this._processRecordsForDbBeforeInsert(aliases);
|
|
858
869
|
const stmt = this._db.prepare(`
|
|
859
870
|
INSERT OR REPLACE INTO ${TABLES.PSEUDONYMITY_ALIASES}
|
|
860
|
-
(commentCid, aliasPrivateKey,
|
|
861
|
-
VALUES (@commentCid, @aliasPrivateKey, @
|
|
871
|
+
(commentCid, aliasPrivateKey, originalAuthorPublicKey, originalAuthorName, mode, insertedAt)
|
|
872
|
+
VALUES (@commentCid, @aliasPrivateKey, @originalAuthorPublicKey, @originalAuthorName, @mode, @insertedAt)
|
|
862
873
|
`);
|
|
863
874
|
const insertMany = this._db.transaction((items) => {
|
|
864
875
|
for (const alias of items)
|
|
@@ -1070,6 +1081,294 @@ export class DbHandler {
|
|
|
1070
1081
|
return { comment, commentUpdate };
|
|
1071
1082
|
});
|
|
1072
1083
|
}
|
|
1084
|
+
queryPageCommentsWithResolvedReplies(options) {
|
|
1085
|
+
// Fetch ALL descendants by following CID-ref lists stored in the DB `replies` column.
|
|
1086
|
+
// Base case: direct children of parentCid.
|
|
1087
|
+
// Recursive case: follow $.best.commentCids from each node's replies JSON.
|
|
1088
|
+
// Returns flat rows with tree_parent for JS tree assembly.
|
|
1089
|
+
const commentUpdateCols = remeda.keys.strict(CommentUpdateSchema.shape);
|
|
1090
|
+
const commentIpfsCols = [...remeda.keys.strict(CommentIpfsSchema.shape), "extraProps"];
|
|
1091
|
+
// Base case uses full table names (not aliases) to match _buildPageQueryParts WHERE clauses
|
|
1092
|
+
const baseCommentUpdateSelects = commentUpdateCols.map((col) => `${TABLES.COMMENT_UPDATES}.${col} AS commentUpdate_${col}`);
|
|
1093
|
+
const baseCommentIpfsSelects = commentIpfsCols.map((col) => `${TABLES.COMMENTS}.${col} AS commentIpfs_${col}`);
|
|
1094
|
+
// Recursive part uses aliases since it joins fresh tables
|
|
1095
|
+
const recCommentUpdateSelects = commentUpdateCols.map((col) => `cu2.${col} AS commentUpdate_${col}`);
|
|
1096
|
+
const recCommentIpfsSelects = commentIpfsCols.map((col) => `c2.${col} AS commentIpfs_${col}`);
|
|
1097
|
+
const { whereClauses, params } = this._buildPageQueryParts(options);
|
|
1098
|
+
// Build recursive filter clauses (same pattern as queryFlattenedPageReplies)
|
|
1099
|
+
const recursiveFilterClauses = [];
|
|
1100
|
+
if (options.excludeCommentsWithDifferentCommunityAddress) {
|
|
1101
|
+
const { clause, params: addrParams } = this._communityAddressClause("c2");
|
|
1102
|
+
recursiveFilterClauses.push(clause);
|
|
1103
|
+
params.push(...addrParams);
|
|
1104
|
+
}
|
|
1105
|
+
if (options.excludeCommentPendingApproval)
|
|
1106
|
+
recursiveFilterClauses.push(this._pendingApprovalClause("c2"));
|
|
1107
|
+
if (options.excludeRemovedComments)
|
|
1108
|
+
recursiveFilterClauses.push(this._removedClause("cu2"));
|
|
1109
|
+
if (options.excludeDeletedComments)
|
|
1110
|
+
recursiveFilterClauses.push(this._deletedFromLookupClause("d2"));
|
|
1111
|
+
if (options.excludeCommentWithApprovedFalse)
|
|
1112
|
+
recursiveFilterClauses.push(this._approvedClause("cu2"));
|
|
1113
|
+
const recursiveWhereExtra = recursiveFilterClauses.length > 0 ? `AND ${recursiveFilterClauses.join(" AND ")}` : "";
|
|
1114
|
+
const deletedLookupJoin = options.excludeDeletedComments
|
|
1115
|
+
? `LEFT JOIN (SELECT cid, json_extract(edit, '$.deleted') AS deleted_flag FROM ${TABLES.COMMENT_UPDATES}) AS d2 ON c2.cid = d2.cid`
|
|
1116
|
+
: "";
|
|
1117
|
+
const queryStr = `
|
|
1118
|
+
WITH RECURSIVE reply_tree AS (
|
|
1119
|
+
-- Base: direct children of the target comment
|
|
1120
|
+
SELECT ${baseCommentIpfsSelects.join(", ")}, ${baseCommentUpdateSelects.join(", ")},
|
|
1121
|
+
${TABLES.COMMENTS}.parentCid AS tree_parent
|
|
1122
|
+
FROM ${TABLES.COMMENTS}
|
|
1123
|
+
INNER JOIN ${TABLES.COMMENT_UPDATES} ON ${TABLES.COMMENTS}.cid = ${TABLES.COMMENT_UPDATES}.cid
|
|
1124
|
+
WHERE ${whereClauses.join(" AND ")}
|
|
1125
|
+
|
|
1126
|
+
UNION ALL
|
|
1127
|
+
|
|
1128
|
+
-- Recursive: follow commentCids from each parent's replies
|
|
1129
|
+
SELECT ${recCommentIpfsSelects.join(", ")}, ${recCommentUpdateSelects.join(", ")},
|
|
1130
|
+
rt.commentUpdate_cid AS tree_parent
|
|
1131
|
+
FROM reply_tree rt
|
|
1132
|
+
CROSS JOIN json_each(
|
|
1133
|
+
json_extract(rt.commentUpdate_replies, '$.best.commentCids')
|
|
1134
|
+
) child_ref
|
|
1135
|
+
JOIN ${TABLES.COMMENTS} c2 ON c2.cid = child_ref.value
|
|
1136
|
+
JOIN ${TABLES.COMMENT_UPDATES} cu2 ON c2.cid = cu2.cid
|
|
1137
|
+
${deletedLookupJoin}
|
|
1138
|
+
WHERE rt.commentUpdate_replies IS NOT NULL
|
|
1139
|
+
AND json_type(rt.commentUpdate_replies, '$.best.commentCids') = 'array'
|
|
1140
|
+
${recursiveWhereExtra}
|
|
1141
|
+
)
|
|
1142
|
+
SELECT * FROM reply_tree
|
|
1143
|
+
`;
|
|
1144
|
+
const rowsRaw = this._db.prepare(queryStr).all(...params);
|
|
1145
|
+
// Group by tree_parent to reconstruct the hierarchy
|
|
1146
|
+
const parsedByCid = new Map();
|
|
1147
|
+
const childrenByParent = new Map();
|
|
1148
|
+
for (const row of rowsRaw) {
|
|
1149
|
+
const { comment, commentUpdate } = this._parsePrefixedComment(row);
|
|
1150
|
+
parsedByCid.set(commentUpdate.cid, { comment, commentUpdate });
|
|
1151
|
+
const parent = row.tree_parent;
|
|
1152
|
+
if (!childrenByParent.has(parent))
|
|
1153
|
+
childrenByParent.set(parent, []);
|
|
1154
|
+
childrenByParent.get(parent).push({ comment, commentUpdate });
|
|
1155
|
+
}
|
|
1156
|
+
// Build a commentUpdate for wire format: strip DB replies, only add resolved replies if present
|
|
1157
|
+
const buildWireCommentUpdate = (commentUpdate, resolvedReplies) => {
|
|
1158
|
+
const { replies: dbReplies, ...rest } = commentUpdate;
|
|
1159
|
+
if (resolvedReplies)
|
|
1160
|
+
return { ...rest, replies: resolvedReplies };
|
|
1161
|
+
// If no resolved inline replies but DB has allPageCids, reconstruct pageCids so clients can fetch pages
|
|
1162
|
+
if (dbReplies) {
|
|
1163
|
+
const dbEntries = dbReplies;
|
|
1164
|
+
const pageCids = {};
|
|
1165
|
+
for (const [sortName, sortEntry] of Object.entries(dbEntries)) {
|
|
1166
|
+
if (sortEntry?.allPageCids?.[0])
|
|
1167
|
+
pageCids[sortName] = sortEntry.allPageCids[0];
|
|
1168
|
+
}
|
|
1169
|
+
if (Object.keys(pageCids).length > 0)
|
|
1170
|
+
return { ...rest, replies: { pages: {}, pageCids } };
|
|
1171
|
+
}
|
|
1172
|
+
return rest;
|
|
1173
|
+
};
|
|
1174
|
+
// Recursively attach nested replies
|
|
1175
|
+
const attachReplies = (cid) => {
|
|
1176
|
+
const children = childrenByParent.get(cid);
|
|
1177
|
+
if (!children?.length)
|
|
1178
|
+
return undefined;
|
|
1179
|
+
// Sort children by the parent's commentCids order.
|
|
1180
|
+
// SQLite's recursive CTE does not guarantee row order matches json_each array order
|
|
1181
|
+
// when additional JOINs are involved, so we must explicitly reorder.
|
|
1182
|
+
const parent = parsedByCid.get(cid);
|
|
1183
|
+
const parentDbReplies = parent?.commentUpdate?.replies;
|
|
1184
|
+
const cidOrder = parentDbReplies?.best?.commentCids;
|
|
1185
|
+
const orderedChildren = cidOrder
|
|
1186
|
+
? cidOrder.map((childCid) => children.find((c) => c.commentUpdate.cid === childCid)).filter(Boolean)
|
|
1187
|
+
: children;
|
|
1188
|
+
return {
|
|
1189
|
+
pages: {
|
|
1190
|
+
best: {
|
|
1191
|
+
comments: orderedChildren.map((child) => ({
|
|
1192
|
+
comment: child.comment,
|
|
1193
|
+
commentUpdate: buildWireCommentUpdate(child.commentUpdate, attachReplies(child.commentUpdate.cid))
|
|
1194
|
+
}))
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
};
|
|
1199
|
+
// Direct children with nested replies attached
|
|
1200
|
+
const directChildren = childrenByParent.get(options.parentCid) ?? [];
|
|
1201
|
+
return directChildren.map((child) => ({
|
|
1202
|
+
comment: child.comment,
|
|
1203
|
+
commentUpdate: buildWireCommentUpdate(child.commentUpdate, attachReplies(child.commentUpdate.cid))
|
|
1204
|
+
}));
|
|
1205
|
+
}
|
|
1206
|
+
resolveRepliesCidRefsForEntries(entries) {
|
|
1207
|
+
// For entries whose replies are in CID-ref format, resolve them by fetching descendants.
|
|
1208
|
+
// Collects all root CIDs from all entries, runs a single recursive query, then distributes results.
|
|
1209
|
+
const commentUpdateCols = remeda.keys.strict(CommentUpdateSchema.shape);
|
|
1210
|
+
const commentIpfsCols = [...remeda.keys.strict(CommentIpfsSchema.shape), "extraProps"];
|
|
1211
|
+
// Gather all CIDs from CID-ref replies across all entries
|
|
1212
|
+
const allCids = [];
|
|
1213
|
+
for (const entry of entries) {
|
|
1214
|
+
const replies = entry.commentUpdate.replies;
|
|
1215
|
+
if (!replies)
|
|
1216
|
+
continue;
|
|
1217
|
+
for (const sortEntry of Object.values(replies)) {
|
|
1218
|
+
if (sortEntry?.commentCids)
|
|
1219
|
+
allCids.push(...sortEntry.commentCids);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
// Build lookup maps from recursive query (only if we have CIDs to resolve)
|
|
1223
|
+
const parsedByCid = new Map();
|
|
1224
|
+
const childrenByParent = new Map();
|
|
1225
|
+
if (allCids.length > 0) {
|
|
1226
|
+
// Fetch all descendant trees starting from these CIDs using a recursive CTE
|
|
1227
|
+
const placeholders = allCids.map(() => "?").join(",");
|
|
1228
|
+
const commentUpdateSelects = commentUpdateCols.map((col) => `cu.${col} AS commentUpdate_${col}`);
|
|
1229
|
+
const commentIpfsSelects = commentIpfsCols.map((col) => `c.${col} AS commentIpfs_${col}`);
|
|
1230
|
+
const recCommentUpdateSelects = commentUpdateCols.map((col) => `cu2.${col} AS commentUpdate_${col}`);
|
|
1231
|
+
const recCommentIpfsSelects = commentIpfsCols.map((col) => `c2.${col} AS commentIpfs_${col}`);
|
|
1232
|
+
const queryStr = `
|
|
1233
|
+
WITH RECURSIVE reply_tree AS (
|
|
1234
|
+
SELECT ${commentIpfsSelects.join(", ")}, ${commentUpdateSelects.join(", ")},
|
|
1235
|
+
c.parentCid AS tree_parent
|
|
1236
|
+
FROM ${TABLES.COMMENTS} c
|
|
1237
|
+
INNER JOIN ${TABLES.COMMENT_UPDATES} cu ON c.cid = cu.cid
|
|
1238
|
+
WHERE c.cid IN (${placeholders})
|
|
1239
|
+
|
|
1240
|
+
UNION ALL
|
|
1241
|
+
|
|
1242
|
+
SELECT ${recCommentIpfsSelects.join(", ")}, ${recCommentUpdateSelects.join(", ")},
|
|
1243
|
+
rt.commentUpdate_cid AS tree_parent
|
|
1244
|
+
FROM reply_tree rt
|
|
1245
|
+
CROSS JOIN json_each(
|
|
1246
|
+
json_extract(rt.commentUpdate_replies, '$.best.commentCids')
|
|
1247
|
+
) child_ref
|
|
1248
|
+
JOIN ${TABLES.COMMENTS} c2 ON c2.cid = child_ref.value
|
|
1249
|
+
JOIN ${TABLES.COMMENT_UPDATES} cu2 ON c2.cid = cu2.cid
|
|
1250
|
+
WHERE rt.commentUpdate_replies IS NOT NULL
|
|
1251
|
+
AND json_type(rt.commentUpdate_replies, '$.best.commentCids') = 'array'
|
|
1252
|
+
)
|
|
1253
|
+
SELECT * FROM reply_tree
|
|
1254
|
+
`;
|
|
1255
|
+
const rowsRaw = this._db.prepare(queryStr).all(...allCids);
|
|
1256
|
+
// Build lookup: cid -> parsed entry
|
|
1257
|
+
for (const row of rowsRaw) {
|
|
1258
|
+
const { comment, commentUpdate } = this._parsePrefixedComment(row);
|
|
1259
|
+
parsedByCid.set(commentUpdate.cid, { comment, commentUpdate });
|
|
1260
|
+
const parent = row.tree_parent;
|
|
1261
|
+
if (!childrenByParent.has(parent))
|
|
1262
|
+
childrenByParent.set(parent, []);
|
|
1263
|
+
childrenByParent.get(parent).push({ comment, commentUpdate });
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
// Build a commentUpdate for wire format: strip DB replies, attach resolved replies or reconstruct pageCids
|
|
1267
|
+
const buildWireCommentUpdate = (commentUpdate, resolvedReplies) => {
|
|
1268
|
+
const { replies: dbReplies, ...rest } = commentUpdate;
|
|
1269
|
+
if (resolvedReplies)
|
|
1270
|
+
return { ...rest, replies: resolvedReplies };
|
|
1271
|
+
// If no resolved inline replies but DB has allPageCids, reconstruct pageCids so clients can fetch pages
|
|
1272
|
+
if (dbReplies) {
|
|
1273
|
+
const dbEntries = dbReplies;
|
|
1274
|
+
const pageCids = {};
|
|
1275
|
+
for (const [sortName, sortEntry] of Object.entries(dbEntries)) {
|
|
1276
|
+
if (sortEntry?.allPageCids?.[0])
|
|
1277
|
+
pageCids[sortName] = sortEntry.allPageCids[0];
|
|
1278
|
+
}
|
|
1279
|
+
if (Object.keys(pageCids).length > 0)
|
|
1280
|
+
return { ...rest, replies: { pages: {}, pageCids } };
|
|
1281
|
+
}
|
|
1282
|
+
return rest;
|
|
1283
|
+
};
|
|
1284
|
+
const attachReplies = (cid) => {
|
|
1285
|
+
const children = childrenByParent.get(cid);
|
|
1286
|
+
if (!children?.length)
|
|
1287
|
+
return undefined;
|
|
1288
|
+
// Sort children by the parent's commentCids order.
|
|
1289
|
+
// SQLite's recursive CTE does not guarantee row order matches json_each array order
|
|
1290
|
+
// when additional JOINs are involved, so we must explicitly reorder.
|
|
1291
|
+
const parent = parsedByCid.get(cid);
|
|
1292
|
+
const parentDbReplies = parent?.commentUpdate?.replies;
|
|
1293
|
+
const cidOrder = parentDbReplies?.best?.commentCids;
|
|
1294
|
+
const orderedChildren = cidOrder
|
|
1295
|
+
? cidOrder.map((childCid) => children.find((c) => c.commentUpdate.cid === childCid)).filter(Boolean)
|
|
1296
|
+
: children;
|
|
1297
|
+
return {
|
|
1298
|
+
pages: {
|
|
1299
|
+
best: {
|
|
1300
|
+
comments: orderedChildren.map((child) => ({
|
|
1301
|
+
comment: child.comment,
|
|
1302
|
+
commentUpdate: buildWireCommentUpdate(child.commentUpdate, attachReplies(child.commentUpdate.cid))
|
|
1303
|
+
}))
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
};
|
|
1308
|
+
// Resolve each entry's CID-ref replies into full nested data
|
|
1309
|
+
return entries.map((entry) => {
|
|
1310
|
+
const replies = entry.commentUpdate.replies;
|
|
1311
|
+
if (!replies)
|
|
1312
|
+
return entry;
|
|
1313
|
+
// Check if it's DB CID-ref format (has commentCids or allPageCids)
|
|
1314
|
+
const isDbFormat = Object.values(replies).some((s) => s?.commentCids || s?.allPageCids);
|
|
1315
|
+
if (!isDbFormat)
|
|
1316
|
+
return entry;
|
|
1317
|
+
// Build resolved pages and pageCids from CID refs
|
|
1318
|
+
const resolvedPages = {};
|
|
1319
|
+
const resolvedPageCids = {};
|
|
1320
|
+
for (const [sortName, sortEntry] of Object.entries(replies)) {
|
|
1321
|
+
if (sortEntry?.commentCids) {
|
|
1322
|
+
const resolvedComments = sortEntry.commentCids
|
|
1323
|
+
.map((cid) => parsedByCid.get(cid))
|
|
1324
|
+
.filter(Boolean)
|
|
1325
|
+
.map((child) => ({
|
|
1326
|
+
comment: child.comment,
|
|
1327
|
+
commentUpdate: buildWireCommentUpdate(child.commentUpdate, attachReplies(child.commentUpdate.cid))
|
|
1328
|
+
}));
|
|
1329
|
+
// Derive nextCid from allPageCids[0]; fall back to legacy nextCid field for old DB rows
|
|
1330
|
+
const nextCidForSort = sortEntry.allPageCids?.[0] ?? sortEntry.nextCid;
|
|
1331
|
+
resolvedPages[sortName] = {
|
|
1332
|
+
comments: resolvedComments,
|
|
1333
|
+
...(nextCidForSort ? { nextCid: nextCidForSort } : {})
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
// Derive pageCid from allPageCids[0] (first page CID for this sort)
|
|
1337
|
+
if (sortEntry?.allPageCids?.[0]) {
|
|
1338
|
+
resolvedPageCids[sortName] = sortEntry.allPageCids[0];
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
const { replies: _dbReplies, ...entryCommentUpdateRest } = entry.commentUpdate;
|
|
1342
|
+
return {
|
|
1343
|
+
...entry,
|
|
1344
|
+
commentUpdate: {
|
|
1345
|
+
...entryCommentUpdateRest,
|
|
1346
|
+
replies: {
|
|
1347
|
+
pages: resolvedPages,
|
|
1348
|
+
...(Object.keys(resolvedPageCids).length > 0 ? { pageCids: resolvedPageCids } : {})
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
queryCommentAndCommentUpdateByCids(cids, opts) {
|
|
1355
|
+
if (cids.length === 0)
|
|
1356
|
+
return [];
|
|
1357
|
+
const placeholders = cids.map(() => "?").join(",");
|
|
1358
|
+
const commentUpdateSelects = opts.commentUpdateCols.map((col) => `cu.${col} AS commentUpdate_${col}`);
|
|
1359
|
+
const commentIpfsSelects = opts.commentIpfsCols.map((col) => `c.${col} AS commentIpfs_${col}`);
|
|
1360
|
+
const queryStr = `
|
|
1361
|
+
SELECT ${commentIpfsSelects.join(", ")}, ${commentUpdateSelects.join(", ")}
|
|
1362
|
+
FROM ${TABLES.COMMENTS} c
|
|
1363
|
+
INNER JOIN ${TABLES.COMMENT_UPDATES} cu ON c.cid = cu.cid
|
|
1364
|
+
WHERE c.cid IN (${placeholders})
|
|
1365
|
+
`;
|
|
1366
|
+
const rows = this._db.prepare(queryStr).all(...cids);
|
|
1367
|
+
return rows.map((row) => {
|
|
1368
|
+
const { comment, commentUpdate } = this._parsePrefixedComment(row);
|
|
1369
|
+
return { comment, commentUpdate };
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1073
1372
|
queryFlattenedPageReplies(options) {
|
|
1074
1373
|
const commentUpdateCols = remeda.keys.strict(options.commentUpdateFieldsToExclude
|
|
1075
1374
|
? remeda.omit(CommentUpdateSchema.shape, options.commentUpdateFieldsToExclude)
|
|
@@ -1146,6 +1445,27 @@ export class DbHandler {
|
|
|
1146
1445
|
return undefined;
|
|
1147
1446
|
return this._parseCommentUpdatesRow(row);
|
|
1148
1447
|
}
|
|
1448
|
+
queryCommentUpdateTimestampBucketReplies(opts) {
|
|
1449
|
+
const row = this._db
|
|
1450
|
+
.prepare(`SELECT updatedAt, postUpdatesBucket, replies FROM ${TABLES.COMMENT_UPDATES} WHERE cid = ?`)
|
|
1451
|
+
.get(opts.cid);
|
|
1452
|
+
if (!row)
|
|
1453
|
+
return undefined;
|
|
1454
|
+
return {
|
|
1455
|
+
updatedAt: row.updatedAt,
|
|
1456
|
+
postUpdatesBucket: row.postUpdatesBucket ?? undefined,
|
|
1457
|
+
replies: typeof row.replies === "string" ? JSON.parse(row.replies) : undefined
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1460
|
+
queryCommentUpdateBucketAndReplies(opts) {
|
|
1461
|
+
const row = this._db.prepare(`SELECT postUpdatesBucket, replies FROM ${TABLES.COMMENT_UPDATES} WHERE cid = ?`).get(opts.cid);
|
|
1462
|
+
if (!row)
|
|
1463
|
+
return undefined;
|
|
1464
|
+
return {
|
|
1465
|
+
postUpdatesBucket: row.postUpdatesBucket ?? undefined,
|
|
1466
|
+
replies: typeof row.replies === "string" ? JSON.parse(row.replies) : undefined
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1149
1469
|
hasCommentWithSignatureEncoded(signatureEncoded) {
|
|
1150
1470
|
const row = this._db
|
|
1151
1471
|
.prepare(`SELECT 1 FROM ${TABLES.COMMENTS}
|
|
@@ -1267,42 +1587,22 @@ export class DbHandler {
|
|
|
1267
1587
|
WHERE (parent.pendingApproval IS NULL OR parent.pendingApproval != 1)
|
|
1268
1588
|
AND COALESCE(lc.actual_last_child_cid, '') != COALESCE(cu_parent.lastChildCid, '')
|
|
1269
1589
|
),
|
|
1270
|
-
|
|
1271
|
-
SELECT
|
|
1272
|
-
cu_parent.cid AS parentCid,
|
|
1273
|
-
json_extract(comment_entry.value, '$.comment.cid') AS comment_child_cid,
|
|
1274
|
-
json_extract(comment_entry.value, '$.commentUpdate.cid') AS update_child_cid,
|
|
1275
|
-
json_extract(comment_entry.value, '$.commentUpdate.updatedAt') AS json_child_updated_at
|
|
1590
|
+
stale_replies AS (
|
|
1591
|
+
SELECT DISTINCT cu_parent.cid
|
|
1276
1592
|
FROM ${TABLES.COMMENT_UPDATES} cu_parent
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1593
|
+
CROSS JOIN json_each(
|
|
1594
|
+
json_extract(cu_parent.replies, '$.best.commentCids')
|
|
1595
|
+
) child_ref
|
|
1596
|
+
JOIN ${TABLES.COMMENT_UPDATES} cu_child ON cu_child.cid = child_ref.value
|
|
1280
1597
|
WHERE cu_parent.replies IS NOT NULL
|
|
1281
|
-
AND json_type(cu_parent.replies, '$.
|
|
1282
|
-
AND
|
|
1283
|
-
),
|
|
1284
|
-
stale_replies_json AS (
|
|
1285
|
-
SELECT r.parentCid AS cid
|
|
1286
|
-
FROM replies_json r
|
|
1287
|
-
LEFT JOIN ${TABLES.COMMENTS} existing_child ON existing_child.cid = COALESCE(r.comment_child_cid, r.update_child_cid)
|
|
1288
|
-
LEFT JOIN ${TABLES.COMMENT_UPDATES} actual_child_update ON actual_child_update.cid = COALESCE(r.comment_child_cid, r.update_child_cid)
|
|
1289
|
-
WHERE COALESCE(r.comment_child_cid, r.update_child_cid) IS NOT NULL
|
|
1290
|
-
AND (
|
|
1291
|
-
existing_child.cid IS NULL
|
|
1292
|
-
OR actual_child_update.cid IS NULL
|
|
1293
|
-
OR (
|
|
1294
|
-
r.json_child_updated_at IS NOT NULL
|
|
1295
|
-
AND actual_child_update.cid IS NOT NULL
|
|
1296
|
-
AND CAST(r.json_child_updated_at AS INTEGER) < actual_child_update.updatedAt
|
|
1297
|
-
)
|
|
1298
|
-
)
|
|
1299
|
-
GROUP BY r.parentCid
|
|
1598
|
+
AND json_type(cu_parent.replies, '$.best.commentCids') = 'array'
|
|
1599
|
+
AND cu_child.updatedAt > cu_parent.insertedAt
|
|
1300
1600
|
),
|
|
1301
1601
|
base_updates AS (
|
|
1302
1602
|
SELECT * FROM direct_updates
|
|
1303
1603
|
UNION SELECT c.* FROM ${TABLES.COMMENTS} c JOIN stale_child_counts scc ON c.cid = scc.cid
|
|
1304
1604
|
UNION SELECT c.* FROM ${TABLES.COMMENTS} c JOIN stale_last_child_cids slc ON c.cid = slc.cid
|
|
1305
|
-
UNION SELECT c.* FROM ${TABLES.COMMENTS} c JOIN
|
|
1605
|
+
UNION SELECT c.* FROM ${TABLES.COMMENTS} c JOIN stale_replies sr ON c.cid = sr.cid
|
|
1306
1606
|
),
|
|
1307
1607
|
authors_to_update AS (SELECT DISTINCT authorSignerAddress FROM base_updates),
|
|
1308
1608
|
author_comments AS (
|
|
@@ -1411,7 +1711,7 @@ export class DbHandler {
|
|
|
1411
1711
|
const aliasesQuery = `
|
|
1412
1712
|
SELECT DISTINCT
|
|
1413
1713
|
comments.authorSignerAddress AS aliasSignerAddress,
|
|
1414
|
-
alias.
|
|
1714
|
+
alias.originalAuthorPublicKey AS originalAuthorPublicKey
|
|
1415
1715
|
FROM ${TABLES.PSEUDONYMITY_ALIASES} AS alias
|
|
1416
1716
|
INNER JOIN ${TABLES.COMMENTS} AS comments ON comments.cid = alias.commentCid
|
|
1417
1717
|
WHERE comments.authorSignerAddress IN (${aliasPlaceholders})
|
|
@@ -1420,7 +1720,7 @@ export class DbHandler {
|
|
|
1420
1720
|
for (const aliasRow of aliasRows) {
|
|
1421
1721
|
let originalAuthorAddress;
|
|
1422
1722
|
try {
|
|
1423
|
-
originalAuthorAddress = getPKCAddressFromPublicKeySync(aliasRow.
|
|
1723
|
+
originalAuthorAddress = getPKCAddressFromPublicKeySync(aliasRow.originalAuthorPublicKey);
|
|
1424
1724
|
}
|
|
1425
1725
|
catch {
|
|
1426
1726
|
throw new Error(`Failed to resolve original author address for alias signer address ${aliasRow.aliasSignerAddress}`);
|
|
@@ -1521,33 +1821,33 @@ export class DbHandler {
|
|
|
1521
1821
|
}
|
|
1522
1822
|
queryPseudonymityAliasByCommentCid(commentCid) {
|
|
1523
1823
|
const row = this._db
|
|
1524
|
-
.prepare(`SELECT commentCid, aliasPrivateKey,
|
|
1824
|
+
.prepare(`SELECT commentCid, aliasPrivateKey, originalAuthorPublicKey, originalAuthorName, mode, insertedAt FROM ${TABLES.PSEUDONYMITY_ALIASES} WHERE commentCid = ?`)
|
|
1525
1825
|
.get(commentCid);
|
|
1526
1826
|
return row;
|
|
1527
1827
|
}
|
|
1528
|
-
queryPseudonymityAliasForPost(
|
|
1828
|
+
queryPseudonymityAliasForPost(originalAuthorPublicKey, postCid) {
|
|
1529
1829
|
const row = this._db
|
|
1530
1830
|
.prepare(`
|
|
1531
|
-
SELECT alias.commentCid, alias.aliasPrivateKey, alias.
|
|
1831
|
+
SELECT alias.commentCid, alias.aliasPrivateKey, alias.originalAuthorPublicKey, alias.originalAuthorName, alias.mode, alias.insertedAt
|
|
1532
1832
|
FROM ${TABLES.PSEUDONYMITY_ALIASES} AS alias
|
|
1533
1833
|
INNER JOIN ${TABLES.COMMENTS} AS comments ON comments.cid = alias.commentCid
|
|
1534
|
-
WHERE alias.mode = 'per-post' AND alias.
|
|
1834
|
+
WHERE alias.mode = 'per-post' AND alias.originalAuthorPublicKey = ? AND comments.postCid = ?
|
|
1535
1835
|
ORDER BY alias.insertedAt ASC
|
|
1536
1836
|
LIMIT 1
|
|
1537
1837
|
`)
|
|
1538
|
-
.get(
|
|
1838
|
+
.get(originalAuthorPublicKey, postCid);
|
|
1539
1839
|
return row;
|
|
1540
1840
|
}
|
|
1541
|
-
queryPseudonymityAliasForAuthor(
|
|
1841
|
+
queryPseudonymityAliasForAuthor(originalAuthorPublicKey) {
|
|
1542
1842
|
const row = this._db
|
|
1543
1843
|
.prepare(`
|
|
1544
|
-
SELECT commentCid, aliasPrivateKey,
|
|
1844
|
+
SELECT commentCid, aliasPrivateKey, originalAuthorPublicKey, originalAuthorName, mode, insertedAt
|
|
1545
1845
|
FROM ${TABLES.PSEUDONYMITY_ALIASES}
|
|
1546
|
-
WHERE mode = 'per-author' AND
|
|
1846
|
+
WHERE mode = 'per-author' AND originalAuthorPublicKey = ?
|
|
1547
1847
|
ORDER BY insertedAt ASC
|
|
1548
1848
|
LIMIT 1
|
|
1549
1849
|
`)
|
|
1550
|
-
.get(
|
|
1850
|
+
.get(originalAuthorPublicKey);
|
|
1551
1851
|
return row;
|
|
1552
1852
|
}
|
|
1553
1853
|
_queryCommentAuthorAndParentWithoutParsing(cid) {
|
|
@@ -1979,13 +2279,13 @@ export class DbHandler {
|
|
|
1979
2279
|
// If the provided address is the original signer, include all alias signer addresses for that author.
|
|
1980
2280
|
const aliasRowsForOriginal = this._db
|
|
1981
2281
|
.prepare(`
|
|
1982
|
-
SELECT alias.commentCid, alias.
|
|
2282
|
+
SELECT alias.commentCid, alias.originalAuthorPublicKey
|
|
1983
2283
|
FROM ${TABLES.PSEUDONYMITY_ALIASES} AS alias
|
|
1984
2284
|
`)
|
|
1985
2285
|
.all();
|
|
1986
2286
|
for (const aliasRow of aliasRowsForOriginal) {
|
|
1987
2287
|
try {
|
|
1988
|
-
const originalAddress = getPKCAddressFromPublicKeySync(aliasRow.
|
|
2288
|
+
const originalAddress = getPKCAddressFromPublicKeySync(aliasRow.originalAuthorPublicKey);
|
|
1989
2289
|
if (originalAddress === authorSignerAddress) {
|
|
1990
2290
|
const commentRow = this._db
|
|
1991
2291
|
.prepare(`SELECT authorSignerAddress FROM ${TABLES.COMMENTS} WHERE cid = ?`)
|
|
@@ -2001,7 +2301,7 @@ export class DbHandler {
|
|
|
2001
2301
|
// If the provided address is an alias, include the original signer address for that alias.
|
|
2002
2302
|
const aliasRowsForAliasAddress = this._db
|
|
2003
2303
|
.prepare(`
|
|
2004
|
-
SELECT alias.
|
|
2304
|
+
SELECT alias.originalAuthorPublicKey
|
|
2005
2305
|
FROM ${TABLES.PSEUDONYMITY_ALIASES} AS alias
|
|
2006
2306
|
INNER JOIN ${TABLES.COMMENTS} AS comments ON comments.cid = alias.commentCid
|
|
2007
2307
|
WHERE comments.authorSignerAddress = ?
|
|
@@ -2009,7 +2309,7 @@ export class DbHandler {
|
|
|
2009
2309
|
.all(authorSignerAddress);
|
|
2010
2310
|
for (const aliasRow of aliasRowsForAliasAddress) {
|
|
2011
2311
|
try {
|
|
2012
|
-
const originalAddress = getPKCAddressFromPublicKeySync(aliasRow.
|
|
2312
|
+
const originalAddress = getPKCAddressFromPublicKeySync(aliasRow.originalAuthorPublicKey);
|
|
2013
2313
|
authorSignerAddresses.add(originalAddress);
|
|
2014
2314
|
}
|
|
2015
2315
|
catch {
|
|
@@ -2073,7 +2373,7 @@ export class DbHandler {
|
|
|
2073
2373
|
// Get original author's address for mod edits (bans/flairs are applied to original author)
|
|
2074
2374
|
const modEditAddresses = [authorSignerAddress];
|
|
2075
2375
|
try {
|
|
2076
|
-
const originalAddress = getPKCAddressFromPublicKeySync(aliasRow.
|
|
2376
|
+
const originalAddress = getPKCAddressFromPublicKeySync(aliasRow.originalAuthorPublicKey);
|
|
2077
2377
|
if (originalAddress !== authorSignerAddress) {
|
|
2078
2378
|
modEditAddresses.push(originalAddress);
|
|
2079
2379
|
}
|
|
@@ -2082,7 +2382,7 @@ export class DbHandler {
|
|
|
2082
2382
|
// ignore malformed keys
|
|
2083
2383
|
}
|
|
2084
2384
|
// For mod edits (bans/flairs), use the original author's domain if available
|
|
2085
|
-
const modEditDomain = aliasRow.
|
|
2385
|
+
const modEditDomain = aliasRow.originalAuthorName || authorDomain;
|
|
2086
2386
|
// Query karma for just this alias, but mod edits from both alias and original
|
|
2087
2387
|
return this._queryCommunityAuthorByAddresses([authorSignerAddress], modEditAddresses, modEditDomain);
|
|
2088
2388
|
}
|
|
@@ -2140,7 +2440,7 @@ export class DbHandler {
|
|
|
2140
2440
|
this._db.prepare(`DELETE FROM ${TABLES.VOTES} WHERE commentCid = ?`).run(cid);
|
|
2141
2441
|
this._db.prepare(`DELETE FROM ${TABLES.COMMENT_EDITS} WHERE commentCid = ?`).run(cid);
|
|
2142
2442
|
this._db.prepare(`DELETE FROM ${TABLES.PSEUDONYMITY_ALIASES} WHERE commentCid = ?`).run(cid);
|
|
2143
|
-
const commentUpdate = this.
|
|
2443
|
+
const commentUpdate = this.queryCommentUpdateBucketAndReplies({ cid });
|
|
2144
2444
|
if (commentUpdate) {
|
|
2145
2445
|
this._db.prepare(`DELETE FROM ${TABLES.COMMENT_UPDATES} WHERE cid = ?`).run(cid);
|
|
2146
2446
|
}
|
|
@@ -2326,36 +2626,25 @@ export class DbHandler {
|
|
|
2326
2626
|
queryAllCommentCidsAndTheirReplies() {
|
|
2327
2627
|
const log = Logger("pkc-js:local-community:db-handler:queryAllCidsUnderThisCommunity");
|
|
2328
2628
|
const rows = this._db
|
|
2329
|
-
.prepare(`SELECT
|
|
2330
|
-
c.cid AS cid,
|
|
2331
|
-
CASE
|
|
2332
|
-
WHEN cu.replies IS NULL THEN NULL
|
|
2333
|
-
ELSE json_set(
|
|
2334
|
-
cu.replies,
|
|
2335
|
-
'$.pages',
|
|
2336
|
-
(
|
|
2337
|
-
SELECT json_group_object(
|
|
2338
|
-
pages.key,
|
|
2339
|
-
json_set(pages.value, '$.comments', json('[]'))
|
|
2340
|
-
)
|
|
2341
|
-
FROM json_each(cu.replies, '$.pages') AS pages
|
|
2342
|
-
)
|
|
2343
|
-
)
|
|
2344
|
-
END AS replies
|
|
2629
|
+
.prepare(`SELECT c.cid AS cid, cu.replies AS replies
|
|
2345
2630
|
FROM ${TABLES.COMMENTS} c
|
|
2346
2631
|
LEFT JOIN ${TABLES.COMMENT_UPDATES} cu ON c.cid = cu.cid`)
|
|
2347
2632
|
.all();
|
|
2348
2633
|
return rows.map((row) => {
|
|
2349
|
-
|
|
2634
|
+
const allPageCids = [];
|
|
2350
2635
|
if (typeof row.replies === "string" && row.replies.length > 0) {
|
|
2351
2636
|
try {
|
|
2352
|
-
|
|
2637
|
+
const parsed = JSON.parse(row.replies);
|
|
2638
|
+
for (const sortEntry of Object.values(parsed)) {
|
|
2639
|
+
if (sortEntry?.allPageCids)
|
|
2640
|
+
allPageCids.push(...sortEntry.allPageCids);
|
|
2641
|
+
}
|
|
2353
2642
|
}
|
|
2354
2643
|
catch (e) {
|
|
2355
2644
|
log.error(`Failed to parse replies JSON for comment ${row.cid} when collecting cids`, e);
|
|
2356
2645
|
}
|
|
2357
2646
|
}
|
|
2358
|
-
return { cid: row.cid,
|
|
2647
|
+
return { cid: row.cid, allPageCids };
|
|
2359
2648
|
});
|
|
2360
2649
|
}
|
|
2361
2650
|
queryPostsWithActiveScore(pageOptions) {
|