/
Reaction.ts
89 lines (79 loc) · 2.31 KB
/
Reaction.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { ContentTypeId } from "@xmtp/xmtp-js";
import type { ContentCodec, EncodedContent } from "@xmtp/xmtp-js";
export const ContentTypeReaction = new ContentTypeId({
authorityId: "xmtp.org",
typeId: "reaction",
versionMajor: 1,
versionMinor: 0,
});
export type Reaction = {
/**
* The message ID for the message that is being reacted to
*/
reference: string;
/**
* The action of the reaction
*/
action: "added" | "removed";
/**
* The content of the reaction
*/
content: string;
/**
* The schema of the content to provide guidance on how to display it
*/
schema: "unicode" | "shortcode" | "custom";
};
type LegacyReactionParameters = Pick<
Reaction,
"action" | "reference" | "schema"
> & {
encoding: "UTF-8";
};
export class ReactionCodec implements ContentCodec<Reaction> {
get contentType(): ContentTypeId {
return ContentTypeReaction;
}
encode(reaction: Reaction): EncodedContent {
const { action, reference, schema, content } = reaction;
return {
type: ContentTypeReaction,
parameters: {},
content: new TextEncoder().encode(
JSON.stringify({ action, reference, schema, content }),
),
};
}
decode(encodedContent: EncodedContent): Reaction {
const decodedContent = new TextDecoder().decode(encodedContent.content);
// First try to decode it in the canonical form.
try {
const reaction = JSON.parse(decodedContent) as Reaction;
const { action, reference, schema, content } = reaction;
return { action, reference, schema, content };
} catch (e) {
// ignore, fall through to legacy decoding
}
// If that fails, try to decode it in the legacy form.
const parameters = encodedContent.parameters as LegacyReactionParameters;
return {
action: parameters.action,
reference: parameters.reference,
schema: parameters.schema,
content: decodedContent,
};
}
fallback(content: Reaction): string | undefined {
switch (content.action) {
case "added":
return `Reacted “${content.content}” to an earlier message`;
case "removed":
return `Removed “${content.content}” from an earlier message`;
default:
return undefined;
}
}
shouldPush(content: Reaction): boolean {
return content.action === "added";
}
}