Skip to content

Feat: Add /disablecommunity and /enablecommunity commands for superadmins#807

Open
Matobi98 wants to merge 6 commits into
lnp2pBot:mainfrom
Matobi98:closecommunity
Open

Feat: Add /disablecommunity and /enablecommunity commands for superadmins#807
Matobi98 wants to merge 6 commits into
lnp2pBot:mainfrom
Matobi98:closecommunity

Conversation

@Matobi98
Copy link
Copy Markdown
Contributor

@Matobi98 Matobi98 commented May 18, 2026

Summary

Closes #804

Add /disablecommunity and /enablecommunity commands so superadmins can disable or
re-enable any community by ID or Telegram group handle, with creator notifications on
each status change. Disabled communities are excluded from discovery, listings, and
earnings management.


Changes

New commands: /disablecommunity and /enablecommunity

Usage:
/disablecommunity id|@groupUsername
/enablecommunity id|@groupUsername

  • Restricted to superadmins via superAdminMiddleware
  • Accept either a MongoDB community _id or a @groupUsername
  • Guard against redundant calls: reply with an error if the community is already in the target state
  • On status change: sets community.enabled flag and sends a DM to the creator notifying them

Model change

  • Added enabled: Boolean field (default true) to the Community schema
  • All community queries now filter by { enabled: { $ne: false } } so disabled communities are invisible to regular users

Bug fix: superAdminMiddleware with callback queries

validateSuperAdmin was reading ctx.update.message.from, which throws when the update
comes from a button press (callback query context). The middleware now falls back to
ctx.update.callback_query.from when available.

Internationalization

Added translations for all new messages across 10 languages (en, es, de, fr,
it, pt, ru, uk, ko, fa).


Summary by CodeRabbit

  • New Features

    • Administrators can now disable or enable communities; creators receive Telegram notifications of status changes
    • Disabled communities are excluded from discovery, user listings, and earnings management
  • Internationalization

    • Added multi-language support for community enable/disable messaging and status notifications across 10+ languages

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Walkthrough

This PR introduces community administrative enable/disable functionality by adding an enabled boolean flag to the Community model, updating all community lookups to treat disabled communities as not-found, implementing superadmin-only /disablecommunity and /enablecommunity commands with creator notification, and providing localized messages across ten languages.

Changes

Community enable/disable administration

Layer / File(s) Summary
Community model: enabled flag
models/community.ts
Add enabled: boolean to ICommunity interface and CommunitySchema with default value true.
Community lookups: enforce enabled filter
bot/modules/community/actions.ts, bot/modules/community/commands.ts, bot/modules/community/messages.ts, bot/modules/orders/scenes.ts, bot/modules/user/scenes/settings.ts
Update all Community database queries from findById to findOne with enabled: { $ne: false } constraint across community info, earnings, discovery, ownership validation, settings flows, and order creation so disabled communities are inaccessible.
Enable/disable command handlers and helpers
bot/modules/community/commands.ts
Import User model and implement findCommunityByInput helper for community lookup by id or @groupUsername, and add disableCommunity and enableCommunity command handlers that validate enabled state, toggle the flag, save, fetch creator username, optionally notify the creator via Telegram, and reply with localized community info text.
Command wiring: middleware and bot handlers
bot/modules/community/index.ts
Import superAdminMiddleware and register /disablecommunity and /enablecommunity as superadmin-only bot commands wired to their handlers.
Localized messages for enable/disable flows
locales/en.yaml, locales/de.yaml, locales/es.yaml, locales/fr.yaml, locales/it.yaml, locales/ko.yaml, locales/pt.yaml, locales/ru.yaml, locales/uk.yaml, locales/fa.yaml
Add 6 i18n keys per language (community disabled/enabled info with community name, group, solvers, and creator username placeholders; admin disable/enable notifications; already-disabled/already-enabled edge case messages) across ten supported locales.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Suggested reviewers

  • grunch
  • Catrya

Poem

🐰 A flag to enable or disable with care,
Communities filtered with the admin's stare,
Localized messages in ten tongues ring true,
Disabled communities fade from view,
Admin commands now wield the might!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ⚠️ Warning The PR title mentions 'disablecommunity' and 'enablecommunity' commands, but the PR objectives describe a '/closecommunity' command for closing/deleting communities. The title and objectives describe fundamentally different features. Update the PR title to accurately reflect the actual changes: either rename to match the closecommunity feature, or ensure the closecommunity implementation matches the enable/disable functionality described in the title.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Copy Markdown
Contributor

@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: 3

🤖 Prompt for all review comments with 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.

Inline comments:
In `@bot/modules/community/commands.ts`:
- Around line 255-256: The code builds a RegExp from raw input and passes it to
Community.findOne({ group: regex }), allowing regex metacharacters in input to
change matching; fix by first normalizing and escaping the user-supplied group
username (remove an optional leading '@' from input, then escape all regex
metacharacters) before constructing the RegExp used as regex, so
Community.findOne still queries the group field case-insensitively but cannot be
manipulated by special characters.
- Around line 324-331: The DM to the owner (creator) via
ctx.telegram.sendMessage can throw and currently prevents sending the final
success reply; wrap the notification call in its own try/catch (or use .catch)
so failures are handled/logged without interrupting flow, e.g., call
ctx.telegram.sendMessage(creator.tg_id, ...) inside try { ... } catch (err) { /*
log err */ } and then always execute and return
ctx.reply(ctx.i18n.t('operation_successful')); ensure you reference creator,
ctx.telegram.sendMessage and ctx.reply when making the change.

In `@locales/en.yaml`:
- Line 731: Update the locale string key community_closed_by_admin to remove the
literal '@' before the template variable so it uses a plain ${communityName}
(since communityName is community.name and may contain spaces/special chars);
locate the community_closed_by_admin entry in locales/en.yaml and replace "An
administrator has closed your community @${communityName}" with "An
administrator has closed your community ${communityName}".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b31e5825-8461-4827-bc64-94a62b556484

📥 Commits

Reviewing files that changed from the base of the PR and between b5b498c and 696abba.

📒 Files selected for processing (13)
  • bot/middleware/user.ts
  • bot/modules/community/commands.ts
  • bot/modules/community/index.ts
  • locales/de.yaml
  • locales/en.yaml
  • locales/es.yaml
  • locales/fa.yaml
  • locales/fr.yaml
  • locales/it.yaml
  • locales/ko.yaml
  • locales/pt.yaml
  • locales/ru.yaml
  • locales/uk.yaml

Comment thread bot/modules/community/commands.ts Outdated
Comment thread bot/modules/community/commands.ts Outdated
Comment thread locales/en.yaml Outdated
Copy link
Copy Markdown
Collaborator

@Luquitasjeffrey Luquitasjeffrey left a comment

Choose a reason for hiding this comment

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

tACK

Comment thread bot/middleware/user.ts Outdated
Copy link
Copy Markdown
Contributor

@mostronatorcoder mostronatorcoder Bot left a comment

Choose a reason for hiding this comment

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

I found a real authorization regression in the new /closecommunity flow, so this cannot be approved yet. Please fix the issue below and then I can re-review.

@mostronatorcoder
Copy link
Copy Markdown
Contributor

I requested changes. Main blocker: the new /closecommunity confirmation message uses doNothingBtn for Cancel, but doNothingBtn is still wired with userMiddleware. This flow is restricted to superadmins, so a superadmin who is not represented as a normal bot user can press Cancel and get no handler at all. In other words, the cancel button can be dead for the intended actor. Please protect that callback with the same auth model as the flow that created it.

@Matobi98 Matobi98 marked this pull request as draft May 18, 2026 23:52
Copy link
Copy Markdown
Contributor

@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: 1

♻️ Duplicate comments (1)
bot/modules/community/commands.ts (1)

50-56: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Escape groupName before building regex in setComm.

Raw user input in RegExp can change match behavior and select the wrong community.

Suggested fix
     if (groupName[0] == '@') {
       // Allow find communities case insensitive
-      const regex = new RegExp(['^', groupName, '$'].join(''), 'i');
+      const escapedGroupName = groupName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+      const regex = new RegExp(`^${escapedGroupName}$`, 'i');
       community = await Community.findOne({
         group: regex,
         enabled: { $ne: false },
       });
🤖 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 `@bot/modules/community/commands.ts` around lines 50 - 56, The code builds a
RegExp from raw user input (groupName) which allows regex metacharacters to
alter matching; in setComm, before creating the regex used in Community.findOne,
escape groupName (e.g., implement/consume an escapeRegExp utility and apply it
to groupName) so special characters are treated literally, then construct the
regex with '^' + escapedGroupName + '$' and the 'i' flag; update the regex
creation and use the escaped variable in the Community.findOne query.
🤖 Prompt for all review comments with 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.

Inline comments:
In `@bot/modules/community/actions.ts`:
- Around line 126-132: The code may pass a null community into the wizard if
Community.findOne returns nothing; update the handler that calls
Community.findOne (using ctx.match?.[1]) to check the returned community before
calling ctx.scene.enter('ADD_EARNINGS_INVOICE_WIZARD_SCENE_ID', { community }),
and if community is null/undefined, bail out with a user-facing
error/notification (e.g., ctx.reply or ctx.answerCbQuery) or redirect elsewhere
instead of entering the scene; reference the Community lookup, ctx.match?.[1],
ctx.scene.enter and ADD_EARNINGS_INVOICE_WIZARD_SCENE_ID to locate where to add
the guard.

---

Duplicate comments:
In `@bot/modules/community/commands.ts`:
- Around line 50-56: The code builds a RegExp from raw user input (groupName)
which allows regex metacharacters to alter matching; in setComm, before creating
the regex used in Community.findOne, escape groupName (e.g., implement/consume
an escapeRegExp utility and apply it to groupName) so special characters are
treated literally, then construct the regex with '^' + escapedGroupName + '$'
and the 'i' flag; update the regex creation and use the escaped variable in the
Community.findOne query.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f1a251f7-caf1-4e25-bdf7-e44240309060

📥 Commits

Reviewing files that changed from the base of the PR and between 696abba and 7801963.

📒 Files selected for processing (17)
  • bot/modules/community/actions.ts
  • bot/modules/community/commands.ts
  • bot/modules/community/index.ts
  • bot/modules/community/messages.ts
  • bot/modules/orders/scenes.ts
  • bot/modules/user/scenes/settings.ts
  • locales/de.yaml
  • locales/en.yaml
  • locales/es.yaml
  • locales/fa.yaml
  • locales/fr.yaml
  • locales/it.yaml
  • locales/ko.yaml
  • locales/pt.yaml
  • locales/ru.yaml
  • locales/uk.yaml
  • models/community.ts
✅ Files skipped from review due to trivial changes (5)
  • locales/pt.yaml
  • locales/ko.yaml
  • locales/es.yaml
  • locales/fr.yaml
  • locales/uk.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • locales/ru.yaml

Comment thread bot/modules/community/actions.ts
Comment thread bot/middleware/user.ts Outdated
@Matobi98 Matobi98 marked this pull request as ready for review May 19, 2026 06:02
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
bot/modules/community/commands.ts (1)

50-56: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Escape groupName before building the regex in setComm.

groupName is interpolated into RegExp without escaping, so metacharacters can change matching behavior and target the wrong community.

Suggested fix
-      const regex = new RegExp(['^', groupName, '$'].join(''), 'i');
+      const escapedGroupName = groupName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+      const regex = new RegExp(`^${escapedGroupName}$`, 'i');
       community = await Community.findOne({
         group: regex,
         enabled: { $ne: false },
       });
🤖 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 `@bot/modules/community/commands.ts` around lines 50 - 56, The code builds a
RegExp from user-controlled groupName in setComm, allowing metacharacters to
alter matching; fix by escaping regex metacharacters in groupName before
creating the RegExp used in Community.findOne (preserve the '^' and '$' anchors
and the 'i' flag), e.g. create an escapedGroupName from groupName using a
regex-escape routine (replace /[.*+?^${}()|[\]\\]/g) and then build the RegExp
from '^' + escapedGroupName + '$' and use that in the existing
Community.findOne({ group: regex, enabled: { $ne: false } }) call.
🤖 Prompt for all review comments with 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.

Duplicate comments:
In `@bot/modules/community/commands.ts`:
- Around line 50-56: The code builds a RegExp from user-controlled groupName in
setComm, allowing metacharacters to alter matching; fix by escaping regex
metacharacters in groupName before creating the RegExp used in Community.findOne
(preserve the '^' and '$' anchors and the 'i' flag), e.g. create an
escapedGroupName from groupName using a regex-escape routine (replace
/[.*+?^${}()|[\]\\]/g) and then build the RegExp from '^' + escapedGroupName +
'$' and use that in the existing Community.findOne({ group: regex, enabled: {
$ne: false } }) call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b45942b4-e690-415e-97eb-eb0d2cdb26b2

📥 Commits

Reviewing files that changed from the base of the PR and between 7801963 and 49a1e26.

📒 Files selected for processing (2)
  • bot/modules/community/actions.ts
  • bot/modules/community/commands.ts

@Luquitasjeffrey
Copy link
Copy Markdown
Collaborator

Please update pr description accordingly as it now adds /enablecommunity and /disablecommunity commands

@Luquitasjeffrey Luquitasjeffrey changed the title Add /closecommunity command so superadmins can close any community Feat: Add /disablecommunity and /enablecommunity commands for superadmins May 19, 2026
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.

Add /disablecommunity and /enablecommunity commands for superadmins

2 participants