rainbowcorn / 仙人指内测版

// ==UserScript==
// @name         仙人指内测版
// @namespace    https://openuserjs.org/users/rainbowcorn
// @version      0.0.2
// @description  仙人南山内测版辅助工具:批量出售物品、批量使用物品、自动检测体力并自动购买恢复
// @author       rainbowcorn
// @match        http://www.joucks.cn:3344/
// @grant        none
// @licence      MIT
// @copyright    2019, rainbowcorn (https://openuserjs.org/users/rainbowcorn)
// @require      http://code.jquery.com/jquery-3.4.1.min.js
// ==/UserScript==

(function() {
    'use strict';

    var host = 'http://www.joucks.cn:3344/api/',
        jq = jQuery.noConflict(),
        XRZCFG = {
            enabled: {
            },
            inProgress: {
                bulkBreakdownEquipments: false,
                bulkSell: false,
                bulkUse:false,
                fationBulkSkill: false,
                shopBulkBuy: false
            },
            interval: {
                bulkBreakdownEquipments: 1000,
                bulkSellButton: 1000,
                bulkUseButton: 1000,
                fationBulkSkill: 1000,
                infoTools: 1000,
                shopBulkBuyButton: 1000
            },
            intervalId: {
                bulkSellButton: 0,
                fationBulkSkill: 0,
                infoTools: 0,
                shopBulkBuyButton: 0
            },
            bulkBuyDefault: 10,
            bulkUseMax: 100,
            fationBulkSkillMax: 10,
            url: {
                buyGoods: host + 'byGoodsToMyUser',
                cook: host + 'makeLifeGoods',
                getShopItems: host + 'getGoodsAndPetMarket',
                getUserGoods: host + 'getUserGoods',
                getUserInfo: host + 'getUserInfo',
                sellGoods: host + 'sellGoods',
                useGood: host + 'useGoodsToUser'
            }
        };

    /**
     * 购买商店内的商品
     *
     * @param id   String   物品ID
     * @param qty  Number   物品数量,只能是正的整数
     * @param name String   物品名称
     * @param cb   Function 回调函数
     */
    function buy (id, qty, cb) {
        if (qty > 0) {
            jq.post(XRZCFG.url.buyGoods, {gid: id}, res => {
                qty --;
                buy(id, qty, cb);
            });
        } else {
            cb();
        }
    }

    /**
     * 更新信息到游戏记录中
     *
     * @param msg String 信息内容可以是单纯的内容也可以是HTML
     */
    function log (msg) {
        let console = document.getElementById('log');
        if (console !== null) {
            // 当信息超过500条时清理console
            if (console.querySelectorAll('p').length > 500) {
                console.innerHTML = '';
            }

            // 把信息写入console
            let p = document.createElement('p');
            p.innerHTML = msg;
            console.prepend(p);
        }
    }

    /**
     * 渲染批量使用帮派技能的按钮
     *
     * @param type   Number      技能编号
     * @param name   String      技能名称
     * @param holder HTMLElement 存放按钮的父元素
     */
    function renderFationKillBulkBtn (type, name, holder) {
        let btn = document.createElement('div');
        btn.id = 'fation-skill-bulk-' + type;
        btn.style.color = '#5f9ea0';
        btn.style.cursor = 'pointer';
        btn.innerHTML = '一键' + name + XRZCFG.fationBulkSkillMax + '次';
        btn.classList.add('row', 'user-fation-skill');
        holder.appendChild(btn);

        btn.addEventListener('click', function () {
            if (!XRZCFG.inProgress.fationBulkSkill) {
                XRZCFG.inProgress.fationBulkSkill = true;
                btn.style.color = '#ccc';
                btn.innerHTML = '批量' + name + '进行中...';
                useFationSkill(type, XRZCFG.fationBulkSkillMax, function () {
                    XRZCFG.inProgress.fationBulkSkill = false;
                    btn.style.color = '#5f9ea0';
                    btn.innerHTML = '一键' + name + XRZCFG.fationBulkSkillMax + '次';
                    log('完成批量' + name + XRZCFG.fationBulkSkillMax + '次');
                });
            } else {
                log('批量' + name + '尚未完成,请稍候...');
            }
        });
    }

    /**
     * 批量在杂货店出售物品
     *
     * @param id   String   物品ID
     * @param qty  Number   物品数量,只能是正的整数
     * @param name String   物品名称
     * @param cb   Function 回调函数
     */
    function sell (id, qty, cb) {
        if (qty > 0) {
            let data = {
                sell_json: JSON.stringify([
                    {id: id, count: qty}
                ]),
                sell_type: 'zhd' //zht = 杂货店
            };
            jq.post(XRZCFG.url.sellGoods, data, res => {
                qty --;
                sell(id, qty, cb)
            });
        } else {
            cb();
        }
    }

    /**
     * 使用背包里的物品
     *
     * @param id   String   物品ID
     * @param qty  Number   物品数量,只能是正的整数
     * @param cb   Function 回调函数
     */
    function use (id, qty, cb) {
        if (qty > 0) {
            jq.post(XRZCFG.url.useGood, {ugid: id}, res => {
                qty --;
                use(id, qty, cb);
            });
        } else {
            cb();
        }
    }

    /**
     * 按照制定次数使用帮派技能
     *
     * @param type Number   1=烹饪, 2=炼药
     * @param qty  Number   使用技能次数,只能是正的整数
     * @param cb   Function 回调函数
     */
    function useFationSkill (type, qty, cb) {
        if (qty > 0) {
            jq.post(XRZCFG.url.cook, {type: type}, res => {
                qty --;
                useFationSkill(type, qty, cb);
            })
        } else {
            cb();
        }
    }

    /**
     * 随时扫描背包内的物品元素,为非武器元素增加批量出售按钮
     */
    XRZCFG.intervalId.bulkSellButton = setInterval(function () {
        let ibs = document.querySelectorAll('.goods-block');
        if (ibs.length) {
            ibs.forEach(ib => {
                let itemId = ib.id.replace('div-', ''),
                    countEl = document.getElementById('count-' + itemId);

                // 如果countEl不存在则视该物品为武器,武器不可以在杂货店出售所以不添加批量出售按钮
                if (countEl !== null) {
                    let count = parseInt(countEl.innerText),
                        name = ib.querySelector('[onclick^="clickGoodsFunc"]').getAttribute('title'),
                        promptBox = ib.querySelector('.prompt-box'),
                        bulkBtn = promptBox.querySelector('.bulk-sell');

                    if (bulkBtn === null) {
                        bulkBtn = document.createElement('div');
                        bulkBtn.style.cursor = 'pointer';
                        bulkBtn.style.color = '#5f9ea0';
                        bulkBtn.classList.add('bulk-sell');
                        promptBox.prepend(bulkBtn);
                        bulkBtn.addEventListener('click', function () {
                            if (!XRZCFG.inProgress.bulkSell) {
                                XRZCFG.inProgress.bulkSell = true;
                                sell(itemId, count, function () {
                                    // 默认所有出售全部成功,删除该物品元素
                                    XRZCFG.inProgress.bulkSell = false;
                                    ib.remove();
                                    log('批量出售了' + count + '个【' + name + '】');
                                });
                            } else {
                                log('正在批量出售物品,请稍候...');
                            }
                        });
                    }
                    bulkBtn.innerHTML = '批量出售 (' + count + ')';
                }
            });
        }
    }, XRZCFG.interval.bulkSellButton);

    /**
     * 随时扫描背包内的物品元素,为非武器元素增加批量使用按钮
     */
    XRZCFG.intervalId.bulkUseButton = setInterval(function () {
        let ibs = document.querySelectorAll('.goods-block');
        if (ibs.length) {
            ibs.forEach(ib => {
                let itemId = ib.id.replace('div-', ''),
                    countEl = document.getElementById('count-' + itemId);

                // 如果countEl不存在则视该物品为武器,武器不可以在杂货店出售所以不添加批量出售按钮
                if (countEl !== null) {
                    let promptBox = ib.querySelector('.prompt-box'),
                        bulkBtn = promptBox.querySelector('.bulk-use'),
                        count = parseInt(countEl.innerText),
                        name = ib.querySelector('[onclick^="clickGoodsFunc"]').getAttribute('title'),
                        qty = count > XRZCFG.bulkUseMax ? XRZCFG.bulkUseMax : count;

                    if (bulkBtn === null) {
                        bulkBtn = document.createElement('div');
                        bulkBtn.style.cursor = 'pointer';
                        bulkBtn.style.color = '#5f9ea0';
                        bulkBtn.classList.add('bulk-use');
                        promptBox.prepend(bulkBtn);
                        bulkBtn.addEventListener('click', function () {
                            if (!XRZCFG.inProgress.bulkUse) {
                                XRZCFG.inProgress.bulkUse = true;
                                use(itemId, qty, function () {
                                    // 默认所有出售全部成功
                                    XRZCFG.inProgress.bulkUse = false;
                                    count -= qty;
                                    bulkBtn.innerHTML = '批量使用 (' + qty + ')';
                                    countEl.innerHTML = count;
                                    if (count <= 0) {
                                        ib.remove();
                                    }
                                    log('批量使用了' + qty + '个【' + name + '】');
                                });
                            } else {
                                log('正在批量使用物品,请稍候...');
                            }
                        });
                    }
                    bulkBtn.innerHTML = '批量使用 (' + qty + ')';
                }
            });
        }
    }, XRZCFG.interval.bulkUseButton);

    /**
     * 随时扫描帮派技能,添加批量使用帮派技能的按钮
     */
    XRZCFG.intervalId.fationBulkSkill = setInterval(function () {
        let fationSkillsEl = document.getElementById('user-fation-skill'),
            strongBtn = document.getElementById('fation-skill-bulk-3'),
            speedBtn = document.getElementById('fation-skill-bulk-4'),
            cookBtn = document.getElementById('fation-skill-bulk-1'),
            refineBtn = document.getElementById('fation-skill-bulk-2'),
            makeBtn = document.getElementById('fation-skill-bulk-5');

        // 渲染强身按钮
        if (strongBtn === null) {
            //renderFationKillBulkBtn(3, '强身', fationSkillsEl);
        }

        // 渲染神速按钮
        if (speedBtn === null) {
            //renderFationKillBulkBtn(4, '神速', fationSkillsEl);
        }

        // 渲染烹饪按钮
        if (cookBtn === null) {
            renderFationKillBulkBtn(1, '烹饪', fationSkillsEl);
        }

        // 渲染炼药按钮
        if (refineBtn === null) {
            renderFationKillBulkBtn(2, '炼药', fationSkillsEl);
        }

        // 渲染打造按钮
        if (makeBtn === null) {
            //renderFationKillBulkBtn(5, '打造', fationSkillsEl);
        }
    }, XRZCFG.interval.fationBulkSkill);

    /**
     * 随时扫描商店内的物品元素,添加批量购买按钮
     * type = 1 // 宠物
     * type = 2 // 物品
     */
    XRZCFG.intervalId.shopBulkBuyButton = setInterval(function () {
        let pbs = document.querySelectorAll('.pet-block:not(.money-block)');
        if (pbs.length) {
            pbs.forEach(pb => {
                let bulkBuy = pb.querySelector('.bulk-buy'),
                    buyBtn = pb.querySelector('.by-pet'),
                    buyFnStr = buyBtn.getAttribute('onclick').replace('byGoodsToSystemFunc', '').replace(/[()\']/g, ''),
                    buyType = buyFnStr.split(',')[0],
                    buyQty = XRZCFG.bulkBuyDefault,
                    itemId = buyFnStr.split(',')[1],
                    name = pb.querySelector('a[title]').innerText,
                    promptBox = pb.querySelector('.prompt-box');

                if (bulkBuy === null) {
                    let bulkBuyBtn = document.createElement('div'),
                        bulkBuyQty = document.createElement('input');

                    // 容器
                    bulkBuy = document.createElement('div');
                    bulkBuy.style.display = 'flex';
                    bulkBuy.style.justifyContent = 'space-between';
                    bulkBuy.style.height = '30px';
                    bulkBuy.style.marginTop = '10px';
                    bulkBuy.style.width = 'calc(100% - 10px)';
                    bulkBuy.classList.add('bulk-buy');

                    // 按钮
                    //bulkBuyBtn.style.backgroundColor = '#fff';
                    //bulkBuyBtn.style.border = '1px solid #333';
                    //bulkBuyBtn.style.borderTopRightRadius = '3px';
                    //bulkBuyBtn.style.borderBottomRightadius = '3px';
                    bulkBuyBtn.style.color = '#5f9ea0';
                    bulkBuyBtn.style.cursor = 'pointer';
                    bulkBuyBtn.style.lineHeight = '30px';
                    //bulkBuyBtn.style.outline = 'none';
                    bulkBuyBtn.style.textAlign = 'center';
                    bulkBuyBtn.style.width = '65px';
                    bulkBuyBtn.innerHTML = '批量购买';
                    bulkBuyBtn.addEventListener('click', function () {
                        if (!XRZCFG.inProgress.shopBulkBuy) {
                            XRZCFG.inProgress.shopBulkBuy = true;
                            buy(itemId, buyQty, function () {
                                XRZCFG.inProgress.shopBulkBuy = false;
                                log('批量购买了' + buyQty + '个【' + name + '】');
                            });
                        } else {
                            log('批量购买正在进行中,请稍候...');
                        }
                    });

                    // 数量
                    bulkBuyQty.style.backgroundColor = '#fff';
                    bulkBuyQty.style.border = '1px solid #666';
                    bulkBuyQty.style.borderRadius = '3px';
                    bulkBuyQty.style.lineHeight = '30px';
                    bulkBuyQty.style.outline = 'none';
                    bulkBuyQty.style.textAlign = 'center';
                    bulkBuyQty.style.width = 'calc(100% - 65px)';
                    bulkBuyQty.innerHTML = '批量购买';
                    bulkBuyQty.type = 'number';
                    bulkBuyQty.value = buyQty;
                    bulkBuyQty.addEventListener('change', function () {
                        if (!isNaN(parseInt(this.value))) {
                            buyQty = parseInt(this.value);
                        }
                    });

                    bulkBuy.append(bulkBuyQty);
                    bulkBuy.append(bulkBuyBtn);
                    promptBox.prepend(bulkBuy);
                }
            });
        }
    }, XRZCFG.interval.shopBulkBuyButton);

    XRZCFG.intervalId.infoTools = setInterval(function () {
        let infoDiv = document.querySelector('.divinfo');
        if (infoDiv !== null) {
            let bulkBreakdownEquipment = infoDiv.querySelector('.bulk-breakdown-equipment');

            if (bulkBreakdownEquipment === null) {
                bulkBreakdownEquipment = document.createElement('select');
                bulkBreakdownEquipment.style.marginBottom = '5px';
                bulkBreakdownEquipment.style.outline = 'none';
                bulkBreakdownEquipment.style.width = '100%';
                bulkBreakdownEquipment.classList.add('bulk-breakdown-equipment');
                refreshBreakdownEquipment(bulkBreakdownEquipment);
                bulkBreakdownEquipment.addEventListener('change', function () {
                    if (!XRZCFG.inProgress.bulkBreakdownEquipments && this.value !== '') {
                        let count = 0,
                            buttons = [],
                            value = this.value;
                        document.querySelectorAll('.goods-block').forEach(function (gb) {
                            if (gb.querySelector('a[title]').title === value) {
                                buttons.push(gb.querySelector('[onclick^="breakDownEquipmentFunc"]'));
                            }
                        });
                        XRZCFG.inProgress.bulkBreakdownEquipments = true;
                        bulkBreakdownEquipment.disabled = true;
                        let intervalId = setInterval(function () {
                            if (count < buttons.length - 1) {
                                buttons[count].click();
                                count ++;
                            } else {
                                XRZCFG.inProgress.bulkBreakdownEquipments = false;
                                bulkBreakdownEquipment.disabled = false;
                                refreshBreakdownEquipment(bulkBreakdownEquipment);
                                clearInterval(intervalId);
                            }
                        }, XRZCFG.interval.bulkBreakdownEquipments);
                    } else {
                        log('正在批量分解装备中,请稍候...');
                    }
                });
                infoDiv.insertBefore(bulkBreakdownEquipment, infoDiv.querySelector('.user-task'));
            }
            if (bulkBreakdownEquipment.length <= 1) {
                refreshBreakdownEquipment(bulkBreakdownEquipment);
            }
        }
    }, XRZCFG.interval.infoTools);

    function refreshBreakdownEquipment (el) {
        let equipments = {};
        el.innerHTML = '<option value="">选择一个装备来批量分解</option>';
        document.querySelectorAll('.goods-block').forEach(function (gb) {
            if (gb.querySelector('[onclick^="breakDownEquipmentFunc"]') !== null) {
                let name = gb.querySelector('a[title]').title;
                if (typeof equipments[name] === 'undefined') {
                    equipments[name] = 1;
                } else {
                    equipments[name] ++;
                }
            }
        });
        for (let name in equipments) {
            el.innerHTML += '<option value="' + name + '">' + name + ' (' + equipments[name] + ')</option>';
        }
        return el
    }
})();