@gryt/core 0.24.0 → 0.25.0
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/index.d.ts +1 -1
- package/dist/mls/content.d.ts +7 -0
- package/dist/mls/content.js +23 -0
- package/dist/mls/reencrypt.d.ts +4 -1
- package/dist/mls/reencrypt.js +5 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export { agreementAt, createTermsGate, GUIDELINES_URL, TERMS_STORAGE_KEY, TERMS_
|
|
|
13
13
|
export { createMlsDmDriver, MlsDriverError, type MlsDriverErrorCode } from "./mls/dmDriver.js";
|
|
14
14
|
export { mlsPinsFromPeerPins } from "./mls/pins.js";
|
|
15
15
|
export { reencryptedId, reencryptMine, type ReencryptCandidate, type ReencryptDeps } from "./mls/reencrypt.js";
|
|
16
|
-
export { decodeMlsDmContent, encodeMlsDmContent, acceptImport, historyBatches, importBatches, MAX_HISTORY_BATCH_BYTES, MLS_DM_CONTENT_VERSION, type MlsDmContent, type MlsHistoryEntry, type MlsImportEntry, readMlsDmContent, } from "./mls/content.js";
|
|
16
|
+
export { decodeMlsDmContent, encodeMlsDmContent, acceptImport, historyBatches, importBatches, MAX_HISTORY_BATCH_BYTES, MLS_DM_CONTENT_VERSION, type MlsDmContent, type MlsHistoryEntry, type MlsHistoryReaction, type MlsImportEntry, readMlsDmContent, } from "./mls/content.js";
|
|
17
17
|
export { applyMlsReaction, mlsReactionAction, type MlsReaction } from "./mls/reactions.js";
|
|
18
18
|
export { type DiscordPackageDm, type DiscordPackageMessage, isDiscordPackage, linksExpireAt, listDiscordDms, type PackageFiles, readDiscordDm, } from "./import/discordPackage.js";
|
|
19
19
|
export { inflateRaw, openZipBytes } from "./import/unzip.js";
|
package/dist/mls/content.d.ts
CHANGED
|
@@ -9,6 +9,13 @@ export interface MlsHistoryEntry {
|
|
|
9
9
|
text: string;
|
|
10
10
|
replyTo?: string;
|
|
11
11
|
attachments?: Record<string, SealedAttachmentKey>;
|
|
12
|
+
/** Who reacted, as the sender's record has it. A claim, like the rest of a shared copy. */
|
|
13
|
+
reactions?: MlsHistoryReaction[];
|
|
14
|
+
}
|
|
15
|
+
export interface MlsHistoryReaction {
|
|
16
|
+
/** A Unicode emoji or `:name:`, what `chat:react` carries. */
|
|
17
|
+
emoji: string;
|
|
18
|
+
users: string[];
|
|
12
19
|
}
|
|
13
20
|
/** One message from the sender's own Discord data. Who wrote it is never in here: the reader takes the MLS sender. */
|
|
14
21
|
export interface MlsImportEntry {
|
package/dist/mls/content.js
CHANGED
|
@@ -17,6 +17,8 @@ const isText = (v) => typeof v === "string" && v.length <= MAX_TEXT;
|
|
|
17
17
|
const isCount = (v) => typeof v === "number" && Number.isSafeInteger(v) && v >= 0;
|
|
18
18
|
const isLabel = (v) => typeof v === "string" && v.length <= MAX_LABEL;
|
|
19
19
|
const MAX_HISTORY_ENTRIES = 200;
|
|
20
|
+
const MAX_HISTORY_REACTIONS = 20;
|
|
21
|
+
const MAX_REACTION_USERS = 50;
|
|
20
22
|
/** Under what one `mls:send` takes once sealed and padded. */
|
|
21
23
|
export const MAX_HISTORY_BATCH_BYTES = 48 * 1024;
|
|
22
24
|
/** One emoji's worth of emoji characters, so a peer can't put a sentence on a message as a reaction. */
|
|
@@ -115,6 +117,8 @@ function historyBody(e) {
|
|
|
115
117
|
out.replyTo = e.replyTo;
|
|
116
118
|
if (e.attachments && Object.keys(e.attachments).length > 0)
|
|
117
119
|
out.attachments = e.attachments;
|
|
120
|
+
if (e.reactions?.length)
|
|
121
|
+
out.reactions = e.reactions;
|
|
118
122
|
return out;
|
|
119
123
|
}
|
|
120
124
|
function importBody(e) {
|
|
@@ -176,6 +180,25 @@ function readHistoryEntry(v) {
|
|
|
176
180
|
return null;
|
|
177
181
|
out.attachments = attachments;
|
|
178
182
|
}
|
|
183
|
+
if (v.reactions !== undefined) {
|
|
184
|
+
const reactions = readHistoryReactions(v.reactions);
|
|
185
|
+
if (!reactions)
|
|
186
|
+
return null;
|
|
187
|
+
out.reactions = reactions;
|
|
188
|
+
}
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
function readHistoryReactions(v) {
|
|
192
|
+
if (!Array.isArray(v) || v.length === 0 || v.length > MAX_HISTORY_REACTIONS)
|
|
193
|
+
return null;
|
|
194
|
+
const out = [];
|
|
195
|
+
for (const r of v) {
|
|
196
|
+
if (!isObject(r) || !isReactionEmoji(r.emoji) || !Array.isArray(r.users))
|
|
197
|
+
return null;
|
|
198
|
+
if (r.users.length === 0 || r.users.length > MAX_REACTION_USERS || !r.users.every(isId))
|
|
199
|
+
return null;
|
|
200
|
+
out.push({ emoji: r.emoji, users: r.users });
|
|
201
|
+
}
|
|
179
202
|
return out;
|
|
180
203
|
}
|
|
181
204
|
function readImportEntry(v) {
|
package/dist/mls/reencrypt.d.ts
CHANGED
|
@@ -11,7 +11,10 @@ export interface ReencryptCandidate {
|
|
|
11
11
|
sealed?: string | null;
|
|
12
12
|
mls_placeholder?: object | null;
|
|
13
13
|
attachments?: readonly string[] | null;
|
|
14
|
-
reactions?: readonly
|
|
14
|
+
reactions?: readonly {
|
|
15
|
+
src: string;
|
|
16
|
+
users?: readonly string[];
|
|
17
|
+
}[] | null;
|
|
15
18
|
poll?: object | null;
|
|
16
19
|
pinned_at?: string | Date | null;
|
|
17
20
|
thread_id?: string | null;
|
package/dist/mls/reencrypt.js
CHANGED
|
@@ -3,10 +3,11 @@ import { historyBatches } from "./content.js";
|
|
|
3
3
|
const DELETE_GAP_MS = 3_100;
|
|
4
4
|
const FETCH_GAP_MS = 700;
|
|
5
5
|
export const reencryptedId = (messageId) => `re-${messageId}`;
|
|
6
|
-
|
|
6
|
+
/* Files stay: an MLS file is deleted after the server's retention, a plaintext one isn't.
|
|
7
|
+
Polls and pins live on the server's row. */
|
|
7
8
|
function canMove(m, me) {
|
|
8
9
|
return m.sender_server_id === me && !!m.text && !m.mls && !m.sealed && !m.mls_placeholder
|
|
9
|
-
&& !m.attachments?.length && !m.
|
|
10
|
+
&& !m.attachments?.length && !m.poll && !m.pinned_at && !m.thread_id;
|
|
10
11
|
}
|
|
11
12
|
async function plaintextOfMine(deps, me) {
|
|
12
13
|
const out = [];
|
|
@@ -30,12 +31,14 @@ export async function reencryptMine(deps, me) {
|
|
|
30
31
|
const originals = new Map(mine.map((m) => [reencryptedId(m.message_id), m.message_id]));
|
|
31
32
|
const entries = mine.map((m) => {
|
|
32
33
|
const reply = m.reply_to_message_id;
|
|
34
|
+
const reactions = (m.reactions ?? []).flatMap((r) => (r.users?.length ? [{ emoji: r.src, users: [...r.users] }] : []));
|
|
33
35
|
return {
|
|
34
36
|
id: reencryptedId(m.message_id),
|
|
35
37
|
senderId: me,
|
|
36
38
|
sentAt: new Date(m.created_at).getTime(),
|
|
37
39
|
text: m.text ?? "",
|
|
38
40
|
...(reply ? { replyTo: ids.has(reply) ? reencryptedId(reply) : reply } : {}),
|
|
41
|
+
...(reactions.length ? { reactions } : {}),
|
|
39
42
|
};
|
|
40
43
|
});
|
|
41
44
|
const batches = historyBatches(entries, deps.newId);
|
package/package.json
CHANGED