import { DyFM_AI_Message, DyFM_AI_MessageRole } from '@futdevpro/fsm-dynamo/ai'; import { DyFM_Error } from '@futdevpro/fsm-dynamo'; import { DyNTS_DiAs_Util } from './dias.util'; import { DyNTS_DiAs_global_settings } from './dias-global-settings.const'; import { Message, TextChannel } from 'discord.js'; xdescribe('| DyNTS_DiAs_Util', () => { describe('| convertDiscordMessagesToOAIConversation', () => { it('| should convert Discord messages to AI conversation format', () => { const mockMessages = [ { author: { bot: false, id: 'user-123', displayName: 'User', }, content: 'User message', }, { author: { bot: true, id: 'bot-123', displayName: 'Bot', }, content: 'Bot response', }, ] as any as Message[]; const result = DyNTS_DiAs_Util.convertDiscordMessagesToOAIConversation({ messages: mockMessages, botClientId: 'bot-123', botDisplayName: 'Bot', issuer: 'issuer-123', }); expect(result.length).toBe(2); expect(result[0].role).toBe(DyFM_AI_MessageRole.user); expect(result[0].content).toBe('User message'); expect(result[1].role).toBe(DyFM_AI_MessageRole.assistant); expect(result[1].content).toBe('Bot response'); }); it('| should identify bot messages by author.bot flag', () => { const mockMessages = [ { author: { bot: true, id: 'bot-123', displayName: 'Bot', }, content: 'Bot message', }, ] as any as Message[]; const result = DyNTS_DiAs_Util.convertDiscordMessagesToOAIConversation({ messages: mockMessages, botClientId: 'bot-123', botDisplayName: 'Bot', issuer: 'issuer-123', }); expect(result[0].role).toBe(DyFM_AI_MessageRole.assistant); }); it('| should identify bot messages by author.id match', () => { const mockMessages = [ { author: { bot: false, id: 'bot-123', displayName: 'Bot', }, content: 'Bot message', }, ] as any as Message[]; const result = DyNTS_DiAs_Util.convertDiscordMessagesToOAIConversation({ messages: mockMessages, botClientId: 'bot-123', botDisplayName: 'Bot', issuer: 'issuer-123', }); expect(result[0].role).toBe(DyFM_AI_MessageRole.assistant); }); it('| should identify bot messages by author.displayName match', () => { const mockMessages = [ { author: { bot: false, id: 'other-123', displayName: 'Bot', }, content: 'Bot message', }, ] as any as Message[]; const result = DyNTS_DiAs_Util.convertDiscordMessagesToOAIConversation({ messages: mockMessages, botClientId: 'bot-123', botDisplayName: 'Bot', issuer: 'issuer-123', }); expect(result[0].role).toBe(DyFM_AI_MessageRole.assistant); }); it('| should convert bot messages with user translation flags to user role', () => { const userTranslationFlag = DyNTS_DiAs_global_settings.userTranslationFlags[0]; const mockMessages = [ { author: { bot: true, id: 'bot-123', displayName: 'Bot', }, content: `Message with ${userTranslationFlag} flag`, }, ] as any as Message[]; const result = DyNTS_DiAs_Util.convertDiscordMessagesToOAIConversation({ messages: mockMessages, botClientId: 'bot-123', botDisplayName: 'Bot', issuer: 'issuer-123', }); expect(result[0].role).toBe(DyFM_AI_MessageRole.user); }); it('| should handle empty messages array', () => { const result = DyNTS_DiAs_Util.convertDiscordMessagesToOAIConversation({ messages: [], botClientId: 'bot-123', botDisplayName: 'Bot', issuer: 'issuer-123', }); expect(result).toEqual([]); }); it('| should convert user messages to user role', () => { const mockMessages = [ { author: { bot: false, id: 'user-123', displayName: 'User', }, content: 'User message', }, ] as any as Message[]; const result = DyNTS_DiAs_Util.convertDiscordMessagesToOAIConversation({ messages: mockMessages, botClientId: 'bot-123', botDisplayName: 'Bot', issuer: 'issuer-123', }); expect(result[0].role).toBe(DyFM_AI_MessageRole.user); }); }); describe('| gatherMessagesForMessage', () => { it('| should throw error when channel is not text based', async () => { const mockMessage = { channel: { isTextBased: () => false, }, author: { id: 'user-123', }, } as any as Message; await expectAsync( DyNTS_DiAs_Util.gatherMessagesForMessage({ message: mockMessage, botClientId: 'bot-123', issuer: 'issuer-123', }) ).toBeRejectedWithError('Message channel is not a text channel!'); }); }); describe('| gatherMessages', () => { it('| should throw error when channel is not text based', async () => { const mockChannel = { isTextBased: () => false, messages: { fetch: jasmine.createSpy('fetch'), }, } as any as TextChannel; await expectAsync( DyNTS_DiAs_Util.gatherMessages({ channel: mockChannel, userId: 'user-123', botClientId: 'bot-123', issuer: 'issuer-123', }) ).toBeRejected(); }); it('| should use default limit when not provided', async () => { const mockMessages = [ { author: { id: 'user-123', displayName: 'User', }, content: 'Message 1', }, { author: { id: 'bot-123', displayName: 'Bot', }, content: 'Message 2', }, ] as any as Message[]; const mockChannel = { isTextBased: () => true, messages: { fetch: jasmine.createSpy('fetch').and.returnValue( Promise.resolve(mockMessages) ), }, } as any as TextChannel; const result = await DyNTS_DiAs_Util.gatherMessages({ channel: mockChannel, userId: 'user-123', botClientId: 'bot-123', issuer: 'issuer-123', }); expect(mockChannel.messages.fetch).toHaveBeenCalledWith({ limit: 100 }); expect(result.length).toBe(2); }); it('| should use provided limit', async () => { const mockMessages = [] as any as Message[]; const mockChannel = { isTextBased: () => true, messages: { fetch: jasmine.createSpy('fetch').and.returnValue( Promise.resolve(mockMessages) ), }, } as any as TextChannel; await DyNTS_DiAs_Util.gatherMessages({ channel: mockChannel, userId: 'user-123', botClientId: 'bot-123', limit: 50, issuer: 'issuer-123', }); expect(mockChannel.messages.fetch).toHaveBeenCalledWith({ limit: 50 }); }); it('| should filter messages with skipFlags', async () => { const mockMessages = [ { author: { id: 'user-123', displayName: 'User', }, content: 'Message 1', }, { author: { id: 'user-123', displayName: 'User', }, content: 'Message 2 [SKIP]', }, ] as any as Message[]; const mockChannel = { isTextBased: () => true, messages: { fetch: jasmine.createSpy('fetch').and.returnValue( Promise.resolve(mockMessages) ), }, } as any as TextChannel; const result = await DyNTS_DiAs_Util.gatherMessages({ channel: mockChannel, userId: 'user-123', botClientId: 'bot-123', skipFlags: ['[SKIP]'], issuer: 'issuer-123', }); expect(result.length).toBe(1); expect(result[0].content).toBe('Message 1'); }); it('| should add author display name when third party messages exist', async () => { const mockMessages = [ { author: { id: 'user-123', displayName: 'User', }, content: 'Message 1', }, { author: { id: 'other-123', displayName: 'Other', }, content: 'Message 2', }, ] as any as Message[]; const mockChannel = { isTextBased: () => true, messages: { fetch: jasmine.createSpy('fetch').and.returnValue( Promise.resolve(mockMessages) ), }, } as any as TextChannel; const result = await DyNTS_DiAs_Util.gatherMessages({ channel: mockChannel, userId: 'user-123', botClientId: 'bot-123', issuer: 'issuer-123', }); expect(result[0].content).toBe('**User** Message 1'); expect(result[1].content).toBe('**Other** Message 2'); }); it('| should throw DyFM_Error on fetch error', async () => { const mockChannel = { isTextBased: () => true, messages: { fetch: jasmine.createSpy('fetch').and.returnValue( Promise.reject(new Error('Fetch failed')) ), }, } as any as TextChannel; await expectAsync( DyNTS_DiAs_Util.gatherMessages({ channel: mockChannel, userId: 'user-123', botClientId: 'bot-123', issuer: 'issuer-123', }) ).toBeRejected(); }); }); });