-
Notifications
You must be signed in to change notification settings - Fork 1
Testingbranch #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ith API reference and WebSocket event details.
|
Warning Rate limit exceeded@Coder-soft has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 13 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughRebrands to "Holo Bridge"; adds comprehensive static documentation (pages + stylesheet + llms.txt); expands Discord serializers and public Discord types; introduces many new Discord event handlers and payload types; adds poll gateway intents and updates startup log text. All changes are additive. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@greptile review pls |
Greptile OverviewGreptile SummaryThis PR rebrands the project from "Discord Web Bridge" to "Holo Bridge" and significantly expands Discord event coverage from basic events to 45+ comprehensive event types including polls, automod, scheduled events, stage instances, and entitlements. Major Changes:
Issues Found:
Confidence Score: 4/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant Discord as Discord Gateway
participant Client as Discord Client
participant Events as Event Handlers
participant Serializers as Serializers
participant Broadcast as Socket.IO
participant WebClient as Web Clients
Discord->>Client: Event (messageCreate, etc.)
Client->>Events: Trigger event handler
Events->>Serializers: Serialize Discord objects
Serializers-->>Events: JSON-safe data
Events->>Events: Create event payload
Events->>Broadcast: broadcastEvent(payload)
alt Guild-specific event
Broadcast->>WebClient: Emit to guild:${guildId} room
else Global/DM event
Broadcast->>WebClient: Emit to all clients
end
Note over WebClient: Receives 'discord' event
Note over Events: 45+ event types supported
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9 files reviewed, 2 comments
| <a href="https://github.com" class="card" target="_blank"> | ||
| <h4>💻 Source Code</h4> | ||
| <p>View the source code on GitHub.</p> | ||
| </a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Link points to generic https://github.com instead of the actual repository
| <a href="https://github.com" class="card" target="_blank"> | |
| <h4>💻 Source Code</h4> | |
| <p>View the source code on GitHub.</p> | |
| </a> | |
| <a href="https://github.com/coder-soft/holobridge" class="card" target="_blank"> | |
| <h4>💻 Source Code</h4> | |
| <p>View the source code on GitHub.</p> | |
| </a> |
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/index.html
Line: 74:77
Comment:
**style:** Link points to generic `https://github.com` instead of the actual repository
```suggestion
<a href="https://github.com/coder-soft/holobridge" class="card" target="_blank">
<h4>💻 Source Code</h4>
<p>View the source code on GitHub.</p>
</a>
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (5)
README.md (1)
1-1: Branding + docs link look good; consider adding a one‑liner about what’s at the docs URLThe rename to “Holo Bridge” and the new documentation link are consistent and helpful. You might optionally add a short description (e.g., “full API reference and getting‑started guide”) next to the link so readers know what to expect without clicking.
Also applies to: 106-108
.env.example (1)
1-1: Env header rename is fine; optionally remind users about secret safetyThe header now matches the Holo Bridge branding, which is good. You might optionally add a brief comment below it like “Do not commit this file with real tokens/API keys” to nudge users toward safe handling of secrets.
llms.txt (1)
21-76: Align path parameter names with the HTML API reference for clarityThe endpoint list is solid, but here you use generic
:idin several routes (e.g.,/api/guilds/:id,/api/guilds/:id/roles) whiledocs/api-reference.htmlstandardizes on:guildId,:roleId, etc. For humans and LLMs this small mismatch can be confusing.I’d recommend updating llms.txt to match the more explicit parameter names from the HTML docs (e.g.,
:guildId,:channelId,:roleId) so all documentation tells the same story.docs/index.html (1)
74-77: Point “Source Code” to this repository instead of the GitHub rootThe docs page looks good. For the “💻 Source Code” card, consider updating the href from
https://github.comto this project’s repo URL (e.g.,https://github.com/Coder-soft/HoloBridge) so users land directly on the right codebase.docs/getting-started.html (1)
21-21: Add accessible label to theme toggle button.The theme toggle button lacks descriptive text or an
aria-labelfor screen readers, making it unclear what the button does to users with assistive technologies.- <button class="theme-toggle" onclick="toggleTheme()">Toggle Theme</button> + <button class="theme-toggle" onclick="toggleTheme()" aria-label="Toggle between light and dark theme">🌙</button>Alternatively, you can add a tooltip or visible text alongside the button to improve discoverability for all users.
Also applies to: 164-179
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
.env.example(1 hunks)README.md(2 hunks)docs/api-reference.html(1 hunks)docs/getting-started.html(1 hunks)docs/index.html(1 hunks)docs/styles.css(1 hunks)docs/websocket.html(1 hunks)llms.txt(1 hunks)src/index.ts(2 hunks)
🔇 Additional comments (3)
src/index.ts (1)
6-7: Startup log renaming is consistent and safeOnly user‑facing messages were updated to “Holo Bridge”; behavior and error handling stay the same. Looks good.
Also applies to: 23-25
docs/styles.css (1)
1-498: Theme and docs styling are cohesive with no obvious issuesThe light/dark theme variables, layout, and docs‑specific components (cards, sidebar, tables, alerts) are structured cleanly and line up with how the HTML pages use them. I don’t see any functional or structural CSS problems here.
docs/api-reference.html (1)
26-773: API reference is accurate and fully synchronized with route implementationsAll documented endpoints—including threads (create, list, archive, lock), bulk delete, role permissions, and member moderation (kick, ban, unban, timeout)—are correctly implemented and match the documentation. No drift detected.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
docs/getting-started.html (1)
39-41: Add<pre><code>wrapper for consistency with other code examples.The git clone commands on lines 40-41 are missing the
<pre><code>wrapper, while all other code examples in the document (npm install, npm run commands, etc.) use it. This inconsistency affects styling and readability.<h3>1. Clone the Repository</h3> + <pre><code>git clone https://github.com/coder-soft/holobridge.git -git clone https://github.com/coder-soft/holobridge.git -cd holobridge +cd holobridge</code></pre>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
docs/getting-started.html(1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.30.0)
docs/getting-started.html
[high] 139-141: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
🔇 Additional comments (1)
docs/getting-started.html (1)
139-141: Clarify placeholder in curl documentation example.Static analysis flagged this curl command as containing a potential authorization token. This is a false positive—
your_api_keyis clearly a placeholder for documentation purposes. To further signal this is an example, consider adding a comment in the example or using a more explicit placeholder name if desired, though the current form is acceptable and conventional for documentation.
…efinitions and documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
docs/websocket.html(1 hunks)src/discord/events/index.ts(1 hunks)src/types/events.types.ts(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/types/events.types.ts (1)
src/types/discord.types.ts (1)
SerializedChannel(50-63)
src/discord/events/index.ts (2)
src/discord/client.ts (1)
discordClient(9-44)src/discord/serializers.ts (1)
serializeChannel(116-146)
🔇 Additional comments (5)
docs/websocket.html (1)
322-392: Thread events documentation is now accurate and complete!The previous critical issue regarding undocumented/unimplemented thread events has been resolved. The documentation now correctly describes the four thread events (
threadCreate,threadUpdate,threadDelete,threadMembersUpdate) that are implemented insrc/discord/events/index.ts, and the data shapes match the type definitions insrc/types/events.types.ts.The examples are clear and accurate:
- Thread create includes
threadandnewlyCreatedflag- Thread update shows
oldandnewstructure- Thread delete provides essential identifiers
- Thread members update correctly documents the member tracking structure
src/types/events.types.ts (2)
181-225: Well-defined thread event payload types.The four new thread event interfaces are correctly structured and align perfectly with the implementation in
src/discord/events/index.ts:
- Consistent with existing event payload patterns
- Appropriate nullable types for
oldvalues and optional fields- Thread-specific data structures properly capture Discord.js thread event details
332-335: Union type correctly extended.The
DiscordEventPayloadunion properly includes all four new thread event types, maintaining type safety for WebSocket event broadcasting.src/discord/events/index.ts (2)
220-254: Thread create, update, and delete handlers are well-implemented.The three handlers correctly:
- Follow the established event broadcasting pattern
- Use
serializeChannelto transform Discord.js thread objects- Handle partial objects appropriately in
threadUpdate- Extract relevant fields in
threadDeletefor deleted threads
218-272: Thread event handlers successfully implemented.All four thread event handlers are now registered and broadcasting events correctly. This resolves the documentation inconsistency flagged in the previous review of
docs/websocket.html.
| discordClient.on('threadMembersUpdate', (addedMembers, removedMembers, thread) => { | ||
| broadcastEvent({ | ||
| event: 'threadMembersUpdate', | ||
| guildId: thread.guildId, | ||
| data: { | ||
| threadId: thread.id, | ||
| guildId: thread.guildId, | ||
| addedMembers: addedMembers.map((m) => ({ | ||
| id: m.id, | ||
| threadId: m.thread?.id ?? thread.id, | ||
| joinedAt: m.joinTimestamp ? new Date(m.joinTimestamp).toISOString() : new Date().toISOString(), | ||
| })), | ||
| removedMemberIds: removedMembers.map((m) => m.id), | ||
| memberCount: thread.memberCount ?? 0, | ||
| }, | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider more explicit handling for missing joinTimestamp.
Line 266 uses new Date() as a fallback when m.joinTimestamp is falsy, which could create misleading timestamps that don't reflect when members actually joined the thread. Consider whether it's better to use null or a sentinel value to indicate unknown join times, or verify that joinTimestamp is always present in Discord.js ThreadMember objects.
- joinedAt: m.joinTimestamp ? new Date(m.joinTimestamp).toISOString() : new Date().toISOString(),
+ joinedAt: new Date(m.joinTimestamp ?? Date.now()).toISOString(),Alternatively, if joinTimestamp can genuinely be null/undefined, document this behavior or make joinedAt nullable in the type definition.
📝 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.
| discordClient.on('threadMembersUpdate', (addedMembers, removedMembers, thread) => { | |
| broadcastEvent({ | |
| event: 'threadMembersUpdate', | |
| guildId: thread.guildId, | |
| data: { | |
| threadId: thread.id, | |
| guildId: thread.guildId, | |
| addedMembers: addedMembers.map((m) => ({ | |
| id: m.id, | |
| threadId: m.thread?.id ?? thread.id, | |
| joinedAt: m.joinTimestamp ? new Date(m.joinTimestamp).toISOString() : new Date().toISOString(), | |
| })), | |
| removedMemberIds: removedMembers.map((m) => m.id), | |
| memberCount: thread.memberCount ?? 0, | |
| }, | |
| }); | |
| }); | |
| discordClient.on('threadMembersUpdate', (addedMembers, removedMembers, thread) => { | |
| broadcastEvent({ | |
| event: 'threadMembersUpdate', | |
| guildId: thread.guildId, | |
| data: { | |
| threadId: thread.id, | |
| guildId: thread.guildId, | |
| addedMembers: addedMembers.map((m) => ({ | |
| id: m.id, | |
| threadId: m.thread?.id ?? thread.id, | |
| joinedAt: new Date(m.joinTimestamp ?? Date.now()).toISOString(), | |
| })), | |
| removedMemberIds: removedMembers.map((m) => m.id), | |
| memberCount: thread.memberCount ?? 0, | |
| }, | |
| }); | |
| }); |
🤖 Prompt for AI Agents
In src/discord/events/index.ts around lines 256 to 272, the current fallback for
missing m.joinTimestamp uses new Date(), producing misleading "now" timestamps;
change the emitted joinedAt to be nullable (e.g., joinedAt: m.joinTimestamp ?
new Date(m.joinTimestamp).toISOString() : null) and update any related
TypeScript types/DTOs and documentation to accept null for joinedAt (or choose a
clear sentinel), or alternatively validate that ThreadMember.joinTimestamp is
always present before emitting and omit the field when unknown.
…ocket.IO event broadcasting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
src/discord/events/index.ts (1)
364-380: Consider more explicit handling for missing joinTimestamp.Line 374 uses
new Date().toISOString()as a fallback whenm.joinedTimestampis falsy, which could create misleading timestamps that don't reflect when members actually joined the thread.This was flagged in a previous review. Consider using
nullfor unknown join times or verifying thatjoinedTimestampis always present in Discord.jsThreadMemberobjects.
🧹 Nitpick comments (6)
src/discord/events/index.ts (2)
597-619: Scheduled event handlers use type assertions that may mask type errors.The
as anycasts on lines 600, 607, and 617 bypass TypeScript's type checking. If the event object is partial and missing required fields,serializeScheduledEventmay throw or produce incorrect output.Consider adding explicit partial checks similar to other handlers:
discordClient.on('guildScheduledEventDelete', (event) => { - // event may be partial, but we still want to broadcast the deletion + if (event.partial) { + // For partial events, emit minimal deletion info + broadcastEvent({ + event: 'guildScheduledEventDelete', + guildId: event.guildId, + data: { id: event.id, guildId: event.guildId, partial: true }, + }); + return; + } broadcastEvent({ event: 'guildScheduledEventDelete', guildId: event.guildId, - data: serializeScheduledEvent(event as any), + data: serializeScheduledEvent(event), }); });
739-753: Entitlement update handler discards old entitlement data.Unlike other update handlers that emit
{ old, new }structure,entitlementUpdateonly serializesnewEntitlement. This inconsistency may confuse consumers expecting the standard update payload format.For consistency with other update events:
discordClient.on('entitlementUpdate', (oldEntitlement, newEntitlement) => { broadcastEvent({ event: 'entitlementUpdate', guildId: newEntitlement.guildId, - data: serializeEntitlement(newEntitlement), + data: { + old: oldEntitlement ? serializeEntitlement(oldEntitlement) : null, + new: serializeEntitlement(newEntitlement), + }, }); });src/discord/serializers.ts (3)
320-343: Imports placed mid-file break conventional module structure.The additional imports are added after existing code (line 320-343) rather than at the top of the file with other imports. This works in TypeScript but deviates from standard conventions.
Consider moving these imports to the top of the file with the existing imports for better organization:
import { Guild, GuildMember, User, // ... existing imports + Sticker, + GuildScheduledEvent, + AutoModerationRule, + // ... new imports } from 'discord.js';
450-450: Fallback to current date may produce misleading timestamps.Lines 450 and 464 use
new Date().toISOString()whenscheduledStartAtorcreatedAtis undefined. This could create confusing data where timestamps don't reflect actual Discord values.Consider using
nullto explicitly indicate missing data:-scheduledStartTime: event.scheduledStartAt?.toISOString() ?? new Date().toISOString(), +scheduledStartTime: event.scheduledStartAt?.toISOString() ?? null, // ... -createdAt: event.createdAt?.toISOString() ?? new Date().toISOString(), +createdAt: event.createdAt?.toISOString() ?? null,Note: This would require updating
SerializedScheduledEvent.scheduledStartTimeandcreatedAttypes to acceptstring | null.Also applies to: 464-464
631-645: Entitlement createdAt uses synthetic current timestamp.Line 643 assigns
new Date().toISOString()with a comment noting "Entitlement doesn't have createdAt directly". This synthetic timestamp doesn't reflect when the entitlement was actually created.Consider either:
- Using
nullto indicate the value isn't available- Using the entitlement's
startsAtas a proxy if appropriate- Documenting this behavior clearly in the type definition
-createdAt: new Date().toISOString(), // Entitlement doesn't have createdAt directly +createdAt: entitlement.startsAt?.toISOString() ?? null, // No direct createdAt availablesrc/types/events.types.ts (1)
336-350: Consider whetherguildIdin nested data should be non-nullable.The
data.guildIdis typed asstring(non-nullable) while the top-levelguildIdisstring | null. Thread member updates only occur in guild contexts, so the nestedguildId: stringis correct, but the top-levelguildIdcould also bestringfor consistency.This is a minor inconsistency that doesn't affect functionality since thread member updates are guild-only events.
export interface ThreadMembersUpdateEvent { event: 'threadMembersUpdate'; - guildId: string | null; + guildId: string; data: { threadId: string; guildId: string;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
docs/websocket.html(1 hunks)src/discord/client.ts(1 hunks)src/discord/events/index.ts(7 hunks)src/discord/serializers.ts(1 hunks)src/types/discord.types.ts(1 hunks)src/types/events.types.ts(10 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/discord/events/index.ts (1)
src/discord/serializers.ts (12)
serializeUser(67-79)serializeChannel(116-146)serializeAuditLogEntry(555-578)serializeGuildEmoji(429-439)serializeSticker(410-427)serializeStageInstance(524-535)serializeScheduledEvent(441-466)serializeAutoModRule(468-498)serializeAutoModAction(500-522)serializeInteraction(580-629)serializeInvite(537-553)serializeEntitlement(631-645)
src/discord/serializers.ts (1)
src/types/discord.types.ts (11)
SerializedSticker(222-237)SerializedEmoji(65-73)SerializedScheduledEvent(243-266)SerializedAutoModRule(272-300)SerializedAutoModAction(302-322)SerializedStageInstance(328-337)SerializedInvite(343-357)SerializedAuditLogEntry(363-379)SerializedInteraction(385-405)SerializedEntitlement(435-447)SerializedWebhook(453-468)
src/types/events.types.ts (1)
src/types/discord.types.ts (12)
SerializedUser(7-17)SerializedChannel(50-63)SerializedAuditLogEntry(363-379)SerializedEmoji(65-73)SerializedSticker(222-237)SerializedStageInstance(328-337)SerializedScheduledEvent(243-266)SerializedAutoModRule(272-300)SerializedAutoModAction(302-322)SerializedInteraction(385-405)SerializedInvite(343-357)SerializedEntitlement(435-447)
🔇 Additional comments (13)
src/discord/events/index.ts (2)
259-270: User update handler correctly handles partial old user.The
userUpdateevent appropriately checks for partial state before serializing the old user, and correctly setsguildId: nullsince this is a global user update event.
13-23: Event handler registration is comprehensive and well-structured.The expanded imports and 45+ event handlers are properly organized by category with clear section comments. The registration message accurately reflects the scope of coverage.
Also applies to: 755-755
src/types/discord.types.ts (2)
385-405: SerializedInteraction includes sensitive token field.The
tokenfield on line 393 allows responding to Discord interactions. Including this in a serialized type intended for API responses could pose security risks if exposed to unauthorized clients.Verify that interaction payloads are only sent to authorized, trusted clients and consider whether the token should be included or redacted.
217-468: New serialized types are well-designed and comprehensive.The type definitions properly handle:
- Nullable fields with
| null- Human-readable name fields alongside numeric enum values
- Nested object structures for metadata
- Consistent field naming conventions
src/discord/serializers.ts (1)
410-439: New serializers are well-implemented with proper null handling.The serializers for stickers, emoji, automod rules/actions, stage instances, invites, and webhooks correctly:
- Handle optional/nullable fields
- Use spread operators to clone arrays (avoiding mutation)
- Include human-readable name fields via lookup maps
- Check for nested object existence before accessing properties
Also applies to: 468-522, 524-553, 647-676
docs/websocket.html (1)
1-944: Documentation accurately reflects all implemented WebSocket events.All 60 documented events are confirmed to exist in
src/discord/events/index.ts. The Socket.IO integration, event serialization, authentication, and subscription handling are properly implemented. The theme toggle functionality correctly manages localStorage persistence and system preference detection. No corrections needed.src/discord/client.ts (1)
35-37: Poll intents correctly added to enable poll events.The
GuildMessagePollsandDirectMessagePollsintents are required for receiving poll-related events (messagePollVoteAdd,messagePollVoteRemove), which aligns with the new poll event handlers added in this PR.src/types/events.types.ts (6)
1-21: LGTM!The imports are well-organized and all necessary serialized types are imported for the new event definitions. Each import corresponds to a type that's properly used in the new event interfaces.
167-210: LGTM!The new message event interfaces follow consistent patterns:
MessageReactionRemoveAllEventandMessageReactionRemoveEmojiEventcorrectly mirror Discord's gateway eventsMessagePollVoteAddEventandMessagePollVoteRemoveEventproperly typeanswerIdasnumber(matching Discord's poll answer ID type)- All events correctly use
guildId: string | nullto support DM contexts
249-256: LGTM!
UserUpdateEventcorrectly typesguildIdas literalnullrather thanstring | nullsince user updates are global events not tied to any specific guild. Theold/newpattern withPartial<SerializedUser> | nullis consistent with other update events.
676-752: LGTM!The
DiscordEventPayloadunion is complete and well-organized. All event interfaces are included and properly categorized with comments matching theDiscordEventTypeunion structure. This ensures type safety when handling Discord events.
27-102: LGTM!The
DiscordEventTypeunion is comprehensive and well-organized with clear category comments. All new Discord gateway events (polls, webhooks, audit logs, emojis, stickers, stage instances, scheduled events, auto-moderation, invites, and entitlements) are properly included.
660-664: Inconsistent entitlement update event pattern — unable to fix due to API limitation.
EntitlementUpdateEventdoesn't follow theold/newpattern used by other update events (EmojiUpdateEvent,StickerUpdateEvent,GuildScheduledEventUpdateEvent, etc.). However, Discord's API provides only the current entitlement object in update payloads, not the previous state. This inconsistency cannot be resolved without Discord API providing historical entitlement data. The type system correctly reflects the API's actual behavior.
| // ========== INTERACTION EVENT ========== | ||
|
|
||
| discordClient.on('interactionCreate', (interaction) => { | ||
| broadcastEvent({ | ||
| event: 'interactionCreate', | ||
| guildId: interaction.guildId, | ||
| data: serializeInteraction(interaction), | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interaction token exposed in serialized payload.
The serializeInteraction function includes the interaction token field, which is sensitive and could potentially be misused if exposed to unauthorized clients. Interaction tokens allow responding to interactions.
Consider omitting or redacting the token in the broadcast payload, or ensure only authorized clients receive this data:
// In serializeInteraction or when broadcasting
-token: interaction.token,
+token: '[REDACTED]', // Or omit entirelyCommittable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/discord/events/index.ts around lines 697 to 705, the serialized
interaction sent to broadcastEvent currently includes the interaction.token
which is sensitive; remove or redact the token from the payload by changing
serializeInteraction to exclude the token (or return a copy with token set to
null/'[REDACTED]') before broadcasting, or add a conditional so token is only
included when the recipient is explicitly authorized; ensure the broadcastEvent
call uses the sanitized object so no raw interaction.token is emitted.
| export function serializeAuditLogEntry(entry: GuildAuditLogsEntry): SerializedAuditLogEntry { | ||
| // Handle partial executor | ||
| let executorSerialized = null; | ||
| if (entry.executor && !('partial' in entry.executor && entry.executor.partial)) { | ||
| executorSerialized = serializeUser(entry.executor as any); | ||
| } | ||
| return { | ||
| id: entry.id, | ||
| guildId: entry.targetId ?? '', // Best effort | ||
| actionType: entry.action, | ||
| actionTypeName: AuditLogEvent[entry.action] ?? 'unknown', | ||
| targetId: entry.targetId, | ||
| executorId: entry.executorId, | ||
| executor: executorSerialized, | ||
| reason: entry.reason ?? null, | ||
| changes: entry.changes.map(change => ({ | ||
| key: change.key, | ||
| old: change.old, | ||
| new: change.new, | ||
| })), | ||
| extra: entry.extra, | ||
| createdAt: entry.createdAt.toISOString(), | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Audit log entry guildId fallback to targetId may be incorrect.
Line 563 uses entry.targetId ?? '' for guildId, but targetId is the ID of the target entity (user, channel, role, etc.), not the guild. This could produce incorrect guild associations.
The guildId should come from the guild context when the handler calls this serializer. Consider accepting it as a parameter:
-export function serializeAuditLogEntry(entry: GuildAuditLogsEntry): SerializedAuditLogEntry {
+export function serializeAuditLogEntry(entry: GuildAuditLogsEntry, guildId: string): SerializedAuditLogEntry {
// ...
return {
id: entry.id,
- guildId: entry.targetId ?? '', // Best effort
+ guildId,
// ...
};
}Then update the event handler to pass the guild ID from the event context.
Committable suggestion skipped: line range outside the PR's diff.
| export function serializeInteraction(interaction: Interaction): SerializedInteraction { | ||
| const base: SerializedInteraction = { | ||
| id: interaction.id, | ||
| type: interaction.type, | ||
| typeName: interactionTypeNames[interaction.type] ?? 'unknown', | ||
| guildId: interaction.guildId, | ||
| channelId: interaction.channelId, | ||
| user: serializeUser(interaction.user), | ||
| member: interaction.member && 'id' in interaction.member | ||
| ? serializeMember(interaction.member as GuildMember) | ||
| : null, | ||
| token: interaction.token, | ||
| applicationId: interaction.applicationId, | ||
| commandName: null, | ||
| commandId: null, | ||
| commandType: null, | ||
| customId: null, | ||
| componentType: null, | ||
| values: null, | ||
| targetId: null, | ||
| locale: interaction.locale, | ||
| guildLocale: interaction.guildLocale ?? null, | ||
| createdAt: interaction.createdAt.toISOString(), | ||
| }; | ||
|
|
||
| if (interaction.isCommand()) { | ||
| base.commandName = interaction.commandName; | ||
| base.commandId = interaction.commandId; | ||
| base.commandType = interaction.commandType; | ||
| } | ||
|
|
||
| if (interaction.isMessageComponent()) { | ||
| base.customId = interaction.customId; | ||
| base.componentType = interaction.componentType; | ||
| } | ||
|
|
||
| if (interaction.isAnySelectMenu()) { | ||
| base.values = interaction.values; | ||
| } | ||
|
|
||
| if (interaction.isContextMenuCommand()) { | ||
| base.targetId = interaction.targetId; | ||
| } | ||
|
|
||
| if (interaction.isModalSubmit()) { | ||
| base.customId = interaction.customId; | ||
| } | ||
|
|
||
| return base; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interaction serializer includes sensitive token - security concern.
Line 591 includes interaction.token in the serialized output. This token allows responding to Discord interactions and should be treated as sensitive data.
If this data is broadcast to potentially untrusted clients, the token should be redacted or omitted:
-token: interaction.token,
+token: '[REDACTED]', // Tokens are sensitive and should not be exposedIf legitimate use cases require the token, ensure the broadcast mechanism restricts access appropriately.
🤖 Prompt for AI Agents
In src/discord/serializers.ts around lines 580 to 629, the serializer currently
includes interaction.token (sensitive) in the serialized object; remove or
redact the token by omitting interaction.token from the returned object (or
replace with a constant like "[REDACTED]") and, if there is a legitimate
internal need to include it, add an explicit opt-in parameter (e.g.
includeSensitive?: boolean) that defaults to false and only includes the raw
token when true and only used in trusted/internal code paths; ensure any callers
that relied on the token are updated to use the opt-in flag and audit broadcast
paths so the token is never sent to untrusted clients.
|
@greptile pls review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
14 files reviewed, 2 comments
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (3)
src/discord/events/index.ts (3)
182-216: Previous concerns addressed.The poll vote handlers now correctly validate that
messageexists before broadcasting, eliminating the empty string issue raised in earlier reviews. The implementation is now safe.
368-384: Still using misleading fallback for missing joinTimestamp.Line 378 uses
new Date().toISOString()whenjoinedTimestampis missing, creating timestamps that falsely suggest members joined at the current moment rather than their actual join time.Apply this diff to use null for unknown join times:
addedMembers: addedMembers.map((m) => ({ id: m.id, threadId: m.thread?.id ?? thread.id, - joinedAt: m.joinedTimestamp ? new Date(m.joinedTimestamp).toISOString() : new Date().toISOString(), + joinedAt: m.joinedTimestamp ? new Date(m.joinedTimestamp).toISOString() : null, })),You'll also need to update the corresponding TypeScript type to make
joinedAtnullable.
701-709: Interaction token still exposed (security risk).The serialized interaction includes the sensitive
tokenfield, as flagged in previous reviews. Interaction tokens allow responding to interactions and should not be broadcast to potentially unauthorized clients.Modify
serializeInteractioninsrc/discord/serializers.tsto omit or redact the token:return { id: interaction.id, type: interaction.type, // ... other fields - token: interaction.token, + // token: interaction.token, // Omitted for security applicationId: interaction.applicationId, // ... rest of fields };Alternatively, if the token is needed for specific authorized use cases, add a parameter to control whether it's included and ensure only authorized clients receive it.
🧹 Nitpick comments (1)
src/discord/events/index.ts (1)
743-748: Consider including old entitlement data for consistency.The
entitlementUpdatehandler only serializes the new entitlement, while most other update handlers throughout the file include both old and new data. IfoldEntitlementis available and useful, consider including it to maintain consistency:discordClient.on('entitlementUpdate', (oldEntitlement, newEntitlement) => { broadcastEvent({ event: 'entitlementUpdate', guildId: newEntitlement.guildId, - data: serializeEntitlement(newEntitlement), + data: { + old: oldEntitlement ? serializeEntitlement(oldEntitlement) : null, + new: serializeEntitlement(newEntitlement), + }, }); });Alternatively, if the old entitlement data is not needed by consumers, document why this handler differs from the standard update pattern.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/discord/events/index.ts(7 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/discord/events/index.ts (1)
src/discord/serializers.ts (12)
serializeUser(67-79)serializeChannel(116-146)serializeAuditLogEntry(555-578)serializeGuildEmoji(429-439)serializeSticker(410-427)serializeStageInstance(524-535)serializeScheduledEvent(441-466)serializeAutoModRule(468-498)serializeAutoModAction(500-522)serializeInteraction(580-629)serializeInvite(537-553)serializeEntitlement(631-645)
🔇 Additional comments (8)
src/discord/events/index.ts (8)
154-180: LGTM! Clean implementation of reaction removal events.Both handlers follow the established broadcasting pattern and correctly extract the necessary identifiers from the event parameters.
263-274: LGTM! Correct handling of global user updates.Appropriately treats user updates as global events (guildId: null) and handles partial old user data safely.
305-328: LGTM! Proper handling of channel pin and webhook events.Both handlers correctly manage nullable values and appropriately filter events (webhookUpdate skips non-guild channels).
330-366: LGTM! Thread event handlers are well-structured.All three handlers appropriately handle thread lifecycle events and safely manage partial data in the update handler.
473-489: LGTM! Appropriate handling of guild integration and audit log events.Both handlers work within the constraints of the Discord.js event data, with audit log serialization safely handling partial executor data.
562-647: LGTM! Stage and scheduled event handlers are well-implemented.The handlers appropriately manage partial data and use type assertions where necessary to work with Discord.js's partial event objects.
649-684: LGTM! AutoMod event handlers are correctly implemented.All four handlers properly serialize auto-moderation data and handle nullable old values in the update handler.
759-759: LGTM! Helpful registration confirmation message.The log message provides clear feedback about the event registration, making it easy to verify the system is properly initialized.
| // ========== STICKER EVENTS ========== | ||
|
|
||
| discordClient.on('stickerCreate', (sticker) => { | ||
| broadcastEvent({ | ||
| event: 'stickerCreate', | ||
| guildId: sticker.guildId ?? '', | ||
| data: serializeSticker(sticker), | ||
| }); | ||
| }); | ||
|
|
||
| discordClient.on('stickerUpdate', (oldSticker, newSticker) => { | ||
| broadcastEvent({ | ||
| event: 'stickerUpdate', | ||
| guildId: newSticker.guildId ?? '', | ||
| data: { | ||
| old: serializeSticker(oldSticker), | ||
| new: serializeSticker(newSticker), | ||
| }, | ||
| }); | ||
| }); | ||
|
|
||
| discordClient.on('stickerDelete', (sticker) => { | ||
| broadcastEvent({ | ||
| event: 'stickerDelete', | ||
| guildId: sticker.guildId ?? '', | ||
| data: serializeSticker(sticker), | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use null instead of empty string for missing guildId.
Lines 525, 533, and 544 use sticker.guildId ?? '', which creates type inconsistency. While guild stickers typically have a guildId, the fallback should be null to match the pattern used throughout the codebase for optional guild associations.
Apply this diff:
discordClient.on('stickerCreate', (sticker) => {
broadcastEvent({
event: 'stickerCreate',
- guildId: sticker.guildId ?? '',
+ guildId: sticker.guildId ?? null,
data: serializeSticker(sticker),
});
});
discordClient.on('stickerUpdate', (oldSticker, newSticker) => {
broadcastEvent({
event: 'stickerUpdate',
- guildId: newSticker.guildId ?? '',
+ guildId: newSticker.guildId ?? null,
data: {
old: serializeSticker(oldSticker),
new: serializeSticker(newSticker),
},
});
});
discordClient.on('stickerDelete', (sticker) => {
broadcastEvent({
event: 'stickerDelete',
- guildId: sticker.guildId ?? '',
+ guildId: sticker.guildId ?? null,
data: serializeSticker(sticker),
});
});🤖 Prompt for AI Agents
In src/discord/events/index.ts around lines 520 to 547, the sticker event
handlers use `sticker.guildId ?? ''`, which introduces an empty-string fallback
and conflicts with the codebase pattern of using `null` for missing guild
associations; change each fallback to `null` so `guildId: sticker.guildId ??
null` for stickerCreate (line ~525), stickerUpdate (line ~533 using
newSticker.guildId), and stickerDelete (line ~544) to maintain consistent typing
and semantics.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Summary by CodeRabbit
Documentation
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.