防沉迷终结者 (精简版本)

不需要任何依赖, 只保留最基本的功能

Instali tiun ĉi skripton?
Author's suggested script

You may also like 4399增强.

Instali tiun ĉi skripton
// ==UserScript==
// @name         防沉迷终结者 (精简版本)
// @description  不需要任何依赖, 只保留最基本的功能
// @namespace    https://fcmsb250.github.io/
// @version      1.0.1
// @icon         https://dsy4567.github.io/logo.svg
// @author       dsy4567 https://greasyfork.org/zh-CN/users/822325 / dsy4567 https://github.com/dsy4567
// @run-at       document-start
// @license      GPL-3.0

// @match        *://*.17yy.com/*
// @match        *://*.4399.com/*
// @match        *://*.7k7k.com/*
// @match        *://*.aiwan4399.com/*
// @match        *://*.iwan4399.com/*
// @match        *://*.zxwyouxi.com/*
// @match        *://*.5054399.net/*
// @match        *://*.5054399.com/*
// @match        *://h5.07073.com/*
// @match        *://*.7724.com/*
// @match        *://*.u7u9.com/*
// @match        *://*.gamedog.cn/*
// @match        *://*.9377.com/*
// @match        *://*.37.com/*
// @match        *://*.4366.com/*

// @unwrap
// @grant        none
// @homepageURL  https://fcmsb250.github.io/
// @supportURL   https://github.com/dsy4567/Fucking-Anti-Indulgence/
// ==/UserScript==

"use strict";
let D = new Date();

/** @returns {HTMLCanvasElement | HTMLScriptElement | HTMLIFrameElement} */
function qs(selector) {
    return document.querySelector(selector);
}
/** @returns {(HTMLCanvasElement | HTMLScriptElement | HTMLIFrameElement)[]} */
function qsa(selector) {
    return document.querySelectorAll(selector);
}

let pageLoaded = false;
let realAddress_17yy = "";
/** @type {Function} */
let _playLoading;
let succeeded = false;
let gamePlatform = "";

const locationHref = location.href;
const host = location.host;
const pathname = location.pathname;
const U = new URL(location.href);

(() => {
    const a = host.split(".");
    for (let i = 0; i < a.length; i++) {
        const ss = a[i];
        if (ss === "com" || ss === "cn") {
            gamePlatform = a[i - 1];
            break;
        }
    }
})();

const /** @type {Record<string, (() => void)[]>} */ rules = {
        4399: [
            // 使防沉迷尝试读取某些全局变量时报错
            // https://www.4399.com/flash/223745_2.htm
            () => {
                Object.defineProperty(unsafeWindow, "smevent", {
                    value: null,
                    writable: false,
                });
                Object.defineProperty(unsafeWindow, "PageWebApiSdk", {
                    value: null,
                    writable: false,
                });
                Object.defineProperty(unsafeWindow, "getBizid", {
                    value: null,
                    writable: false,
                });
            },
            // https://h.4399.com/zzy/236117.htm
            () => {
                if (
                    host !== "h.4399.com" ||
                    (host === "h.4399.com" && !pathname.includes("/play/"))
                )
                    return;

                log(["4399 手机端防沉迷"]);

                const url = unsafeWindow.webServer + unsafeWindow.gameiframe;
                if (url && unsafeWindow.webServer && unsafeWindow.gameiframe) {
                    succeeded = 1;
                    location.href = url;
                }
            },
            // https://www.4399.com/flash/209443.htm
            () => {
                if (
                    host !== "h.api.4399.com" ||
                    (host === "h.api.4399.com" && pathname !== "/g.php")
                )
                    return;

                log(["4399 h5页游防沉迷(h.api.4399.com/g.php)"]);

                const gameId = U.searchParams.get("gameId");
                if (!gameId) return;
                fetch("https://h.api.4399.com/intermodal/user/grant2", {
                    method: "POST",
                    body: `gameId=${gameId}&authType=cookie&cookieValue=${getMiddleString(
                        "Pauth=",
                        ";",
                        document.cookie
                    )}`,
                    headers: {
                        "Content-Type":
                            "application/x-www-form-urlencoded; charset=UTF-8",
                    },
                })
                    .then(res => res.json())
                    .then(resp => {
                        log([resp]);
                        if (resp.data.game.gameUrl)
                            location.href = resp.data.game.gameUrl;
                        else throw new Error("[防沉迷终结者] gameUrl 为空");
                    })
                    .catch(err => console.error(err));
                succeeded = 1;
            },
        ],

        // 4399 在线玩
        zxwyouxi: [
            // https://www.zxwyouxi.com/g/100057159
            () => {
                if (
                    host !== "www.zxwyouxi.com" ||
                    (host === "www.zxwyouxi.com" && !pathname.startsWith("/g/"))
                )
                    return;

                log(["4399 h5页游防沉迷(www.zxwyouxi.com/g/)"]);

                fetch("https://h.api.4399.com/intermodal/user/grant2", {
                    method: "POST",
                    body: `gameId=${getMiddleString(
                        "/g/",
                        "",
                        locationHref,
                        "3"
                    )}&authType=token&userId=${getMiddleString(
                        "4399_HTML5_PREVIEW_USERID=",
                        ";",
                        document.cookie
                    )}&accessToken=${getMiddleString(
                        "HTML5_ACCESS_TOKEN=",
                        ";",
                        document.cookie
                    )}`,
                    headers: {
                        "Content-Type":
                            "application/x-www-form-urlencoded; charset=UTF-8",
                    },
                })
                    .then(res => res.json())
                    .then(resp => {
                        log([resp]);
                        if (resp.data.game.gameUrl)
                            location.href = resp.data.game.gameUrl;
                        else throw new Error("[防沉迷终结者] gameUrl 为空");
                    })
                    .catch(err => console.error(err));
                succeeded = 1;
            },
        ],
        "7k7k": [
            // http://www.7k7k.com/swf/205652.htm
            () => {
                if (!unsafeWindow.play22) return;

                log(["7k7k防沉迷"]);

                unsafeWindow.play22.playLoading();
                if (!_playLoading) {
                    _playLoading = unsafeWindow.play22.playLoading;
                }
                unsafeWindow.play22.playLoading = () => {}; // 防止重复调用
                succeeded = 1;
            },
            // http://m.7k7k.com/flash/205652.htm
            () => {
                if (
                    host !== "m.7k7k.com" ||
                    (host === "m.7k7k.com" &&
                        !pathname.includes("/flash/") &&
                        host === "m.7k7k.com" &&
                        !pathname.includes("/swf/"))
                )
                    return;

                log(["7k7k手机端防沉迷"]);

                unsafeWindow.open = null;
                const f = () => {
                    removeListeners("div.gameInfo_begin.jsbegin");
                    qs("div.gameInfo_begin.jsbegin").addEventListener(
                        "click",
                        () =>
                            fetch(unsafeWindow.gameInfo.gameUrl)
                                .then(res => res.text())
                                .then(html => {
                                    location.href = getMiddleString(
                                        'gameUrl: "',
                                        '",',
                                        html,
                                        "1"
                                    );
                                })
                    );
                };
                pageLoaded ? f() : addEventListener("DOMContentLoaded", f);
                succeeded = 1;
            },
            // http://h5.7k7k.com/mb/mb2/5b5dd7da8ad23b748f9ea32a7a3cedfa.html?gid=f5c4dbf7fb41d89d76a333332f33f853&tid=94606&qs=1
            () => {
                if (
                    host !== "m.7k7k.com" ||
                    (host === "m.7k7k.com" &&
                        !pathname.includes("/web/H5GAMES.html"))
                )
                    return;

                log(["7k7k h5页游防沉迷"]);

                fetch(
                    `//h5.7k7k.com/api_redirect/game/start/?client=0&account=${getMiddleString(
                        "userid=",
                        ";",
                        document.cookie,
                        "2"
                    )}&appkey=${getMiddleString(
                        "gid=",
                        "&",
                        locationHref,
                        "2"
                    )}&uid=${getMiddleString(
                        "userid=",
                        ";",
                        document.cookie,
                        "2"
                    )}&tid=${getMiddleString("tid=", "&", locationHref, "2")}`
                )
                    .then(res => res.json())
                    .then(json => {
                        location.href = json.url;
                    });
                succeeded = 1;
            },
            () => {
                if (
                    !host.includes("h5.7k7k.com") ||
                    (host.includes("h5.7k7k.com") &&
                        !pathname.includes("/game/"))
                )
                    return;

                log(["7k7k h5页游(手机端)防沉迷"]);

                fetch(
                    `//h5.7k7k.com/api_redirect/game/start/?client=0&account=${getMiddleString(
                        "userid=",
                        ";",
                        document.cookie,
                        "2"
                    )}&appkey=${unsafeWindow.gid[0]}&uid=${getMiddleString(
                        "userid=",
                        ";",
                        document.cookie,
                        "2"
                    )}&tid=${unsafeWindow.tid}`
                )
                    .then(res => res.json())
                    .then(json => {
                        location.href = json.url;
                    });
                succeeded = 1;
            },
        ],
        "17yy": [
            // https://www.17yy.com/f/play/246085.html
            // https://www.17yy.com/f/play/246568.html
            () => {
                if (
                    host !== "www.17yy.com" ||
                    (host === "www.17yy.com" && !pathname.startsWith("/f/play"))
                )
                    return;

                log(["17yy防沉迷"]);

                try {
                    if (qs("#flashgame").src === realAddress_17yy) return;
                } catch (e) {}
                try {
                    if (qs("#flash_frame").src === realAddress_17yy) return;
                } catch (e) {}

                fetch("//www.17yy.com/e/payapi/vip_ajax.php", {
                    method: "POST",
                    body: `action=getStatus&id=${getMiddleString(
                        "/f/play/",
                        ".html",
                        locationHref,
                        "3"
                    )}`,
                    headers: {
                        "Content-Type":
                            "application/x-www-form-urlencoded; charset=UTF-8",
                    },
                })
                    .then(res => res.json())
                    .then(resp => {
                        try {
                            qs("#flashgame").src = realAddress_17yy =
                                "//" +
                                unsafeWindow.server +
                                "/" +
                                unsafeWindow.classes +
                                "/" +
                                unsafeWindow.date +
                                "/" +
                                resp.data.game_path;
                        } catch (e) {}
                        try {
                            qs("#flash_frame").src = realAddress_17yy =
                                "//" +
                                unsafeWindow.server +
                                "/" +
                                unsafeWindow.classes +
                                "/" +
                                unsafeWindow.date +
                                "/" +
                                resp.data.game_path;
                        } catch (e) {}
                    });
                succeeded = 1;
            },
        ],
        7724: [
            // https://www.7724.com/XuanCaiTuXing/
            () => {
                if (
                    host !== "i.7724.com" ||
                    (host === "i.7724.com" &&
                        !locationHref.includes("/user/danjilogin?url="))
                )
                    return;

                log(["7724防沉迷"]);

                let url = getMiddleString(
                    "danjilogin?url=",
                    undefined,
                    locationHref,
                    "1"
                );
                location.href = url;
                succeeded = 1;
            },
        ],
        4366: [
            // http://wvw.4366.com/game_login.php?game=bscq&server=new
            () => {
                if (
                    !host.includes("wvw.4366.com") ||
                    (host.includes("wvw.4366.com") &&
                        !pathname.includes("/game_login.php"))
                )
                    return;

                log(["4366防沉迷"]);

                fetch(locationHref)
                    .then(res => res.text())
                    .then(html => {
                        let url = getMiddleString(
                            'align="left" id="iframe" src="',
                            '" name="mainFrame" scrolling="auto"',
                            html,
                            "1"
                        );
                        location.href = url;
                    });
                succeeded = 1;
            },
        ],
        37: [
            // https://game.37.com/server_list_901.html
            () => {
                if (
                    !host.includes("game.37.com") ||
                    (host.includes("game.37.com") &&
                        !pathname.includes("/play.php"))
                )
                    return;

                log(["37防沉迷"]);

                fetch(locationHref)
                    .then(res => res.text())
                    .then(html => {
                        let url = getMiddleString(
                            'src="//gameapp.37.com/controller/enter_game.php',
                            '" id="mainFrame"',
                            html,
                            "1",
                            "//gameapp.37.com/controller/enter_game.php"
                        );
                        location.href = url;
                    });
                succeeded = 1;
            },
        ],
        9377: [
            // http://www.9377.com/bscq/
            () => {
                if (
                    !host.includes("wvw.9377.com") ||
                    (host.includes("wvw.9377.com") &&
                        !pathname.includes("/game_login.php"))
                )
                    return;

                log(["9377防沉迷"]);

                fetch(locationHref)
                    .then(res => res.text())
                    .then(html => {
                        let url = getMiddleString(
                            'id="iframe" src="',
                            '" name="mainFrame" scrolling="auto"',
                            html,
                            "1"
                        );
                        location.href = url;
                    });
                succeeded = 1;
            },
        ],
    };
const blackList = [
    "#addiv",
    "#anti-indulge",
    "#anti-indulge-prompt",
    "#Anti_mask",
    "#Anti_open",
    "#app > div > div.cover.splash",
    "#chCoverDiv",
    "#codepop6",
    "#cover",
    "#div_dialog",
    "#easyDialogBox",
    "#fcmIframe",
    "#Guide",
    "#loginCertify",
    "#messageBox",
    "#overlay",
    "#page_wallpaper > div.xiaowei.xiaowei-orange > div.xw-left > div.xw-game > div.xw-top > div > div",
    "#pop2",
    "#pusher",
    "#shadow",
    "#swfdiv > div.box",
    "#tc100",
    "#yx_log",

    ".codegs",
    ".cmMask",
    ".fixedModal",
    ".mask",
    ".play_load",
    ".popup-c",
    ".realName",
    ".sdkDialog",
    ".toolDialog",
    ".ui-forbidden",
    ".webtipss",

    "body > div.show_box.popup_bg",
    "div[style*='z-index: 99999']",
];

/**
 * 为某个字符串获取两个字符串中间的字符串(不包括那两个字符串)
 * @param {String} begin
 * @param {String} end (可以是空字符串)
 * @param {String} target
 * @param {String | undefined} type "1": 网址, "2": 字母 + 数字, "3": 数字 (可选)
 * @param {String | undefined} append 在匹配到字符串, 判断字符串类型之前, 给匹配到的字符串前面追加指定的字符串 (可选)
 * @returns {String}
 */
function getMiddleString(begin, end, target, type, append) {
    target = target.substring(target.indexOf(begin) + begin.length);
    if (end) {
        target = decodeURI(target.substring(0, target.indexOf(end)));
    }
    if (append) {
        target = append + target;
    }
    switch (type) {
        case "1":
            if (!(/^https?:\/\//gi.test(target) || target.startsWith("//"))) {
                throw new Error("[防沉迷终结者] 不正确的字符串类型");
            }
            break;
        case "2":
            if (!/^[0-9a-zA-Z]*$/g.test(target)) {
                throw new Error("[防沉迷终结者] 不正确的字符串类型");
            }
            break;
        case "3":
            if (isNaN(Number(target))) {
                throw new Error("[防沉迷终结者] 不正确的字符串类型");
            }
            break;

        default:
            break;
    }
    return target;
}

function removeListeners(selector) {
    qsa(selector).forEach(oldElement => {
        const newElement = oldElement.cloneNode(true);
        oldElement.parentNode.replaceChild(newElement, oldElement);
    });
}

function capitalizeFirstLetter(str) {
    str = str[0].toUpperCase() + str.substring(1, str.length);
    return str;
}

/** @param {any[]} data */
function log(data) {
    console.log("[防沉迷终结者]", ...data, locationHref);
}

function crackAnti() {
    let /** @type {(() => void)[]} */ rule;
    Object.keys(rules).forEach(ruleName => {
        if (gamePlatform.includes(ruleName)) rule = rules[ruleName];
    });
    if (succeeded || !rule) {
        return log(["破解被取消或未匹配规则"]);
    }

    const begin = new Date().getTime();

    for (const func of rule) {
        try {
            func();
            if (succeeded) break;
        } catch (e) {
            console.error(e);
        }
    }

    log(["破解结束, 用时" + (new Date().getTime() - begin) + "ms"]);
}

// 添加加样式表
let css = "";
for (let i = 0; i < blackList.length; i++) {
    const element = blackList[i];
    css += element + ",";
}
css += `#qwqawaqaq
            {
                display: none !important;
                min-width: 0 !important;
                width: 0 !important;
                max-width: 0 !important;
                min-height: 0 !important;
                height: 0 !important;
                max-height: 0 !important;
                z-index: -999 !important;
                font-size: 0 !important;
                overflow: hidden !important;
            }`;
(css => {
    let s = document.createElement("style");
    s.innerHTML = css;
    document.head.append(s);
})(css);
log(["添加样式表成功"]);

addEventListener("DOMContentLoaded", () => {
    pageLoaded = true;
});

addEventListener("load", () => {
    crackAnti();
});
crackAnti();

log(["脚本执行完毕, 用时" + (new Date().getTime() - D.getTime()) + "ms "]);