Skip to content

autoclose groups#22

Merged
znanx merged 2 commits intoznanx:masterfrom
Kiznaiverr:moon
Dec 24, 2025
Merged

autoclose groups#22
znanx merged 2 commits intoznanx:masterfrom
Kiznaiverr:moon

Conversation

@Kiznaiverr
Copy link
Contributor

Add Auto Group Open/Close Feature

Summary

This PR adds an auto group open/close feature that allows group admins to schedule when a group should be opened or closed automatically.

This addresses the request in issue #19


Changes

  • Add scheduled auto group open/close.
  • Allow per-group time configuration by group admins.
  • Automatically open/close groups based on the configured schedule.

Screenshot

Screenshot 2025-12-22 155947

Copilot AI review requested due to automatic review settings December 22, 2025 14:50
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an auto group open/close feature that allows group admins to schedule when WhatsApp groups should automatically open or close. The feature uses time-based scheduling with per-group configuration and runs on a cron job every minute to check and update group statuses.

  • Introduces scheduled auto group open/close with configurable time ranges (e.g., 14:30-15:00)
  • Adds commands for setting schedules (.setautoclose) and toggling the feature (.autoclose on/off)
  • Integrates cron-based scheduler that runs every minute to enforce configured schedules

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
plugins/admin/setautoclose.js New command plugin for configuring auto group open/close time schedules
lib/system/autoclose.js New scheduler module implementing cron-based automatic group status updates
plugins/admin/moderation.js Extended moderation commands to support toggling autoclose on/off
plugins/group/groupinfo.js Updated group info display to show autoclose status and schedule
lib/system/models.js Added autoclose data model to group schema
lib/system/listeners.js Initialized autoclose scheduler on bot startup and updated image path

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const groupSet = global.db.groups[x.jid]
if (!groupSet) return
const pic = await conn.sock.profilePictureUrl(x.member, 'image') || await Func.fetchBuffer('./src/image/default.jpg')
const pic = await conn.sock.profilePictureUrl(x.member, 'image') || await Func.fetchBuffer('./lib/assets/images/default.jpg')
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

This file path change from './src/image/default.jpg' to './lib/assets/images/default.jpg' appears to be unrelated to the auto group open/close feature. The directory './lib/assets/images/' does not exist in the codebase, while './src/image/default.jpg' is used consistently in other files. This change should either be removed or done in a separate PR with proper file migration.

Suggested change
const pic = await conn.sock.profilePictureUrl(x.member, 'image') || await Func.fetchBuffer('./lib/assets/images/default.jpg')
const pic = await conn.sock.profilePictureUrl(x.member, 'image') || await Func.fetchBuffer('./src/image/default.jpg')

Copilot uses AI. Check for mistakes.
const currMin = curr[0] * 60 + curr[1]
const startMin = st[0] * 60 + st[1]
const endMin = ed[0] * 60 + ed[1]

Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

The time range comparison logic does not handle cross-midnight scenarios. If a group should be closed from 23:00 to 01:00, the current implementation would incorrectly evaluate this range. When endMin is less than startMin (indicating a cross-midnight range), the logic should check if currMin is either greater than or equal to startMin OR less than endMin.

Suggested change
// Handle ranges that cross midnight (e.g., 23:00–01:00)
if (endMin < startMin) {
return currMin >= startMin || currMin < endMin
}
// Normal same-day range

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +71
// Close group if time is within range
if (shouldBeClosed && !isClosed) {
try {
await conn.groupSettingUpdate(jid, 'announcement')
groupSet.autoclose.isClosed = true
conn.reply(jid, Func.texted('bold', `🚩 Group status changed CLOSED due to autoclose set ${start}-${end}`))
} catch (e) {
console.log(`Error closing group ${jid}:`, e.message)
}
}
// Open group if time is outside range
else if (!shouldBeClosed && isClosed) {
try {
await conn.groupSettingUpdate(jid, 'not_announcement')
groupSet.autoclose.isClosed = false
conn.reply(jid, Func.texted('bold', `🚩 Group status changed OPEN due to autoclose set ${start}-${end}`))
} catch (e) {
console.log(`Error opening group ${jid}:`, e.message)
}
}
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

When manually opening or closing a group via the 'group' command (plugins/admin/restrict.js) or 'gcopt' command (plugins/owner/gc.js), the isClosed flag in the autoclose configuration is not updated. This can lead to state inconsistency where the scheduler may immediately re-close a manually opened group or vice versa. Consider adding logic to update groupSet.autoclose.isClosed when manual group status changes occur, or handle this scenario in the scheduler to check actual group status before making changes.

Copilot uses AI. Check for mistakes.
try {
await conn.groupSettingUpdate(jid, 'announcement')
groupSet.autoclose.isClosed = true
conn.reply(jid, Func.texted('bold', `🚩 Group status changed CLOSED due to autoclose set ${start}-${end}`))
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

The error message states 'Group status changed CLOSED' but the past tense and capitalization are inconsistent with the opening message. For consistency with the corresponding open message (line 67), consider changing to 'Group status changed to CLOSED' or simply 'Group has been closed automatically'.

Suggested change
conn.reply(jid, Func.texted('bold', `🚩 Group status changed CLOSED due to autoclose set ${start}-${end}`))
conn.reply(jid, Func.texted('bold', `🚩 Group status changed to CLOSED due to autoclose set ${start}-${end}`))

Copilot uses AI. Check for mistakes.
try {
await conn.groupSettingUpdate(jid, 'not_announcement')
groupSet.autoclose.isClosed = false
conn.reply(jid, Func.texted('bold', `🚩 Group status changed OPEN due to autoclose set ${start}-${end}`))
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

The error message states 'Group status changed OPEN' but would be clearer and more consistent with the closing message if it said 'Group status changed to OPEN' or 'Group has been opened automatically'.

Copilot uses AI. Check for mistakes.
}

if (args[0].toLowerCase() === 'off') {
groupSet.autoclose.active = false
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

When disabling autoclose with 'off', consider resetting the isClosed flag to false as well. If a group is currently in the closed state due to autoclose and an admin disables the feature, leaving isClosed as true could cause confusion about the intended state. It would be clearer to set isClosed to false when the feature is disabled.

Suggested change
groupSet.autoclose.active = false
groupSet.autoclose.active = false
groupSet.autoclose.isClosed = false

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +24
if (type === 'autoclose' && !setting.autoclose) {
setting.autoclose = {
active: false,
start: null,
end: null,
isClosed: false
}
}

Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

The initialization logic for autoclose in moderation.js duplicates the object structure already defined in lib/system/models.js (lines 41-46). If the structure needs to change in the future, it would need to be updated in multiple places. Consider extracting this to a shared function or constant, or simply rely on the model defaults being applied during database initialization.

Suggested change
if (type === 'autoclose' && !setting.autoclose) {
setting.autoclose = {
active: false,
start: null,
end: null,
isClosed: false
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +26
if (!groupSet.autoclose) {
groupSet.autoclose = {
active: false,
start: null,
end: null,
isClosed: false
}
}
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

Similar to moderation.js, this initialization duplicates the autoclose object structure from lib/system/models.js. Consider using a shared constant or helper function to maintain consistency and reduce duplication.

Copilot uses AI. Check for mistakes.
const endTotalMin = endHour * 60 + endMin

if (startTotalMin >= endTotalMin) {
return conn.reply(m.chat, `🚩 *Invalid time range!*\n\nStart time must be before end time.\n\n*Example* : ${Func.texted('code', '.setautoclose 14:30-15:00')}`, m)
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

The time range validation does not handle cross-midnight scenarios. For example, if a group admin wants to close from 23:00 to 01:00 (close at 11 PM and open at 1 AM), this validation would reject it since startTotalMin (1380) is greater than endTotalMin (60). Consider supporting cross-midnight time ranges or adding a clear error message explaining this limitation.

Suggested change
return conn.reply(m.chat, `🚩 *Invalid time range!*\n\nStart time must be before end time.\n\n*Example* : ${Func.texted('code', '.setautoclose 14:30-15:00')}`, m)
return conn.reply(m.chat, `🚩 *Invalid time range!*\n\nStart time must be earlier than end time *on the same day*.\nCross-midnight ranges like 23:00-01:00 are currently not supported.\n\n*Example* : ${Func.texted('code', '.setautoclose 14:30-15:00')}`, m)

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +79
cron.schedule('* * * * *', async () => {
try {
if (!global.db?.groups) return

const currentTime = getCurrentTime()

for (const [jid, groupSet] of Object.entries(global.db.groups)) {
if (!groupSet.autoclose?.active || !groupSet.autoclose.start || !groupSet.autoclose.end) continue

const { start, end, isClosed } = groupSet.autoclose
const shouldBeClosed = isTimeInRange(currentTime, start, end)

// Close group if time is within range
if (shouldBeClosed && !isClosed) {
try {
await conn.groupSettingUpdate(jid, 'announcement')
groupSet.autoclose.isClosed = true
conn.reply(jid, Func.texted('bold', `🚩 Group status changed CLOSED due to autoclose set ${start}-${end}`))
} catch (e) {
console.log(`Error closing group ${jid}:`, e.message)
}
}
// Open group if time is outside range
else if (!shouldBeClosed && isClosed) {
try {
await conn.groupSettingUpdate(jid, 'not_announcement')
groupSet.autoclose.isClosed = false
conn.reply(jid, Func.texted('bold', `🚩 Group status changed OPEN due to autoclose set ${start}-${end}`))
} catch (e) {
console.log(`Error opening group ${jid}:`, e.message)
}
}
}
} catch (e) {
console.log('Error in auto_close scheduler:', e.message)
}
}, {
scheduled: true,
timezone: process.env.TZ || 'Asia/Jakarta'
})
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

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

The cron job runs every minute for all groups with autoclose enabled. If there are many groups (e.g., hundreds), this could become a performance bottleneck. Consider implementing a more efficient scheduling approach, such as using separate timers for each group or batching group status changes. Additionally, the current approach may cause all groups to be processed simultaneously at the top of each minute, creating a spike in API calls to WhatsApp.

Copilot uses AI. Check for mistakes.
@znanx znanx merged commit d35b43e into znanx:master Dec 24, 2025
9 checks passed
@znanx znanx mentioned this pull request Dec 24, 2025
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.

2 participants