Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/lib/moment/__tests__/mapMetadataToSupabase.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,32 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';

vi.mock('@/lib/metadata/getMetadataHandler', () => ({ default: vi.fn() }));
vi.mock('@/lib/arweave/getMimeType', () => ({ default: vi.fn() }));
vi.mock('@/lib/farcaster/getFarcasterUsernameByAddress', () => ({
default: vi.fn(),
}));
vi.mock('@/lib/ens/resolveAddressToEns', () => ({ default: vi.fn() }));

import { mapMetadataToSupabase } from '../mapMetadataToSupabase';
import getMetadataHandler from '@/lib/metadata/getMetadataHandler';
import getMimeType from '@/lib/arweave/getMimeType';
import getFarcasterUsernameByAddress from '@/lib/farcaster/getFarcasterUsernameByAddress';
import resolveAddressToEns from '@/lib/ens/resolveAddressToEns';

const mockGetMetadata = vi.mocked(getMetadataHandler);
const mockGetMimeType = vi.mocked(getMimeType);
const mockGetFarcasterUsername = vi.mocked(getFarcasterUsernameByAddress);
const mockResolveEns = vi.mocked(resolveAddressToEns);

describe('mapMetadataToSupabase', () => {
beforeEach(() => vi.clearAllMocks());
beforeEach(() => {
vi.clearAllMocks();
// When metadata has no `artist` field, mapMetadataToSupabase falls back
// to a real Farcaster/ENS lookup for the creator address. Default both
// to "not found" so tests that don't care about this fallback don't hit
// the network and hang.
mockGetFarcasterUsername.mockResolvedValue(undefined);
mockResolveEns.mockResolvedValue(null);
});

it('returns empty records for empty input', async () => {
const result = await mapMetadataToSupabase([]);
Expand Down
8 changes: 8 additions & 0 deletions src/lib/telegram/chat/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ export function createTelegramChatBot() {
secretToken: process.env.TELEGRAM_CHAT_WEBHOOK_SECRET_TOKEN,
mode: 'webhook',
});
// The adapter defaults persistMessageHistory to true, which writes every
// message to Redis (msg-history:<chatId>) forever. Nothing in this repo
// reads that history back (no LLM context use), so it's pure write waste.
// Field is typed readonly upstream but is a plain mutable class field at
// runtime — force it off here instead of forking the adapter.
(
telegramAdapter as { persistMessageHistory: boolean }
).persistMessageHistory = false;
Comment on lines +19 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Add a runtime assertion to catch silent failure if the field becomes non-writable.

The cast bypasses the readonly type constraint, which is intentional and well-documented. However, if the upstream library later changes persistMessageHistory to a getter-only or non-writable property, the assignment at line 21 would silently fail — no error thrown, but Redis history writes would resume unnoticed. A post-assignment assertion would catch this at startup.

🛡️ Suggested defensive assertion
   (
     telegramAdapter as { persistMessageHistory: boolean }
   ).persistMessageHistory = false;
+  if (
+    (telegramAdapter as { persistMessageHistory: boolean }).persistMessageHistory !== false
+  ) {
+    throw new Error(
+      'Failed to disable persistMessageHistory on Telegram adapter — field may be non-writable'
+    );
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(
telegramAdapter as { persistMessageHistory: boolean }
).persistMessageHistory = false;
(
telegramAdapter as { persistMessageHistory: boolean }
).persistMessageHistory = false;
if (
(telegramAdapter as { persistMessageHistory: boolean }).persistMessageHistory !== false
) {
throw new Error(
'Failed to disable persistMessageHistory on Telegram adapter — field may be non-writable'
);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/telegram/chat/bot.ts` around lines 19 - 21, The assignment in bot.ts
that sets telegramAdapter.persistMessageHistory to false should be followed by a
runtime check so startup fails if the property is no longer writable. Update the
bot initialization logic around telegramAdapter to verify the value actually
changed after the assignment, and throw or log an explicit error if it did not.
Use the existing telegramAdapter setup in the chat/bot.ts flow so the assertion
sits immediately after the persistMessageHistory write.


const bot = new Chat({
userName: process.env.TELEGRAM_CHAT_BOT_USERNAME!,
Expand Down
Loading