@@ -214,15 +214,15 @@ function setupSocketHandlers(io, db) {
214214 c.parent_channel_id, c.position, c.is_private, c.expires_at, c.is_temp_voice,
215215 c.streams_enabled, c.music_enabled, c.media_enabled, c.slow_mode_interval, c.category, c.sort_alphabetical,
216216 c.cleanup_exempt, c.channel_type, c.voice_user_limit, c.notification_type, c.voice_enabled, c.text_enabled, c.voice_bitrate,
217- c.afk_sub_code, c.afk_timeout_minutes, c.read_only
217+ c.afk_sub_code, c.afk_timeout_minutes, c.read_only, c.auto_delete_mode, c.auto_delete_interval_hours
218218 FROM channels c WHERE c.is_dm = 0
219219 UNION
220220 SELECT c.id, c.name, c.code, c.created_by, c.topic, c.is_dm,
221221 c.code_visibility, c.code_mode, c.code_rotation_type, c.code_rotation_interval,
222222 c.parent_channel_id, c.position, c.is_private, c.expires_at, c.is_temp_voice,
223223 c.streams_enabled, c.music_enabled, c.media_enabled, c.slow_mode_interval, c.category, c.sort_alphabetical,
224224 c.cleanup_exempt, c.channel_type, c.voice_user_limit, c.notification_type, c.voice_enabled, c.text_enabled, c.voice_bitrate,
225- c.afk_sub_code, c.afk_timeout_minutes, c.read_only
225+ c.afk_sub_code, c.afk_timeout_minutes, c.read_only, c.auto_delete_mode, c.auto_delete_interval_hours
226226 FROM channels c
227227 JOIN channel_members cm ON c.id = cm.channel_id
228228 WHERE cm.user_id = ? AND c.is_dm = 1
@@ -237,7 +237,7 @@ function setupSocketHandlers(io, db) {
237237 c.parent_channel_id, c.position, c.is_private, c.expires_at, c.is_temp_voice,
238238 c.streams_enabled, c.music_enabled, c.media_enabled, c.slow_mode_interval, c.category, c.sort_alphabetical,
239239 c.cleanup_exempt, c.channel_type, c.voice_user_limit, c.notification_type, c.voice_enabled, c.text_enabled, c.voice_bitrate,
240- c.afk_sub_code, c.afk_timeout_minutes, c.read_only
240+ c.afk_sub_code, c.afk_timeout_minutes, c.read_only, c.auto_delete_mode, c.auto_delete_interval_hours
241241 FROM channels c
242242 JOIN channel_members cm ON c.id = cm.channel_id
243243 WHERE cm.user_id = ?
@@ -908,20 +908,44 @@ function setupSocketHandlers(io, db) {
908908 setInterval ( ( ) => {
909909 try {
910910 const expired = db . prepare (
911- "SELECT id, code FROM channels WHERE expires_at IS NOT NULL AND expires_at <= datetime('now')"
911+ "SELECT id, code, auto_delete_mode, auto_delete_interval_hours FROM channels WHERE expires_at IS NOT NULL AND expires_at <= datetime('now')"
912912 ) . all ( ) ;
913913 for ( const ch of expired ) {
914- db . prepare ( 'DELETE FROM reactions WHERE message_id IN (SELECT id FROM messages WHERE channel_id = ?)' ) . run ( ch . id ) ;
915- db . prepare ( 'DELETE FROM pinned_messages WHERE channel_id = ?' ) . run ( ch . id ) ;
916- db . prepare ( 'DELETE FROM messages WHERE channel_id = ?' ) . run ( ch . id ) ;
917- db . prepare ( 'DELETE FROM channel_members WHERE channel_id = ?' ) . run ( ch . id ) ;
918- db . prepare ( 'DELETE FROM channels WHERE id = ?' ) . run ( ch . id ) ;
919- io . to ( `channel:${ ch . code } ` ) . to ( `voice:${ ch . code } ` ) . emit ( 'channel-deleted' , { code : ch . code , reason : 'expired' } ) ;
920- channelUsers . delete ( ch . code ) ;
921- voiceUsers . delete ( ch . code ) ;
922- activeMusic . delete ( ch . code ) ;
923- musicQueues . delete ( ch . code ) ;
924- console . log ( `[Temporary] Channel "${ ch . code } " expired and was deleted` ) ;
914+ if ( ch . auto_delete_mode === 'clear' ) {
915+ // #5390 — clear-messages mode: wipe message-related rows but keep
916+ // the channel, its members, permissions, roles, and integrations
917+ // intact. Then rearm the timer using the original interval so the
918+ // sweep repeats (e.g. daily flood-channel reset) until an admin
919+ // disables it. If for some reason the interval wasn't stored,
920+ // fall back to disabling the timer to avoid getting stuck firing
921+ // a zero-second loop.
922+ db . prepare ( 'DELETE FROM reactions WHERE message_id IN (SELECT id FROM messages WHERE channel_id = ?)' ) . run ( ch . id ) ;
923+ db . prepare ( 'DELETE FROM pinned_messages WHERE channel_id = ?' ) . run ( ch . id ) ;
924+ db . prepare ( 'DELETE FROM messages WHERE channel_id = ?' ) . run ( ch . id ) ;
925+ const interval = ch . auto_delete_interval_hours ;
926+ if ( interval && interval > 0 ) {
927+ const nextExpiry = new Date ( Date . now ( ) + interval * 3600000 ) . toISOString ( ) ;
928+ db . prepare ( 'UPDATE channels SET expires_at = ? WHERE id = ?' ) . run ( nextExpiry , ch . id ) ;
929+ } else {
930+ db . prepare ( 'UPDATE channels SET expires_at = NULL WHERE id = ?' ) . run ( ch . id ) ;
931+ }
932+ io . to ( `channel:${ ch . code } ` ) . emit ( 'channel-messages-cleared' , { code : ch . code , reason : 'auto-clear' } ) ;
933+ // Refresh channel lists so the new expires_at propagates to clients.
934+ try { broadcastChannelLists ( ) ; } catch { }
935+ console . log ( `[Temporary] Channel "${ ch . code } " messages cleared (auto-clear mode)` ) ;
936+ } else {
937+ db . prepare ( 'DELETE FROM reactions WHERE message_id IN (SELECT id FROM messages WHERE channel_id = ?)' ) . run ( ch . id ) ;
938+ db . prepare ( 'DELETE FROM pinned_messages WHERE channel_id = ?' ) . run ( ch . id ) ;
939+ db . prepare ( 'DELETE FROM messages WHERE channel_id = ?' ) . run ( ch . id ) ;
940+ db . prepare ( 'DELETE FROM channel_members WHERE channel_id = ?' ) . run ( ch . id ) ;
941+ db . prepare ( 'DELETE FROM channels WHERE id = ?' ) . run ( ch . id ) ;
942+ io . to ( `channel:${ ch . code } ` ) . to ( `voice:${ ch . code } ` ) . emit ( 'channel-deleted' , { code : ch . code , reason : 'expired' } ) ;
943+ channelUsers . delete ( ch . code ) ;
944+ voiceUsers . delete ( ch . code ) ;
945+ activeMusic . delete ( ch . code ) ;
946+ musicQueues . delete ( ch . code ) ;
947+ console . log ( `[Temporary] Channel "${ ch . code } " expired and was deleted` ) ;
948+ }
925949 }
926950 } catch ( err ) {
927951 console . error ( 'Temporary channel cleanup error:' , err ) ;
0 commit comments