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}×=${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;
} // *********** 删除版本调用此方法即可 ***********
function deleteVersion(versionName) {
var uri = '/apps/{appId}/platformId/{pid}/userId/{userId}/isShow/{isShow}/disableVersion';
var data = {
appId: "当前操作的AppID",
pid: 1,
isShow: false,
userId: "当前登录的QQ号(需要有操作权限)",
version: ""
}; data.version = versionName; return ajaxAsync('GET', uri, data, undefined);
} // 示例 V2.4.xxx.xx的版本仅保留三个指定的版本,其余全部删除掉
var liElementArray = document.getElementsByTagName('li');
var keepVersionList = ['2.4.2.2003206', '2.4.0.2003171', '2.4.3.2003255', '2.4.1.2003203'];
for (var i = 0, len = liElementArray.length; i < len; i++) {
var liElement = liElementArray[i];
if (liElement.className === '_2DfZ7MzVviIlRz6RqqrP3w') {
if (/\>(2\.4\.\d\.\d+)\</.test(liElement.outerHTML)) {
var versionName = RegExp['$1']; if (keepVersionList.indexOf(versionName) == -1) {
console.log(versionName); deleteVersion(versionName);
} else {
console.log('skip version : ' + versionName);
} }
}
}
如果正巧遇到有几十个上百个版本需要批量删除的,可以直接copy上面的代码,适当进行修改便可使用。
bugly中批量隐藏版本的更多相关文章
- 查看nginx | apache | php | tengine | tomcat版本的信息以及如何隐藏版本信息【转】
转自: 查看nginx | apache | php | tengine | tomcat版本的信息以及如何隐藏版本信息 - 追马 - 51CTO技术博客http://lovelace.blog.51 ...
- The server of Apache (四)——配置防盗链和隐藏版本信息
一.防盗链 防盗链就是防止别人的网站代码里面盗用我们服务器的图片.文件.视频等相关资源,比如我们的网页的图片有链接,别人把链接复制粘贴到他们的服务器页面里,图片不在他们自己的网站里,每次打开他们的网站 ...
- 【C++】继承中的隐藏与覆盖
没有访问控制符时默认为私有继承. 当基类中的某个函数有若干个重载版本,继承类中也实现了该函数的某个重载版本时,参数完全相同的基类版本被覆盖,基类的其他版本被隐藏. 1.若要在继承类中使用基类的被覆盖方 ...
- DjVu、PDF中的隐藏文本
作者:马健邮箱:stronghorse_mj@hotmail.com发布:2012.06.11 目录一.背景二.DjVu中的隐藏文本三.PDF中的隐藏文本 一.背景 目前对于扫描电子文档,网上比较流行 ...
- 校对双层PDF中的隐藏文本
作者:马健邮箱:stronghorse_mj@hotmail.com发布:2012.06.11 目录一.背景二.能够校对的PDF需要满足的条件三.校对工具的选择四.校对过程五.延伸讨论 事先声明:本文 ...
- 继承中的隐藏(hide)重写(Override)和多态(Polymorphism)
继承中的隐藏:(不要使用隐藏,语法没有错误但是开发项目时会被视为错误) 在继承类中完全保留基类中的函数名 //基类,交通工具 class Vehicle { public void Run() { C ...
- 使用正则表达式在VS中批量移除 try-catch
使用正则表达式在VS中批量移除 try-catch 前言 try-catch 意为捕获错误,一般在可能出错的地方使用(如调用外部函数或外部设备),以对错误进行正确的处理,并进行后续操作而不至于程序直接 ...
- 一起看看MySQL中的隐藏列
摘要:在mysql的多版本并发控制mvcc中,我们知道mysql中存在一些隐藏列,例如行标识.事务ID.回滚指针等,不知道大家是否和我一样好奇过,要怎样才能实际地看到这些隐藏列的值呢? 本文分享自华为 ...
- 向Android模拟器中批量导入通讯录联系人
使用adb命令向Android模拟器中批量导入通讯录联系人的方法: 使用adb提供的命令, 可以非常方便地从PC中将通讯录批量导入android模拟器中. 首先要先准备好固定格式的vcf文件, 该文件 ...
随机推荐
- java多线程快速入门(一)
1.什么是进程 比如:QQ.QQ游戏.eclipse都是进程,可以通过任务管理器查看进程 2.进程和线程区别 线程是进程的一部分,一个进程可以包含多个线程,一个线程只能属于一个进程 进程是所有线程的集 ...
- LeetCode(60): 第k个排列
Medium! 题目描述: 给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列. 按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下: "123" ...
- LeetCode(36): 有效的数独
Medium! 题目描述: 判断一个 9x9 的数独是否有效.只需要根据以下规则,验证已经填入的数字是否有效即可. 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1 ...
- Laravel Eloquent 数据查询结果中日期的格式化
两种情况: 使用 Model 的查询 例如: $item = App\Models\Apple::first(); $date = $item->created_at->format('Y ...
- Memcached和Redis
作者:刘旭晖 Raymond 转载请注明出处 Email:colorant at 163.com BLOG:http://blog.csdn.net/colorant/ Memcached和Redis ...
- Ext.js项目(一)
这个项目整体采用代码生成器生成,具体看下图:
- android app 流量统计
https://blog.csdn.net/yzy9508/article/details/48300265 | android 数据流量统计 - CSDN博客https://blog.csdn.ne ...
- 白化(Whitening): PCA 与 ZCA (转)
转自:findbill 本文讨论白化(Whitening),以及白化与 PCA(Principal Component Analysis) 和 ZCA(Zero-phase Component Ana ...
- BZOJ1966 [Ahoi2005]VIRUS 病毒检测 动态规划
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1966 题意概括 现在有一些串和一个病毒模板.让你统计非病毒串的总数.串个数<=500. 串由 ...
- Evolution ZOJ2853
矩阵太大导致爆栈 解决方法:矩阵不要开在main函数里面 全部在外面处理 main函数只能处理简单的赋值和加减 损失的要自减!! 最后为 sum+=t[i]*ans.m[i][n-1]; 得 ...