PageSourceSearch

https://pupwife.com/projects/chatroom/scripts/messageCleanup.js

js pupwife.com collected 2026-09-30 15:07:15 UTC 9,443 bytes, 262 lines download raw bytes

1/**
2 * Message Cleanup System
3 * Automatically deletes old messages and images to prevent Firebase bloat
4 */
5
6window.ChatroomMessageCleanup = (function() {
7    'use strict';
8
9    // Default retention period: 30 days
10    // Can be changed via settings (1-90 days)
11    let retentionDays = 30;
12    let cleanupRunning = false;
13    let lastCleanupTime = null;
14
15    /**
16     * Initialize cleanup system
17     */
18    function init() {
19        // Load retention period from settings
20        loadRetentionSettings();
21        
22        // Run cleanup on page load (if enough time has passed)
23        checkAndRunCleanup();
24        
25        // Set up periodic cleanup check (every hour)
26        setInterval(() => {
27            checkAndRunCleanup();
28        }, 60 * 60 * 1000); // 1 hour
29        
30        // Also run cleanup when user becomes active (after 5 minutes of inactivity)
31        let activityTimeout;
32        document.addEventListener('mousemove', () => {
33            clearTimeout(activityTimeout);
34            activityTimeout = setTimeout(() => {
35                checkAndRunCleanup();
36            }, 5 * 60 * 1000); // 5 minutes
37        });
38    }
39
40    /**
41     * Load retention settings
42     */
43    function loadRetentionSettings() {
44        try {
45            const saved = localStorage.getItem('chatroom_retention_days');
46            if (saved) {
47                const days = parseInt(saved, 10);
48                if (days >= 1 && days <= 90) {
49                    retentionDays = days;
50                }
51            }
52        } catch (e) {
53            console.error('Error loading retention settings:', e);
54        }
55    }
56
57    /**
58     * Set retention period (in days)
59     */
60    function setRetentionDays(days) {
61        if (days >= 1 && days <= 90) {
62            retentionDays = days;
63            try {
64                localStorage.setItem('chatroom_retention_days', days.toString());
65            } catch (e) {
66                console.error('Error saving retention settings:', e);
67            }
68        }
69    }
70
71    /**
72     * Get retention period
73     */
74    function getRetentionDays() {
75        return retentionDays;
76    }
77
78    /**
79     * Check if cleanup should run and run it if needed
80     */
81    function checkAndRunCleanup() {
82        // Don't run if already running
83        if (cleanupRunning) return;
84        
85        // Check if enough time has passed since last cleanup (at least 1 hour)
86        const now = Date.now();
87        if (lastCleanupTime && (now - lastCleanupTime) < 60 * 60 * 1000) {
88            return;
89        }
90        
91        // Run cleanup
92        runCleanup();
93    }
94
95    /**
96     * Run cleanup to delete old messages
97     */
98    async function runCleanup() {
99        if (cleanupRunning) {
100            console.log('Cleanup already running, skipping...');
101            return;
102        }
103
104        cleanupRunning = true;
105        const cutoffTime = Date.now() - (retentionDays * 24 * 60 * 60 * 1000);
106        
107        console.log(`🧹 Starting message cleanup (deleting messages older than ${retentionDays} days)...`);
108        
109        try {
110            if (!firebase || !firebase.database) {
111                console.error('Firebase not available for cleanup');
112                cleanupRunning = false;
113                return;
114            }
115
116            const channelsRef = firebase.database().ref('chatroom/channels');
117            const dmsRef = firebase.database().ref('chatroom/dms');
118            
119            let deletedCount = 0;
120            
121            // Cleanup channel messages
122            const channelsSnapshot = await channelsRef.once('value');
123            if (channelsSnapshot.exists()) {
124                const channels = channelsSnapshot.val();
125                const cleanupPromises = [];
126                
127                for (const channelId in channels) {
128                    const messagesRef = channelsRef.child(channelId).child('messages');
129                    const messagesSnapshot = await messagesRef.once('value');
130                    
131                    if (messagesSnapshot.exists()) {
132                        const messages = messagesSnapshot.val();
133                        const deletePromises = [];
134                        
135                        for (const messageId in messages) {
136                            const message = messages[messageId];
137                            if (message.timestamp && message.timestamp < cutoffTime) {
138                                deletePromises.push(
139                                    messagesRef.child(messageId).remove()
140                                        .then(() => {
141                                            deletedCount++;
142                                            return true;
143                                        })
144                                        .catch(err => {
145                                            console.error(`Error deleting message ${messageId}:`, err);
146                                            return false;
147                                        })
148                                );
149                            }
150                        }
151                        
152                        // Batch delete old messages (limit concurrent operations)
153                        if (deletePromises.length > 0) {
154                            cleanupPromises.push(
155                                Promise.all(deletePromises.slice(0, 50)) // Process 50 at a time
156                            );
157                        }
158                    }
159                }
160                
161                // Wait for all channel cleanups to complete
162                await Promise.all(cleanupPromises);
163            }
164            
165            // Cleanup DM messages
166            const dmsSnapshot = await dmsRef.once('value');
167            if (dmsSnapshot.exists()) {
168                const conversations = dmsSnapshot.val();
169                const cleanupPromises = [];
170                
171                for (const conversationId in conversations) {
172                    const messagesRef = dmsRef.child(conversationId).child('messages');
173                    const messagesSnapshot = await messagesRef.once('value');
174                    
175                    if (messagesSnapshot.exists()) {
176                        const messages = messagesSnapshot.val();
177                        const deletePromises = [];
178                        
179                        for (const messageId in messages) {
180                            const message = messages[messageId];
181                            if (message.timestamp && message.timestamp < cutoffTime) {
182                                deletePromises.push(
183                                    messagesRef.child(messageId).remove()
184                                        .then(() => {
185                                            deletedCount++;
186                                            return true;
187                                        })
188                                        .catch(err => {
189                                            console.error(`Error deleting DM message ${messageId}:`, err);
190                                            return false;
191                                        })
192                                );
193                            }
194                        }
195                        
196                        // Batch delete old messages
197                        if (deletePromises.length > 0) {
198                            cleanupPromises.push(
199                                Promise.all(deletePromises.slice(0, 50)) // Process 50 at a time
200                            );
201                        }
202                    }
203                }
204                
205                // Wait for all DM cleanups to complete
206                await Promise.all(cleanupPromises);
207            }
208            
209            lastCleanupTime = Date.now();
210            console.log(`✅ Cleanup complete! Deleted ${deletedCount} old messages.`);
211            
212            // Show notification if cleanup deleted messages
213            if (deletedCount > 0 && window.ChatroomNotifications) {
214                window.ChatroomNotifications.showToast(
215                    `Cleaned up ${deletedCount} old message${deletedCount !== 1 ? 's' : ''}`,
216                    'info'
217                );
218            }
219            
220        } catch (error) {
221            console.error('Error during cleanup:', error);
222        } finally {
223            cleanupRunning = false;
224        }
225    }
226
227    /**
228     * Manual cleanup trigger (for testing or immediate cleanup)
229     */
230    function manualCleanup() {
231        console.log('Manual cleanup triggered');
232        runCleanup();
233    }
234
235    /**
236     * Get cleanup status
237     */
238    function getStatus() {
239        return {
240            retentionDays: retentionDays,
241            lastCleanupTime: lastCleanupTime,
242            isRunning: cleanupRunning
243        };
244    }
245
246    // Initialize on load
247    if (document.readyState === 'loading') {
248        document.addEventListener('DOMContentLoaded', init);
249    } else {
250        init();
251    }
252
253    return {
254        init,
255        runCleanup,
256        manualCleanup,
257        setRetentionDays,
258        getRetentionDays,
259        getStatus
260    };
261})();
262

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.