mightypork / RedditThrottle

// ==UserScript==
// @name         RedditThrottle
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Stops you from wasting unhealthy amounts of time on Reddit
// @author       MightyPork
// @match        https://reddit.com/*
// @match        https://www.reddit.com/*
// @grant        none
// @license      MIT
// ==/UserScript==


// # What this plugin does
//
// After a set time, the Reddit interface will be covered by an overlay with a countdown.
// When the countdown expires, you can click the overlay to get another window of reddit time.
//
// When you first open the tab, it's configurable whether to start immemdiately or show the
// expired overlay waiting for a click.
//
// With some adjustments this could be adapted to any website.

(function() {
    'use strict';

    // ---------------- CONFIGURATION -----------------------

    /* How long to allow mastodon access */
    const OPEN_TIME_MIN = 5

    /* Duration of the lock-down period */
    const LOCKED_TIME_MIN = 25

    /* Toggle: Automatically unlock when opening mastodon after the lock time has passed
     * If 'false', the overlay will be shown waiting for a click */
    const AUTO_UNLOCK = false

    /* CSS query to find wrapper for injecting the overlay */
    const WRAPPER_QUERY = 'body'

    /* Overlay text config */
    const TEXT_LOCKED = 'r/throttled'
    const TEXT_UNLOCK = 'Click to waste time'

    /* Overlay colors */
    const BACKGROUND = 'white'
    const FOREGROUND = '#FF4001'

    // -----------------------------------------------------

    let locked, t_opened, t_close, overlay

    const _log = (msg) => console.log('[Throttle] ' + msg)

    /** Get unix timestamp */
    const time = () => Math.round(+new Date()/1000)

    /** Check if lock time elapsed and user can unlock */
    const isUnlockAllowed = () => (time() >= t_close + LOCKED_TIME_MIN*60)

    /** Unlock on request by user */
    const doUnlock = () => {
        _log("Unlocked")
        const now = time()
        t_close = now + OPEN_TIME_MIN*60
        t_opened = now;
        localStorage.setItem("mt_opentime", t_opened)
        overlay.style.display = 'none'
        locked = false
    }

    const doLock = () => {
        _log("Opening overlay")
        locked = true
        updateLockedText()
        overlay.style.display = 'flex'
    }

    const updateLockedText = () => {
        if (isUnlockAllowed()) {
            overlay.textContent = TEXT_UNLOCK
            overlay.style.cursor = 'pointer'
        } else {
            const remain = t_close+LOCKED_TIME_MIN*60 - time()

            let t = `${remain} s`
            if (remain > 60) {
                t = `${Math.floor(remain/60)}:${(''+(remain%60)).padStart(2, '0')}`
            }

            overlay.textContent = `${TEXT_LOCKED} | ${t}`
            overlay.style.cursor = 'default'
        }
    }

    /* Load settings */
    {
        const now = time()

        t_opened = localStorage.getItem("mt_opentime")
        if (t_opened === null) {
            t_opened = now
            localStorage.setItem("mt_opentime", t_opened)
        } else {
            t_opened = +t_opened
        }
        t_close = t_opened + OPEN_TIME_MIN*60

        locked = (now > t_close)

        _log(`Started, open time ${OPEN_TIME_MIN} min, lock time ${LOCKED_TIME_MIN} min`)
        _log(`Last open ${Math.round((now - t_opened) / 6) / 10} min ago`)
    }

    /* build the overlay */
    {
        overlay = document.createElement('DIV')
        overlay.style.display = 'none'
        overlay.style.fontSize = '48pt'
        overlay.style.background = BACKGROUND
        overlay.style.position = 'fixed'
        overlay.style.justifyContent = 'center'
        overlay.style.alignItems = 'center'
        overlay.style.left = '0'
        overlay.style.top = '0'
        overlay.style.right = '0'
        overlay.style.bottom = '0'
        overlay.style.zIndex = '999'
        overlay.style.color = FOREGROUND
        overlay.textContent = TEXT_LOCKED

        /* append to the main wrapper */
        document.querySelector(WRAPPER_QUERY).appendChild(overlay)

        /* Handler for user unlocking by overlay click */
        overlay.addEventListener('click', () => {
            if (isUnlockAllowed()) doUnlock();
        })
    }

    /* Apply the initial lock, or auto-unlock */
    if (locked) doLock()
    if (AUTO_UNLOCK && locked && isUnlockAllowed()) {
        doUnlock();
    }

    /* Main timing loop */
    setInterval(() => {
        if (locked) updateLockedText()
        if (!locked && time() >= t_close) doLock()
    }, 1000)
})();