@tloncorp/openclaw 0.1.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/README.md +174 -0
- package/dist/index.js +190 -0
- package/dist/index.js.map +1 -0
- package/dist/src/account-fields.js +17 -0
- package/dist/src/account-fields.js.map +1 -0
- package/dist/src/actions.js +164 -0
- package/dist/src/actions.js.map +1 -0
- package/dist/src/channel.js +400 -0
- package/dist/src/channel.js.map +1 -0
- package/dist/src/config-schema.js +55 -0
- package/dist/src/config-schema.js.map +1 -0
- package/dist/src/monitor/approval.js +194 -0
- package/dist/src/monitor/approval.js.map +1 -0
- package/dist/src/monitor/discovery.js +64 -0
- package/dist/src/monitor/discovery.js.map +1 -0
- package/dist/src/monitor/history.js +158 -0
- package/dist/src/monitor/history.js.map +1 -0
- package/dist/src/monitor/index.js +1940 -0
- package/dist/src/monitor/index.js.map +1 -0
- package/dist/src/monitor/media.js +128 -0
- package/dist/src/monitor/media.js.map +1 -0
- package/dist/src/monitor/processed-messages.js +38 -0
- package/dist/src/monitor/processed-messages.js.map +1 -0
- package/dist/src/monitor/utils.js +283 -0
- package/dist/src/monitor/utils.js.map +1 -0
- package/dist/src/onboarding.js +178 -0
- package/dist/src/onboarding.js.map +1 -0
- package/dist/src/runtime.js +11 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/settings.js +305 -0
- package/dist/src/settings.js.map +1 -0
- package/dist/src/targets.js +85 -0
- package/dist/src/targets.js.map +1 -0
- package/dist/src/types.js +79 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/urbit/api-client.js +104 -0
- package/dist/src/urbit/api-client.js.map +1 -0
- package/dist/src/urbit/auth.js +35 -0
- package/dist/src/urbit/auth.js.map +1 -0
- package/dist/src/urbit/base-url.js +45 -0
- package/dist/src/urbit/base-url.js.map +1 -0
- package/dist/src/urbit/channel-ops.js +136 -0
- package/dist/src/urbit/channel-ops.js.map +1 -0
- package/dist/src/urbit/context.js +42 -0
- package/dist/src/urbit/context.js.map +1 -0
- package/dist/src/urbit/errors.js +36 -0
- package/dist/src/urbit/errors.js.map +1 -0
- package/dist/src/urbit/fetch.js +23 -0
- package/dist/src/urbit/fetch.js.map +1 -0
- package/dist/src/urbit/foreigns.js +6 -0
- package/dist/src/urbit/foreigns.js.map +1 -0
- package/dist/src/urbit/http-poke.js +56 -0
- package/dist/src/urbit/http-poke.js.map +1 -0
- package/dist/src/urbit/send.js +208 -0
- package/dist/src/urbit/send.js.map +1 -0
- package/dist/src/urbit/sse-client.js +453 -0
- package/dist/src/urbit/sse-client.js.map +1 -0
- package/dist/src/urbit/story.js +286 -0
- package/dist/src/urbit/story.js.map +1 -0
- package/dist/src/urbit/upload.js +51 -0
- package/dist/src/urbit/upload.js.map +1 -0
- package/openclaw.plugin.json +10 -0
- package/package.json +84 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval system for managing DM, channel mention, and group invite approvals.
|
|
3
|
+
*
|
|
4
|
+
* When an unknown ship tries to interact with the bot, the owner receives
|
|
5
|
+
* a notification and can approve or deny the request.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate a unique approval ID in the format: {type}-{timestamp}-{shortHash}
|
|
9
|
+
*/
|
|
10
|
+
export function generateApprovalId(type) {
|
|
11
|
+
const timestamp = Date.now();
|
|
12
|
+
const randomPart = Math.random().toString(36).substring(2, 6);
|
|
13
|
+
return `${type}-${timestamp}-${randomPart}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a pending approval object.
|
|
17
|
+
*/
|
|
18
|
+
export function createPendingApproval(params) {
|
|
19
|
+
return {
|
|
20
|
+
id: generateApprovalId(params.type),
|
|
21
|
+
type: params.type,
|
|
22
|
+
requestingShip: params.requestingShip,
|
|
23
|
+
channelNest: params.channelNest,
|
|
24
|
+
groupFlag: params.groupFlag,
|
|
25
|
+
messagePreview: params.messagePreview,
|
|
26
|
+
originalMessage: params.originalMessage,
|
|
27
|
+
timestamp: Date.now(),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Truncate text to a maximum length with ellipsis.
|
|
32
|
+
*/
|
|
33
|
+
function truncate(text, maxLength) {
|
|
34
|
+
if (text.length <= maxLength) {
|
|
35
|
+
return text;
|
|
36
|
+
}
|
|
37
|
+
return text.substring(0, maxLength - 3) + "...";
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Format a notification message for the owner about a pending approval.
|
|
41
|
+
*/
|
|
42
|
+
export function formatApprovalRequest(approval) {
|
|
43
|
+
const preview = approval.messagePreview ? `\n"${truncate(approval.messagePreview, 100)}"` : "";
|
|
44
|
+
switch (approval.type) {
|
|
45
|
+
case "dm":
|
|
46
|
+
return (`New DM request from ${approval.requestingShip}:${preview}\n\n` +
|
|
47
|
+
`Reply "approve", "deny", or "block" (ID: ${approval.id})`);
|
|
48
|
+
case "channel":
|
|
49
|
+
return (`${approval.requestingShip} mentioned you in ${approval.channelNest}:${preview}\n\n` +
|
|
50
|
+
`Reply "approve", "deny", or "block"\n` +
|
|
51
|
+
`(ID: ${approval.id})`);
|
|
52
|
+
case "group":
|
|
53
|
+
return (`Group invite from ${approval.requestingShip} to join ${approval.groupFlag}\n\n` +
|
|
54
|
+
`Reply "approve", "deny", or "block"\n` +
|
|
55
|
+
`(ID: ${approval.id})`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Parse an owner's response to an approval request.
|
|
60
|
+
* Supports formats:
|
|
61
|
+
* - "approve" / "deny" / "block" (applies to most recent pending)
|
|
62
|
+
* - "approve dm-1234567890-abc" / "deny dm-1234567890-abc" (specific ID)
|
|
63
|
+
* - "block" permanently blocks the ship via Tlon's native blocking
|
|
64
|
+
*/
|
|
65
|
+
export function parseApprovalResponse(text) {
|
|
66
|
+
const trimmed = text.trim().toLowerCase();
|
|
67
|
+
// Match "approve", "deny", or "block" optionally followed by an ID
|
|
68
|
+
const match = trimmed.match(/^(approve|deny|block)(?:\s+(.+))?$/);
|
|
69
|
+
if (!match) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const action = match[1];
|
|
73
|
+
const id = match[2]?.trim();
|
|
74
|
+
return { action, id };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if a message text looks like an approval response.
|
|
78
|
+
* Used to determine if we should intercept the message before normal processing.
|
|
79
|
+
*/
|
|
80
|
+
export function isApprovalResponse(text) {
|
|
81
|
+
const trimmed = text.trim().toLowerCase();
|
|
82
|
+
return trimmed.startsWith("approve") || trimmed.startsWith("deny") || trimmed.startsWith("block");
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Find a pending approval by ID, or return the most recent if no ID specified.
|
|
86
|
+
*/
|
|
87
|
+
export function findPendingApproval(pendingApprovals, id) {
|
|
88
|
+
if (id) {
|
|
89
|
+
return pendingApprovals.find((a) => a.id === id);
|
|
90
|
+
}
|
|
91
|
+
// Return most recent
|
|
92
|
+
return pendingApprovals[pendingApprovals.length - 1];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Check if there's already a pending approval for the same ship/channel/group combo.
|
|
96
|
+
* Used to avoid sending duplicate notifications.
|
|
97
|
+
*/
|
|
98
|
+
export function hasDuplicatePending(pendingApprovals, type, requestingShip, channelNest, groupFlag) {
|
|
99
|
+
return pendingApprovals.some((approval) => {
|
|
100
|
+
if (approval.type !== type || approval.requestingShip !== requestingShip) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (type === "channel" && approval.channelNest !== channelNest) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (type === "group" && approval.groupFlag !== groupFlag) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Remove a pending approval from the list by ID.
|
|
114
|
+
*/
|
|
115
|
+
export function removePendingApproval(pendingApprovals, id) {
|
|
116
|
+
return pendingApprovals.filter((a) => a.id !== id);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Format a confirmation message after an approval action.
|
|
120
|
+
*/
|
|
121
|
+
export function formatApprovalConfirmation(approval, action) {
|
|
122
|
+
if (action === "block") {
|
|
123
|
+
return `Blocked ${approval.requestingShip}. They will no longer be able to contact the bot.`;
|
|
124
|
+
}
|
|
125
|
+
const actionText = action === "approve" ? "Approved" : "Denied";
|
|
126
|
+
switch (approval.type) {
|
|
127
|
+
case "dm":
|
|
128
|
+
if (action === "approve") {
|
|
129
|
+
return `${actionText} DM access for ${approval.requestingShip}. They can now message the bot.`;
|
|
130
|
+
}
|
|
131
|
+
return `${actionText} DM request from ${approval.requestingShip}.`;
|
|
132
|
+
case "channel":
|
|
133
|
+
if (action === "approve") {
|
|
134
|
+
return `${actionText} ${approval.requestingShip} for ${approval.channelNest}. They can now interact in this channel.`;
|
|
135
|
+
}
|
|
136
|
+
return `${actionText} ${approval.requestingShip} for ${approval.channelNest}.`;
|
|
137
|
+
case "group":
|
|
138
|
+
if (action === "approve") {
|
|
139
|
+
return `${actionText} group invite from ${approval.requestingShip} to ${approval.groupFlag}. Joining group...`;
|
|
140
|
+
}
|
|
141
|
+
return `${actionText} group invite from ${approval.requestingShip} to ${approval.groupFlag}.`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Parse an admin command from owner message.
|
|
146
|
+
* Supports:
|
|
147
|
+
* - "unblock ~ship" - unblock a specific ship
|
|
148
|
+
* - "blocked" - list all blocked ships
|
|
149
|
+
* - "pending" - list all pending approvals
|
|
150
|
+
*/
|
|
151
|
+
export function parseAdminCommand(text) {
|
|
152
|
+
const trimmed = text.trim().toLowerCase();
|
|
153
|
+
// "blocked" - list blocked ships
|
|
154
|
+
if (trimmed === "blocked") {
|
|
155
|
+
return { type: "blocked" };
|
|
156
|
+
}
|
|
157
|
+
// "pending" - list pending approvals
|
|
158
|
+
if (trimmed === "pending") {
|
|
159
|
+
return { type: "pending" };
|
|
160
|
+
}
|
|
161
|
+
// "unblock ~ship" - unblock a specific ship
|
|
162
|
+
const unblockMatch = trimmed.match(/^unblock\s+(~[\w-]+)$/);
|
|
163
|
+
if (unblockMatch) {
|
|
164
|
+
return { type: "unblock", ship: unblockMatch[1] };
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if a message text looks like an admin command.
|
|
170
|
+
*/
|
|
171
|
+
export function isAdminCommand(text) {
|
|
172
|
+
return parseAdminCommand(text) !== null;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Format the list of blocked ships for display to owner.
|
|
176
|
+
*/
|
|
177
|
+
export function formatBlockedList(ships) {
|
|
178
|
+
if (ships.length === 0) {
|
|
179
|
+
return "No ships are currently blocked.";
|
|
180
|
+
}
|
|
181
|
+
return `Blocked ships (${ships.length}):\n${ships.map((s) => `• ${s}`).join("\n")}`;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Format the list of pending approvals for display to owner.
|
|
185
|
+
*/
|
|
186
|
+
export function formatPendingList(approvals) {
|
|
187
|
+
if (approvals.length === 0) {
|
|
188
|
+
return "No pending approval requests.";
|
|
189
|
+
}
|
|
190
|
+
return `Pending approvals (${approvals.length}):\n${approvals
|
|
191
|
+
.map((a) => `• ${a.id}: ${a.type} from ${a.requestingShip}`)
|
|
192
|
+
.join("\n")}`;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../../../src/monitor/approval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwBH;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAkB;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9D,OAAO,GAAG,IAAI,IAAI,SAAS,IAAI,UAAU,EAAE,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAA4B;IAChE,OAAO;QACL,EAAE,EAAE,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC;QACnC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,IAAY,EAAE,SAAiB;IAC/C,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAyB;IAC7D,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,QAAQ,CAAC,cAAc,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAE/F,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,IAAI;YACP,OAAO,CACL,uBAAuB,QAAQ,CAAC,cAAc,IAAI,OAAO,MAAM;gBAC/D,4CAA4C,QAAQ,CAAC,EAAE,GAAG,CAC3D,CAAC;QAEJ,KAAK,SAAS;YACZ,OAAO,CACL,GAAG,QAAQ,CAAC,cAAc,qBAAqB,QAAQ,CAAC,WAAW,IAAI,OAAO,MAAM;gBACpF,uCAAuC;gBACvC,QAAQ,QAAQ,CAAC,EAAE,GAAG,CACvB,CAAC;QAEJ,KAAK,OAAO;YACV,OAAO,CACL,qBAAqB,QAAQ,CAAC,cAAc,YAAY,QAAQ,CAAC,SAAS,MAAM;gBAChF,uCAAuC;gBACvC,QAAQ,QAAQ,CAAC,EAAE,GAAG,CACvB,CAAC;IACN,CAAC;AACH,CAAC;AAOD;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE1C,mEAAmE;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAClE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAiC,CAAC;IACxD,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IAE5B,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,OAAO,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AACpG,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,gBAAmC,EACnC,EAAW;IAEX,IAAI,EAAE,EAAE,CAAC;QACP,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,qBAAqB;IACrB,OAAO,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,gBAAmC,EACnC,IAAkB,EAClB,cAAsB,EACtB,WAAoB,EACpB,SAAkB;IAElB,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;QACxC,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,cAAc,KAAK,cAAc,EAAE,CAAC;YACzE,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;YAC/D,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,gBAAmC,EACnC,EAAU;IAEV,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B,CACxC,QAAyB,EACzB,MAAoC;IAEpC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,WAAW,QAAQ,CAAC,cAAc,mDAAmD,CAAC;IAC/F,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEhE,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,IAAI;YACP,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,GAAG,UAAU,kBAAkB,QAAQ,CAAC,cAAc,iCAAiC,CAAC;YACjG,CAAC;YACD,OAAO,GAAG,UAAU,oBAAoB,QAAQ,CAAC,cAAc,GAAG,CAAC;QAErE,KAAK,SAAS;YACZ,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,GAAG,UAAU,IAAI,QAAQ,CAAC,cAAc,QAAQ,QAAQ,CAAC,WAAW,0CAA0C,CAAC;YACxH,CAAC;YACD,OAAO,GAAG,UAAU,IAAI,QAAQ,CAAC,cAAc,QAAQ,QAAQ,CAAC,WAAW,GAAG,CAAC;QAEjF,KAAK,OAAO;YACV,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,GAAG,UAAU,sBAAsB,QAAQ,CAAC,cAAc,OAAO,QAAQ,CAAC,SAAS,oBAAoB,CAAC;YACjH,CAAC;YACD,OAAO,GAAG,UAAU,sBAAsB,QAAQ,CAAC,cAAc,OAAO,QAAQ,CAAC,SAAS,GAAG,CAAC;IAClG,CAAC;AACH,CAAC;AAWD;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE1C,iCAAiC;IACjC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IAED,qCAAqC;IACrC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IAED,4CAA4C;IAC5C,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC5D,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,iBAAiB,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAe;IAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,iCAAiC,CAAC;IAC3C,CAAC;IACD,OAAO,kBAAkB,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACtF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAA4B;IAC5D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,+BAA+B,CAAC;IACzC,CAAC;IACD,OAAO,sBAAsB,SAAS,CAAC,MAAM,OAAO,SAAS;SAC1D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,cAAc,EAAE,CAAC;SAC3D,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { formatChangesDate } from "./utils.js";
|
|
2
|
+
export async function fetchGroupChanges(api, runtime, daysAgo = 5) {
|
|
3
|
+
try {
|
|
4
|
+
const changeDate = formatChangesDate(daysAgo);
|
|
5
|
+
runtime.log?.(`[tlon] Fetching group changes since ${daysAgo} days ago (${changeDate})...`);
|
|
6
|
+
const changes = await api.scry(`/groups-ui/v5/changes/${changeDate}.json`);
|
|
7
|
+
if (changes) {
|
|
8
|
+
runtime.log?.("[tlon] Successfully fetched changes data");
|
|
9
|
+
return changes;
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
runtime.log?.(`[tlon] Failed to fetch changes (falling back to full init): ${error?.message ?? String(error)}`);
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Fetch groups-ui init data, returning channels and foreigns.
|
|
20
|
+
* This is a single scry that provides both channel discovery and pending invites.
|
|
21
|
+
*/
|
|
22
|
+
export async function fetchInitData(api, runtime) {
|
|
23
|
+
try {
|
|
24
|
+
runtime.log?.("[tlon] Fetching groups-ui init data...");
|
|
25
|
+
const initData = (await api.scry("/groups-ui/v6/init.json"));
|
|
26
|
+
const channels = [];
|
|
27
|
+
const channelToGroup = new Map();
|
|
28
|
+
if (initData?.groups) {
|
|
29
|
+
for (const [groupFlag, groupData] of Object.entries(initData.groups)) {
|
|
30
|
+
if (groupData && typeof groupData === "object" && groupData.channels) {
|
|
31
|
+
for (const channelNest of Object.keys(groupData.channels)) {
|
|
32
|
+
if (channelNest.startsWith("chat/") || channelNest.startsWith("heap/") || channelNest.startsWith("diary/")) {
|
|
33
|
+
channels.push(channelNest);
|
|
34
|
+
channelToGroup.set(channelNest, groupFlag);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (channels.length > 0) {
|
|
41
|
+
runtime.log?.(`[tlon] Auto-discovered ${channels.length} channel(s)`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
runtime.log?.("[tlon] No channels found via auto-discovery");
|
|
45
|
+
}
|
|
46
|
+
const foreigns = initData?.foreigns || null;
|
|
47
|
+
if (foreigns) {
|
|
48
|
+
const pendingCount = Object.values(foreigns).filter((f) => f.invites?.some((i) => i.valid)).length;
|
|
49
|
+
if (pendingCount > 0) {
|
|
50
|
+
runtime.log?.(`[tlon] Found ${pendingCount} pending group invite(s)`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { channels, channelToGroup, foreigns };
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
runtime.log?.(`[tlon] Init data fetch failed: ${error?.message ?? String(error)}`);
|
|
57
|
+
return { channels: [], channelToGroup: new Map(), foreigns: null };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export async function fetchAllChannels(api, runtime) {
|
|
61
|
+
const { channels } = await fetchInitData(api, runtime);
|
|
62
|
+
return channels;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../../src/monitor/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { extractMessageText } from "./utils.js";
|
|
2
|
+
/**
|
|
3
|
+
* Format a number as @ud (with dots every 3 digits from the right)
|
|
4
|
+
* e.g., 170141184507799509469114119040828178432 -> 170.141.184.507.799.509.469.114.119.040.828.178.432
|
|
5
|
+
*/
|
|
6
|
+
function formatUd(id) {
|
|
7
|
+
const str = String(id).replace(/\./g, ""); // Remove any existing dots
|
|
8
|
+
const reversed = str.split("").toReversed();
|
|
9
|
+
const chunks = [];
|
|
10
|
+
for (let i = 0; i < reversed.length; i += 3) {
|
|
11
|
+
chunks.push(reversed
|
|
12
|
+
.slice(i, i + 3)
|
|
13
|
+
.toReversed()
|
|
14
|
+
.join(""));
|
|
15
|
+
}
|
|
16
|
+
return chunks.toReversed().join(".");
|
|
17
|
+
}
|
|
18
|
+
const messageCache = new Map();
|
|
19
|
+
const MAX_CACHED_MESSAGES = 100;
|
|
20
|
+
export function lookupCachedMessage(channelNest, messageId) {
|
|
21
|
+
const cache = messageCache.get(channelNest);
|
|
22
|
+
if (!cache)
|
|
23
|
+
return undefined;
|
|
24
|
+
const normalizedId = String(messageId).replace(/\./g, "");
|
|
25
|
+
return cache.find((m) => m.id && String(m.id).replace(/\./g, "") === normalizedId);
|
|
26
|
+
}
|
|
27
|
+
export function cacheMessage(channelNest, message) {
|
|
28
|
+
if (!messageCache.has(channelNest)) {
|
|
29
|
+
messageCache.set(channelNest, []);
|
|
30
|
+
}
|
|
31
|
+
const cache = messageCache.get(channelNest);
|
|
32
|
+
if (!cache) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
cache.unshift(message);
|
|
36
|
+
if (cache.length > MAX_CACHED_MESSAGES) {
|
|
37
|
+
cache.pop();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export async function fetchChannelHistory(api, channelNest, count = 50, runtime) {
|
|
41
|
+
try {
|
|
42
|
+
const scryPath = `/channels/v4/${channelNest}/posts/newest/${count}/outline.json`;
|
|
43
|
+
runtime?.log?.(`[tlon] Fetching history: ${scryPath}`);
|
|
44
|
+
const data = await api.scry(scryPath);
|
|
45
|
+
if (!data) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
let posts = [];
|
|
49
|
+
if (Array.isArray(data)) {
|
|
50
|
+
posts = data;
|
|
51
|
+
}
|
|
52
|
+
else if (data.posts && typeof data.posts === "object") {
|
|
53
|
+
posts = Object.values(data.posts);
|
|
54
|
+
}
|
|
55
|
+
else if (typeof data === "object") {
|
|
56
|
+
posts = Object.values(data);
|
|
57
|
+
}
|
|
58
|
+
const messages = posts
|
|
59
|
+
.map((item) => {
|
|
60
|
+
const essay = item.essay || item["r-post"]?.set?.essay;
|
|
61
|
+
const seal = item.seal || item["r-post"]?.set?.seal;
|
|
62
|
+
return {
|
|
63
|
+
author: essay?.author || "unknown",
|
|
64
|
+
content: extractMessageText(essay?.content || []),
|
|
65
|
+
timestamp: essay?.sent || Date.now(),
|
|
66
|
+
id: seal?.id,
|
|
67
|
+
};
|
|
68
|
+
})
|
|
69
|
+
.filter((msg) => msg.content);
|
|
70
|
+
runtime?.log?.(`[tlon] Extracted ${messages.length} messages from history`);
|
|
71
|
+
return messages;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
runtime?.log?.(`[tlon] Error fetching channel history: ${error?.message ?? String(error)}`);
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export async function getChannelHistory(api, channelNest, count = 50, runtime) {
|
|
79
|
+
const cache = messageCache.get(channelNest) ?? [];
|
|
80
|
+
if (cache.length >= count) {
|
|
81
|
+
runtime?.log?.(`[tlon] Using cached messages (${cache.length} available)`);
|
|
82
|
+
return cache.slice(0, count);
|
|
83
|
+
}
|
|
84
|
+
runtime?.log?.(`[tlon] Cache has ${cache.length} messages, need ${count}, fetching from scry...`);
|
|
85
|
+
return await fetchChannelHistory(api, channelNest, count, runtime);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Fetch thread/reply history for a specific parent post.
|
|
89
|
+
* Used to get context when entering a thread conversation.
|
|
90
|
+
*/
|
|
91
|
+
export async function fetchThreadHistory(api, channelNest, parentId, count = 50, runtime) {
|
|
92
|
+
try {
|
|
93
|
+
// Tlon API: fetch replies to a specific post
|
|
94
|
+
// Format: /channels/v4/{nest}/posts/post/{parentId}/replies/newest/{count}.json
|
|
95
|
+
// parentId needs @ud formatting (dots every 3 digits)
|
|
96
|
+
const formattedParentId = formatUd(parentId);
|
|
97
|
+
runtime?.log?.(`[tlon] Thread history - parentId: ${parentId} -> formatted: ${formattedParentId}`);
|
|
98
|
+
const scryPath = `/channels/v4/${channelNest}/posts/post/id/${formattedParentId}/replies/newest/${count}.json`;
|
|
99
|
+
runtime?.log?.(`[tlon] Fetching thread history: ${scryPath}`);
|
|
100
|
+
const data = await api.scry(scryPath);
|
|
101
|
+
if (!data) {
|
|
102
|
+
runtime?.log?.(`[tlon] No thread history data returned`);
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
let replies = [];
|
|
106
|
+
if (Array.isArray(data)) {
|
|
107
|
+
replies = data;
|
|
108
|
+
}
|
|
109
|
+
else if (data.replies && Array.isArray(data.replies)) {
|
|
110
|
+
replies = data.replies;
|
|
111
|
+
}
|
|
112
|
+
else if (typeof data === "object") {
|
|
113
|
+
replies = Object.values(data);
|
|
114
|
+
}
|
|
115
|
+
const messages = replies
|
|
116
|
+
.map((item) => {
|
|
117
|
+
// Thread replies use 'memo' structure
|
|
118
|
+
const memo = item.memo || item["r-reply"]?.set?.memo || item;
|
|
119
|
+
const seal = item.seal || item["r-reply"]?.set?.seal;
|
|
120
|
+
return {
|
|
121
|
+
author: memo?.author || "unknown",
|
|
122
|
+
content: extractMessageText(memo?.content || []),
|
|
123
|
+
timestamp: memo?.sent || Date.now(),
|
|
124
|
+
id: seal?.id || item.id,
|
|
125
|
+
};
|
|
126
|
+
})
|
|
127
|
+
.filter((msg) => msg.content);
|
|
128
|
+
runtime?.log?.(`[tlon] Extracted ${messages.length} thread replies from history`);
|
|
129
|
+
return messages;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
runtime?.log?.(`[tlon] Error fetching thread history: ${error?.message ?? String(error)}`);
|
|
133
|
+
// Fall back to trying alternate path structure
|
|
134
|
+
try {
|
|
135
|
+
const altPath = `/channels/v4/${channelNest}/posts/post/id/${formatUd(parentId)}.json`;
|
|
136
|
+
runtime?.log?.(`[tlon] Trying alternate path: ${altPath}`);
|
|
137
|
+
const data = await api.scry(altPath);
|
|
138
|
+
if (data?.seal?.meta?.replyCount > 0 && data?.replies) {
|
|
139
|
+
const replies = Array.isArray(data.replies) ? data.replies : Object.values(data.replies);
|
|
140
|
+
const messages = replies
|
|
141
|
+
.map((reply) => ({
|
|
142
|
+
author: reply.memo?.author || "unknown",
|
|
143
|
+
content: extractMessageText(reply.memo?.content || []),
|
|
144
|
+
timestamp: reply.memo?.sent || Date.now(),
|
|
145
|
+
id: reply.seal?.id,
|
|
146
|
+
}))
|
|
147
|
+
.filter((msg) => msg.content);
|
|
148
|
+
runtime?.log?.(`[tlon] Extracted ${messages.length} replies from post data`);
|
|
149
|
+
return messages;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (altError) {
|
|
153
|
+
runtime?.log?.(`[tlon] Alternate path also failed: ${altError?.message ?? String(altError)}`);
|
|
154
|
+
}
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../../src/monitor/history.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,SAAS,QAAQ,CAAC,EAAmB;IACnC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,2BAA2B;IACtE,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAI,CACT,QAAQ;aACL,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;aACf,UAAU,EAAE;aACZ,IAAI,CAAC,EAAE,CAAC,CACZ,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvC,CAAC;AASD,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAC;AAC3D,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,MAAM,UAAU,mBAAmB,CAAC,WAAmB,EAAE,SAAiB;IACxE,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,YAAY,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,WAAmB,EAAE,OAAyB;IACzE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QACnC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvB,IAAI,KAAK,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACvC,KAAK,CAAC,GAAG,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAiD,EACjD,WAAmB,EACnB,KAAK,GAAG,EAAE,EACV,OAAoB;IAEpB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,gBAAgB,WAAW,iBAAiB,KAAK,eAAe,CAAC;QAClF,OAAO,EAAE,GAAG,EAAE,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAQ,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,KAAK,GAAU,EAAE,CAAC;QACtB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACxD,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,QAAQ,GAAG,KAAK;aACnB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC;YACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC;YAEpD,OAAO;gBACL,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,SAAS;gBAClC,OAAO,EAAE,kBAAkB,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC;gBACjD,SAAS,EAAE,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE;gBACpC,EAAE,EAAE,IAAI,EAAE,EAAE;aACO,CAAC;QACxB,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEhC,OAAO,EAAE,GAAG,EAAE,CAAC,oBAAoB,QAAQ,CAAC,MAAM,wBAAwB,CAAC,CAAC;QAC5E,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,EAAE,GAAG,EAAE,CAAC,0CAA0C,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5F,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAiD,EACjD,WAAmB,EACnB,KAAK,GAAG,EAAE,EACV,OAAoB;IAEpB,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAClD,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QAC1B,OAAO,EAAE,GAAG,EAAE,CAAC,iCAAiC,KAAK,CAAC,MAAM,aAAa,CAAC,CAAC;QAC3E,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,CAAC,oBAAoB,KAAK,CAAC,MAAM,mBAAmB,KAAK,yBAAyB,CAAC,CAAC;IAClG,OAAO,MAAM,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAiD,EACjD,WAAmB,EACnB,QAAgB,EAChB,KAAK,GAAG,EAAE,EACV,OAAoB;IAEpB,IAAI,CAAC;QACH,6CAA6C;QAC7C,gFAAgF;QAChF,sDAAsD;QACtD,MAAM,iBAAiB,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,OAAO,EAAE,GAAG,EAAE,CACZ,qCAAqC,QAAQ,kBAAkB,iBAAiB,EAAE,CACnF,CAAC;QAEF,MAAM,QAAQ,GAAG,gBAAgB,WAAW,kBAAkB,iBAAiB,mBAAmB,KAAK,OAAO,CAAC;QAC/G,OAAO,EAAE,GAAG,EAAE,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QAE9D,MAAM,IAAI,GAAQ,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,EAAE,GAAG,EAAE,CAAC,wCAAwC,CAAC,CAAC;YACzD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,OAAO,GAAU,EAAE,CAAC;QACxB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACvD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QACzB,CAAC;aAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO;aACrB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,sCAAsC;YACtC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,IAAI,IAAI,IAAI,CAAC;YAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC;YAErD,OAAO;gBACL,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,SAAS;gBACjC,OAAO,EAAE,kBAAkB,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;gBAChD,SAAS,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE;gBACnC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,EAAE;aACJ,CAAC;QACxB,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEhC,OAAO,EAAE,GAAG,EAAE,CAAC,oBAAoB,QAAQ,CAAC,MAAM,8BAA8B,CAAC,CAAC;QAClF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,EAAE,GAAG,EAAE,CAAC,yCAAyC,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC3F,+CAA+C;QAC/C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,gBAAgB,WAAW,kBAAkB,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;YACvF,OAAO,EAAE,GAAG,EAAE,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;YAC3D,MAAM,IAAI,GAAQ,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAE1C,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAAG,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;gBACtD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACzF,MAAM,QAAQ,GAAG,OAAO;qBACrB,GAAG,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,CAAC;oBACpB,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,SAAS;oBACvC,OAAO,EAAE,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;oBACtD,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE;oBACzC,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE;iBACnB,CAAC,CAAC;qBACF,MAAM,CAAC,CAAC,GAAqB,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAElD,OAAO,EAAE,GAAG,EAAE,CAAC,oBAAoB,QAAQ,CAAC,MAAM,yBAAyB,CAAC,CAAC;gBAC7E,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAAC,OAAO,QAAa,EAAE,CAAC;YACvB,OAAO,EAAE,GAAG,EAAE,CAAC,sCAAsC,QAAQ,EAAE,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|