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}×=${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上面的代码,适当进行修改便可使用。