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
20 changes: 20 additions & 0 deletions src/activities/discord/gateway/add-channelId.activity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { GatewayMessageCreateDispatchData } from 'discord-api-types/v10';
import { DatabaseManager, makeThreadRepository } from '@togethercrew.dev/db';

export async function getChannelIdFromThread(
data: GatewayMessageCreateDispatchData,
) {
Comment on lines +4 to +6
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add explicit return type and parameter validation.

The function should have an explicit return type and validate required parameters.

-export async function getChannelIdFromThread(
-  data: GatewayMessageCreateDispatchData,
-) {
+export async function getChannelIdFromThread(
+  data: GatewayMessageCreateDispatchData,
+): Promise<string> {
+  if (!data.guild_id || !data.channel_id) {
+    throw new Error('Missing required guild_id or channel_id');
+  }
📝 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
export async function getChannelIdFromThread(
data: GatewayMessageCreateDispatchData,
) {
export async function getChannelIdFromThread(
data: GatewayMessageCreateDispatchData,
): Promise<string> {
if (!data.guild_id || !data.channel_id) {
throw new Error('Missing required guild_id or channel_id');
}
// …rest of implementation unchanged
🤖 Prompt for AI Agents
In src/activities/discord/gateway/add-channelId.activity.ts around lines 4 to 6,
the function getChannelIdFromThread lacks an explicit return type and does not
validate its input parameter. Add an explicit return type that matches the
expected output of the function. Also, include validation logic to check that
the required properties exist on the data parameter before processing, and
handle cases where the input is invalid by returning an appropriate value or
throwing an error.

try {
let channelId: string;
const dbConnection = await DatabaseManager.getInstance().getGuildDb(
data.guild_id,
);
const threadRepository = makeThreadRepository(dbConnection);
channelId = (await threadRepository.findOne({ id: data.channel_id }))
.parent_id;
Comment on lines +8 to +14
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential null pointer exception and improve error handling.

The code doesn't handle the case where the thread is not found in the database, which will cause a runtime error when trying to access .parent_id on null/undefined.

-  try {
-    let channelId: string;
-    const dbConnection = await DatabaseManager.getInstance().getGuildDb(
-      data.guild_id,
-    );
-    const threadRepository = makeThreadRepository(dbConnection);
-    channelId = (await threadRepository.findOne({ id: data.channel_id }))
-      .parent_id;
-    return channelId;
+  try {
+    const dbConnection = await DatabaseManager.getInstance().getGuildDb(
+      data.guild_id,
+    );
+    const threadRepository = makeThreadRepository(dbConnection);
+    const thread = await threadRepository.findOne({ id: data.channel_id });
+    
+    if (!thread) {
+      throw new Error(`Thread not found: ${data.channel_id}`);
+    }
+    
+    if (!thread.parent_id) {
+      throw new Error(`Thread ${data.channel_id} has no parent channel`);
+    }
+    
+    return thread.parent_id;
📝 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
let channelId: string;
const dbConnection = await DatabaseManager.getInstance().getGuildDb(
data.guild_id,
);
const threadRepository = makeThreadRepository(dbConnection);
channelId = (await threadRepository.findOne({ id: data.channel_id }))
.parent_id;
const dbConnection = await DatabaseManager.getInstance().getGuildDb(
data.guild_id,
);
const threadRepository = makeThreadRepository(dbConnection);
const thread = await threadRepository.findOne({ id: data.channel_id });
if (!thread) {
throw new Error(`Thread not found: ${data.channel_id}`);
}
if (!thread.parent_id) {
throw new Error(`Thread ${data.channel_id} has no parent channel`);
}
return thread.parent_id;
🤖 Prompt for AI Agents
In src/activities/discord/gateway/add-channelId.activity.ts around lines 8 to
14, the code assigns channelId from the parent_id of a thread fetched from the
database without checking if the thread exists. To fix this, add a null check
after fetching the thread; if the thread is null or undefined, handle the error
appropriately (e.g., throw an error or return early) before accessing parent_id
to prevent a runtime null pointer exception.

return channelId;
} catch (error) {
console.error('Error in getChannelIdFromThread:', error);
throw error;
}
Comment on lines +16 to +19
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use proper logging instead of console.error.

Consistent with other parts of the codebase, use a proper logger instead of console.error.

+import parentLogger from '../../../config/logger.config';
+
+const logger = parentLogger.child({ activity: 'discord:gateway:add-channelId' });

  } catch (error) {
-    console.error('Error in getChannelIdFromThread:', error);
+    logger.error({ error, guildId: data.guild_id, channelId: data.channel_id }, 'Failed to get channel ID from thread');
     throw error;
   }
📝 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
} catch (error) {
console.error('Error in getChannelIdFromThread:', error);
throw error;
}
import parentLogger from '../../../config/logger.config';
const logger = parentLogger.child({ activity: 'discord:gateway:add-channelId' });
// … other code …
} catch (error) {
logger.error(
{ error, guildId: data.guild_id, channelId: data.channel_id },
'Failed to get channel ID from thread'
);
throw error;
}
🤖 Prompt for AI Agents
In src/activities/discord/gateway/add-channelId.activity.ts around lines 16 to
19, replace the use of console.error with the project's standard logging utility
to maintain consistency. Import the appropriate logger if not already imported,
then use it to log the error instead of console.error, ensuring the log message
includes the error details clearly.

}
1 change: 1 addition & 0 deletions src/activities/discord/gateway/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './channelSelection.activity';
export * from './ignoreUser.activity';
export * from './mapping.activity';
export * from './persistence.activity';
export * from './add-channelId.activity';
31 changes: 21 additions & 10 deletions src/activities/discord/gateway/mapping.activity.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
import {
GatewayChannelCreateDispatchData, GatewayChannelDeleteDispatchData,
GatewayChannelUpdateDispatchData, GatewayGuildMemberAddDispatchData,
GatewayGuildMemberRemoveDispatchData, GatewayGuildMemberUpdateDispatchData,
GatewayGuildRoleCreateDispatchData, GatewayGuildRoleDeleteDispatchData,
GatewayGuildRoleUpdateDispatchData, GatewayMessageCreateDispatchData,
GatewayMessageDeleteBulkDispatchData, GatewayMessageDeleteDispatchData,
GatewayMessageReactionAddDispatchData, GatewayMessageReactionRemoveAllDispatchData,
GatewayMessageReactionRemoveDispatchData, GatewayMessageReactionRemoveEmojiDispatchData,
GatewayMessageUpdateDispatchData
GatewayChannelCreateDispatchData,
GatewayChannelDeleteDispatchData,
GatewayChannelUpdateDispatchData,
GatewayGuildMemberAddDispatchData,
GatewayGuildMemberRemoveDispatchData,
GatewayGuildMemberUpdateDispatchData,
GatewayGuildRoleCreateDispatchData,
GatewayGuildRoleDeleteDispatchData,
GatewayGuildRoleUpdateDispatchData,
GatewayMessageCreateDispatchData,
GatewayMessageDeleteBulkDispatchData,
GatewayMessageDeleteDispatchData,
GatewayMessageReactionAddDispatchData,
GatewayMessageReactionRemoveAllDispatchData,
GatewayMessageReactionRemoveDispatchData,
GatewayMessageReactionRemoveEmojiDispatchData,
GatewayMessageUpdateDispatchData,
} from 'discord-api-types/v10';

import { IRawInfo } from '@togethercrew.dev/db';

import parentLogger from '../../../config/logger.config';
import {
ChannelMappers, GuildMemberMappers, MessageMappers, RoleMappers
ChannelMappers,
GuildMemberMappers,
MessageMappers,
RoleMappers,
} from '../../../workflows/discord/gateway/mappers';

const logger = parentLogger.child({ activity: 'discord:event:map' });
Expand Down
21 changes: 17 additions & 4 deletions src/activities/discord/gateway/persistence.activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@ import { Snowflake } from 'discord.js';
import { FilterQuery } from 'mongoose';

import {
DatabaseManager, IChannel, IChannelUpdateBody, IGuildMember, IGuildMemberUpdateBody, IRawInfo,
IRawInfoUpdateBody, IRole, IRoleUpdateBody, IThread, makeChannelRepository,
makeGuildMemberRepository, makeRawInfoRepository, makeRoleRepository, makeThreadRepository,
ThreadUpdateBody
DatabaseManager,
IChannel,
IChannelUpdateBody,
IGuildMember,
IGuildMemberUpdateBody,
IRawInfo,
IRawInfoUpdateBody,
IRole,
IRoleUpdateBody,
IThread,
makeChannelRepository,
makeGuildMemberRepository,
makeRawInfoRepository,
makeRoleRepository,
makeThreadRepository,
ThreadUpdateBody,
} from '@togethercrew.dev/db';

import parentLogger from '../../../config/logger.config';
Expand Down Expand Up @@ -138,6 +150,7 @@ export async function createRawInfo(
data: IRawInfo,
): Promise<void> {
try {
console.log('Creating raw info', data);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace console.log with proper logging.

Using console.log in production code is not recommended. Use the existing logger instead for consistency and proper log management.

-    console.log('Creating raw info', data);
+    logger.debug({ guildId, data }, 'Creating raw info');
📝 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
console.log('Creating raw info', data);
- console.log('Creating raw info', data);
+ logger.debug({ guildId, data }, 'Creating raw info');
🤖 Prompt for AI Agents
In src/activities/discord/gateway/persistence.activity.ts at line 153, replace
the console.log statement with the existing logger instance used in the project.
Use the appropriate logging method (e.g., logger.info or logger.debug) to log
the message 'Creating raw info' along with the data object, ensuring consistent
and manageable logging across the codebase.

const dbConnection =
await DatabaseManager.getInstance().getGuildDb(guildId);
const repository = makeRawInfoRepository(dbConnection);
Expand Down
10 changes: 8 additions & 2 deletions src/examples/client/discordGateway.example.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { GatewayDispatchEvents, GatewayDispatchPayload } from 'discord-api-types/v10';
import {
GatewayDispatchEvents,
GatewayDispatchPayload,
} from 'discord-api-types/v10';
import { IntentsBitField } from 'discord.js';

import { REST } from '@discordjs/rest';
import { WebSocketManager, WebSocketShardEvents } from '@discordjs/ws';
import { Client as TemporalClient, Connection as TemporalConnection } from '@temporalio/client';
import {
Client as TemporalClient,
Connection as TemporalConnection,
} from '@temporalio/client';

import { DiscordGatewayEventWorkflow } from '../../workflows/discord/gateway';

Expand Down
21 changes: 5 additions & 16 deletions src/libs/telegram/helpers/transformTelegramChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,10 @@ const commonOptionalDict = [
];

// Private chat specific fields
const privateChatOptionalDict = [
'chat_photo',
'chat_shared',
];
const privateChatOptionalDict = ['chat_photo', 'chat_shared'];

// Group chat specific fields
const groupChatOptionalDict = [
'chat_photo',
'chat_shared',
];
const groupChatOptionalDict = ['chat_photo', 'chat_shared'];

// Supergroup specific fields
const supergroupOptionalDict = [
Expand All @@ -71,14 +65,9 @@ const supergroupOptionalDict = [
];

// Channel specific fields
const channelOptionalDict = [
'chat_photo',
'chat_shared',
];
const channelOptionalDict = ['chat_photo', 'chat_shared'];

export function transformTelegramChat(
chat: Chat,
): Record<string, any> {
export function transformTelegramChat(chat: Chat): Record<string, any> {
// Make a shallow copy of the chat
const obj: Record<string, any> = { ...chat };

Expand Down Expand Up @@ -112,4 +101,4 @@ export function transformTelegramChat(
});

return obj;
}
}
4 changes: 3 additions & 1 deletion src/libs/telegram/services/chat.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ class ChatService {
if (tx) {
tx.run(CREATE_OR_UPDATE_CHAT, { chat: transformTelegramChat(chat) });
} else {
await neo4jService.run(CREATE_OR_UPDATE_CHAT, { chat: transformTelegramChat(chat) });
await neo4jService.run(CREATE_OR_UPDATE_CHAT, {
chat: transformTelegramChat(chat),
});
}
}

Expand Down
31 changes: 26 additions & 5 deletions src/workflows/discord/gateway/handlers/message.handler.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import {
GatewayMessageCreateDispatchData, GatewayMessageDeleteBulkDispatchData,
GatewayMessageDeleteDispatchData, GatewayMessageReactionAddDispatchData,
GatewayMessageReactionRemoveAllDispatchData, GatewayMessageReactionRemoveDispatchData,
GatewayMessageReactionRemoveEmojiDispatchData, GatewayMessageUpdateDispatchData
GatewayMessageCreateDispatchData,
GatewayMessageDeleteBulkDispatchData,
GatewayMessageDeleteDispatchData,
GatewayMessageReactionAddDispatchData,
GatewayMessageReactionRemoveAllDispatchData,
GatewayMessageReactionRemoveDispatchData,
GatewayMessageReactionRemoveEmojiDispatchData,
GatewayMessageUpdateDispatchData,
} from 'discord-api-types/v10';

import { proxyActivities } from '@temporalio/workflow';

import type * as Activities from '../../../../activities';
import {
DatabaseManager,
makeChannelRepository,
makeRawInfoRepository,
makeThreadRepository,
} from '@togethercrew.dev/db';
Comment on lines +15 to +20
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove unused imports.

These database-related imports are not used anywhere in the file and should be removed to avoid confusion.

-import {
-  DatabaseManager,
-  makeChannelRepository,
-  makeRawInfoRepository,
-  makeThreadRepository,
-} from '@togethercrew.dev/db';
📝 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
import {
DatabaseManager,
makeChannelRepository,
makeRawInfoRepository,
makeThreadRepository,
} from '@togethercrew.dev/db';
🤖 Prompt for AI Agents
In src/workflows/discord/gateway/handlers/message.handler.ts between lines 15
and 20, remove the imports DatabaseManager, makeChannelRepository,
makeRawInfoRepository, and makeThreadRepository from '@togethercrew.dev/db' as
they are not used anywhere in the file and only add unnecessary clutter.


const activities = proxyActivities<typeof Activities>({
startToCloseTimeout: '1 minute',
Expand All @@ -28,8 +38,18 @@ export class MessageHandler {
static async create(data: GatewayMessageCreateDispatchData) {
if (!(await guardMessage(data.guild_id, data.channel_id, data.author.id)))
return;

const mapped = await activities.mapMessageCreate(data);
// TODO: Need to remove this section
const tempData: any = data;
const isThreadMessage =
tempData.channel_type === 10 ||
tempData.channel_type === 11 ||
tempData.channel_type === 12;
if (isThreadMessage) {
const channelId = await activities.getChannelIdFromThread(data);
mapped.channelId = channelId;
}
// TODO: Until Here
Comment on lines +42 to +52
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve type safety and use constants for channel types.

The current implementation has several issues: type casting to any, hard-coded magic numbers, and no error handling for the async call.

+// Discord channel types constants
+const DISCORD_CHANNEL_TYPES = {
+  GUILD_PUBLIC_THREAD: 11,
+  GUILD_PRIVATE_THREAD: 12,
+  GUILD_NEWS_THREAD: 10,
+} as const;

-    // TODO: Need to remove this section
-    const tempData: any = data;
-    const isThreadMessage =
-      tempData.channel_type === 10 ||
-      tempData.channel_type === 11 ||
-      tempData.channel_type === 12;
-    if (isThreadMessage) {
-      const channelId = await activities.getChannelIdFromThread(data);
-      mapped.channelId = channelId;
-    }
-    // TODO: Until Here
+    // TODO: Need to remove this section
+    const isThreadMessage =
+      'channel_type' in data && (
+        data.channel_type === DISCORD_CHANNEL_TYPES.GUILD_NEWS_THREAD ||
+        data.channel_type === DISCORD_CHANNEL_TYPES.GUILD_PUBLIC_THREAD ||
+        data.channel_type === DISCORD_CHANNEL_TYPES.GUILD_PRIVATE_THREAD
+      );
+    if (isThreadMessage) {
+      try {
+        const channelId = await activities.getChannelIdFromThread(data);
+        mapped.channelId = channelId;
+      } catch (error) {
+        // Log error but don't fail the entire operation
+        console.error('Failed to get channel ID from thread:', error);
+      }
+    }
+    // TODO: Until Here
📝 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
// TODO: Need to remove this section
const tempData: any = data;
const isThreadMessage =
tempData.channel_type === 10 ||
tempData.channel_type === 11 ||
tempData.channel_type === 12;
if (isThreadMessage) {
const channelId = await activities.getChannelIdFromThread(data);
mapped.channelId = channelId;
}
// TODO: Until Here
// Discord channel types constants
const DISCORD_CHANNEL_TYPES = {
GUILD_PUBLIC_THREAD: 11,
GUILD_PRIVATE_THREAD: 12,
GUILD_NEWS_THREAD: 10,
} as const;
// TODO: Need to remove this section
const isThreadMessage =
'channel_type' in data && (
data.channel_type === DISCORD_CHANNEL_TYPES.GUILD_NEWS_THREAD ||
data.channel_type === DISCORD_CHANNEL_TYPES.GUILD_PUBLIC_THREAD ||
data.channel_type === DISCORD_CHANNEL_TYPES.GUILD_PRIVATE_THREAD
);
if (isThreadMessage) {
try {
const channelId = await activities.getChannelIdFromThread(data);
mapped.channelId = channelId;
} catch (error) {
// Log error but don't fail the entire operation
console.error('Failed to get channel ID from thread:', error);
}
}
// TODO: Until Here
🤖 Prompt for AI Agents
In src/workflows/discord/gateway/handlers/message.handler.ts around lines 42 to
52, replace the use of 'any' type casting with proper typing for the data
object, define and use named constants or enums for the channel_type values
instead of hard-coded numbers 10, 11, and 12, and add error handling for the
asynchronous call to activities.getChannelIdFromThread to handle potential
failures gracefully.

await activities.createRawInfo(data.guild_id, mapped);
}

Expand All @@ -38,6 +58,7 @@ export class MessageHandler {
return;

const mapped = await activities.mapMessageUpdate(data);

await activities.updateRawInfo(
data.guild_id,
{ messageId: data.id },
Expand Down
5 changes: 3 additions & 2 deletions src/workflows/discord/gateway/handlers/thread.handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
GatewayThreadCreateDispatchData, GatewayThreadDeleteDispatchData,
GatewayThreadUpdateDispatchData
GatewayThreadCreateDispatchData,
GatewayThreadDeleteDispatchData,
GatewayThreadUpdateDispatchData,
} from 'discord-api-types/v10';

import { proxyActivities } from '@temporalio/workflow';
Expand Down
8 changes: 5 additions & 3 deletions src/workflows/discord/gateway/mappers/message.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
GatewayMessageReactionAddDispatchData, GatewayMessageReactionRemoveAllDispatchData,
GatewayMessageReactionRemoveDispatchData, GatewayMessageReactionRemoveEmojiDispatchData,
GatewayMessageUpdateDispatchData
GatewayMessageReactionAddDispatchData,
GatewayMessageReactionRemoveAllDispatchData,
GatewayMessageReactionRemoveDispatchData,
GatewayMessageReactionRemoveEmojiDispatchData,
GatewayMessageUpdateDispatchData,
} from 'discord-api-types/v10';

import { IRawInfo, IRawInfoUpdateBody } from '@togethercrew.dev/db';
Expand Down
2 changes: 1 addition & 1 deletion src/workflows/telegram/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export { TelegramVerifyWorkflow } from './TelegramVerifyWorkflow';
export { TelegramEventWorkflow } from './TelegramEventWorkflow';
export { TelegramQuestionWorkflow } from './TelegramQuestionWorkflow';
export { TelegramSummaryWorkflow } from './TelegramSummaryWorkflow';
export { TelegramVectorIngestionWorkflow } from './TelegramVectorIngestionWorkflow';
export { TelegramVectorIngestionWorkflow } from './TelegramVectorIngestionWorkflow';