Greasy Fork

Magic Way Idle

法师助手

目前为 2024-10-02 提交的版本。查看 最新版本

// ==UserScript==
// @name         Magic Way Idle
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  法师助手
// @match        https://www.milkywayidle.com/*
// @match        https://test.milkywayidle.com/*
// @run-at       document-start
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_notification
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function () {
//法师排行榜
const secureData = {
    app_id: "cli_a66edef774b8d00d",
    secret: "RfrFWOp2N4o83FOuNGF6vfIqSAf10W6h",
    baseToken: "PtCAbTAR5aI1YxsdKhic5VnPnFb",
    tableID: "tblhiqRHvAtx7Rba",
};
let tenant_access_token = "";

    //脚本初始化
    script_init();
    function script_init(){
        //切换logo提示脚本已生效
        replaceIcon();
        replaceText();
        //通知权限测试
        Notification.requestPermission().then(function(result) {
            if (result === 'denied') {
                console.log('拒绝显示系统通知');
                return;
            }
            if (result === 'default') {
                console.log('默认');
                return;
            }
            console.log('允许显示系统通知')
        });
        //拦截WS
        hookWS();
        //更新飞书Token
        getTenantToken();
    }

    //改logo(脚本生效测试)
    function replaceIcon() {
        const targetDiv = document.querySelector('div.Header_logoContainer__1sCnZ');
        const load_check=document.querySelector('div.Header_totalLevel__8LY3Q');
        if (load_check && targetDiv && targetDiv.children.length > 0 && targetDiv.querySelector('svg')) {
            let originalIcon = targetDiv.firstChild;
            originalIcon.innerHTML =`<use href="/static/media/skills_sprite.2f50e113.svg#magic"></use>`;
        }else {
            setTimeout(replaceIcon, 500);
        }
    }
    //改title(脚本生效测试)
    function replaceText() {
        const targetDiv = document.querySelector('div.Header_title__5Mj8z');
        const load_check=document.querySelector('div.Header_totalLevel__8LY3Q');
        if (load_check && targetDiv && targetDiv.children.length > 0 && targetDiv.querySelector('svg')) {
                const originaltext = targetDiv.firstChild;
                const newtext = document.createElement('img');
                newtext.src = 'https://tupian.li/images/2024/10/03/66fd73f009f84.png';
                newtext.width = '64';
                newtext.height = '64';
                originaltext.parentNode.replaceChild(newtext, originaltext);
        }else {
            setTimeout(replaceText, 500);
        }
    }

    //拦截WS
    function hookWS() {
        const dataProperty = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
        const oriGet = dataProperty.get;
        dataProperty.get = hookedGet;
        Object.defineProperty(MessageEvent.prototype, "data", dataProperty);
        function hookedGet() {
            const socket = this.currentTarget;
            if (!(socket instanceof WebSocket)) {
                return oriGet.call(this);
            }
            if (socket.url.indexOf("api.milkywayidle.com/ws") <= -1 && socket.url.indexOf("api-test.milkywayidle.com/ws") <= -1) {
                return oriGet.call(this);
            }
            const message = oriGet.call(this);
            Object.defineProperty(this, "data", { value: message });
            return handleMessage(message);
        }
    }

    //WS拦截后处理
    function handleMessage(message,debug=false) {
        let obj = JSON.parse(message);
        //死亡报警
        if (obj && obj.type === "new_battle") {
            if(debug)console.log(obj);
            obj.players.forEach((player) => {
                if(player.isActive==false){
                    showNotification("有人死了");
                }
            });
        } else if (obj && obj.type === "battle_updated") {
             if(debug)console.log(obj);
             for (const key in obj.pMap) {
                 //防继承
                if (obj.pMap.hasOwnProperty(key)) {
                    const player = obj.pMap[key];
                    if(player.cHP==0){
                        showNotification("有人死了");
                    }
                }
            }
        }

        //提交数据库
        try{
            if (obj && obj.type === "profile_shared") {
                const profile = obj.profile;
                const name = profile.sharableCharacter.name;
                const guild_name = profile.guildName;
                const skills = profile.characterSkills;
                const birth = profile.sharableCharacter.createdAt.slice(0, 10).replace(/-/g, '/');
                console.log("Name:", name);
                console.log("Guild Name:", guild_name);
                console.log("Skills and Experience:");
                const info = [name, guild_name, birth];
                const skillOrder = [
                    "stamina",
                    "intelligence",
                    "attack",
                    "power",
                    "defense",
                    "ranged",
                    "magic",
                    "total_level",
                ];
                for (let skillName of skillOrder) {
                    const skill = skills.find((s) => s.skillHrid.endsWith(skillName));
                    if (skill) {
                        const skillLevel = skill.level;
                        const skillExp = Math.round(skill.experience); // 保留经验为整数
                        info.push(skillLevel, skillExp);
                    }
                }
                console.log(info.join(", "));
                RecordInfo(info);
            }
        } catch (error) {
            console.error("提交数据库失败:", error);
            return message;
        }

        //other
        return message;
    }

    //正式通知
    function showNotification(text_to_print){
        let notification = new Notification('Magic Way Idle', {
            body: text_to_print,
        });
    }

    //用户记录
    async function RecordInfo(info) {
        let [
            姓名,
            公会名,
            生日,
            耐力等级,
            耐力经验,
            智力等级,
            智力经验,
            攻击等级,
            攻击经验,
            力量等级,
            力量经验,
            防御等级,
            防御经验,
            远程等级,
            远程经验,
            魔法等级,
            魔法经验,
            总等级,
            总经验
        ] = info;

        const req_url = `https://open.feishu.cn/open-apis/bitable/v1/apps/${secureData.baseToken}/tables/${secureData.tableID}/records`;
        const post_header = {
            Authorization: `Bearer ${tenant_access_token}`,
            "Content-Type": "application/json",
        };

        // Build record payload
        const payload = {
            fields: {
                姓名: 姓名,
                公会名: 公会名,
                生日: 生日,
                耐力等级: 耐力等级,
                耐力经验: 耐力经验,
                智力等级: 智力等级,
                智力经验: 智力经验,
                攻击等级: 攻击等级,
                攻击经验: 攻击经验,
                力量等级: 力量等级,
                力量经验: 力量经验,
                防御等级: 防御等级,
                防御经验: 防御经验,
                远程等级: 远程等级,
                远程经验: 远程经验,
                魔法等级: 魔法等级,
                魔法经验: 魔法经验,
                总等级: 总等级,
                总经验: 总经验
            },

        };

        console.log("???:",JSON.stringify(payload));
        // Send POST request to record information
        GM_xmlhttpRequest({
            method: "POST",
            url: req_url,
            headers: post_header,
            data: JSON.stringify(payload),
            onload: function (response) {
                //   console.log("记录信息响应:", response.responseText);
                try {
                    const responseData = JSON.parse(response.responseText);
                    if (responseData.code === 0) {
                        //          console.log("成功记录信息:", responseData.data);
                    } else {
                        //        console.error("记录信息失败或数据格式不正确");
                    }
                } catch (error) {

                    //   console.error("解析记录信息响应时出错:", error);
                }
            },
            onerror: function (error) {
                //console.error("Error recording information:", error);
            },
        });
    }

    //获取飞书 tenant_access_token
    async function getTenantToken() {
        const req_url = `https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal`;
        const payload = {
            app_id: secureData.app_id,
            app_secret: secureData.secret,
        };
        await post_api(req_url, payload);
    }

    //提交飞书 POST request
    async function post_api(req_url, payload) {
        const payloadJson = JSON.stringify(payload);

        let post_header = {
            "Content-Type": "application/json",
        };

        // Send the POST request
        GM_xmlhttpRequest({
            method: "POST",
            url: req_url,
            headers: post_header,
            data: payloadJson,
            onload: function (response) {
                console.log(req_url);
                console.log("响应:", response.responseText);
                try {
                    const responseData = JSON.parse(response.responseText);
                    if (responseData.tenant_access_token) {
                        tenant_access_token = responseData.tenant_access_token;
                        // Store tenant_access_token securely

                        console.log("获取的 tenant_access_token:", tenant_access_token);
                    } else {
                        console.error("未能获取 tenant_access_token");
                    }
                } catch (error) {
                    console.error("解析响应时出错:", error);
                }
            },
            onerror: function (error) {
                console.error("Error fetching data:", error);
            },
        });
    }

})();