Prayer Timer

Prayer timer for Torn that tracks time since last prayer

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Prayer Timer
// @namespace    Randy's Tools
// @version      2.3
// @description  Prayer timer for Torn that tracks time since last prayer
// @author       Randy
// @match        https://www.torn.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    const STORAGE_KEY = 'torn_prayer_timer';
    const HOURS_48 = 48 * 60 * 60 * 1000; // 48 hours in milliseconds
    const HOURS_36 = 36 * 60 * 60 * 1000; // 36 hours in milliseconds
    const HOURS_24 = 24 * 60 * 60 * 1000; // 24 hours in milliseconds

    let timerElement;
    let intervalId;
    let initAttempts = 0;
    const maxInitAttempts = 10;

    // Create the timer button
    function createTimerButton() {
        // Remove existing timer if it exists
        const existing = document.getElementById('prayer-timer-btn');
        if (existing) {
            existing.remove();
        }

        const button = document.createElement('div');
        button.id = 'prayer-timer-btn';
        button.style.cssText = `
            position: fixed;
            top: 10px;
            left: 10px;
            z-index: 10000;
            background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
            color: white;
            padding: 8px 12px;
            border-radius: 8px;
            font-family: Arial, sans-serif;
            font-size: 12px;
            font-weight: bold;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
            border: 2px solid rgba(255,255,255,0.2);
            backdrop-filter: blur(10px);
            transition: all 0.3s ease;
            min-width: 140px;
            text-align: center;
            user-select: none;
            cursor: pointer;
        `;

        // Add click handler to navigate to church
        button.addEventListener('click', function() {
            window.location.href = 'https://www.torn.com/church.php';
        });

        // Add hover effects
        button.addEventListener('mouseenter', function() {
            this.style.transform = 'scale(1.05)';
            this.style.boxShadow = '0 6px 16px rgba(0,0,0,0.4)';
        });

        button.addEventListener('mouseleave', function() {
            this.style.transform = 'scale(1)';
            this.style.boxShadow = '0 4px 12px rgba(0,0,0,0.3)';
        });

        document.body.appendChild(button);
        timerElement = button;
        console.log('Prayer timer button created successfully');
        return button;
    }

    // Get stored timer data
    function getTimerData() {
        const stored = localStorage.getItem(STORAGE_KEY);
        if (stored) {
            try {
                return JSON.parse(stored);
            } catch (e) {
                console.error('Error parsing timer data:', e);
            }
        }
        return null;
    }

    // Save timer data
    function saveTimerData(data) {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
    }

    // Reset the timer (start from 0)
    function resetTimer() {
        const now = Date.now();
        
        saveTimerData({
            startTime: now,
            isActive: true
        });

        console.log('Prayer timer reset - starting from 0');
    }

    // Format time elapsed
    function formatTimeElapsed(milliseconds) {
        const hours = Math.floor(milliseconds / (1000 * 60 * 60));
        const minutes = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60));
        const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);

        if (hours > 0) {
            return `${hours}h ${minutes}m ${seconds}s`;
        } else if (minutes > 0) {
            return `${minutes}m ${seconds}s`;
        } else {
            return `${seconds}s`;
        }
    }

    // Update timer display
    function updateTimerDisplay() {
        if (!timerElement) {
            console.warn('Timer element not found, attempting to recreate...');
            if (document.body) {
                createTimerButton();
            }
            return;
        }

        const timerData = getTimerData();
        
        if (!timerData || !timerData.isActive) {
            // No timer data, start from 0
            resetTimer();
            timerElement.innerHTML = '⛪ 0s';
            timerElement.style.background = 'linear-gradient(135deg, #4CAF50 0%, #45a049 100%)';
            return;
        }

        const now = Date.now();
        const timeElapsed = now - timerData.startTime;
        
        if (timeElapsed >= HOURS_48) {
            // Past 48 hours - shame message
            timerElement.innerHTML = '💀 You suck, try again';
            timerElement.style.background = 'linear-gradient(135deg, #424242 0%, #212121 100%)';
        } else if (timeElapsed >= HOURS_36) {
            // 36-48 hours - red
            const formatted = formatTimeElapsed(timeElapsed);
            timerElement.innerHTML = `🔴 ${formatted}`;
            timerElement.style.background = 'linear-gradient(135deg, #f44336 0%, #d32f2f 100%)';
        } else if (timeElapsed >= HOURS_24) {
            // 24-36 hours - yellow
            const formatted = formatTimeElapsed(timeElapsed);
            timerElement.innerHTML = `🟡 ${formatted}`;
            timerElement.style.background = 'linear-gradient(135deg, #ff9800 0%, #f57c00 100%)';
        } else {
            // 0-24 hours - green
            const formatted = formatTimeElapsed(timeElapsed);
            timerElement.innerHTML = `🟢 ${formatted}`;
            timerElement.style.background = 'linear-gradient(135deg, #4CAF50 0%, #45a049 100%)';
        }
    }

    // Monitor for pray button clicks ONLY
    function monitorPrayButton() {
        document.addEventListener('click', function(e) {
            const target = e.target;
            
            // Only check if we're on the church page
            if (!window.location.href.includes('/church.php')) {
                return;
            }
            
            // Check for exact "Pray" text or value
            const text = target.textContent?.trim() || '';
            const value = target.value?.trim() || '';
            
            // Look for exact "Pray" match (case insensitive)
            if (text.toLowerCase() === 'pray' || value.toLowerCase() === 'pray') {
                console.log('Pray button clicked - resetting timer');
                setTimeout(() => {
                    resetTimer();
                    updateTimerDisplay();
                }, 100);
            }
            
            // Also check parent elements in case the text is in a span inside a button
            let parent = target.parentElement;
            while (parent && parent !== document.body) {
                const parentText = parent.textContent?.trim() || '';
                const parentValue = parent.value?.trim() || '';
                
                if (parentText.toLowerCase() === 'pray' || parentValue.toLowerCase() === 'pray') {
                    console.log('Pray button (parent) clicked - resetting timer');
                    setTimeout(() => {
                        resetTimer();
                        updateTimerDisplay();
                    }, 100);
                    break;
                }
                parent = parent.parentElement;
            }
        });
    }

    // Check if timer is visible and recreate if needed
    function ensureTimerVisible() {
        const existing = document.getElementById('prayer-timer-btn');
        if (!existing && document.body) {
            console.log('Timer not found, recreating...');
            createTimerButton();
            updateTimerDisplay();
        }
    }

    // Initialize the extension with retry mechanism
    function init() {
        initAttempts++;
        
        // Wait for document body to be available
        if (!document.body) {
            if (initAttempts < maxInitAttempts) {
                console.log(`Init attempt ${initAttempts}: waiting for document.body...`);
                setTimeout(init, 100);
            } else {
                console.error('Failed to initialize: document.body not available');
            }
            return;
        }

        // Create timer button
        createTimerButton();
        
        // Start timer updates
        updateTimerDisplay();
        
        // Clear any existing interval
        if (intervalId) {
            clearInterval(intervalId);
        }
        intervalId = setInterval(updateTimerDisplay, 1000);

        // Monitor for pray button clicks
        monitorPrayButton();

        // Set up visibility check interval
        setInterval(ensureTimerVisible, 5000); // Check every 5 seconds

        console.log('Torn Prayer Timer initialized successfully');
    }

    // Multiple initialization strategies
    function startInitialization() {
        // Strategy 1: Immediate if DOM is ready
        if (document.readyState === 'complete' || document.readyState === 'interactive') {
            setTimeout(init, 50);
        }
        
        // Strategy 2: DOM Content Loaded
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', () => {
                setTimeout(init, 100);
            });
        }
        
        // Strategy 3: Window load (fallback)
        window.addEventListener('load', () => {
            setTimeout(init, 200);
        });
        
        // Strategy 4: Immediate retry (for dynamic pages)
        setTimeout(() => {
            if (!document.getElementById('prayer-timer-btn')) {
                init();
            }
        }, 500);
    }

    // Handle page navigation and dynamic content
    let currentUrl = location.href;
    const observer = new MutationObserver(() => {
        if (location.href !== currentUrl) {
            currentUrl = location.href;
            // Ensure timer is still visible after navigation
            setTimeout(ensureTimerVisible, 1000);
        }
    });

    // Start observing when body is available
    function startObserver() {
        if (document.body) {
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        } else {
            setTimeout(startObserver, 100);
        }
    }

    // Start everything
    startInitialization();
    startObserver();

    // Cleanup on page unload
    window.addEventListener('beforeunload', () => {
        if (intervalId) {
            clearInterval(intervalId);
        }
        observer.disconnect();
    });

})();