Skip to content

Conversation

@Kavyashri217
Copy link

@Kavyashri217 Kavyashri217 commented Dec 23, 2025

Date: 23-12-2025

Developer Name: Kavyashri K R


Issue Ticket Number

Description

Changes made:

  1. Updated enrichGroupDataWithMembershipInfo to compute memberCount from existing Discord role membership data.
  2. No changes to Discord service integrations.
  3. No frontend or schema changes.

What this changes:

  1. Fixed inaccurate group member counts by updating how memberCount is computed in the backend.
  2. memberCount is now derived from live Discord role membership.
  3. Firestore group–user mappings continue to be used only for membership checks (isMember).

Scope:
Backend

Documentation Updated?

  • Yes
  • No

Under Feature Flag

  • Yes
  • No

Database Changes

  • Yes
  • No

Breaking Changes

  • Yes
  • No

Development Tested?

  • Yes
  • No

Screenshots

Screenshot 1 image

Test Coverage

Screenshot 1

Additional Notes

@coderabbitai
Copy link

coderabbitai bot commented Dec 23, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The enrichGroupDataWithMembershipInfo function in models/discordactions.js has been modified to calculate member counts using live Discord member data via liveRoleIdToCountMap rather than Firestore-based group-to-user mappings. The rest of the group enrichment logic remains unchanged.

Changes

Cohort / File(s) Summary
Member Count Data Source
models/discordactions.js
Modified enrichGroupDataWithMembershipInfo to compute memberCount from live Discord member data (liveRoleIdToCountMap from getDiscordMembers) instead of Firestore-based role mappings (roleIdToCountMap). Added live mapping logic block and comments; includes commented-out alternative implementation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 From the vaults of Firestore deep we soared,
To Discord's live streams, freshly poured,
Where member counts now dance and flow,
Real-time magic sets the glow! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing group member count computation in the enrichGroupDataWithMembershipInfo function.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The pull request description clearly outlines changes to enrichGroupDataWithMembershipInfo, explains the impact on group member counts, and specifies the scope and related considerations.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12f8cdf and 730d955.

📒 Files selected for processing (1)
  • models/discordactions.js
🧰 Additional context used
🪛 GitHub Actions: Tests
models/discordactions.js

[error] 1-1: Failed to parse URL from DISCORD_BASE_URL/discord-members during enrichGroupDataWithMembershipInfo.


[warning] 338-338: Generic Object Injection Sink security/detect-object-injection.

🪛 GitHub Check: build (22.10.0)
models/discordactions.js

[warning] 338-338:
Generic Object Injection Sink


[warning] 338-338:
Generic Object Injection Sink

Comment on lines 330 to 340
// Discord live role membership (used for memberCount)
const discordMembers = await getDiscordMembers();
const liveRoleIdToCountMap = {};

discordMembers.forEach((member) => {
if (!member.roles) return;

member.roles.forEach((roleId) => {
liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1;
});
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Missing error handling for Discord API call causes pipeline failure.

The pipeline is failing with Failed to parse URL from DISCORD_BASE_URL/discord-members because getDiscordMembers() is called without error handling. If the Discord API is unavailable or misconfigured, the entire function fails with no fallback.

Consider wrapping this in a try/catch and falling back to the Firestore-based count (roleIdToCountMap) when Discord is unreachable:

🔎 Proposed fix with graceful degradation
     // Discord live role membership (used for memberCount)
-    const discordMembers = await getDiscordMembers();
     const liveRoleIdToCountMap = {};
+    let useFirestoreFallback = false;

-    discordMembers.forEach((member) => {
-      if (!member.roles) return;
+    try {
+      const discordMembers = await getDiscordMembers();
+      discordMembers.forEach((member) => {
+        if (!member.roles) return;

-      member.roles.forEach((roleId) => {
-        liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1;
+        member.roles.forEach((roleId) => {
+          liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1;
+        });
       });
-    });
+    } catch (error) {
+      logger.warn("Failed to fetch Discord members, falling back to Firestore counts", error);
+      useFirestoreFallback = true;
+    }

Then update line 352:

-        memberCount: liveRoleIdToCountMap[group.roleid] || 0,
+        memberCount: useFirestoreFallback
+          ? (roleIdToCountMap[group.roleid] || 0)
+          : (liveRoleIdToCountMap[group.roleid] || 0),
🧰 Tools
🪛 GitHub Actions: Tests

[warning] 338-338: Generic Object Injection Sink security/detect-object-injection.

🪛 GitHub Check: build (22.10.0)

[warning] 338-338:
Generic Object Injection Sink


[warning] 338-338:
Generic Object Injection Sink

🤖 Prompt for AI Agents
In models/discordactions.js around lines 330 to 340, the call to
getDiscordMembers() has no error handling so any Discord API failure crashes the
flow; wrap the await getDiscordMembers() in a try/catch, on success populate
liveRoleIdToCountMap as shown, and on error log the error and set
liveRoleIdToCountMap = {} (or leave undefined) so the later code falls back to
the Firestore-derived roleIdToCountMap; ensure the catch does not rethrow and
that subsequent merges/use of liveRoleIdToCountMap check for its presence before
overriding Firestore counts.

// This says how many users we have for a given roleId
roleIdToCountMap[groupToUserMapping.roleid] = (roleIdToCountMap[groupToUserMapping.roleid] ?? 0) + 1;
// Discord live role membership (used for memberCount)
const discordMembers = await getDiscordMembers();
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider caching Discord member data to reduce API calls.

getDiscordMembers() is now called on every invocation of enrichGroupDataWithMembershipInfo. If this function is called frequently (e.g., on group listing pages), this could:

  • Increase latency due to network round-trips
  • Hit Discord API rate limits
  • Cause failures if Discord is temporarily unavailable

Consider implementing a short-lived cache (e.g., 1-5 minutes) for the Discord members data, or fetching it at a higher level and passing it as a parameter.

Comment on lines 337 to 339
member.roles.forEach((roleId) => {
liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1;
});
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider using Map instead of plain object to avoid prototype pollution risk.

Static analysis flagged this as a "Generic Object Injection Sink." While Discord role IDs are safe numeric strings, using a Map would eliminate the warning and provide better type safety:

🔎 Alternative using Map
-    const liveRoleIdToCountMap = {};
+    const liveRoleIdToCountMap = new Map();

     discordMembers.forEach((member) => {
       if (!member.roles) return;

       member.roles.forEach((roleId) => {
-        liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1;
+        liveRoleIdToCountMap.set(roleId, (liveRoleIdToCountMap.get(roleId) || 0) + 1);
       });
     });

Then update line 352:

-        memberCount: liveRoleIdToCountMap[group.roleid] || 0,
+        memberCount: liveRoleIdToCountMap.get(group.roleid) || 0,

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Actions: Tests

[warning] 338-338: Generic Object Injection Sink security/detect-object-injection.

🪛 GitHub Check: build (22.10.0)

[warning] 338-338:
Generic Object Injection Sink


[warning] 338-338:
Generic Object Injection Sink

🤖 Prompt for AI Agents
In models/discordactions.js around lines 337-339, replace the plain object usage
for liveRoleIdToCountMap with a Map to avoid prototype pollution warnings:
initialize liveRoleIdToCountMap as new Map(), then inside the loop read the
current count with liveRoleIdToCountMap.get(roleId) || 0 and update it with
liveRoleIdToCountMap.set(roleId, count + 1). Also update any later code that
expects a plain object to either accept a Map or convert the Map to an object
via Object.fromEntries(liveRoleIdToCountMap) where needed.

Comment on lines 3 to 5

const rawBaseUrl = config.get("services.discordBot.baseUrl");
const DISCORD_BASE_URL = rawBaseUrl && rawBaseUrl !== "DISCORD_BASE_URL" ? rawBaseUrl : "http://localhost:8080";
Copy link
Member

Choose a reason for hiding this comment

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

why is this change required? isn't the config file already handling fallback value?

Copy link
Author

Choose a reason for hiding this comment

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

undone the changes as the config file was already handling the fallback value

Copy link
Member

Choose a reason for hiding this comment

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

the use of adding fetchStub here is unclear, test changes in this file don't seem to be using it, can you point me where is it being used?

Copy link
Author

Choose a reason for hiding this comment

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

The fetch stub isn’t used directly in this test. The request hits /discord-actions/groups, which internally calls getDiscordMembers().

The stub ensures that call doesn’t make a real Discord API request and keeps the integration test deterministic.

* @returns {Promise<Array<object>>} - An array of group objects with enriched information.
*/

/* istanbul ignore next */
Copy link
Member

Choose a reason for hiding this comment

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

please remove unnecessary comments from this file

Copy link
Author

Choose a reason for hiding this comment

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

/* istanbul ignore next */ was added to exclude a defensive error path that depends on external Discord failures and isn’t reliably testable. Without this, coverage reports false negatives even though the core logic is already covered.

Copy link
Member

Choose a reason for hiding this comment

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

@Kavyashri217 please remove this

Copy link
Author

Choose a reason for hiding this comment

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

Removed the comment

@MayankBansal12
Copy link
Member

MayankBansal12 commented Dec 24, 2025

@Kavyashri217

  • Please add screen recording for your changes not the code screenshot
  • Please attach test coverage as well
  • One of the Tests is failing, please fix that

@Kavyashri217 Kavyashri217 deleted the kavyashri/fix-group-member-count branch January 1, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants