Skip to content

Commit b9c7b15

Browse files
author
Sorra
committed
SB-0MNP9QU9S0078KAT: add non-text attachment rejection test and update README to document attachment ingestion
1 parent 6664e0d commit b9c7b15

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ SourceBase automatically extracts URLs from Discord messages, fetches content me
3030
- Behavior and limits:
3131
- The bot writes the provided text to a temporary file and calls the OpenBrain CLI (`ob add`) with a `file://` URL so the existing CLI-based ingestion pipeline is reused.
3232
- To avoid abuse, the bot enforces a conservative default size limit of 64 KiB for direct text ingestion. You can override this limit with the environment variable `OB_ADD_MAX_BYTES` (value in bytes).
33+
- Attachment support:
34+
- You can reply to a message that contains a text-like file attachment (for example `.md`, `.markdown`, `.txt`) with `ob add` and the bot will fetch the attachment body and ingest it.
35+
- The bot accepts files with a text/* Content-Type or filenames ending in `.md`, `.markdown`, or `.txt`. Binary files (e.g. `application/octet-stream`) are rejected with a helpful error.
36+
- The same size limit (default 64 KiB, configurable via `OB_ADD_MAX_BYTES`) applies to attachments; oversized attachments are rejected with a clear message.
3337
- If the bot cannot fetch the referenced message (reply flow), it will reply with a helpful message explaining the permission issue and how to proceed.
3438
- If the CLI is unavailable, the bot will notify the user with a friendly error message.
3539

tests/index.ob-add.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,37 @@ describe("ob add message handler failure modes", () => {
273273
expect(replies[0]).toContain("too large to ingest");
274274
});
275275

276+
it("rejects non-text/binary attachment from referenced message", async () => {
277+
const onMonitoredMessage = await loadMonitoredMessageHandler(async () => {
278+
await vi.doMock("../src/bot/cli-runner.js", async (importOriginal) => {
279+
const actual: any = await importOriginal();
280+
return {
281+
...actual,
282+
runAddCommand: vi.fn(() => createAddGenerator([], { success: false, error: "", url: "", id: undefined } as any)),
283+
runCliCommand: vi.fn(),
284+
runQueueCommand: vi.fn(),
285+
runSummaryCommand: vi.fn(),
286+
runStatsCommand: vi.fn(async () => ({ totalLinks: 0, processedCount: 0, pendingCount: 0, failedCount: 0 })),
287+
isCliAvailable: vi.fn(async () => true),
288+
CliRunnerError: class MockCliRunnerError extends Error {},
289+
};
290+
});
291+
});
292+
293+
// Mock fetch to return a non-text Content-Type
294+
global.fetch = vi.fn(async () => ({ ok: true, headers: { get: (_: string) => "application/octet-stream" }, text: async () => "\u0000\u0001binary" } as any));
295+
296+
const { message, replies } = createFakeMessage("ob add");
297+
const att = { url: "https://example.test/file.bin", name: "file.bin" };
298+
message.reference = { messageId: "ref-bin" };
299+
message.channel = { messages: { fetch: vi.fn().mockResolvedValue({ content: "", attachments: { size: 1, first: () => att } }) } };
300+
301+
await onMonitoredMessage(message);
302+
303+
expect(replies.length).toBeGreaterThan(0);
304+
expect(replies[0]).toContain("does not appear to be a text file");
305+
});
306+
276307
it("handles inline attachment on same message as ob add", async () => {
277308
const onMonitoredMessage = await loadMonitoredMessageHandler(async () => {
278309
await vi.doMock("../src/bot/cli-runner.js", async (importOriginal) => {

0 commit comments

Comments
 (0)