bugly中批量隐藏版本

App项目使用Bugly的内测分发功能进行整包的测试,但日积月累之后,版本就会特别多。而线上同时跑的版本可能不过三个左右,那么多版本会干扰到查看崩溃、选择版本,如何隐藏呢?

右上角,更多 –> 产品设置 –> 版本管理

可是bugly有bug,只能设置显示,不能设置隐藏 >_<,好几十个版本要一个一个去点击隐藏,好麻烦,所以就用Fiddler抓了一下包然后整了一个脚本。

注:本想直接用一个for循环里 new Image().src 的方法直接批量请求,但发现它请求的时候参数fsn每次都不一样,而且头里面加了X-token,所以只能去扒它的代码了,用webpack发布的脚本,对源码进行了适当的修改。

//     uuid.js
//
//     Copyright (c) 2010-2012 Robert Kieffer
//     MIT License - http://opensource.org/licenses/mit-license.php
// Unique ID creation requires a high quality random # generator.  We feature
// detect to determine the best RNG source, normalizing to a function that
// returns 128-bits of randomness, since that's what's usually required
// var _rng = require('./rng');
var rng;

// var crypto = global.crypto || global.msCrypto; // for IE 11
// if (crypto && crypto.getRandomValues) {
//   // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
//   // Moderately fast, high quality
//   var _rnds8 = new Uint8Array(16);
//   rng = function whatwgRNG() {
//     crypto.getRandomValues(_rnds8);
//     return _rnds8;
//   };
// }

if (!rng) {
    // Math.random()-based (RNG)
    //
    // If all else fails, use Math.random().  It's fast, but is of unspecified
    // quality.
    var _rnds = new Array(16);
    rng = function() {
        for (var i = 0, r; i < 16; i++) {
            if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
            _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
        }

        return _rnds;
    };
}

// module.exports = rng;
var _rng = rng;



//////////////////
// WEBPACK FOOTER
// ./~/uuid/rng-browser.js
// module id = 955
// module chunks = 0


// Maps for number <-> hex string conversion
var _byteToHex = [];
var _hexToByte = {};
for (var i = 0; i < 256; i++) {
    _byteToHex[i] = (i + 0x100).toString(16).substr(1);
    _hexToByte[_byteToHex[i]] = i;
}

// **`parse()` - Parse a UUID into it's component bytes**
function parse(s, buf, offset) {
    var i = (buf && offset) || 0,
        ii = 0;

    buf = buf || [];
    s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
        if (ii < 16) { // Don't overflow!
            buf[i + ii++] = _hexToByte[oct];
        }
    });

    // Zero out remaining bytes if string was short
    while (ii < 16) {
        buf[i + ii++] = 0;
    }

    return buf;
}

// **`unparse()` - Convert UUID byte array (ala parse()) into a string**
function unparse(buf, offset) {
    var i = offset || 0,
        bth = _byteToHex;
    return bth[buf[i++]] + bth[buf[i++]] +
        bth[buf[i++]] + bth[buf[i++]] + '-' +
        bth[buf[i++]] + bth[buf[i++]] + '-' +
        bth[buf[i++]] + bth[buf[i++]] + '-' +
        bth[buf[i++]] + bth[buf[i++]] + '-' +
        bth[buf[i++]] + bth[buf[i++]] +
        bth[buf[i++]] + bth[buf[i++]] +
        bth[buf[i++]] + bth[buf[i++]];
}

// **`v1()` - Generate time-based UUID**
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html

// random #'s we need to init node and clockseq
var _seedBytes = _rng();

// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
var _nodeId = [
    _seedBytes[0] | 0x01,
    _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
];

// Per 4.2.2, randomize (14 bit) clockseq
var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;

// Previous uuid creation time
var _lastMSecs = 0,
    _lastNSecs = 0;

// See https://github.com/broofa/node-uuid for API details
function v1(options, buf, offset) {
    var i = buf && offset || 0;
    var b = buf || [];

    options = options || {};

    var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;

    // UUID timestamps are 100 nano-second units since the Gregorian epoch,
    // (1582-10-15 00:00).  JSNumbers aren't precise enough for this, so
    // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
    // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
    var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();

    // Per 4.2.1.2, use count of uuid's generated during the current clock
    // cycle to simulate higher resolution clock
    var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;

    // Time since last uuid creation (in msecs)
    var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;

    // Per 4.2.1.2, Bump clockseq on clock regression
    if (dt < 0 && options.clockseq === undefined) {
        clockseq = clockseq + 1 & 0x3fff;
    }

    // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
    // time interval
    if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
        nsecs = 0;
    }

    // Per 4.2.1.2 Throw error if too many uuids are requested
    if (nsecs >= 10000) {
        throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
    }

    _lastMSecs = msecs;
    _lastNSecs = nsecs;
    _clockseq = clockseq;

    // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
    msecs += 12219292800000;

    // `time_low`
    var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
    b[i++] = tl >>> 24 & 0xff;
    b[i++] = tl >>> 16 & 0xff;
    b[i++] = tl >>> 8 & 0xff;
    b[i++] = tl & 0xff;

    // `time_mid`
    var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
    b[i++] = tmh >>> 8 & 0xff;
    b[i++] = tmh & 0xff;

    // `time_high_and_version`
    b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
    b[i++] = tmh >>> 16 & 0xff;

    // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
    b[i++] = clockseq >>> 8 | 0x80;

    // `clock_seq_low`
    b[i++] = clockseq & 0xff;

    // `node`
    var node = options.node || _nodeId;
    for (var n = 0; n < 6; n++) {
        b[i + n] = node[n];
    }

    return buf ? buf : unparse(b);
}

// **`v4()` - Generate random UUID**

// See https://github.com/broofa/node-uuid for API details
function v4(options, buf, offset) {
    // Deprecated - 'format' argument, as supported in v1.2
    var i = buf && offset || 0;

    if (typeof(options) == 'string') {
        buf = options == 'binary' ? new Array(16) : null;
        options = null;
    }
    options = options || {};

    var rnds = options.random || (options.rng || _rng)();

    // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
    rnds[6] = (rnds[6] & 0x0f) | 0x40;
    rnds[8] = (rnds[8] & 0x3f) | 0x80;

    // Copy bytes to buffer, if provided
    if (buf) {
        for (var ii = 0; ii < 16; ii++) {
            buf[i + ii] = rnds[ii];
        }
    }

    return buf || unparse(rnds);
}

// Export public API
var uuid = v4;
uuid.v1 = v1;
uuid.v4 = v4;
uuid.parse = parse;
uuid.unparse = unparse;



function $param(json) {
    return Object.keys(json).reduce((sum, key) => {
        return `${(sum.length ? `${sum}&` : sum)}${key}=${json[key]}`;
    }, '');
}




function getCookie(name) {
    var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
    if (arr = document.cookie.match(reg))
        return unescape(arr[2]);
    else
        return null;
}

// 根据php打到cookie的skey值生成一个token,然后把这个值塞到请求头
function getToken() {
    /* eslint-disable no-bitwise*/
    var skey = getCookie('token-skey');
    let hash = 5381;
    if (skey) {
        for (let i = 0, len = skey.length; i < len; ++i) {
            hash += (hash << 5 & 0x7fffffff) + skey.charAt(i).charCodeAt();
        }
        return hash & 0x7fffffff;
    }
}

var APP_JSON_CONTENT_TYPE = 'application/json;charset=utf-8';
var REG_URL_PARAM = /\{(\w+)\}/ig;
var basehttp = "https://bugly.qq.com/v2";
var baseUrl = "https://bugly.qq.com/v2";

var apiBaseUrl = "https://api.bugly.qq.com/bugly2.0/";

function ajaxAsync(method, uri, data = {}, options) {
    var headers = {
        method,
        credentials: 'include',
        headers: {
            'Content-Type': APP_JSON_CONTENT_TYPE,
            Accept: APP_JSON_CONTENT_TYPE,
            'X-token': getToken(),
        },
    };

    // var mmHeader = {
    //   method: 'POST',
    //   credentials: 'include',
    //   headers: {
    //     'Content-Type': APP_JSON_CONTENT_TYPE,
    //     Accept: APP_JSON_CONTENT_TYPE,
    //     'X-token': getToken(),
    //   },
    // };

    if (method !== 'GET' && method !== 'DELETE') {
        headers.body = JSON.stringify(data);
    }

    // console.log("fetch header: %s, url: %s", JSON.stringify(headers));
    var startTime = new Date().getTime();
    return fetch(getReqUrl(method, uri, data, options), headers).then((response) => {
            var endTime = new Date().getTime();
            if (uri.indexOf('mmLogFromWeb') === -1 && uri.indexOf('trail/organize') === -1 &&
                uri.indexOf('trail/trailer') === -1) {
                // var param = {
                //   interface: uri,
                //   times: endTime - startTime,
                //   statusCode: response.status,
                // };
                // mmHeader.body = JSON.stringify(param);
                var imgSrc = `${window.webSitePathName}/mmLogFromWeb?interface=${uri}&times=${endTime - startTime}&statusCode=${response.status}`;
                var img = new Image();
                img.src = imgSrc;
                // fetch(getReqUrl('POST', "/mmLogFromWeb", data, {}), mmHeader).catch((response) => Promise.resolve({ response }));
            }
            return new Promise((resolve) => {
                response.json().then((json) => {
                    resolve({
                        json,
                        response
                    });
                }).catch(() => {
                    resolve({
                        response
                    });
                });
            });
        }).then(({
            json,
            response
        }) => Promise.resolve({
            json,
            response
        }))
        .catch((response) => {
            return Promise.resolve({
                response
            });
        });
}

function getReqUrl(method, uri, data, options) {
    let url = uri;
    // console.log("getReqUrl: ", method, ", data: ", data);
    if (uri.slice(0, basehttp.length) === basehttp) {
        url = uri;
        // url = uri;
    } else {
        url = (uri.indexOf('api') > -1 ? apiBaseUrl : baseUrl) + uri;
    }
    // console.log("before data: ", JSON.stringify(data), ", url: ", url, ", userId: ", data.userId);
    url = url.replace(REG_URL_PARAM, (...args) => {
        var key = args && !!args[1] && args[1];
        var ret = key ? data[key] : args[0];
        delete data[key];
        return ret;
    });
    //if (!Object.keys(data).length) {
    //  return url;
    //}
    if (method === 'GET' || method === 'DELETE') {
        var dataLength = Object.keys(data).length;
        url += (dataLength > 0 ? `?${$param(data)}` : '');
    }
    if (options && options.query) {
        url += (`?${$param(options.query)}`);
    }
    // 万一不是restful设计的url,需要处理,先?分割,然后token分割,然后合并
    // console.log("url === ", url);
    // if (url && url.indexOf("?") != -1) {
    //    let urlArr = url.split("?");//
    //    if (urlArr.length) {
    //        let baseUrlHead = urlArr[0].split("/token/")[0];
    //        url = baseUrlHead + "?" + urlArr[1] + "&token=" + token;//重新拼接url
    //    }
    // }
    if (url) {
        if (url.indexOf('?') !== -1) {
            url += '&fsn=' + uuid.v4();
        } else {
            url += '?fsn=' + uuid.v4();
        }
    }

    return url;
}

// *********** 删除版本调用此方法即可 ***********

如果正巧遇到有几十个上百个版本需要批量删除的,可以直接copy上面的代码,适当进行修改便可使用。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java 成神之路

spring 之 import标签、alias标签、beans标签 解析

618100
来自专栏Python小屋

Python回文判断代码优化与6个思考题

送个福利:清华大学出版社和新宝图书专营店联合推出正版特价图书《Python程序设计开发宝典》,原价69元,特价47.6元,详情:https://detail.t...

38360
来自专栏我和未来有约会

如何在silverlihgt中使用右键

一般我们在silverlight中点击右键会出现如下的对话筐. ? ? 在flash中 其提供了一个可定制话的右键菜单系统.(ContextMenu) 这个...

21970
来自专栏Pythonista

牛掰的python与unix

  加载subprocess模块仅仅是将可以使用的代码文件加载进来。也可以创建自己的模块或文件,拱以后重复使用,这与加载subprocess模块的方法相同。IP...

12220
来自专栏向治洪

Android杀毒实现原理及实例

一个杀毒软甲最核心的部分一个是病毒库一个是杀毒引擎,病毒库从服务器中获得,杀毒引擎实际上是判断程序中的包名和签名是否匹配病毒库中的包名和签名,如果匹配则为病毒,...

30070
来自专栏finleyMa

ant design源码分析 1 研究方法

ant design 是一套设计语言。 这里为了学习react,我主要学习用 React实现 的各个组件。这个是由官方维护的,代码质量高些。还有 基于vue ...

45620
来自专栏木宛城主

Unity应用架构设计(3)——构建View和ViewModel的生命周期

对于一个View而言,本质上是一个MonoBehaviour。它本身就具备生命周期这个概念,比如,Awake,Start,Update,OnDestory等。...

25450
来自专栏移动开发面面观

OpenGL学习笔记——上色

15940
来自专栏葡萄城控件技术团队

扩展GridView控件——为内容项添加拖放及分组功能

引言 相信大家对GridView都不陌生,是非常有用的控件,用于平铺有序的显示多个内容项。打开任何WinRT应用或者是微软合作商的网站,都会在APP中发现Gri...

37950
来自专栏Java与Android技术栈

基于RxJava2实现的简单图片爬虫

今年十月份以来,跟朋友尝试导入一些图片到tensorflow来生成模型,这就需要大量的图片。刚开始我只写了一个简单的HttpClient程序来抓取图片,后来为了...

16920

扫码关注云+社区

领取腾讯云代金券