export class ScraperUtils { constructor() { this.activityIndicator = document.getElementById('activity_indicator'); this.endTimeElement = document.getElementById('end_time'); this.serverTimeElement = document.getElementById('server_time'); this.timeLeftElement = document.getElementById('time-left'); // New element for countdown this.stopButton = document.getElementById('stopButton'); this.startButton = document.getElementById('startButton'); this.statusContainer = document.getElementById('status_container'); this.loadingIndicator = document.getElementById('loading_indicator'); this.statusContent = document.querySelectorAll('#status_content'); this.serverTime = null; this.endTime = null; this.pollInterval = null; // Add this line this.init(); } async init() { this.showLoadingIndicator(); try { await Promise.all([ this.updateServerTime(), this.checkScrapingStatus() ]); } catch (error) { console.error("Error during initialization:", error); } // Start polling for status updates this.startPolling(); // Only start the clock and wait for end time if scraping is active if (this.activityIndicator.textContent === 'Active') { if (!this.endTime) { try { await this.fetchEndTime(); } catch (error) { console.error("Error fetching end time:", error); } } if (this.serverTime && this.endTime) { this.startClock(); } } // Hide loading indicator regardless of scraping status this.hideLoadingIndicator(); } startPolling() { // Poll every 2 seconds this.pollInterval = setInterval(async () => { await this.checkScrapingStatus(); }, 2000); } stopPolling() { if (this.pollInterval) { clearInterval(this.pollInterval); this.pollInterval = null; } } showLoadingIndicator() { this.statusContainer.classList.remove('d-none'); this.loadingIndicator.classList.remove('d-none'); this.statusContent.forEach(element => element.classList.add('d-none')); } hideLoadingIndicator() { this.loadingIndicator.classList.add('d-none'); this.statusContent.forEach(element => element.classList.remove('d-none')); } async checkScrapingStatus() { try { const response = await fetch('/scraping_status'); const data = await response.json(); if (data.scraping_active) { if (this.startButton) this.startButton.disabled = true; if (this.stopButton) this.stopButton.disabled = false; this.activityIndicator.classList.remove('text-bg-danger'); this.activityIndicator.classList.add('text-bg-success'); this.activityIndicator.textContent = 'Active'; // Fetch end time if we don't have it yet if (!this.endTime) { await this.fetchEndTime(); } this.endTimeElement.classList.remove('d-none'); this.timeLeftElement.classList.remove('d-none'); } else { if (this.startButton) this.startButton.disabled = false; if (this.stopButton) this.stopButton.disabled = true; this.activityIndicator.classList.remove('text-bg-success'); this.activityIndicator.classList.add('text-bg-danger'); this.activityIndicator.textContent = 'Inactive'; this.endTimeElement.classList.add('d-none'); this.timeLeftElement.classList.add('d-none'); // Reset end time when inactive this.endTime = null; } } catch (error) { console.error('Error checking scraping status:', error); } } async updateServerTime() { try { const response = await fetch('/server_time'); const data = await response.json(); this.serverTime = new Date(data.server_time.replace(' ', 'T')); this.serverTimeElement.textContent = `Server Time (TCT): ${this.formatDateToHHMMSS(this.serverTime)}`; } catch (error) { console.error('Error fetching server time:', error); } } async fetchEndTime() { if (this.endTime) return; try { const response = await fetch('/scraping_get_end_time'); const data = await response.json(); if (data.end_time) { this.endTime = new Date(data.end_time); this.endTimeElement.textContent = `Running until ${this.formatDateToYYYYMMDDHHMMSS(this.endTime)} TCT`; } } catch (error) { this.endTimeElement.textContent = 'Error fetching end time'; console.error('Error fetching end time:', error); } } startClock() { const updateClock = () => { if (this.serverTime) { this.serverTime.setSeconds(this.serverTime.getSeconds() + 1); this.serverTimeElement.textContent = `Server Time (TCT): ${this.formatDateToHHMMSS(this.serverTime)}`; } if (this.endTime && this.serverTime) { const timeLeft = this.endTime - this.serverTime; this.timeLeftElement.textContent = `Time Left: ${timeLeft > 0 ? this.formatMillisecondsToHHMMSS(timeLeft) : '00:00:00'}`; } }; // Immediately update the clock updateClock(); // Continue updating every second setInterval(updateClock, 1000); } formatDateToYYYYMMDDHHMMSS(date) { if (!(date instanceof Date) || isNaN(date)) { console.error('Invalid date:', date); return ''; } return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ` + `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(date.getSeconds()).padStart(2, '0')}`; } formatDateToHHMMSS(date) { if (!(date instanceof Date) || isNaN(date)) { console.error('Invalid date:', date); return ''; } return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(date.getSeconds()).padStart(2, '0')}`; } formatMillisecondsToHHMMSS(ms) { const totalSeconds = Math.floor(ms / 1000); const hours = Math.floor(totalSeconds / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const seconds = totalSeconds % 60; return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`; } // Add cleanup method cleanup() { this.stopPolling(); } } // Add event listener for page unload window.addEventListener('unload', () => { if (window.scraperUtils) { window.scraperUtils.cleanup(); } });