Skip to content

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

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

Feat: Add /disablecommunity and /enablecommunity commands for superadmins#807
Matobi98 wants to merge 9 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

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

    • Super-admins can enable or disable communities; creators can be optionally notified of status changes.
  • Changes

    • Disabled communities are treated as unavailable across discovery, listings, order/earnings flows, and user settings.
    • Community lookups now respect enabled/disabled state and preserve user defaults when a community is disabled (but cleared when deleted).
  • Internationalization

    • Added localized messages for enable/disable flows (info, admin notices, already-enabled/disabled).

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3dc80f29-7b70-4c53-b382-9fa9e0bd88e3

📥 Commits

Reviewing files that changed from the base of the PR and between e115cc1 and 19c286a.

📒 Files selected for processing (2)
  • bot/modules/orders/commands.ts
  • util/communityHelper.ts

Walkthrough

Adds an enabled boolean to Community, updates lookups to treat disabled communities as not-found, implements superadmin /disablecommunity and /enablecommunity commands (with creator notification), and adds localized messages for enable/disable flows.

Changes

Community enable/disable administration

Layer / File(s) Summary
Community model: enabled flag
models/community.ts
Add enabled: boolean to ICommunity and CommunitySchema with default 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, util/communityHelper.ts
Replace several findById calls with findOne queries including enabled: { $ne: false }; adjust private-chat default handling so deleted defaults are cleared while disabled defaults are preserved but not resolved.
Enable/disable command handlers and helpers
bot/modules/community/commands.ts
Add findCommunityByInput and buildCommunityInfoText; implement disableCommunity and enableCommunity that validate input/state, toggle community.enabled, save, fetch creator username via User.findById, optionally notify creator via Telegram i18n keys, and reply with localized info text.
Command wiring: middleware and bot handlers
bot/modules/community/index.ts
Import superAdminMiddleware and register /disablecommunity and /enablecommunity as superadmin-only commands wired to the new 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 i18n keys for community_disabled_info, community_enabled_info, community_disabled_by_admin, community_enabled_by_admin, community_already_disabled, and community_already_enabled with placeholders for community name, group, solvers, and creator username.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • lnp2pBot/bot#675: Both modify util/communityHelper.ts and community resolution logic.
  • lnp2pBot/bot#795: Overlaps in community admin/update flow and order-creation community lookups.

Suggested reviewers

  • grunch
  • mostronatorcoder

Poem

🐰 I hopped through models, fields, and strings,
I planted a switch so the community sings,
Disabled ones hide while the enabled stay bright,
Admins may toggle by day or by night,
I nibble on i18n and bask in the light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding /disablecommunity and /enablecommunity commands for superadmins.
Linked Issues check ✅ Passed All requirements from issue #804 are met: enabled field added to Community model, both commands implemented with proper access control, disabled communities excluded from user/admin/order flows.
Out of Scope Changes check ✅ Passed All changes align with the PR objectives. Query filters refactoring to exclude disabled communities, internationalization, and error handling improvements are all in-scope for implementing the feature.

✏️ 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
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.

Almost done, but there is a bug if the user wants to enter the order creation wizzard, it doesn't responds anything to the user:

Image

And this appears in the logs:

Image

Please fix those two bugs and this gets my ACK

@Luquitasjeffrey Luquitasjeffrey mentioned this pull request May 21, 2026
2 tasks
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.

I think this behaviour should be changed:
If community was disabled it should set user's default_community_id to null, so they can continue operating on the global order channel.
image

Right now it's only printing the message but it isn't setting user's community id to null

The message is messleading, this isn't unlinking the user with the deleted community, if the user attempts to create an order on a deleted community the message should say something like:

Your default community has ben disabled, I unlinked you from that community. Try creating your order again.

And it sets users community_id to null

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