Add /closecommunity command so superadmins can close any community#807
Add /closecommunity command so superadmins can close any community#807Matobi98 wants to merge 5 commits into
/closecommunity command so superadmins can close any community#807Conversation
WalkthroughAdds an ChangesCommunity enable/disable
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
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
📒 Files selected for processing (13)
bot/middleware/user.tsbot/modules/community/commands.tsbot/modules/community/index.tslocales/de.yamllocales/en.yamllocales/es.yamllocales/fa.yamllocales/fr.yamllocales/it.yamllocales/ko.yamllocales/pt.yamllocales/ru.yamllocales/uk.yaml
| next: () => void, | ||
| ) => { | ||
| const admin = await validateSuperAdmin(ctx); | ||
| const tgId = |
There was a problem hiding this comment.
Why is this necessary??
There was a problem hiding this comment.
Ohh, now I understand, if the flows comes from a button click, it checks who clicked the button, LGTM
|
I requested changes. Main blocker: the new /closecommunity confirmation message uses |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
bot/modules/community/commands.ts (1)
50-56:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEscape
groupNamebefore building regex insetComm.Raw user input in
RegExpcan 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
📒 Files selected for processing (17)
bot/modules/community/actions.tsbot/modules/community/commands.tsbot/modules/community/index.tsbot/modules/community/messages.tsbot/modules/orders/scenes.tsbot/modules/user/scenes/settings.tslocales/de.yamllocales/en.yamllocales/es.yamllocales/fa.yamllocales/fr.yamllocales/it.yamllocales/ko.yamllocales/pt.yamllocales/ru.yamllocales/uk.yamlmodels/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
| const community = await Community.findOne({ | ||
| _id: ctx.match?.[1], | ||
| enabled: { $ne: false }, | ||
| }); | ||
| ctx.scene.enter('ADD_EARNINGS_INVOICE_WIZARD_SCENE_ID', { | ||
| community, | ||
| }); |
There was a problem hiding this comment.
Guard null community before entering the earnings wizard.
If the community is disabled/deleted between UI render and callback click, this path can push null into wizard state and fail later.
Suggested fix
const community = await Community.findOne({
_id: ctx.match?.[1],
enabled: { $ne: false },
});
+ if (community == null) {
+ return ctx.reply(ctx.i18n.t('community_not_found'));
+ }
ctx.scene.enter('ADD_EARNINGS_INVOICE_WIZARD_SCENE_ID', {
community,
});🤖 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/actions.ts` around lines 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.
| const tgId = | ||
| 'callback_query' in ctx.update | ||
| ? ctx.update.callback_query.from.id.toString() | ||
| : undefined; | ||
| const admin = await validateSuperAdmin(ctx, tgId); |
There was a problem hiding this comment.
Please revert this changes because now with the /disablecommuinty and /enablecommunity approach is no longer needed
Summary
Add a new
/closecommunitycommand so superadmins can close any community by ID or Telegram group handle, with a confirmation step before executing the action.Changes
New command:
/closecommunityUsage:
/closecommunity
/closecommunity @GroupUsername
superAdminMiddleware@groupUsernameBug fix:
superAdminMiddlewarewith callback queriesvalidateSuperAdminwas readingctx.update.message.from, which throws when the update comes from a button press (callback query context). The middleware now correctly falls back tocallback_query.fromwhen available.Summary by CodeRabbit
New Features
Behavior Changes
Localization