LINUX.DO CloudFlare Challenge Bypass

Automatically redirects to the challenge page when CloudFlare protection fails, improving browsing experience on linux.do

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name                 LINUX.DO CloudFlare Challenge Bypass
// @name:zh-CN           LINUX.DO CloudFlare 5秒盾自动跳转
// @namespace            https://github.com/utags
// @homepageURL          https://github.com/utags/userscripts#readme
// @supportURL           https://github.com/utags/userscripts/issues
// @version              0.3.2
// @description          Automatically redirects to the challenge page when CloudFlare protection fails, improving browsing experience on linux.do
// @description:zh-CN    当 CloudFlare 5秒盾检测失败时,自动跳转到 challenge 页面,提升 linux.do 的浏览体验
// @author               Pipecraft
// @license              MIT
// @match                https://linux.do/*
// @icon                 https://wsrv.nl/?w=64&h=64&url=https%3A%2F%2Ft3.gstatic.com%2FfaviconV2%3Fclient%3DSOCIAL%26type%3DFAVICON%26fallback_opts%3DTYPE%2CSIZE%2CURL%26url%3Dhttps%3A%2F%2Flinux.do%26size%3D64
// @grant                GM_registerMenuCommand
// ==/UserScript==
//
;(() => {
  'use strict'
  var CONFIG = {
    ERROR_TEXTS: [
      '403 error',
      '\u8BE5\u56DE\u5E94\u662F\u5F88\u4E45\u4EE5\u524D\u521B\u5EFA\u7684',
      'reaction was created too long ago',
      '\u6211\u4EEC\u65E0\u6CD5\u52A0\u8F7D\u8BE5\u8BDD\u9898',
      'You are not allowed to react',
    ],
    DIALOG_SELECTOR: '.dialog-body',
    CHALLENGE_PATH: '/challenge',
    DEBUG: false,
    MENU_TEXT: '\u624B\u52A8\u89E6\u53D1 Challenge \u8DF3\u8F6C',
  }
  var log = (...args) => {
    if (CONFIG.DEBUG) {
      console.log('[LINUX.DO Auto Challenge]', ...args)
    }
  }
  function isChallengePage() {
    return globalThis.location.pathname.startsWith(CONFIG.CHALLENGE_PATH)
  }
  function isNotFoundPage() {
    return Boolean(document.querySelector('.page-not-found'))
  }
  function getRedirectParamUrl() {
    try {
      const sp = new URLSearchParams(globalThis.location.search)
      const raw = sp.get('redirect')
      if (!raw) return void 0
      const url = new URL(raw, globalThis.location.origin)
      if (url.origin !== globalThis.location.origin) return void 0
      return url.href
    } catch (e) {
      return void 0
    }
  }
  var NOT_FOUND_REDIRECT_GUARD_KEY = 'linux_do_auto_challenge_nf_guard'
  function getNotFoundRedirectGuardTs() {
    try {
      const raw = sessionStorage.getItem(NOT_FOUND_REDIRECT_GUARD_KEY)
      const n = raw ? Number(raw) : 0
      return Number.isFinite(n) ? n : 0
    } catch (e) {
      return 0
    }
  }
  function setNotFoundRedirectGuardTs(ts) {
    try {
      sessionStorage.setItem(NOT_FOUND_REDIRECT_GUARD_KEY, String(ts))
    } catch (e) {}
  }
  function redirectFromNotFoundPage() {
    const fallback = ''.concat(globalThis.location.origin, '/')
    const target = getRedirectParamUrl() || fallback
    const now = Date.now()
    const guardTs = getNotFoundRedirectGuardTs()
    if (guardTs && now - guardTs < 5e3) {
      return
    }
    setNotFoundRedirectGuardTs(now)
    if (target === globalThis.location.href) {
      globalThis.location.replace(fallback)
      return
    }
    globalThis.location.replace(target)
  }
  function isChallengeFailure() {
    if (isChallengePage()) {
      return false
    }
    try {
      const dialogElement = document.querySelector(CONFIG.DIALOG_SELECTOR)
      if (!dialogElement) return false
      const text = dialogElement.textContent || ''
      return CONFIG.ERROR_TEXTS.some((errorText) => text.includes(errorText))
    } catch (error) {
      log('\u68C0\u6D4B\u5931\u8D25\u9875\u9762\u65F6\u51FA\u9519:', error)
      return false
    }
  }
  function redirectToChallenge() {
    try {
      if (isChallengePage()) return
      const redirectUrl = ''
        .concat(CONFIG.CHALLENGE_PATH, '?redirect=')
        .concat(encodeURIComponent(globalThis.location.href))
      log('\u91CD\u5B9A\u5411\u5230:', redirectUrl)
      globalThis.location.href = redirectUrl
    } catch (error) {
      log('\u91CD\u5B9A\u5411\u65F6\u51FA\u9519:', error)
    }
  }
  function checkAndRedirect(observer) {
    if (isChallengeFailure()) {
      if (observer) observer.disconnect()
      redirectToChallenge()
      return true
    }
    return false
  }
  function manualTrigger() {
    log('\u624B\u52A8\u89E6\u53D1 Challenge \u8DF3\u8F6C')
    if (isChallengePage()) {
      alert('\u5DF2\u5728 Challenge \u9875\u9762\uFF0C\u65E0\u9700\u8DF3\u8F6C')
      return
    }
    redirectToChallenge()
  }
  function initScript() {
    log('\u521D\u59CB\u5316\u811A\u672C')
    if (isChallengePage()) {
      if (isNotFoundPage()) {
        redirectFromNotFoundPage()
        return
      }
      log(
        '\u5DF2\u5728 challenge \u9875\u9762\uFF0C\u4E0D\u6267\u884C\u811A\u672C'
      )
      return
    }
    if (checkAndRedirect()) return
    try {
      const observer = new MutationObserver((mutations, obs) => {
        if (isChallengePage()) {
          if (isNotFoundPage()) {
            redirectFromNotFoundPage()
          }
        } else {
          checkAndRedirect(obs)
        }
      })
      observer.observe(document.body, {
        childList: true,
        subtree: true,
        characterData: true,
      })
      log('DOM \u89C2\u5BDF\u5668\u5DF2\u542F\u52A8')
    } catch (error) {
      log('\u542F\u52A8 DOM \u89C2\u5BDF\u5668\u65F6\u51FA\u9519:', error)
    }
    try {
      GM_registerMenuCommand(CONFIG.MENU_TEXT, manualTrigger)
      log('\u83DC\u5355\u547D\u4EE4\u5DF2\u6CE8\u518C')
    } catch (error) {
      log('\u6CE8\u518C\u83DC\u5355\u547D\u4EE4\u65F6\u51FA\u9519:', error)
    }
  }
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initScript)
  } else {
    initScript()
  }
})()