jefrichat-mcp 0.4.0 → 0.6.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/http.js +84 -16
- package/dist/index.js +125 -17
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -49397,6 +49397,61 @@ var MIME = {
|
|
|
49397
49397
|
".zip": "application/zip"
|
|
49398
49398
|
};
|
|
49399
49399
|
var mimeOf = (name) => MIME[np.extname(name).toLowerCase()] ?? "application/octet-stream";
|
|
49400
|
+
function screenshotDir() {
|
|
49401
|
+
try {
|
|
49402
|
+
const out = cp.execFileSync("defaults", ["read", "com.apple.screencapture", "location"], { encoding: "utf8", timeout: 2e3 }).trim();
|
|
49403
|
+
if (out) return out.startsWith("~") ? np.join(os2.homedir(), out.slice(1)) : out;
|
|
49404
|
+
} catch {
|
|
49405
|
+
}
|
|
49406
|
+
const desktop = np.join(os2.homedir(), "Desktop");
|
|
49407
|
+
return fs2.existsSync(desktop) ? desktop : null;
|
|
49408
|
+
}
|
|
49409
|
+
function resolveLocalFile(rawPath) {
|
|
49410
|
+
const expand = (p) => p.startsWith("~") ? np.join(os2.homedir(), p.slice(1)) : p;
|
|
49411
|
+
const exists = (p) => {
|
|
49412
|
+
try {
|
|
49413
|
+
return fs2.existsSync(p) ? p : null;
|
|
49414
|
+
} catch {
|
|
49415
|
+
return null;
|
|
49416
|
+
}
|
|
49417
|
+
};
|
|
49418
|
+
const abs = expand(rawPath);
|
|
49419
|
+
let hit = exists(abs);
|
|
49420
|
+
if (hit) return hit;
|
|
49421
|
+
const UNI = /[ ]/g;
|
|
49422
|
+
for (const v of [abs.replace(/ /g, "\u202F"), abs.replace(UNI, " "), abs.replace(/ (AM|PM)(\.[a-z0-9]+)?$/i, "\u202F$1$2")]) {
|
|
49423
|
+
hit = exists(v);
|
|
49424
|
+
if (hit) return hit;
|
|
49425
|
+
}
|
|
49426
|
+
const base = np.basename(abs);
|
|
49427
|
+
const looksLikeShot = /screencaptureui/i.test(abs) || /^Screenshot[\s ]/i.test(base);
|
|
49428
|
+
if (looksLikeShot) {
|
|
49429
|
+
const dir = screenshotDir();
|
|
49430
|
+
if (dir) {
|
|
49431
|
+
let files = [];
|
|
49432
|
+
try {
|
|
49433
|
+
files = fs2.readdirSync(dir);
|
|
49434
|
+
} catch {
|
|
49435
|
+
}
|
|
49436
|
+
const norm = (s) => s.replace(/[ \s]+/g, " ").trim().toLowerCase();
|
|
49437
|
+
const want = norm(base);
|
|
49438
|
+
for (const f of files) if (norm(f) === want) {
|
|
49439
|
+
hit = exists(np.join(dir, f));
|
|
49440
|
+
if (hit) return hit;
|
|
49441
|
+
}
|
|
49442
|
+
const shots = files.filter((f) => /^Screenshot[\s ].*\.(png|jpe?g)$/i.test(f)).map((f) => {
|
|
49443
|
+
const p = np.join(dir, f);
|
|
49444
|
+
try {
|
|
49445
|
+
return { p, m: fs2.statSync(p).mtimeMs };
|
|
49446
|
+
} catch {
|
|
49447
|
+
return { p, m: 0 };
|
|
49448
|
+
}
|
|
49449
|
+
}).filter((x) => x.m > 0).sort((a, b) => b.m - a.m);
|
|
49450
|
+
if (shots.length && Date.now() - shots[0].m < 5 * 60 * 1e3) return shots[0].p;
|
|
49451
|
+
}
|
|
49452
|
+
}
|
|
49453
|
+
return null;
|
|
49454
|
+
}
|
|
49400
49455
|
var MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
|
|
49401
49456
|
var MB = (n) => (n / 1024 / 1024).toFixed(1);
|
|
49402
49457
|
var WS_SAFE_FILE_BYTES = 45 * 1024 * 1024;
|
|
@@ -49541,8 +49596,8 @@ ${fp}`);
|
|
|
49541
49596
|
`I can't read local files from the cloud connector. Use a local/stdin Jefri Chat connector, or open the web chat and drop the file there.`
|
|
49542
49597
|
);
|
|
49543
49598
|
}
|
|
49544
|
-
const abs =
|
|
49545
|
-
if (!
|
|
49599
|
+
const abs = resolveLocalFile(path2);
|
|
49600
|
+
if (!abs) {
|
|
49546
49601
|
return fail(
|
|
49547
49602
|
`I can't find a file at ${path2} on this machine.`
|
|
49548
49603
|
);
|
|
@@ -49602,8 +49657,8 @@ ${fp}`);
|
|
|
49602
49657
|
`I can't read local files from the cloud connector. Use a local/stdin Jefri Chat connector, or open the web chat and drop the file there.`
|
|
49603
49658
|
);
|
|
49604
49659
|
}
|
|
49605
|
-
const abs =
|
|
49606
|
-
if (!
|
|
49660
|
+
const abs = resolveLocalFile(path2);
|
|
49661
|
+
if (!abs) {
|
|
49607
49662
|
return fail(
|
|
49608
49663
|
`I can't find a file at ${path2} on this machine.`
|
|
49609
49664
|
);
|
|
@@ -49662,8 +49717,8 @@ ${psCmd}
|
|
|
49662
49717
|
(Alternatively the user can drag "${fname}" straight into the chat: ${dropLink})`
|
|
49663
49718
|
);
|
|
49664
49719
|
}
|
|
49665
|
-
const abs =
|
|
49666
|
-
if (!
|
|
49720
|
+
const abs = resolveLocalFile(path2);
|
|
49721
|
+
if (!abs) {
|
|
49667
49722
|
return fail(`I can't find a file at ${path2} on this machine.`);
|
|
49668
49723
|
}
|
|
49669
49724
|
const buf = fs2.readFileSync(abs);
|
|
@@ -50207,8 +50262,8 @@ ${cmd}`);
|
|
|
50207
50262
|
${cmd}`
|
|
50208
50263
|
);
|
|
50209
50264
|
}
|
|
50210
|
-
const abs =
|
|
50211
|
-
if (!
|
|
50265
|
+
const abs = resolveLocalFile(path2);
|
|
50266
|
+
if (!abs) return fail(`I can't find a file at ${path2} on this machine.`);
|
|
50212
50267
|
const buf = fs2.readFileSync(abs);
|
|
50213
50268
|
name = np.basename(abs);
|
|
50214
50269
|
mime = mimeOf(name);
|
|
@@ -50243,19 +50298,22 @@ ${cmd}`
|
|
|
50243
50298
|
"jefri_history",
|
|
50244
50299
|
{
|
|
50245
50300
|
title: "Read conversation history",
|
|
50246
|
-
description: "Read the recent message history of
|
|
50301
|
+
description: "Read the recent message history of a conversation \u2014 either a DM (pass `with` = a username) or a GROUP (pass `groupId`, from jefri_groups). Shows past messages AND any files/images (with how to download them).",
|
|
50247
50302
|
inputSchema: {
|
|
50248
|
-
with: external_exports.string().describe("the other person's username"),
|
|
50303
|
+
with: external_exports.string().optional().describe("the other person's username (for a DM)"),
|
|
50304
|
+
groupId: external_exports.string().optional().describe("a group's id (for group history) \u2014 from jefri_groups"),
|
|
50249
50305
|
limit: external_exports.number().optional().describe("max messages to return (default 20)")
|
|
50250
50306
|
}
|
|
50251
50307
|
},
|
|
50252
|
-
async ({ with: other, limit }) => withClient(async (c) => {
|
|
50253
|
-
|
|
50308
|
+
async ({ with: other, groupId, limit }) => withClient(async (c) => {
|
|
50309
|
+
if (!other && !groupId) return fail("Give `with` (a username, for a DM) or `groupId` (for a group).");
|
|
50310
|
+
const convId = groupId ? groupConversationId(groupId) : dmConversationId(c.identity.username, other);
|
|
50311
|
+
const label = groupId ? "this group" : `@${other}`;
|
|
50254
50312
|
const p = waitFor(c, "history", (e) => e.conversationId === convId);
|
|
50255
50313
|
c.history(convId);
|
|
50256
50314
|
const res = await p;
|
|
50257
50315
|
const msgs = (res?.messages ?? []).slice(-(limit ?? 20));
|
|
50258
|
-
if (!msgs.length) return ok(`No messages yet
|
|
50316
|
+
if (!msgs.length) return ok(`No messages yet in ${label}.`);
|
|
50259
50317
|
const lines = await Promise.all(msgs.map(async (m) => {
|
|
50260
50318
|
if (m.encryptionMode === "private_e2e" && m.encryptedPayload) {
|
|
50261
50319
|
try {
|
|
@@ -50265,7 +50323,11 @@ ${cmd}`
|
|
|
50265
50323
|
return `${m.senderUsername}: \u{1F512} Private message unavailable on this device`;
|
|
50266
50324
|
}
|
|
50267
50325
|
}
|
|
50268
|
-
|
|
50326
|
+
if (m.kind === "file") {
|
|
50327
|
+
const dl = groupId ? `jefri_download_file(groupId: "${groupId}", fileName: "${m.fileName}")` : `jefri_download_file(from: "${m.senderUsername}", fileName: "${m.fileName}")`;
|
|
50328
|
+
return `${m.senderUsername}: \u{1F4CE} ${m.fileName} \u2014 to save it call ${dl}`;
|
|
50329
|
+
}
|
|
50330
|
+
return `${m.senderUsername}: ${m.content}`;
|
|
50269
50331
|
}));
|
|
50270
50332
|
return ok(lines.join("\n"));
|
|
50271
50333
|
})
|
|
@@ -50332,10 +50394,16 @@ ${cmd}`
|
|
|
50332
50394
|
})
|
|
50333
50395
|
);
|
|
50334
50396
|
}
|
|
50335
|
-
function attachInbox(c, inbox, self) {
|
|
50397
|
+
function attachInbox(c, inbox, self, onIncoming) {
|
|
50336
50398
|
const capture = (e) => {
|
|
50337
50399
|
const m = e.message;
|
|
50338
|
-
if (m.senderUsername !== self)
|
|
50400
|
+
if (m.senderUsername !== self) {
|
|
50401
|
+
inbox.push(m);
|
|
50402
|
+
try {
|
|
50403
|
+
onIncoming?.(m);
|
|
50404
|
+
} catch {
|
|
50405
|
+
}
|
|
50406
|
+
}
|
|
50339
50407
|
};
|
|
50340
50408
|
c.on("message_received", capture);
|
|
50341
50409
|
c.on("file_received", capture);
|
package/dist/index.js
CHANGED
|
@@ -25305,6 +25305,61 @@ var MIME = {
|
|
|
25305
25305
|
".zip": "application/zip"
|
|
25306
25306
|
};
|
|
25307
25307
|
var mimeOf = (name) => MIME[np.extname(name).toLowerCase()] ?? "application/octet-stream";
|
|
25308
|
+
function screenshotDir() {
|
|
25309
|
+
try {
|
|
25310
|
+
const out = cp.execFileSync("defaults", ["read", "com.apple.screencapture", "location"], { encoding: "utf8", timeout: 2e3 }).trim();
|
|
25311
|
+
if (out) return out.startsWith("~") ? np.join(os2.homedir(), out.slice(1)) : out;
|
|
25312
|
+
} catch {
|
|
25313
|
+
}
|
|
25314
|
+
const desktop = np.join(os2.homedir(), "Desktop");
|
|
25315
|
+
return fs2.existsSync(desktop) ? desktop : null;
|
|
25316
|
+
}
|
|
25317
|
+
function resolveLocalFile(rawPath) {
|
|
25318
|
+
const expand = (p) => p.startsWith("~") ? np.join(os2.homedir(), p.slice(1)) : p;
|
|
25319
|
+
const exists = (p) => {
|
|
25320
|
+
try {
|
|
25321
|
+
return fs2.existsSync(p) ? p : null;
|
|
25322
|
+
} catch {
|
|
25323
|
+
return null;
|
|
25324
|
+
}
|
|
25325
|
+
};
|
|
25326
|
+
const abs = expand(rawPath);
|
|
25327
|
+
let hit = exists(abs);
|
|
25328
|
+
if (hit) return hit;
|
|
25329
|
+
const UNI = /[ ]/g;
|
|
25330
|
+
for (const v of [abs.replace(/ /g, "\u202F"), abs.replace(UNI, " "), abs.replace(/ (AM|PM)(\.[a-z0-9]+)?$/i, "\u202F$1$2")]) {
|
|
25331
|
+
hit = exists(v);
|
|
25332
|
+
if (hit) return hit;
|
|
25333
|
+
}
|
|
25334
|
+
const base = np.basename(abs);
|
|
25335
|
+
const looksLikeShot = /screencaptureui/i.test(abs) || /^Screenshot[\s ]/i.test(base);
|
|
25336
|
+
if (looksLikeShot) {
|
|
25337
|
+
const dir = screenshotDir();
|
|
25338
|
+
if (dir) {
|
|
25339
|
+
let files = [];
|
|
25340
|
+
try {
|
|
25341
|
+
files = fs2.readdirSync(dir);
|
|
25342
|
+
} catch {
|
|
25343
|
+
}
|
|
25344
|
+
const norm = (s) => s.replace(/[ \s]+/g, " ").trim().toLowerCase();
|
|
25345
|
+
const want = norm(base);
|
|
25346
|
+
for (const f of files) if (norm(f) === want) {
|
|
25347
|
+
hit = exists(np.join(dir, f));
|
|
25348
|
+
if (hit) return hit;
|
|
25349
|
+
}
|
|
25350
|
+
const shots = files.filter((f) => /^Screenshot[\s ].*\.(png|jpe?g)$/i.test(f)).map((f) => {
|
|
25351
|
+
const p = np.join(dir, f);
|
|
25352
|
+
try {
|
|
25353
|
+
return { p, m: fs2.statSync(p).mtimeMs };
|
|
25354
|
+
} catch {
|
|
25355
|
+
return { p, m: 0 };
|
|
25356
|
+
}
|
|
25357
|
+
}).filter((x) => x.m > 0).sort((a, b) => b.m - a.m);
|
|
25358
|
+
if (shots.length && Date.now() - shots[0].m < 5 * 60 * 1e3) return shots[0].p;
|
|
25359
|
+
}
|
|
25360
|
+
}
|
|
25361
|
+
return null;
|
|
25362
|
+
}
|
|
25308
25363
|
var MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
|
|
25309
25364
|
var MB = (n) => (n / 1024 / 1024).toFixed(1);
|
|
25310
25365
|
var WS_SAFE_FILE_BYTES = 45 * 1024 * 1024;
|
|
@@ -25449,8 +25504,8 @@ ${fp}`);
|
|
|
25449
25504
|
`I can't read local files from the cloud connector. Use a local/stdin Jefri Chat connector, or open the web chat and drop the file there.`
|
|
25450
25505
|
);
|
|
25451
25506
|
}
|
|
25452
|
-
const abs =
|
|
25453
|
-
if (!
|
|
25507
|
+
const abs = resolveLocalFile(path3);
|
|
25508
|
+
if (!abs) {
|
|
25454
25509
|
return fail(
|
|
25455
25510
|
`I can't find a file at ${path3} on this machine.`
|
|
25456
25511
|
);
|
|
@@ -25510,8 +25565,8 @@ ${fp}`);
|
|
|
25510
25565
|
`I can't read local files from the cloud connector. Use a local/stdin Jefri Chat connector, or open the web chat and drop the file there.`
|
|
25511
25566
|
);
|
|
25512
25567
|
}
|
|
25513
|
-
const abs =
|
|
25514
|
-
if (!
|
|
25568
|
+
const abs = resolveLocalFile(path3);
|
|
25569
|
+
if (!abs) {
|
|
25515
25570
|
return fail(
|
|
25516
25571
|
`I can't find a file at ${path3} on this machine.`
|
|
25517
25572
|
);
|
|
@@ -25570,8 +25625,8 @@ ${psCmd}
|
|
|
25570
25625
|
(Alternatively the user can drag "${fname}" straight into the chat: ${dropLink})`
|
|
25571
25626
|
);
|
|
25572
25627
|
}
|
|
25573
|
-
const abs =
|
|
25574
|
-
if (!
|
|
25628
|
+
const abs = resolveLocalFile(path3);
|
|
25629
|
+
if (!abs) {
|
|
25575
25630
|
return fail(`I can't find a file at ${path3} on this machine.`);
|
|
25576
25631
|
}
|
|
25577
25632
|
const buf = fs2.readFileSync(abs);
|
|
@@ -26115,8 +26170,8 @@ ${cmd}`);
|
|
|
26115
26170
|
${cmd}`
|
|
26116
26171
|
);
|
|
26117
26172
|
}
|
|
26118
|
-
const abs =
|
|
26119
|
-
if (!
|
|
26173
|
+
const abs = resolveLocalFile(path3);
|
|
26174
|
+
if (!abs) return fail(`I can't find a file at ${path3} on this machine.`);
|
|
26120
26175
|
const buf = fs2.readFileSync(abs);
|
|
26121
26176
|
name = np.basename(abs);
|
|
26122
26177
|
mime = mimeOf(name);
|
|
@@ -26151,19 +26206,22 @@ ${cmd}`
|
|
|
26151
26206
|
"jefri_history",
|
|
26152
26207
|
{
|
|
26153
26208
|
title: "Read conversation history",
|
|
26154
|
-
description: "Read the recent message history of
|
|
26209
|
+
description: "Read the recent message history of a conversation \u2014 either a DM (pass `with` = a username) or a GROUP (pass `groupId`, from jefri_groups). Shows past messages AND any files/images (with how to download them).",
|
|
26155
26210
|
inputSchema: {
|
|
26156
|
-
with: external_exports.string().describe("the other person's username"),
|
|
26211
|
+
with: external_exports.string().optional().describe("the other person's username (for a DM)"),
|
|
26212
|
+
groupId: external_exports.string().optional().describe("a group's id (for group history) \u2014 from jefri_groups"),
|
|
26157
26213
|
limit: external_exports.number().optional().describe("max messages to return (default 20)")
|
|
26158
26214
|
}
|
|
26159
26215
|
},
|
|
26160
|
-
async ({ with: other, limit }) => withClient(async (c) => {
|
|
26161
|
-
|
|
26216
|
+
async ({ with: other, groupId, limit }) => withClient(async (c) => {
|
|
26217
|
+
if (!other && !groupId) return fail("Give `with` (a username, for a DM) or `groupId` (for a group).");
|
|
26218
|
+
const convId = groupId ? groupConversationId(groupId) : dmConversationId(c.identity.username, other);
|
|
26219
|
+
const label = groupId ? "this group" : `@${other}`;
|
|
26162
26220
|
const p = waitFor(c, "history", (e) => e.conversationId === convId);
|
|
26163
26221
|
c.history(convId);
|
|
26164
26222
|
const res = await p;
|
|
26165
26223
|
const msgs = (res?.messages ?? []).slice(-(limit ?? 20));
|
|
26166
|
-
if (!msgs.length) return ok(`No messages yet
|
|
26224
|
+
if (!msgs.length) return ok(`No messages yet in ${label}.`);
|
|
26167
26225
|
const lines = await Promise.all(msgs.map(async (m) => {
|
|
26168
26226
|
if (m.encryptionMode === "private_e2e" && m.encryptedPayload) {
|
|
26169
26227
|
try {
|
|
@@ -26173,7 +26231,11 @@ ${cmd}`
|
|
|
26173
26231
|
return `${m.senderUsername}: \u{1F512} Private message unavailable on this device`;
|
|
26174
26232
|
}
|
|
26175
26233
|
}
|
|
26176
|
-
|
|
26234
|
+
if (m.kind === "file") {
|
|
26235
|
+
const dl = groupId ? `jefri_download_file(groupId: "${groupId}", fileName: "${m.fileName}")` : `jefri_download_file(from: "${m.senderUsername}", fileName: "${m.fileName}")`;
|
|
26236
|
+
return `${m.senderUsername}: \u{1F4CE} ${m.fileName} \u2014 to save it call ${dl}`;
|
|
26237
|
+
}
|
|
26238
|
+
return `${m.senderUsername}: ${m.content}`;
|
|
26177
26239
|
}));
|
|
26178
26240
|
return ok(lines.join("\n"));
|
|
26179
26241
|
})
|
|
@@ -26240,15 +26302,49 @@ ${cmd}`
|
|
|
26240
26302
|
})
|
|
26241
26303
|
);
|
|
26242
26304
|
}
|
|
26243
|
-
function attachInbox(c, inbox2, self) {
|
|
26305
|
+
function attachInbox(c, inbox2, self, onIncoming) {
|
|
26244
26306
|
const capture = (e) => {
|
|
26245
26307
|
const m = e.message;
|
|
26246
|
-
if (m.senderUsername !== self)
|
|
26308
|
+
if (m.senderUsername !== self) {
|
|
26309
|
+
inbox2.push(m);
|
|
26310
|
+
try {
|
|
26311
|
+
onIncoming?.(m);
|
|
26312
|
+
} catch {
|
|
26313
|
+
}
|
|
26314
|
+
}
|
|
26247
26315
|
};
|
|
26248
26316
|
c.on("message_received", capture);
|
|
26249
26317
|
c.on("file_received", capture);
|
|
26250
26318
|
}
|
|
26251
26319
|
|
|
26320
|
+
// src/notify.ts
|
|
26321
|
+
import cp2 from "node:child_process";
|
|
26322
|
+
var OFF = process.env.JEFRI_NOTIFY === "0" || process.env.JEFRI_NOTIFY === "false";
|
|
26323
|
+
var clean = (s) => (s || "").replace(/[\r\n\t]+/g, " ").replace(/[\x00-\x1F]/g, "").slice(0, 140).trim();
|
|
26324
|
+
function notifyIncoming(title, body) {
|
|
26325
|
+
if (OFF) return;
|
|
26326
|
+
const t = clean(title) || "Jefri Chat";
|
|
26327
|
+
const b = clean(body);
|
|
26328
|
+
try {
|
|
26329
|
+
process.stderr.write("\x07");
|
|
26330
|
+
} catch {
|
|
26331
|
+
}
|
|
26332
|
+
try {
|
|
26333
|
+
if (process.platform === "darwin") {
|
|
26334
|
+
const esc2 = (x) => x.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
26335
|
+
const script = `display notification "${esc2(b)}" with title "${esc2(t)}" sound name "Ping"`;
|
|
26336
|
+
cp2.spawn("osascript", ["-e", script], { stdio: "ignore", detached: true }).unref();
|
|
26337
|
+
} else if (process.platform === "win32") {
|
|
26338
|
+
const esc2 = (x) => x.replace(/'/g, "''");
|
|
26339
|
+
const ps = `Add-Type -AssemblyName System.Windows.Forms;$n=New-Object System.Windows.Forms.NotifyIcon;$n.Icon=[System.Drawing.SystemIcons]::Information;$n.BalloonTipTitle='${esc2(t)}';$n.BalloonTipText='${esc2(b)}';$n.Visible=$true;$n.ShowBalloonTip(6000);Start-Sleep -Milliseconds 6500;$n.Dispose()`;
|
|
26340
|
+
cp2.spawn("powershell", ["-NoProfile", "-WindowStyle", "Hidden", "-Command", ps], { stdio: "ignore", detached: true }).unref();
|
|
26341
|
+
} else {
|
|
26342
|
+
cp2.spawn("notify-send", ["-a", "Jefri Chat", t, b], { stdio: "ignore", detached: true }).unref();
|
|
26343
|
+
}
|
|
26344
|
+
} catch {
|
|
26345
|
+
}
|
|
26346
|
+
}
|
|
26347
|
+
|
|
26252
26348
|
// src/index.ts
|
|
26253
26349
|
var SERVER = process.env.ACP_SERVER ?? "http://localhost:4000";
|
|
26254
26350
|
var TOKEN = process.env.ACP_TOKEN;
|
|
@@ -26302,7 +26398,19 @@ function ensureClient() {
|
|
|
26302
26398
|
if (c.identity) cacheToken(c.token);
|
|
26303
26399
|
}
|
|
26304
26400
|
const self = c.identity?.username ?? USERNAME;
|
|
26305
|
-
|
|
26401
|
+
const groupNames = /* @__PURE__ */ new Map();
|
|
26402
|
+
const refreshGroups = () => c.groups().then((gs) => {
|
|
26403
|
+
groupNames.clear();
|
|
26404
|
+
for (const g of gs) groupNames.set(g.id, g.name);
|
|
26405
|
+
}).catch(() => {
|
|
26406
|
+
});
|
|
26407
|
+
void refreshGroups();
|
|
26408
|
+
setInterval(refreshGroups, 6e4).unref?.();
|
|
26409
|
+
attachInbox(c, inbox, self, (m) => {
|
|
26410
|
+
const preview = m.kind === "file" ? `\u{1F4CE} ${m.fileName ?? "file"}` : m.content ?? "";
|
|
26411
|
+
const where = m.groupId ? ` \xB7 ${groupNames.get(m.groupId) ?? "group"}` : "";
|
|
26412
|
+
notifyIncoming("Jefri Chat", `${m.senderUsername}${where}: ${preview}`);
|
|
26413
|
+
});
|
|
26306
26414
|
log(`connected to ${SERVER} as ${self}`);
|
|
26307
26415
|
return c;
|
|
26308
26416
|
})().catch((e) => {
|
package/package.json
CHANGED